• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdepimlibs-4.8.3 API Reference
  • KDE Home
  • Contact Us
 

KPIMTextedit Library

textedit.cpp
00001 /*
00002   Copyright (c) 2009 Thomas McGuire <mcguire@kde.org>
00003 
00004   Based on KMail and libkdepim code by:
00005   Copyright 2007 Laurent Montel <montel@kde.org>
00006 
00007   This library is free software; you can redistribute it and/or modify it
00008   under the terms of the GNU Library General Public License as published by
00009   the Free Software Foundation; either version 2 of the License, or (at your
00010   option) any later version.
00011 
00012   This library is distributed in the hope that it will be useful, but WITHOUT
00013   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00015   License for more details.
00016 
00017   You should have received a copy of the GNU Library General Public License
00018   along with this library; see the file COPYING.LIB.  If not, write to the
00019   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00020   02110-1301, USA.
00021 */
00022 #include "textedit.h"
00023 
00024 #include "emailquotehighlighter.h"
00025 
00026 #include <kmime/kmime_codecs.h>
00027 
00028 #include <KDE/KAction>
00029 #include <KDE/KActionCollection>
00030 #include <KDE/KCursor>
00031 #include <KDE/KFileDialog>
00032 #include <KDE/KLocalizedString>
00033 #include <KDE/KMessageBox>
00034 #include <KDE/KPushButton>
00035 #include <KDE/KUrl>
00036 
00037 #include <QtCore/QBuffer>
00038 #include <QtCore/QDateTime>
00039 #include <QtCore/QMimeData>
00040 #include <QtCore/QFileInfo>
00041 #include <QtCore/QPointer>
00042 #include <QtGui/QKeyEvent>
00043 #include <QtGui/QTextLayout>
00044 
00045 #include "textutils.h"
00046 #include <QPlainTextEdit>
00047 
00048 namespace KPIMTextEdit {
00049 
00050 class TextEditPrivate
00051 {
00052   public:
00053 
00054     TextEditPrivate( TextEdit *parent )
00055       : actionAddImage( 0 ),
00056         actionDeleteLine( 0 ),
00057         q( parent ),
00058         imageSupportEnabled( false )
00059     {
00060     }
00061 
00070     void addImageHelper( const QString &imageName, const QImage &image );
00071 
00075     QList<QTextImageFormat> embeddedImageFormats() const;
00076 
00081     void fixupTextEditString( QString &text ) const;
00082 
00086     void init();
00087 
00092     void _k_slotAddImage();
00093 
00094     void _k_slotDeleteLine();
00095 
00097     KAction *actionAddImage;
00098 
00100     KAction *actionDeleteLine;
00101 
00103     TextEdit *q;
00104 
00106     bool imageSupportEnabled;
00107 
00113     QStringList mImageNames;
00114 
00126     bool spellCheckingEnabled;
00127 
00128     QString configFile;
00129 };
00130 
00131 } // namespace
00132 
00133 using namespace KPIMTextEdit;
00134 
00135 void TextEditPrivate::fixupTextEditString( QString &text ) const
00136 {
00137   // Remove line separators. Normal \n chars are still there, so no linebreaks get lost here
00138   text.remove( QChar::LineSeparator );
00139 
00140   // Get rid of embedded images, see QTextImageFormat documentation:
00141   // "Inline images are represented by an object replacement character (0xFFFC in Unicode) "
00142   text.remove( 0xFFFC );
00143 
00144   // In plaintext mode, each space is non-breaking.
00145   text.replace( QChar::Nbsp, QChar::fromAscii( ' ' ) );
00146 }
00147 
00148 TextEdit::TextEdit( const QString &text, QWidget *parent )
00149   : KRichTextWidget( text, parent ),
00150     d( new TextEditPrivate( this ) )
00151 {
00152   d->init();
00153 }
00154 
00155 TextEdit::TextEdit( QWidget *parent )
00156   : KRichTextWidget( parent ),
00157     d( new TextEditPrivate( this ) )
00158 {
00159   d->init();
00160 }
00161 
00162 TextEdit::TextEdit( QWidget *parent, const QString &configFile )
00163   : KRichTextWidget( parent ),
00164     d( new TextEditPrivate( this ) )
00165 {
00166   d->init();
00167   d->configFile = configFile;
00168 }
00169 
00170 TextEdit::~TextEdit()
00171 {
00172 }
00173 
00174 bool TextEdit::eventFilter( QObject *o, QEvent *e )
00175 {
00176 #ifndef QT_NO_CURSOR
00177   if ( o == this ) {
00178     KCursor::autoHideEventFilter( o, e );
00179   }
00180 #endif
00181   return KRichTextWidget::eventFilter( o, e );
00182 }
00183 
00184 void TextEditPrivate::init()
00185 {
00186   q->setSpellInterface( q );
00187   // We tell the KRichTextWidget to enable spell checking, because only then it will
00188   // call createHighlighter() which will create our own highlighter which also
00189   // does quote highlighting.
00190   // However, *our* spellchecking is still disabled. Our own highlighter only
00191   // cares about our spellcheck status, it will not highlight missspelled words
00192   // if our spellchecking is disabled.
00193   // See also KEMailQuotingHighlighter::highlightBlock().
00194   spellCheckingEnabled = false;
00195   q->setCheckSpellingEnabledInternal( true );
00196 
00197 #ifndef QT_NO_CURSOR
00198   KCursor::setAutoHideCursor( q, true, true );
00199 #endif
00200   q->installEventFilter( q );
00201 }
00202 
00203 QString TextEdit::configFile() const
00204 {
00205   return d->configFile;
00206 }
00207 
00208 void TextEdit::keyPressEvent ( QKeyEvent * e )
00209 {
00210   if ( e->key() ==  Qt::Key_Return ) {
00211     QTextCursor cursor = textCursor();
00212     int oldPos = cursor.position();
00213     int blockPos = cursor.block().position();
00214 
00215     //selection all the line.
00216     cursor.movePosition( QTextCursor::StartOfBlock );
00217     cursor.movePosition( QTextCursor::EndOfBlock, QTextCursor::KeepAnchor );
00218     QString lineText = cursor.selectedText();
00219     if ( ( ( oldPos - blockPos )  > 0 ) &&
00220          ( ( oldPos - blockPos ) < int( lineText.length() ) ) ) {
00221       bool isQuotedLine = false;
00222       int bot = 0; // bot = begin of text after quote indicators
00223       while ( bot < lineText.length() ) {
00224         if( ( lineText[bot] == QChar::fromAscii( '>' ) ) ||
00225             ( lineText[bot] == QChar::fromAscii( '|' ) ) ) {
00226           isQuotedLine = true;
00227           ++bot;
00228         } else if ( lineText[bot].isSpace() ) {
00229           ++bot;
00230         } else {
00231           break;
00232         }
00233       }
00234       KRichTextWidget::keyPressEvent( e );
00235       // duplicate quote indicators of the previous line before the new
00236       // line if the line actually contained text (apart from the quote
00237       // indicators) and the cursor is behind the quote indicators
00238       if ( isQuotedLine &&
00239            ( bot != lineText.length() ) &&
00240            ( ( oldPos - blockPos ) >= int( bot ) ) ) {
00241         // The cursor position might have changed unpredictably if there was selected
00242         // text which got replaced by a new line, so we query it again:
00243         cursor.movePosition( QTextCursor::StartOfBlock );
00244         cursor.movePosition( QTextCursor::EndOfBlock, QTextCursor::KeepAnchor );
00245         QString newLine = cursor.selectedText();
00246 
00247         // remove leading white space from the new line and instead
00248         // add the quote indicators of the previous line
00249         int leadingWhiteSpaceCount = 0;
00250         while ( ( leadingWhiteSpaceCount < newLine.length() ) &&
00251                 newLine[leadingWhiteSpaceCount].isSpace() ) {
00252           ++leadingWhiteSpaceCount;
00253         }
00254         newLine = newLine.replace( 0, leadingWhiteSpaceCount, lineText.left( bot ) );
00255         cursor.insertText( newLine );
00256         //cursor.setPosition( cursor.position() + 2 );
00257         cursor.movePosition( QTextCursor::StartOfBlock );
00258         setTextCursor( cursor );
00259       }
00260     } else {
00261       KRichTextWidget::keyPressEvent( e );
00262     }
00263   } else {
00264     KRichTextWidget::keyPressEvent( e );
00265   }
00266 }
00267 
00268 bool TextEdit::isSpellCheckingEnabled() const
00269 {
00270   return d->spellCheckingEnabled;
00271 }
00272 
00273 void TextEdit::setSpellCheckingEnabled( bool enable )
00274 {
00275   EMailQuoteHighlighter *hlighter = dynamic_cast<EMailQuoteHighlighter*>( highlighter() );
00276   if ( hlighter ) {
00277     hlighter->toggleSpellHighlighting( enable );
00278   }
00279 
00280   d->spellCheckingEnabled = enable;
00281   emit checkSpellingChanged( enable );
00282 }
00283 
00284 bool TextEdit::shouldBlockBeSpellChecked( const QString &block ) const
00285 {
00286   return !isLineQuoted( block );
00287 }
00288 
00289 bool KPIMTextEdit::TextEdit::isLineQuoted( const QString &line ) const
00290 {
00291   return quoteLength( line ) > 0;
00292 }
00293 
00294 int KPIMTextEdit::TextEdit::quoteLength( const QString &line ) const
00295 {
00296   bool quoteFound = false;
00297   int startOfText = -1;
00298   for ( int i = 0; i < line.length(); i++ ) {
00299     if ( line[i] == QLatin1Char( '>' ) || line[i] == QLatin1Char( '|' ) ) {
00300       quoteFound = true;
00301     } else if ( line[i] != QLatin1Char( ' ' ) ) {
00302       startOfText = i;
00303       break;
00304     }
00305   }
00306   if ( quoteFound ) {
00307     if ( startOfText == -1 ) {
00308       startOfText = line.length() - 1;
00309     }
00310     return startOfText;
00311   } else {
00312     return 0;
00313   }
00314 }
00315 
00316 const QString KPIMTextEdit::TextEdit::defaultQuoteSign() const
00317 {
00318   return QLatin1String( "> " );
00319 }
00320 
00321 void TextEdit::createHighlighter()
00322 {
00323   EMailQuoteHighlighter *emailHighLighter = new EMailQuoteHighlighter( this );
00324 
00325   setHighlighterColors( emailHighLighter );
00326 
00327   //TODO change config
00328   KRichTextWidget::setHighlighter( emailHighLighter );
00329 
00330   if ( !spellCheckingLanguage().isEmpty() ) {
00331     setSpellCheckingLanguage( spellCheckingLanguage() );
00332   }
00333   setSpellCheckingEnabled( isSpellCheckingEnabled() );
00334 }
00335 
00336 void TextEdit::setHighlighterColors( EMailQuoteHighlighter *highlighter )
00337 {
00338   Q_UNUSED( highlighter );
00339 }
00340 
00341 QString TextEdit::toWrappedPlainText() const
00342 {
00343   QString temp;
00344   QTextDocument *doc = document();
00345   QTextBlock block = doc->begin();
00346   while ( block.isValid() ) {
00347     QTextLayout *layout = block.layout();
00348     const int numberOfLine( layout->lineCount() );
00349     for ( int i = 0; i < numberOfLine; i++ ) {
00350       QTextLine line = layout->lineAt( i );
00351       temp += block.text().mid( line.textStart(), line.textLength() ) + QLatin1Char( '\n' );
00352     }
00353     block = block.next();
00354   }
00355 
00356   // Remove the last superfluous newline added above
00357   if ( temp.endsWith( QLatin1Char( '\n' ) ) ) {
00358     temp.chop( 1 );
00359   }
00360 
00361   d->fixupTextEditString( temp );
00362   return temp;
00363 }
00364 
00365 QString TextEdit::toCleanPlainText() const
00366 {
00367   QString temp = toPlainText();
00368   d->fixupTextEditString( temp );
00369   return temp;
00370 }
00371 
00372 void TextEdit::createActions( KActionCollection *actionCollection )
00373 {
00374   KRichTextWidget::createActions( actionCollection );
00375 
00376   if ( d->imageSupportEnabled ) {
00377     d->actionAddImage = new KAction( KIcon( QLatin1String( "insert-image" ) ),
00378                                     i18n( "Add Image" ), this );
00379     actionCollection->addAction( QLatin1String( "add_image" ), d->actionAddImage );
00380     connect( d->actionAddImage, SIGNAL(triggered(bool)), SLOT(_k_slotAddImage()) );
00381   }
00382 
00383   d->actionDeleteLine = new KAction( i18n( "Delete Line" ), this );
00384   d->actionDeleteLine->setShortcut( QKeySequence( Qt::CTRL + Qt::Key_K ) );
00385   actionCollection->addAction( QLatin1String( "delete_line" ), d->actionDeleteLine );
00386   connect( d->actionDeleteLine, SIGNAL(triggered(bool)), SLOT(_k_slotDeleteLine()) );
00387 }
00388 
00389 void TextEdit::addImage( const KUrl &url )
00390 {
00391   QImage image;
00392   if ( !image.load( url.path() ) ) {
00393     KMessageBox::error( this,
00394                         i18nc( "@info",
00395                                "Unable to load image <filename>%1</filename>.",
00396                                url.path() ) );
00397     return;
00398   }
00399   QFileInfo fi( url.path() );
00400   QString imageName = fi.baseName().isEmpty() ? QLatin1String( "image.png" )
00401                                               : QString( fi.baseName() + QLatin1String( ".png" ) );
00402   d->addImageHelper( imageName, image );
00403 }
00404 
00405 void TextEdit::loadImage ( const QImage &image, const QString &matchName,
00406                            const QString &resourceName )
00407 {
00408   QSet<int> cursorPositionsToSkip;
00409   QTextBlock currentBlock = document()->begin();
00410   QTextBlock::iterator it;
00411   while ( currentBlock.isValid() ) {
00412     for ( it = currentBlock.begin(); !it.atEnd(); ++it ) {
00413       QTextFragment fragment = it.fragment();
00414       if ( fragment.isValid() ) {
00415         QTextImageFormat imageFormat = fragment.charFormat().toImageFormat();
00416         if ( imageFormat.isValid() && imageFormat.name() == matchName ) {
00417           int pos = fragment.position();
00418           if ( !cursorPositionsToSkip.contains( pos ) ) {
00419             QTextCursor cursor( document() );
00420             cursor.setPosition( pos );
00421             cursor.setPosition( pos + 1, QTextCursor::KeepAnchor );
00422             cursor.removeSelectedText();
00423             document()->addResource( QTextDocument::ImageResource,
00424                                      QUrl( resourceName ), QVariant( image ) );
00425             cursor.insertImage( resourceName );
00426 
00427             // The textfragment iterator is now invalid, restart from the beginning
00428             // Take care not to replace the same fragment again, or we would be in
00429             // an infinite loop.
00430             cursorPositionsToSkip.insert( pos );
00431             it = currentBlock.begin();
00432           }
00433         }
00434       }
00435     }
00436     currentBlock = currentBlock.next();
00437   }
00438 }
00439 
00440 void TextEditPrivate::addImageHelper( const QString &imageName, const QImage &image )
00441 {
00442   QString imageNameToAdd = imageName;
00443   QTextDocument *document = q->document();
00444 
00445   // determine the imageNameToAdd
00446   int imageNumber = 1;
00447   while ( mImageNames.contains( imageNameToAdd ) ) {
00448     QVariant qv = document->resource( QTextDocument::ImageResource, QUrl( imageNameToAdd ) );
00449     if ( qv == image ) {
00450       // use the same name
00451       break;
00452     }
00453     int firstDot = imageName.indexOf( QLatin1Char( '.' ) );
00454     if ( firstDot == -1 ) {
00455       imageNameToAdd = imageName + QString::number( imageNumber++ );
00456     } else {
00457       imageNameToAdd = imageName.left( firstDot ) + QString::number( imageNumber++ ) +
00458                        imageName.mid( firstDot );
00459     }
00460   }
00461 
00462   if ( !mImageNames.contains( imageNameToAdd ) ) {
00463     document->addResource( QTextDocument::ImageResource, QUrl( imageNameToAdd ), image );
00464     mImageNames << imageNameToAdd;
00465   }
00466   q->textCursor().insertImage( imageNameToAdd );
00467   q->enableRichTextMode();
00468 }
00469 
00470 ImageWithNameList TextEdit::imagesWithName() const
00471 {
00472   ImageWithNameList retImages;
00473   QStringList seenImageNames;
00474   QList<QTextImageFormat> imageFormats = d->embeddedImageFormats();
00475   foreach ( const QTextImageFormat &imageFormat, imageFormats ) {
00476     if ( !seenImageNames.contains( imageFormat.name() ) ) {
00477       QVariant resourceData = document()->resource( QTextDocument::ImageResource,
00478                                                     QUrl( imageFormat.name() ) );
00479       QImage image = qvariant_cast<QImage>( resourceData );
00480       QString name = imageFormat.name();
00481       ImageWithNamePtr newImage( new ImageWithName );
00482       newImage->image = image;
00483       newImage->name = name;
00484       retImages.append( newImage );
00485       seenImageNames.append( imageFormat.name() );
00486     }
00487   }
00488   return retImages;
00489 }
00490 
00491 QList< QSharedPointer<EmbeddedImage> > TextEdit::embeddedImages() const
00492 {
00493   ImageWithNameList normalImages = imagesWithName();
00494   QList< QSharedPointer<EmbeddedImage> > retImages;
00495   foreach ( const ImageWithNamePtr &normalImage, normalImages ) {
00496     QBuffer buffer;
00497     buffer.open( QIODevice::WriteOnly );
00498     normalImage->image.save( &buffer, "PNG" );
00499 
00500     qsrand( QDateTime::currentDateTime().toTime_t() + qHash( normalImage->name ) );
00501     QSharedPointer<EmbeddedImage> embeddedImage( new EmbeddedImage() );
00502     retImages.append( embeddedImage );
00503     embeddedImage->image = KMime::Codec::codecForName( "base64" )->encode( buffer.buffer() );
00504     embeddedImage->imageName = normalImage->name;
00505     embeddedImage->contentID = QString( QLatin1String( "%1@KDE" ) ).arg( qrand() );
00506   }
00507   return retImages;
00508 }
00509 
00510 QList<QTextImageFormat> TextEditPrivate::embeddedImageFormats() const
00511 {
00512   QTextDocument *doc = q->document();
00513   QList<QTextImageFormat> retList;
00514 
00515   QTextBlock currentBlock = doc->begin();
00516   while ( currentBlock.isValid() ) {
00517     QTextBlock::iterator it;
00518     for ( it = currentBlock.begin(); !it.atEnd(); ++it ) {
00519       QTextFragment fragment = it.fragment();
00520       if ( fragment.isValid() ) {
00521         QTextImageFormat imageFormat = fragment.charFormat().toImageFormat();
00522         if ( imageFormat.isValid() ) {
00523           //TODO: Replace with a way to see if an image is an embedded image or a remote
00524           QUrl url(imageFormat.name());
00525           if( !url.isValid() || !url.scheme().startsWith( QLatin1String( "http" ) ) ) {
00526             retList.append( imageFormat );
00527           }
00528         }
00529       }
00530     }
00531     currentBlock = currentBlock.next();
00532   }
00533   return retList;
00534 }
00535 
00536 void TextEditPrivate::_k_slotAddImage()
00537 {
00538   QPointer<KFileDialog> fdlg = new KFileDialog( QString(), QString(), q );
00539   fdlg->setOperationMode( KFileDialog::Other );
00540   fdlg->setCaption( i18n( "Add Image" ) );
00541   fdlg->okButton()->setGuiItem( KGuiItem( i18n( "&Add" ), QLatin1String( "document-open" ) ) );
00542   fdlg->setMode( KFile::Files );
00543   if ( fdlg->exec() != KDialog::Accepted ) {
00544     delete fdlg;
00545     return;
00546   }
00547 
00548   const KUrl::List files = fdlg->selectedUrls();
00549   foreach ( const KUrl &url, files ) {
00550     q->addImage( url );
00551   }
00552   delete fdlg;
00553 }
00554 
00555 void KPIMTextEdit::TextEdit::enableImageActions()
00556 {
00557   d->imageSupportEnabled = true;
00558 }
00559 
00560 bool KPIMTextEdit::TextEdit::isEnableImageActions() const
00561 {
00562   return d->imageSupportEnabled;
00563 }
00564 
00565 QByteArray KPIMTextEdit::TextEdit::imageNamesToContentIds(
00566   const QByteArray &htmlBody, const KPIMTextEdit::ImageList &imageList )
00567 {
00568   QByteArray result = htmlBody;
00569   if ( !imageList.isEmpty() ) {
00570     foreach ( const QSharedPointer<EmbeddedImage> &image, imageList ) {
00571       const QString newImageName = QLatin1String( "cid:" ) + image->contentID;
00572       QByteArray quote( "\"" );
00573       result.replace( QByteArray( quote + image->imageName.toLocal8Bit() + quote ),
00574                       QByteArray( quote + newImageName.toLocal8Bit() + quote ) );
00575     }
00576   }
00577   return result;
00578 }
00579 
00580 void TextEdit::insertImage( const QImage &image, const QFileInfo &fileInfo )
00581 {
00582   QString imageName = fileInfo.baseName().isEmpty() ?
00583                         i18nc( "Start of the filename for an image", "image" ) :
00584                         fileInfo.baseName();
00585   d->addImageHelper( imageName, image );
00586 }
00587 
00588 void TextEdit::insertFromMimeData( const QMimeData *source )
00589 {
00590   // Add an image if that is on the clipboard
00591   if ( textMode() == KRichTextEdit::Rich && source->hasImage() && d->imageSupportEnabled ) {
00592     QImage image = qvariant_cast<QImage>( source->imageData() );
00593     QFileInfo fi( source->text() );
00594     insertImage( image, fi );
00595     return;
00596   }
00597 
00598   // Attempt to paste HTML contents into the text edit in plain text mode,
00599   // prevent this and prevent plain text instead.
00600   if ( textMode() == KRichTextEdit::Plain && source->hasHtml() ) {
00601     if ( source->hasText() ) {
00602       insertPlainText( source->text() );
00603       return;
00604     }
00605   }
00606 
00607   KRichTextWidget::insertFromMimeData( source );
00608 }
00609 
00610 bool KPIMTextEdit::TextEdit::canInsertFromMimeData( const QMimeData *source ) const
00611 {
00612   if ( source->hasHtml() && textMode() == KRichTextEdit::Rich ) {
00613     return true;
00614   }
00615 
00616   if ( source->hasText() ) {
00617     return true;
00618   }
00619 
00620   if ( textMode() == KRichTextEdit::Rich && source->hasImage() && d->imageSupportEnabled ) {
00621     return true;
00622   }
00623 
00624   return KRichTextWidget::canInsertFromMimeData( source );
00625 }
00626 
00627 bool TextEdit::isFormattingUsed() const
00628 {
00629   if ( textMode() == Plain ) {
00630     return false;
00631   }
00632 
00633   return TextUtils::containsFormatting( document() );
00634 }
00635 
00636 void TextEditPrivate::_k_slotDeleteLine()
00637 {
00638   if ( q->hasFocus() ) {
00639     q->deleteCurrentLine();
00640   }
00641 }
00642 
00643 void TextEdit::deleteCurrentLine()
00644 {
00645   QTextCursor cursor = textCursor();
00646   QTextBlock block = cursor.block();
00647   const QTextLayout *layout = block.layout();
00648 
00649   // The current text block can have several lines due to word wrapping.
00650   // Search the line the cursor is in, and then delete it.
00651   for ( int lineNumber = 0; lineNumber < layout->lineCount(); lineNumber++ ) {
00652     QTextLine line = layout->lineAt( lineNumber );
00653     const bool lastLineInBlock = ( line.textStart() + line.textLength() == block.length() - 1 );
00654     const bool oneLineBlock = ( layout->lineCount() == 1 );
00655     const int startOfLine = block.position() + line.textStart();
00656     int endOfLine = block.position() + line.textStart() + line.textLength();
00657     if ( !lastLineInBlock ) {
00658       endOfLine -= 1;
00659     }
00660 
00661     // Found the line where the cursor is in
00662     if ( cursor.position() >= startOfLine && cursor.position() <= endOfLine ) {
00663       int deleteStart = startOfLine;
00664       int deleteLength = line.textLength();
00665       if ( oneLineBlock ) {
00666         deleteLength++; // The trailing newline
00667       }
00668 
00669       // When deleting the last line in the document,
00670       // remove the newline of the line before the last line instead
00671       if ( deleteStart + deleteLength >= document()->characterCount() &&
00672            deleteStart > 0 ) {
00673         deleteStart--;
00674       }
00675 
00676       cursor.beginEditBlock();
00677       cursor.setPosition( deleteStart );
00678       cursor.movePosition( QTextCursor::NextCharacter, QTextCursor::KeepAnchor, deleteLength );
00679       cursor.removeSelectedText();
00680       cursor.endEditBlock();
00681       return;
00682     }
00683   }
00684 
00685 }
00686 
00687 #include "textedit.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Mon May 14 2012 04:44:16 by doxygen 1.7.5 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KPIMTextedit Library

Skip menu "KPIMTextedit Library"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Members
  • File List
  • Related Pages

kdepimlibs-4.8.3 API Reference

Skip menu "kdepimlibs-4.8.3 API Reference"
  • akonadi
  •   contact
  •   kmime
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  •   richtextbuilders
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal