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
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
00070
00071
00072
00073
00074
00075
00076
00077
00078
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
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
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
00137
00138 QTextBlock currentBlock = cursor.block();
00139 if (cursor.currentList()->count() == cursor.currentList()->itemNumber(currentBlock) + 1) {
00140
00141 if (currentBlock.next().textList()) {
00142 reformatList();
00143 }
00144
00145
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
00180 }
00181 list->add(droppedBlock);
00182 }
00183
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
00217
00218 }
00219
00220 void NestedListHelper::reformatList(QTextBlock block)
00221 {
00222 if (block.textList()) {
00223 int minimumIndent = block.textList()->format().indent();
00224
00225
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
00353
00354
00355
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 }