• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.14.38 API Reference
  • KDE Home
  • Contact Us
 

KDEUI

  • kdeui
  • widgets
nestedlisthelper.cpp
Go to the documentation of this file.
1
22#include "nestedlisthelper.h"
23
24#include <QtGui/QKeyEvent>
25#include <QtGui/QTextCursor>
26#include <QtGui/QTextList>
27#include <QtGui/QTextBlock>
28#include <QtGui/QTextDocumentFragment>
29
30#include <ktextedit.h>
31#include <kdebug.h>
32
33NestedListHelper::NestedListHelper(QTextEdit *te)
34{
35 textEdit = te;
36 listBottomMargin = 12;
37 listTopMargin = 12;
38 listNoMargin = 0;
39}
40
41NestedListHelper::~NestedListHelper()
42{
43}
44
45bool NestedListHelper::handleBeforeKeyPressEvent(QKeyEvent *event)
46{
47 QTextCursor cursor = textEdit->textCursor();
48
49 // Only attempt to handle Backspace while on a list
50 if ((event->key() != Qt::Key_Backspace)
51 || (!cursor.currentList()))
52 return false;
53
54 bool handled = false;
55
56 if (!cursor.hasSelection()
57 && cursor.currentList()
58 && event->key() == Qt::Key_Backspace
59 && cursor.atBlockStart()) {
60 handleOnIndentLess();
61 handled = true;
62 }
63
64 if (cursor.hasSelection()
65 && cursor.currentList()
66 && event->key() == Qt::Key_Backspace
67 && cursor.atBlockStart()) {
68
69 // Workaround for qt bug 211460:
70 // If there is a list with selection like this:
71 //
72 // * one
73 // * <cursor>t<anchor>wo
74 //
75 // and backspace is pressed, the bullet is removed, but not
76 // the 't'.
77 // Fixed scheduled for qt4.5
78 // -- Stephen Kelly, 8th June 2008
79
80 cursor.removeSelectedText();
81 handled = true;
82 }
83
84 return handled;
85}
86
87bool NestedListHelper::canIndent() const
88{
89 if ((textEdit->textCursor().block().isValid())
90// && ( textEdit->textCursor().block().previous().isValid() )
91 ) {
92 QTextBlock block = textEdit->textCursor().block();
93 QTextBlock prevBlock = textEdit->textCursor().block().previous();
94 if (block.textList()) {
95 if (prevBlock.textList()) {
96 return block.textList()->format().indent() <= prevBlock.textList()->format().indent();
97 }
98 } else {
99 return true;
100 }
101 }
102 return false;
103}
104
105bool NestedListHelper::canDedent() const
106{
107 QTextBlock thisBlock = textEdit->textCursor().block();
108 QTextBlock nextBlock = thisBlock.next();
109 if (thisBlock.isValid()) {
110 int nextBlockIndent = 0;
111 int thisBlockIndent = 0;
112 if (nextBlock.isValid() && nextBlock.textList())
113 nextBlockIndent = nextBlock.textList()->format().indent();
114 if (thisBlock.textList()) {
115 thisBlockIndent = thisBlock.textList()->format().indent();
116 if (thisBlockIndent >= nextBlockIndent)
117 return thisBlock.textList()->format().indent() > 0;
118 }
119 }
120 return false;
121
122}
123
124bool NestedListHelper::handleAfterKeyPressEvent(QKeyEvent *event)
125{
126 // Only attempt to handle Backspace and Return
127 if ((event->key() != Qt::Key_Backspace)
128 && (event->key() != Qt::Key_Return))
129 return false;
130
131 QTextCursor cursor = textEdit->textCursor();
132 bool handled = false;
133
134 if (!cursor.hasSelection() && cursor.currentList()) {
135
136 // Check if we're on the last list item.
137 // itemNumber is zero indexed
138 QTextBlock currentBlock = cursor.block();
139 if (cursor.currentList()->count() == cursor.currentList()->itemNumber(currentBlock) + 1) {
140 // Last block in this list, but may have just gained another list below.
141 if (currentBlock.next().textList()) {
142 reformatList();
143 }
144
145 // No need to reformatList in this case. reformatList is slow.
146 if ((event->key() == Qt::Key_Return) || (event->key() == Qt::Key_Backspace)) {
147 reformatBoundingItemSpacing();
148 handled = true;
149 }
150 } else {
151 reformatList();
152 }
153 }
154 return handled;
155}
156
157
158bool NestedListHelper::handleAfterDropEvent(QDropEvent *dropEvent)
159{
160 Q_UNUSED(dropEvent);
161 QTextCursor cursor = topOfSelection();
162
163 QTextBlock droppedBlock = cursor.block();
164 int firstDroppedItemIndent = droppedBlock.textList()->format().indent();
165
166 int minimumIndent = droppedBlock.previous().textList()->format().indent();
167
168 if (firstDroppedItemIndent < minimumIndent) {
169 cursor = QTextCursor(droppedBlock);
170 QTextListFormat fmt = droppedBlock.textList()->format();
171 fmt.setIndent(minimumIndent);
172 QTextList* list = cursor.createList(fmt);
173
174 int endOfDrop = bottomOfSelection().position();
175 while (droppedBlock.next().position() < endOfDrop) {
176 droppedBlock = droppedBlock.next();
177 if (droppedBlock.textList()->format().indent() != firstDroppedItemIndent) {
178
179 // new list?
180 }
181 list->add(droppedBlock);
182 }
183// list.add( droppedBlock );
184 }
185
186 reformatBoundingItemSpacing();
187 return true;
188}
189
190void NestedListHelper::processList(QTextList* list)
191{
192 QTextBlock block = list->item(0);
193 int thisListIndent = list->format().indent();
194
195 QTextCursor cursor = QTextCursor(block);
196 list = cursor.createList(list->format());
197 bool processingSubList = false;
198 while (block.next().textList() != 0) {
199 block = block.next();
200
201 QTextList* nextList = block.textList();
202 int nextItemIndent = nextList->format().indent();
203 if (nextItemIndent < thisListIndent) {
204 return;
205 } else if (nextItemIndent > thisListIndent) {
206 if (processingSubList) {
207 continue;
208 }
209 processingSubList = true;
210 processList(nextList);
211 } else {
212 processingSubList = false;
213 list->add(block);
214 }
215 }
216// delete nextList;
217// nextList = 0;
218}
219
220void NestedListHelper::reformatList(QTextBlock block)
221{
222 if (block.textList()) {
223 int minimumIndent = block.textList()->format().indent();
224
225 // Start at the top of the list
226 while (block.previous().textList() != 0) {
227 if (block.previous().textList()->format().indent() < minimumIndent) {
228 break;
229 }
230 block = block.previous();
231 }
232
233 processList(block.textList());
234
235 }
236}
237
238void NestedListHelper::reformatList()
239{
240 QTextCursor cursor = textEdit->textCursor();
241 reformatList(cursor.block());
242}
243
244QTextCursor NestedListHelper::topOfSelection()
245{
246 QTextCursor cursor = textEdit->textCursor();
247
248 if (cursor.hasSelection())
249 cursor.setPosition(qMin(cursor.position(), cursor.anchor()));
250 return cursor;
251}
252
253QTextCursor NestedListHelper::bottomOfSelection()
254{
255 QTextCursor cursor = textEdit->textCursor();
256
257 if (cursor.hasSelection())
258 cursor.setPosition(qMax(cursor.position(), cursor.anchor()));
259 return cursor;
260}
261
262void NestedListHelper::handleOnIndentMore()
263{
264 QTextCursor cursor = textEdit->textCursor();
265
266 QTextListFormat listFmt;
267 if (!cursor.currentList()) {
268
269 QTextListFormat::Style style;
270 cursor = topOfSelection();
271 cursor.movePosition(QTextCursor::PreviousBlock);
272 if (cursor.currentList()) {
273 style = cursor.currentList()->format().style();
274 } else {
275
276 cursor = bottomOfSelection();
277 cursor.movePosition(QTextCursor::NextBlock);
278
279 if (cursor.currentList()) {
280 style = cursor.currentList()->format().style();
281 } else {
282 style = QTextListFormat::ListDisc;
283 }
284 }
285 handleOnBulletType(style);
286 } else {
287 listFmt = cursor.currentList()->format();
288 listFmt.setIndent(listFmt.indent() + 1);
289
290 cursor.createList(listFmt);
291 reformatList();
292 }
293
294 reformatBoundingItemSpacing();
295}
296
297void NestedListHelper::handleOnIndentLess()
298{
299 QTextCursor cursor = textEdit->textCursor();
300 QTextList* currentList = cursor.currentList();
301 if (!currentList)
302 return;
303 QTextListFormat listFmt;
304 listFmt = currentList->format();
305 if (listFmt.indent() > 1) {
306 listFmt.setIndent(listFmt.indent() - 1);
307 cursor.createList(listFmt);
308 reformatList(cursor.block());
309 } else {
310 QTextBlockFormat bfmt;
311 bfmt.setObjectIndex(-1);
312 cursor.setBlockFormat(bfmt);
313 reformatList(cursor.block().next());
314 }
315 reformatBoundingItemSpacing();
316}
317
318
319void NestedListHelper::handleOnBulletType(int styleIndex)
320{
321 QTextCursor cursor = textEdit->textCursor();
322 if (styleIndex != 0) {
323 QTextListFormat::Style style = (QTextListFormat::Style)styleIndex;
324 QTextList *currentList = cursor.currentList();
325 QTextListFormat listFmt;
326
327 cursor.beginEditBlock();
328
329 if (currentList) {
330 listFmt = currentList->format();
331 listFmt.setStyle(style);
332 currentList->setFormat(listFmt);
333 } else {
334 listFmt.setStyle(style);
335 cursor.createList(listFmt);
336 }
337
338 cursor.endEditBlock();
339 } else {
340 QTextBlockFormat bfmt;
341 bfmt.setObjectIndex(-1);
342 cursor.setBlockFormat(bfmt);
343 reformatBoundingItemSpacing();
344 }
345
346 reformatBoundingItemSpacing();
347 reformatList();
348}
349
350void NestedListHelper::reformatBoundingItemSpacing(QTextBlock block)
351{
352 // This is a workaround for qt bug 201228. Spacing between items is not kept
353 // consistent.
354 // Fixed scheduled for qt4.5
355 // -- Stephen Kelly, 8th June 2008
356
357 int nextBlockTopMargin = listNoMargin;
358 int previousBlockBottomMargin = listNoMargin;
359 int thisBlockBottomMargin = listBottomMargin;
360 int thisBlockTopMargin = listTopMargin;
361 bool prevBlockValid = block.previous().isValid();
362 bool nextBlockValid = block.next().isValid();
363
364 if (block.textList()) {
365 if (prevBlockValid && block.previous().textList()) {
366 thisBlockTopMargin = listNoMargin;
367 }
368
369 if (nextBlockValid && block.next().textList()) {
370 thisBlockBottomMargin = listNoMargin;
371 }
372 } else {
373 if (prevBlockValid && !block.previous().textList()) {
374 thisBlockTopMargin = listNoMargin;
375 }
376 if (nextBlockValid && !block.next().textList()) {
377 thisBlockBottomMargin = listNoMargin;
378 }
379
380 }
381 QTextBlockFormat fmt;
382 QTextCursor cursor;
383
384 fmt = block.blockFormat();
385 fmt.setBottomMargin(thisBlockBottomMargin);
386 fmt.setTopMargin(thisBlockTopMargin);
387 cursor = QTextCursor(block);
388 cursor.setBlockFormat(fmt);
389
390 if (nextBlockValid) {
391 block = block.next();
392 fmt = block.blockFormat();
393 fmt.setTopMargin(nextBlockTopMargin);
394 cursor = QTextCursor(block);
395 cursor.setBlockFormat(fmt);
396
397 block = block.previous();
398 }
399 if (prevBlockValid) {
400 block = block.previous();
401 fmt = block.blockFormat();
402 fmt.setBottomMargin(previousBlockBottomMargin);
403 cursor = QTextCursor(block);
404 cursor.setBlockFormat(fmt);
405 }
406}
407
408void NestedListHelper::reformatBoundingItemSpacing()
409{
410 reformatBoundingItemSpacing(topOfSelection().block());
411 reformatBoundingItemSpacing(bottomOfSelection().block());
412}
QTextEdit
kdebug.h
ktextedit.h
nestedlisthelper.h
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDEUI

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

kdelibs-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
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