• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KDEUI

nestedlisthelper.cpp

Go to the documentation of this file.
00001 
00022 #include "nestedlisthelper.h"
00023 
00024 #include <QtGui/QKeyEvent>
00025 #include <QtGui/QTextCursor>
00026 #include <QtGui/QTextList>
00027 #include <QtGui/QTextBlock>
00028 #include <QtGui/QTextDocumentFragment>
00029 
00030 #include <ktextedit.h>
00031 #include <kdebug.h>
00032 
00033 NestedListHelper::NestedListHelper(QTextEdit *te)
00034 {
00035     textEdit = te;
00036     listBottomMargin = 12;
00037     listTopMargin = 12;
00038     listNoMargin = 0;
00039 }
00040 
00041 NestedListHelper::~NestedListHelper()
00042 {
00043 }
00044 
00045 bool NestedListHelper::handleBeforeKeyPressEvent(QKeyEvent *event)
00046 {
00047     QTextCursor cursor = textEdit->textCursor();
00048 
00049     // Only attempt to handle Backspace while on a list
00050     if ((event->key() != Qt::Key_Backspace)
00051             || (!cursor.currentList()))
00052         return false;
00053 
00054     bool handled = false;
00055 
00056     if (!cursor.hasSelection()
00057             && cursor.currentList()
00058             && event->key() == Qt::Key_Backspace
00059             && cursor.atBlockStart()) {
00060         handleOnIndentLess();
00061         handled = true;
00062     }
00063 
00064     if (cursor.hasSelection()
00065             && cursor.currentList()
00066             && event->key() == Qt::Key_Backspace
00067             && cursor.atBlockStart()) {
00068 
00069         // Workaround for qt bug 211460:
00070         // If there is a list with selection like this:
00071         //
00072         //   * one
00073         //   * <cursor>t<anchor>wo
00074         //
00075         // and backspace is pressed, the bullet is removed, but not
00076         // the 't'.
00077         // Fixed scheduled for qt4.5
00078         // -- Stephen Kelly, 8th June 2008
00079 
00080         cursor.removeSelectedText();
00081         handled = true;
00082     }
00083 
00084     return handled;
00085 }
00086 
00087 bool NestedListHelper::canIndent() const
00088 {
00089     if ((textEdit->textCursor().block().isValid())
00090 //            && (  textEdit->textCursor().block().previous().isValid() )
00091        ) {
00092         QTextBlock block = textEdit->textCursor().block();
00093         QTextBlock prevBlock = textEdit->textCursor().block().previous();
00094         if (block.textList()) {
00095             if (prevBlock.textList()) {
00096                 return block.textList()->format().indent() <= prevBlock.textList()->format().indent();
00097             }
00098         } else {
00099             return true;
00100         }
00101     }
00102     return false;
00103 }
00104 
00105 bool NestedListHelper::canDedent() const
00106 {
00107     QTextBlock thisBlock = textEdit->textCursor().block();
00108     QTextBlock nextBlock = thisBlock.next();
00109     if (thisBlock.isValid()) {
00110         int nextBlockIndent = 0;
00111         int thisBlockIndent = 0;
00112         if (nextBlock.isValid() && nextBlock.textList())
00113             nextBlockIndent = nextBlock.textList()->format().indent();
00114         if (thisBlock.textList()) {
00115             thisBlockIndent = thisBlock.textList()->format().indent();
00116             if (thisBlockIndent >= nextBlockIndent)
00117                 return thisBlock.textList()->format().indent() > 0;
00118         }
00119     }
00120     return false;
00121 
00122 }
00123 
00124 bool NestedListHelper::handleAfterKeyPressEvent(QKeyEvent *event)
00125 {
00126     // Only attempt to handle Backspace and Return
00127     if ((event->key() != Qt::Key_Backspace)
00128             && (event->key() != Qt::Key_Return))
00129         return false;
00130 
00131     QTextCursor cursor = textEdit->textCursor();
00132     bool handled = false;
00133 
00134     if (!cursor.hasSelection() && cursor.currentList()) {
00135 
00136         // Check if we're on the last list item.
00137         // itemNumber is zero indexed
00138         QTextBlock currentBlock = cursor.block();
00139         if (cursor.currentList()->count() == cursor.currentList()->itemNumber(currentBlock) + 1) {
00140             // Last block in this list, but may have just gained another list below.
00141             if (currentBlock.next().textList()) {
00142                 reformatList();
00143             }
00144 
00145             // No need to reformatList in this case. reformatList is slow.
00146             if ((event->key() == Qt::Key_Return) || (event->key() == Qt::Key_Backspace)) {
00147                 reformatBoundingItemSpacing();
00148                 handled = true;
00149             }
00150         } else {
00151             reformatList();
00152         }
00153     }
00154     return handled;
00155 }
00156 
00157 
00158 bool NestedListHelper::handleAfterDropEvent(QDropEvent *dropEvent)
00159 {
00160     Q_UNUSED(dropEvent);
00161     QTextCursor cursor = topOfSelection();
00162 
00163     QTextBlock droppedBlock = cursor.block();
00164     int firstDroppedItemIndent = droppedBlock.textList()->format().indent();
00165 
00166     int minimumIndent = droppedBlock.previous().textList()->format().indent();
00167 
00168     if (firstDroppedItemIndent < minimumIndent) {
00169         cursor = QTextCursor(droppedBlock);
00170         QTextListFormat fmt = droppedBlock.textList()->format();
00171         fmt.setIndent(minimumIndent);
00172         QTextList* list = cursor.createList(fmt);
00173 
00174         int endOfDrop = bottomOfSelection().position();
00175         while (droppedBlock.next().position() < endOfDrop) {
00176             droppedBlock = droppedBlock.next();
00177             if (droppedBlock.textList()->format().indent() != firstDroppedItemIndent) {
00178 
00179                 // new list?
00180             }
00181             list->add(droppedBlock);
00182         }
00183 //         list.add( droppedBlock );
00184     }
00185 
00186     reformatBoundingItemSpacing();
00187     return true;
00188 }
00189 
00190 void NestedListHelper::processList(QTextList* list)
00191 {
00192     QTextBlock block = list->item(0);
00193     int thisListIndent = list->format().indent();
00194 
00195     QTextCursor cursor = QTextCursor(block);
00196     list = cursor.createList(list->format());
00197     bool processingSubList  = false;
00198     while (block.next().textList() != 0) {
00199         block = block.next();
00200 
00201         QTextList* nextList = block.textList();
00202         int nextItemIndent = nextList->format().indent();
00203         if (nextItemIndent < thisListIndent) {
00204             return;
00205         } else if (nextItemIndent > thisListIndent) {
00206             if (processingSubList) {
00207                 continue;
00208             }
00209             processingSubList = true;
00210             processList(nextList);
00211         } else {
00212             processingSubList = false;
00213             list->add(block);
00214         }
00215     }
00216 //     delete nextList;
00217 //     nextList = 0;
00218 }
00219 
00220 void NestedListHelper::reformatList(QTextBlock block)
00221 {
00222     if (block.textList()) {
00223         int minimumIndent =  block.textList()->format().indent();
00224 
00225         // Start at the top of the list
00226         while (block.previous().textList() != 0) {
00227             if (block.previous().textList()->format().indent() < minimumIndent) {
00228                 break;
00229             }
00230             block = block.previous();
00231         }
00232 
00233         processList(block.textList());
00234 
00235     }
00236 }
00237 
00238 void NestedListHelper::reformatList()
00239 {
00240     QTextCursor cursor = textEdit->textCursor();
00241     reformatList(cursor.block());
00242 }
00243 
00244 QTextCursor NestedListHelper::topOfSelection()
00245 {
00246     QTextCursor cursor = textEdit->textCursor();
00247 
00248     if (cursor.hasSelection())
00249         cursor.setPosition(qMin(cursor.position(), cursor.anchor()));
00250     return cursor;
00251 }
00252 
00253 QTextCursor NestedListHelper::bottomOfSelection()
00254 {
00255     QTextCursor cursor = textEdit->textCursor();
00256 
00257     if (cursor.hasSelection())
00258         cursor.setPosition(qMax(cursor.position(), cursor.anchor()));
00259     return cursor;
00260 }
00261 
00262 void NestedListHelper::handleOnIndentMore()
00263 {
00264     QTextCursor cursor = textEdit->textCursor();
00265 
00266     QTextListFormat listFmt;
00267     if (!cursor.currentList()) {
00268 
00269         QTextListFormat::Style style;
00270         cursor = topOfSelection();
00271         cursor.movePosition(QTextCursor::PreviousBlock);
00272         if (cursor.currentList()) {
00273             style = cursor.currentList()->format().style();
00274         } else {
00275 
00276             cursor = bottomOfSelection();
00277             cursor.movePosition(QTextCursor::NextBlock);
00278 
00279             if (cursor.currentList()) {
00280                 style = cursor.currentList()->format().style();
00281             } else {
00282                 style = QTextListFormat::ListDisc;
00283             }
00284         }
00285         handleOnBulletType(style);
00286     } else {
00287         listFmt = cursor.currentList()->format();
00288         listFmt.setIndent(listFmt.indent() + 1);
00289 
00290         cursor.createList(listFmt);
00291         reformatList();
00292     }
00293 
00294     reformatBoundingItemSpacing();
00295 }
00296 
00297 void NestedListHelper::handleOnIndentLess()
00298 {
00299     QTextCursor cursor = textEdit->textCursor();
00300     QTextList* currentList = cursor.currentList();
00301     if (!currentList)
00302         return;
00303     QTextListFormat listFmt;
00304     listFmt = currentList->format();
00305     if (listFmt.indent() > 1) {
00306         listFmt.setIndent(listFmt.indent() - 1);
00307         cursor.createList(listFmt);
00308         reformatList(cursor.block());
00309     } else {
00310         QTextBlockFormat bfmt;
00311         bfmt.setObjectIndex(-1);
00312         cursor.setBlockFormat(bfmt);
00313         reformatList(cursor.block().next());
00314     }
00315     reformatBoundingItemSpacing();
00316 }
00317 
00318 
00319 void NestedListHelper::handleOnBulletType(int styleIndex)
00320 {
00321     QTextCursor cursor = textEdit->textCursor();
00322     if (styleIndex != 0) {
00323         QTextListFormat::Style style = (QTextListFormat::Style)styleIndex;
00324         QTextList *currentList = cursor.currentList();
00325         QTextListFormat listFmt;
00326 
00327         cursor.beginEditBlock();
00328 
00329         if (currentList) {
00330             listFmt = currentList->format();
00331             listFmt.setStyle(style);
00332             currentList->setFormat(listFmt);
00333         } else {
00334             listFmt.setStyle(style);
00335             cursor.createList(listFmt);
00336         }
00337 
00338         cursor.endEditBlock();
00339     } else {
00340         QTextBlockFormat bfmt;
00341         bfmt.setObjectIndex(-1);
00342         cursor.setBlockFormat(bfmt);
00343         reformatBoundingItemSpacing();
00344     }
00345 
00346     reformatBoundingItemSpacing();
00347     reformatList();
00348 }
00349 
00350 void NestedListHelper::reformatBoundingItemSpacing(QTextBlock block)
00351 {
00352     // This is a workaround for qt bug 201228. Spacing between items is not kept
00353     // consistent.
00354     // Fixed scheduled for qt4.5
00355     // -- Stephen Kelly, 8th June 2008
00356 
00357     int nextBlockTopMargin = listNoMargin;
00358     int previousBlockBottomMargin = listNoMargin;
00359     int thisBlockBottomMargin = listBottomMargin;
00360     int thisBlockTopMargin = listTopMargin;
00361     bool prevBlockValid = block.previous().isValid();
00362     bool nextBlockValid = block.next().isValid();
00363 
00364     if (block.textList()) {
00365         if (prevBlockValid && block.previous().textList()) {
00366             thisBlockTopMargin = listNoMargin;
00367         }
00368 
00369         if (nextBlockValid && block.next().textList()) {
00370             thisBlockBottomMargin = listNoMargin;
00371         }
00372     } else {
00373         if (prevBlockValid && !block.previous().textList()) {
00374             thisBlockTopMargin = listNoMargin;
00375         }
00376         if (nextBlockValid && !block.next().textList()) {
00377             thisBlockBottomMargin = listNoMargin;
00378         }
00379 
00380     }
00381     QTextBlockFormat fmt;
00382     QTextCursor cursor;
00383 
00384     fmt = block.blockFormat();
00385     fmt.setBottomMargin(thisBlockBottomMargin);
00386     fmt.setTopMargin(thisBlockTopMargin);
00387     cursor = QTextCursor(block);
00388     cursor.setBlockFormat(fmt);
00389 
00390     if (nextBlockValid) {
00391         block = block.next();
00392         fmt = block.blockFormat();
00393         fmt.setTopMargin(nextBlockTopMargin);
00394         cursor = QTextCursor(block);
00395         cursor.setBlockFormat(fmt);
00396 
00397         block = block.previous();
00398     }
00399     if (prevBlockValid) {
00400         block = block.previous();
00401         fmt = block.blockFormat();
00402         fmt.setBottomMargin(previousBlockBottomMargin);
00403         cursor = QTextCursor(block);
00404         cursor.setBlockFormat(fmt);
00405     }
00406 }
00407 
00408 void NestedListHelper::reformatBoundingItemSpacing()
00409 {
00410     reformatBoundingItemSpacing(topOfSelection().block());
00411     reformatBoundingItemSpacing(bottomOfSelection().block());
00412 }

KDEUI

Skip menu "KDEUI"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal