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

KDEUI

  • sources
  • kde-4.12
  • kdelibs
  • 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 
33 NestedListHelper::NestedListHelper(QTextEdit *te)
34 {
35  textEdit = te;
36  listBottomMargin = 12;
37  listTopMargin = 12;
38  listNoMargin = 0;
39 }
40 
41 NestedListHelper::~NestedListHelper()
42 {
43 }
44 
45 bool 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 
87 bool 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 
105 bool 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 
124 bool 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 
158 bool 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 
190 void 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 
220 void 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 
238 void NestedListHelper::reformatList()
239 {
240  QTextCursor cursor = textEdit->textCursor();
241  reformatList(cursor.block());
242 }
243 
244 QTextCursor 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 
253 QTextCursor 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 
262 void 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 
297 void 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 
319 void 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 
350 void 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 
408 void NestedListHelper::reformatBoundingItemSpacing()
409 {
410  reformatBoundingItemSpacing(topOfSelection().block());
411  reformatBoundingItemSpacing(bottomOfSelection().block());
412 }
kdebug.h
ktextedit.h
nestedlisthelper.h
QTextEdit
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:49:16 by doxygen 1.8.7 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 API Reference

Skip menu "kdelibs 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
  • kjsembed
  •   WTF
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Nepomuk-Core
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

Search



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