kdeui Library API Documentation

ktextedit.cpp

00001 /* This file is part of the KDE libraries
00002    Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00017    Boston, MA 02111-1307, USA.
00018 */
00019 
00020 #include "ktextedit.h"
00021 
00022 #include <qapplication.h>
00023 #include <qclipboard.h>
00024 #include <qpopupmenu.h>
00025 
00026 #include <ksyntaxhighlighter.h>
00027 #include <kspell.h>
00028 #include <kcursor.h>
00029 #include <kglobalsettings.h>
00030 #include <kstdaccel.h>
00031 #include <kiconloader.h>
00032 #include <klocale.h>
00033 
00034 class KTextEdit::KTextEditPrivate
00035 {
00036 public:
00037     KTextEditPrivate()
00038         : customPalette( false ),
00039           checkSpellingEnabled( false ),
00040           highlighter( 0 ),
00041           spell( 0 )
00042     {}
00043     ~KTextEditPrivate() {
00044         delete highlighter;
00045         delete spell;
00046     }
00047 
00048     bool customPalette;
00049     bool checkSpellingEnabled;
00050     KDictSpellingHighlighter *highlighter;
00051     KSpell *spell;
00052 };
00053 
00054 KTextEdit::KTextEdit( const QString& text, const QString& context,
00055                       QWidget *parent, const char *name )
00056     : QTextEdit ( text, context, parent, name )
00057 {
00058     d = new KTextEditPrivate();
00059     KCursor::setAutoHideCursor( this, true, false );
00060 }
00061 
00062 KTextEdit::KTextEdit( QWidget *parent, const char *name )
00063     : QTextEdit ( parent, name )
00064 {
00065     d = new KTextEditPrivate();
00066     KCursor::setAutoHideCursor( this, true, false );
00067 }
00068 
00069 KTextEdit::~KTextEdit()
00070 {
00071     delete d;
00072 }
00073 
00074 void KTextEdit::keyPressEvent( QKeyEvent *e )
00075 {
00076     KKey key( e );
00077 
00078     if ( KStdAccel::copy().contains( key ) ) {
00079         copy();
00080         e->accept();
00081         return;
00082     }
00083     else if ( KStdAccel::paste().contains( key ) ) {
00084         paste();
00085         e->accept();
00086         return;
00087     }
00088     else if ( KStdAccel::cut().contains( key ) ) {
00089         cut();
00090         e->accept();
00091         return;
00092     }
00093     else if ( KStdAccel::undo().contains( key ) ) {
00094         undo();
00095         e->accept();
00096         return;
00097     }
00098     else if ( KStdAccel::redo().contains( key ) ) {
00099         redo();
00100         e->accept();
00101         return;
00102     }
00103     else if ( KStdAccel::deleteWordBack().contains( key ) )
00104     {
00105         deleteWordBack();
00106         e->accept();
00107         return;
00108     }
00109     else if ( KStdAccel::deleteWordForward().contains( key ) )
00110     {
00111         deleteWordForward();
00112         e->accept();
00113         return;
00114     }/*
00115      
00116      HACK HACK! WORK ARROUND!
00117      it looks like there is a bug in qt... commenting these lines fixes
00118      some cursor movement problems with BIDI... please uncomment these 
00119      lines after QT is fixed
00120      
00121     else if ( KStdAccel::backwardWord().contains( key ) )
00122     {
00123       moveCursor(MoveWordBackward, false );
00124       e->accept();
00125       return;
00126     }
00127     else if ( KStdAccel::forwardWord().contains( key ) )
00128     {
00129       moveCursor( MoveWordForward, false );
00130       e->accept();
00131       return;
00132     }*/
00133     else if ( KStdAccel::next().contains( key ) )
00134     {
00135       moveCursor( MovePgDown, false );
00136       e->accept();
00137       return;
00138     }
00139     else if ( KStdAccel::prior().contains( key ) )
00140     {
00141       moveCursor( MovePgUp, false );
00142       e->accept();
00143       return;
00144     }
00145     else if ( KStdAccel::home().contains( key ) )
00146     {
00147       moveCursor( MoveHome, false );
00148       e->accept();
00149       return;
00150     }
00151     else if ( KStdAccel::end().contains( key ) )
00152     {
00153       moveCursor( MoveEnd, false );
00154       e->accept();
00155       return;
00156     }
00157     else if ( KStdAccel::beginningOfLine().contains( key ) )
00158     {
00159       moveCursor( MoveLineStart, false );
00160       e->accept();
00161       return;
00162     }
00163     else if ( KStdAccel::endOfLine().contains( key ) )
00164     {
00165       moveCursor(MoveLineEnd, false);
00166       e->accept();
00167       return;
00168     }
00169 
00170     else if ( e->key() == Key_Insert &&
00171               (e->state() == (ShiftButton | ControlButton)) )
00172     {
00173         QString text = QApplication::clipboard()->text( QClipboard::Selection);
00174         if ( !text.isEmpty() )
00175             insert( text );
00176         e->accept();
00177         return;
00178     }
00179 
00180     // ignore Ctrl-Return so that KDialogs can close the dialog
00181     else if ( e->state() == ControlButton &&
00182               (e->key() == Key_Return || e->key() == Key_Enter) &&
00183               topLevelWidget()->inherits( "KDialog" ) )
00184     {
00185         e->ignore();
00186         return;
00187     }
00188     
00189     QTextEdit::keyPressEvent( e );
00190 }
00191 
00192 void KTextEdit::deleteWordBack()
00193 {
00194     removeSelection();
00195     moveCursor( MoveWordBackward, true );
00196     removeSelectedText();
00197 }
00198 
00199 void KTextEdit::deleteWordForward()
00200 {
00201     removeSelection();
00202     moveCursor( MoveWordForward, true );
00203     removeSelectedText();
00204 }
00205 
00206 void KTextEdit::slotAllowTab()
00207 {
00208 setTabChangesFocus(!tabChangesFocus());
00209 }
00210 
00211 QPopupMenu *KTextEdit::createPopupMenu( const QPoint &pos )
00212 {
00213     enum { IdUndo, IdRedo, IdSep1, IdCut, IdCopy, IdPaste, IdClear, IdSep2, IdSelectAll };
00214 
00215     QPopupMenu *menu = QTextEdit::createPopupMenu( pos );
00216 
00217     if ( isReadOnly() )
00218       menu->changeItem( menu->idAt(0), SmallIconSet("editcopy"), menu->text( menu->idAt(0) ) );
00219     else {
00220       int id = menu->idAt(0);
00221       menu->changeItem( id - IdUndo, SmallIconSet("undo"), menu->text( id - IdUndo) );
00222       menu->changeItem( id - IdRedo, SmallIconSet("redo"), menu->text( id - IdRedo) );
00223       menu->changeItem( id - IdCut, SmallIconSet("editcut"), menu->text( id - IdCut) );
00224       menu->changeItem( id - IdCopy, SmallIconSet("editcopy"), menu->text( id - IdCopy) );
00225       menu->changeItem( id - IdPaste, SmallIconSet("editpaste"), menu->text( id - IdPaste) );
00226       menu->changeItem( id - IdClear, SmallIconSet("editclear"), menu->text( id - IdClear) );
00227 
00228         menu->insertSeparator();
00229         id = menu->insertItem( SmallIconSet( "spellcheck" ), i18n( "Check Spelling..." ),
00230                                    this, SLOT( checkSpelling() ) );
00231 
00232         if( text().isEmpty() )
00233             menu->setItemEnabled( id, false );
00234 
00235         id = menu->insertItem( i18n( "Auto Spell Check" ),
00236                                this, SLOT( toggleAutoSpellCheck() ) );
00237         menu->setItemChecked(id, d->checkSpellingEnabled);
00238     menu->insertSeparator();
00239     id=menu->insertItem(i18n("Allow Tabulations"),this,SLOT(slotAllowTab()));
00240     menu->setItemChecked(id, !tabChangesFocus());
00241     }
00242 
00243     return menu;
00244 }
00245 
00246 QPopupMenu *KTextEdit::createPopupMenu()
00247 {
00248     return QTextEdit::createPopupMenu();
00249 }
00250 
00251 void KTextEdit::contentsWheelEvent( QWheelEvent *e )
00252 {
00253     if ( KGlobalSettings::wheelMouseZooms() )
00254         QTextEdit::contentsWheelEvent( e );
00255     else // thanks, we don't want to zoom, so skip QTextEdit's impl.
00256         QScrollView::contentsWheelEvent( e );
00257 }
00258 
00259 void KTextEdit::setPalette( const QPalette& palette )
00260 {
00261     QTextEdit::setPalette( palette );
00262     // unsetPalette() is not virtual and calls setPalette() as well
00263     // so we can use ownPalette() to find out about unsetting
00264     d->customPalette = ownPalette();
00265 }
00266 
00267 void KTextEdit::toggleAutoSpellCheck()
00268 {
00269     setCheckSpellingEnabled( !d->checkSpellingEnabled );
00270 }
00271 
00272 void KTextEdit::setCheckSpellingEnabled( bool check )
00273 {
00274     if ( check == d->checkSpellingEnabled )
00275         return;
00276 
00277     // From the above statment we know know that if we're turning checking
00278     // on that we need to create a new highlighter and if we're turning it
00279     // off we should remove the old one.
00280 
00281     d->checkSpellingEnabled = check;
00282     if ( check )
00283     {
00284         if (hasFocus())
00285             d->highlighter = new KDictSpellingHighlighter( this );
00286     }
00287     else
00288     {
00289         delete d->highlighter;
00290         d->highlighter = 0;
00291     }
00292 }
00293 
00294 void KTextEdit::focusInEvent( QFocusEvent *e )
00295 {
00296     if ( d->checkSpellingEnabled && !d->highlighter )
00297         d->highlighter = new KDictSpellingHighlighter( this );
00298 
00299     QTextEdit::focusInEvent( e );
00300 }
00301 
00302 bool KTextEdit::checkSpellingEnabled() const
00303 {
00304     return d->checkSpellingEnabled;
00305 }
00306 
00307 void KTextEdit::setReadOnly(bool readOnly)
00308 {
00309     if ( readOnly == isReadOnly() )
00310         return;
00311 
00312     if (readOnly)
00313     {
00314         bool custom = ownPalette();
00315         QPalette p = palette();
00316         QColor color = p.color(QPalette::Disabled, QColorGroup::Background);
00317         p.setColor(QColorGroup::Base, color);
00318         p.setColor(QColorGroup::Background, color);
00319         setPalette(p);
00320         d->customPalette = custom;
00321     }
00322     else
00323     {
00324         if ( d->customPalette )
00325         {
00326             QPalette p = palette();
00327             QColor color = p.color(QPalette::Normal, QColorGroup::Base);
00328             p.setColor(QColorGroup::Base, color);
00329             p.setColor(QColorGroup::Background, color);
00330             setPalette( p );
00331         }
00332         else
00333             unsetPalette();
00334     }
00335 
00336     QTextEdit::setReadOnly (readOnly);
00337 }
00338 
00339 void KTextEdit::virtual_hook( int, void* )
00340 { /*BASE::virtual_hook( id, data );*/ }
00341 
00342 void KTextEdit::checkSpelling()
00343 {
00344     delete d->spell;
00345     d->spell = new KSpell( this, i18n( "Spell Checking" ),
00346                           this, SLOT( slotSpellCheckReady( KSpell *) ), 0, true, true);
00347 
00348     connect( d->spell, SIGNAL( death() ),
00349              this, SLOT( spellCheckerFinished() ) );
00350 
00351     connect( d->spell, SIGNAL( misspelling( const QString &, const QStringList &, unsigned int ) ),
00352              this, SLOT( spellCheckerMisspelling( const QString &, const QStringList &, unsigned int ) ) );
00353 
00354     connect( d->spell, SIGNAL( corrected( const QString &, const QString &, unsigned int ) ),
00355              this, SLOT( spellCheckerCorrected( const QString &, const QString &, unsigned int ) ) );
00356 }
00357 
00358 void KTextEdit::spellCheckerMisspelling( const QString &text, const QStringList &, unsigned int pos )
00359 {
00360     highLightWord( text.length(), pos );
00361 }
00362 
00363 void KTextEdit::spellCheckerCorrected( const QString &oldWord, const QString &newWord, unsigned int pos )
00364 {
00365     unsigned int l = 0;
00366     unsigned int cnt = 0;
00367     if ( oldWord != newWord ) {
00368         posToRowCol( pos, l, cnt );
00369         setSelection( l, cnt, l, cnt + oldWord.length() );
00370         removeSelectedText();
00371         insert( newWord );
00372     }
00373 }
00374 
00375 void KTextEdit::posToRowCol(unsigned int pos, unsigned int &line, unsigned int &col)
00376 {
00377     for ( line = 0; line < static_cast<uint>( lines() ) && col <= pos; line++ )
00378         col += paragraphLength( line ) + 1;
00379 
00380     line--;
00381     col = pos - col + paragraphLength( line ) + 1;
00382 }
00383 
00384 void KTextEdit::spellCheckerFinished()
00385 {
00386     delete d->spell;
00387     d->spell = 0L;
00388 }
00389 
00390 void KTextEdit::slotSpellCheckReady( KSpell *s )
00391 {
00392     s->check( text() );
00393     connect( s, SIGNAL( done( const QString & ) ), this, SLOT( slotSpellCheckDone( const QString & ) ) );
00394 }
00395 
00396 void KTextEdit::slotSpellCheckDone( const QString &s )
00397 {
00398     if ( s != text() )
00399         setText( s );
00400 }
00401 
00402 
00403 void KTextEdit::highLightWord( unsigned int length, unsigned int pos )
00404 {
00405     unsigned int l = 0;
00406     unsigned int cnt = 0;
00407     posToRowCol( pos, l, cnt );
00408     setSelection( l, cnt, l, cnt + length );
00409 }
00410 
00411 #include "ktextedit.moc"
KDE Logo
This file is part of the documentation for kdeui Library Version 3.3.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sun Jan 15 13:32:55 2006 by doxygen 1.4.2 written by Dimitri van Heesch, © 1997-2003