Qt 4.8
qtextcursor.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qtextcursor.h"
43 #include "qtextcursor_p.h"
44 #include "qglobal.h"
45 #include "qtextdocumentfragment.h"
47 #include "qtextlist.h"
48 #include "qtexttable.h"
49 #include "qtexttable_p.h"
50 #include "qtextengine_p.h"
52 
53 #include <qtextlayout.h>
54 #include <qdebug.h>
55 
57 
58 enum {
59  AdjustPrev = 0x1,
60  AdjustUp = 0x3,
61  AdjustNext = 0x4,
62  AdjustDown = 0x12
63 };
64 
66  : priv(p), x(0), position(0), anchor(0), adjusted_anchor(0),
67  currentCharFormat(-1), visualNavigation(false), keepPositionOnInsert(false),
68  changed(false)
69 {
70  priv->addCursor(this);
71 }
72 
74  : QSharedData(rhs)
75 {
76  position = rhs.position;
77  anchor = rhs.anchor;
79  priv = rhs.priv;
80  x = rhs.x;
84  changed = rhs.changed;
85  priv->addCursor(this);
86 }
87 
89 {
90  if (priv)
91  priv->removeCursor(this);
92 }
93 
95 {
97  // not(!) <= , so that inserting text adjusts the cursor correctly
98  if (position < positionOfChange
99  || (position == positionOfChange
102  )
103  ) {
104  result = CursorUnchanged;
105  } else {
106  if (charsAddedOrRemoved < 0 && position < positionOfChange - charsAddedOrRemoved)
107  position = positionOfChange;
108  else
109  position += charsAddedOrRemoved;
110 
111  currentCharFormat = -1;
112  }
113 
114  if (anchor >= positionOfChange
115  && (anchor != positionOfChange || op != QTextUndoCommand::KeepCursor)) {
116  if (charsAddedOrRemoved < 0 && anchor < positionOfChange - charsAddedOrRemoved)
117  anchor = positionOfChange;
118  else
119  anchor += charsAddedOrRemoved;
120  }
121 
122  if (adjusted_anchor >= positionOfChange
123  && (adjusted_anchor != positionOfChange || op != QTextUndoCommand::KeepCursor)) {
124  if (charsAddedOrRemoved < 0 && adjusted_anchor < positionOfChange - charsAddedOrRemoved)
125  adjusted_anchor = positionOfChange;
126  else
127  adjusted_anchor += charsAddedOrRemoved;
128  }
129 
130  return result;
131 }
132 
134 {
135  if (priv->isInEditBlock()) {
136  x = -1; // mark dirty
137  return;
138  }
139 
140  QTextBlock block = this->block();
141  const QTextLayout *layout = blockLayout(block);
142  int pos = position - block.position();
143 
144  QTextLine line = layout->lineForTextPosition(pos);
145  if (line.isValid())
146  x = line.cursorToX(pos);
147  else
148  x = -1; // delayed init. Makes movePosition() call setX later on again.
149 }
150 
152 {
153  if (anchor == position)
154  return;
155  currentCharFormat = -1;
156  int pos1 = position;
157  int pos2 = adjusted_anchor;
159  if (pos1 > pos2) {
160  pos1 = adjusted_anchor;
161  pos2 = position;
163  }
164 
165  // deleting inside table? -> delete only content
167  if (table) {
168  priv->beginEditBlock();
169  int startRow, startCol, numRows, numCols;
170  selectedTableCells(&startRow, &numRows, &startCol, &numCols);
171  clearCells(table, startRow, startCol, numRows, numCols, op);
173  priv->endEditBlock();
174  } else {
175  priv->remove(pos1, pos2-pos1, op);
177  priv->finishEdit();
178  }
179 
180 }
181 
182 void QTextCursorPrivate::clearCells(QTextTable *table, int startRow, int startCol, int numRows, int numCols, QTextUndoCommand::Operation op)
183 {
184  priv->beginEditBlock();
185 
186  for (int row = startRow; row < startRow + numRows; ++row)
187  for (int col = startCol; col < startCol + numCols; ++col) {
188  QTextTableCell cell = table->cellAt(row, col);
189  const int startPos = cell.firstPosition();
190  const int endPos = cell.lastPosition();
191  Q_ASSERT(startPos <= endPos);
192  priv->remove(startPos, endPos - startPos, op);
193  }
194 
195  priv->endEditBlock();
196 }
197 
198 bool QTextCursorPrivate::canDelete(int pos) const
199 {
201  QTextCharFormat fmt = priv->formatCollection()->charFormat((*fit)->format);
202  return (fmt.objectIndex() == -1 || fmt.objectType() == QTextFormat::ImageObject);
203 }
204 
206 {
208  int idx = formats->indexForFormat(format);
209  Q_ASSERT(formats->format(idx).isBlockFormat());
210 
211  priv->insertBlock(position, idx, formats->indexForFormat(charFormat));
212  currentCharFormat = -1;
213 }
214 
216 {
218  if (position == anchor)
219  return;
220 
221  QTextFrame *f_position = priv->frameAt(position);
222  QTextFrame *f_anchor = priv->frameAt(adjusted_anchor);
223 
224  if (f_position != f_anchor) {
225  // find common parent frame
226  QList<QTextFrame *> positionChain;
227  QList<QTextFrame *> anchorChain;
228  QTextFrame *f = f_position;
229  while (f) {
230  positionChain.prepend(f);
231  f = f->parentFrame();
232  }
233  f = f_anchor;
234  while (f) {
235  anchorChain.prepend(f);
236  f = f->parentFrame();
237  }
238  Q_ASSERT(positionChain.at(0) == anchorChain.at(0));
239  int i = 1;
240  int l = qMin(positionChain.size(), anchorChain.size());
241  for (; i < l; ++i) {
242  if (positionChain.at(i) != anchorChain.at(i))
243  break;
244  }
245 
246  if (m <= QTextCursor::WordLeft) {
247  if (i < positionChain.size())
248  position = positionChain.at(i)->firstPosition() - 1;
249  } else {
250  if (i < positionChain.size())
251  position = positionChain.at(i)->lastPosition() + 1;
252  }
253  if (position < adjusted_anchor) {
254  if (i < anchorChain.size())
255  adjusted_anchor = anchorChain.at(i)->lastPosition() + 1;
256  } else {
257  if (i < anchorChain.size())
258  adjusted_anchor = anchorChain.at(i)->firstPosition() - 1;
259  }
260 
261  f_position = positionChain.at(i-1);
262  }
263 
264  // same frame, either need to adjust to cell boundaries or return
265  QTextTable *table = qobject_cast<QTextTable *>(f_position);
266  if (!table)
267  return;
268 
269  QTextTableCell c_position = table->cellAt(position);
270  QTextTableCell c_anchor = table->cellAt(adjusted_anchor);
271  if (c_position != c_anchor) {
272  bool before;
273  int col_position = c_position.column();
274  int col_anchor = c_anchor.column();
275  if (col_position == col_anchor) {
276  before = c_position.row() < c_anchor.row();
277  } else {
278  before = col_position < col_anchor;
279  }
280 
281  // adjust to cell boundaries
282  if (m <= QTextCursor::WordLeft) {
283  position = c_position.firstPosition();
284  if (!before)
285  --position;
286  } else {
287  position = c_position.lastPosition();
288  if (before)
289  ++position;
290  }
292  adjusted_anchor = c_anchor.lastPosition();
293  else
294  adjusted_anchor = c_anchor.firstPosition();
295  }
296  currentCharFormat = -1;
297 }
298 
300 {
301  Q_ASSERT(from <= to);
302  if (position == anchor)
303  return;
304 
306  if (!t)
307  return;
308  QTextTableCell removedCellFrom = t->cellAt(from);
309  QTextTableCell removedCellEnd = t->cellAt(to);
310  if (! removedCellFrom.isValid() || !removedCellEnd.isValid())
311  return;
312 
313  int curFrom = position;
314  int curTo = adjusted_anchor;
315  if (curTo < curFrom)
316  qSwap(curFrom, curTo);
317 
318  QTextTableCell cellStart = t->cellAt(curFrom);
319  QTextTableCell cellEnd = t->cellAt(curTo);
320 
321  if (cellStart.row() >= removedCellFrom.row() && cellEnd.row() <= removedCellEnd.row()
322  && cellStart.column() >= removedCellFrom.column()
323  && cellEnd.column() <= removedCellEnd.column()) { // selection is completely removed
324  // find a new position, as close as possible to where we were.
325  QTextTableCell cell;
326  if (removedCellFrom.row() == 0 && removedCellEnd.row() == t->rows()-1) // removed n columns
327  cell = t->cellAt(cellStart.row(), removedCellEnd.column()+1);
328  else if (removedCellFrom.column() == 0 && removedCellEnd.column() == t->columns()-1) // removed n rows
329  cell = t->cellAt(removedCellEnd.row() + 1, cellStart.column());
330 
331  int newPosition;
332  if (cell.isValid())
333  newPosition = cell.firstPosition();
334  else
335  newPosition = t->lastPosition()+1;
336 
337  setPosition(newPosition);
338  anchor = newPosition;
339  adjusted_anchor = newPosition;
340  x = 0;
341  }
342  else if (cellStart.row() >= removedCellFrom.row() && cellStart.row() <= removedCellEnd.row()
343  && cellEnd.row() > removedCellEnd.row()) {
344  int newPosition = t->cellAt(removedCellEnd.row() + 1, cellStart.column()).firstPosition();
345  if (position < anchor)
346  position = newPosition;
347  else
348  anchor = adjusted_anchor = newPosition;
349  }
350  else if (cellStart.column() >= removedCellFrom.column() && cellStart.column() <= removedCellEnd.column()
351  && cellEnd.column() > removedCellEnd.column()) {
352  int newPosition = t->cellAt(cellStart.row(), removedCellEnd.column()+1).firstPosition();
353  if (position < anchor)
354  position = newPosition;
355  else
356  anchor = adjusted_anchor = newPosition;
357  }
358 }
359 
361 {
362  currentCharFormat = -1;
363  bool adjustX = true;
364  QTextBlock blockIt = block();
365  bool visualMovement = priv->defaultCursorMoveStyle == Qt::VisualMoveStyle;
366 
367  if (!blockIt.isValid())
368  return false;
369 
370  if (blockIt.textDirection() == Qt::RightToLeft) {
371  if (op == QTextCursor::WordLeft)
373  else if (op == QTextCursor::WordRight)
375 
376  if (!visualMovement) {
377  if (op == QTextCursor::Left)
379  else if (op == QTextCursor::Right)
381  }
382  }
383 
384  const QTextLayout *layout = blockLayout(blockIt);
385  int relativePos = position - blockIt.position();
386  QTextLine line;
387  if (!priv->isInEditBlock())
388  line = layout->lineForTextPosition(relativePos);
389 
391 
392  int newPosition = position;
393 
394  if (x == -1 && !priv->isInEditBlock() && (op == QTextCursor::Up || op == QTextCursor::Down))
395  setX();
396 
397  switch(op) {
398  case QTextCursor::NoMove:
399  return true;
400 
401  case QTextCursor::Start:
402  newPosition = 0;
403  break;
405  newPosition = blockIt.position();
406  if (line.isValid())
407  newPosition += line.textStart();
408 
409  break;
410  }
412  newPosition = blockIt.position();
413  break;
414  }
416  if (blockIt == priv->blocksBegin())
417  return false;
418  blockIt = blockIt.previous();
419 
420  newPosition = blockIt.position();
421  break;
422  }
424 #ifdef Q_WS_MAC
426  newPosition = qMin(position, adjusted_anchor);
427  else
428 #endif
430  break;
431  case QTextCursor::Left:
432 #ifdef Q_WS_MAC
434  newPosition = visualMovement ? qMax(position, adjusted_anchor)
436  else
437 #endif
438  newPosition = visualMovement ? priv->leftCursorPosition(position)
440  break;
442  if (relativePos == 0)
443  break;
444 
445  // skip if already at word start
446  QTextEngine *engine = layout->engine();
447  engine->attributes();
448  if ((relativePos == blockIt.length() - 1)
449  && (engine->atSpace(relativePos - 1) || engine->atWordSeparator(relativePos - 1)))
450  return false;
451 
452  if (relativePos < blockIt.length()-1)
453  ++position;
454 
455  // FALL THROUGH!
456  }
460  break;
461  case QTextCursor::Up: {
462  int i = line.lineNumber() - 1;
463  if (i == -1) {
464  if (blockIt == priv->blocksBegin())
465  return false;
466  int blockPosition = blockIt.position();
467  QTextTable *table = qobject_cast<QTextTable *>(priv->frameAt(blockPosition));
468  if (table) {
469  QTextTableCell cell = table->cellAt(blockPosition);
470  if (cell.firstPosition() == blockPosition) {
471  int row = cell.row() - 1;
472  if (row >= 0) {
473  blockPosition = table->cellAt(row, cell.column()).lastPosition();
474  } else {
475  // move to line above the table
476  blockPosition = table->firstPosition() - 1;
477  }
478  blockIt = priv->blocksFind(blockPosition);
479  } else {
480  blockIt = blockIt.previous();
481  }
482  } else {
483  blockIt = blockIt.previous();
484  }
485  layout = blockLayout(blockIt);
486  i = layout->lineCount()-1;
487  }
488  if (layout->lineCount()) {
489  QTextLine line = layout->lineAt(i);
490  newPosition = line.xToCursor(x) + blockIt.position();
491  } else {
492  newPosition = blockIt.position();
493  }
494  adjustX = false;
495  break;
496  }
497 
498  case QTextCursor::End:
499  newPosition = priv->length() - 1;
500  break;
501  case QTextCursor::EndOfLine: {
502  if (!line.isValid() || line.textLength() == 0) {
503  if (blockIt.length() >= 1)
504  // position right before the block separator
505  newPosition = blockIt.position() + blockIt.length() - 1;
506  break;
507  }
508  newPosition = blockIt.position() + line.textStart() + line.textLength();
509  if (line.lineNumber() < layout->lineCount() - 1) {
510  const QString text = blockIt.text();
511  // ###### this relies on spaces being the cause for linebreaks.
512  // this doesn't work with japanese
513  if (text.at(line.textStart() + line.textLength() - 1).isSpace())
514  --newPosition;
515  }
516  break;
517  }
518  case QTextCursor::EndOfWord: {
519  QTextEngine *engine = layout->engine();
520  engine->attributes();
521  const int len = blockIt.length() - 1;
522  if (relativePos >= len)
523  return false;
524  if (engine->atWordSeparator(relativePos)) {
525  ++relativePos;
526  while (relativePos < len && engine->atWordSeparator(relativePos))
527  ++relativePos;
528  } else {
529  while (relativePos < len && !engine->atSpace(relativePos) && !engine->atWordSeparator(relativePos))
530  ++relativePos;
531  }
532  newPosition = blockIt.position() + relativePos;
533  break;
534  }
536  if (blockIt.length() >= 1)
537  // position right before the block separator
538  newPosition = blockIt.position() + blockIt.length() - 1;
539  break;
540  case QTextCursor::NextBlock: {
541  blockIt = blockIt.next();
542  if (!blockIt.isValid())
543  return false;
544 
545  newPosition = blockIt.position();
546  break;
547  }
549 #ifdef Q_WS_MAC
551  newPosition = qMax(position, adjusted_anchor);
552  else
553 #endif
555  break;
556  case QTextCursor::Right:
557 #ifdef Q_WS_MAC
559  newPosition = visualMovement ? qMin(position, adjusted_anchor)
561  else
562 #endif
563  newPosition = visualMovement ? priv->rightCursorPosition(position)
565  break;
569  break;
570 
571  case QTextCursor::Down: {
572  int i = line.lineNumber() + 1;
573 
574  if (i >= layout->lineCount()) {
575  int blockPosition = blockIt.position() + blockIt.length() - 1;
576  QTextTable *table = qobject_cast<QTextTable *>(priv->frameAt(blockPosition));
577  if (table) {
578  QTextTableCell cell = table->cellAt(blockPosition);
579  if (cell.lastPosition() == blockPosition) {
580  int row = cell.row() + cell.rowSpan();
581  if (row < table->rows()) {
582  blockPosition = table->cellAt(row, cell.column()).firstPosition();
583  } else {
584  // move to line below the table
585  blockPosition = table->lastPosition() + 1;
586  }
587  blockIt = priv->blocksFind(blockPosition);
588  } else {
589  blockIt = blockIt.next();
590  }
591  } else {
592  blockIt = blockIt.next();
593  }
594 
595  if (blockIt == priv->blocksEnd())
596  return false;
597  layout = blockLayout(blockIt);
598  i = 0;
599  }
600  if (layout->lineCount()) {
601  QTextLine line = layout->lineAt(i);
602  newPosition = line.xToCursor(x) + blockIt.position();
603  } else {
604  newPosition = blockIt.position();
605  }
606  adjustX = false;
607  break;
608  }
609  case QTextCursor::NextCell: // fall through
610  case QTextCursor::PreviousCell: // fall through
611  case QTextCursor::NextRow: // fall through
614  if (!table)
615  return false;
616 
617  QTextTableCell cell = table->cellAt(position);
618  Q_ASSERT(cell.isValid());
619  int column = cell.column();
620  int row = cell.row();
621  const int currentRow = row;
622  if (op == QTextCursor::NextCell || op == QTextCursor::NextRow) {
623  do {
624  column += cell.columnSpan();
625  if (column >= table->columns()) {
626  column = 0;
627  ++row;
628  }
629  cell = table->cellAt(row, column);
630  // note we also continue while we have not reached a cell thats not merged with one above us
631  } while (cell.isValid()
632  && ((op == QTextCursor::NextRow && currentRow == cell.row())
633  || cell.row() < row));
634  }
635  else if (op == QTextCursor::PreviousCell || op == QTextCursor::PreviousRow) {
636  do {
637  --column;
638  if (column < 0) {
639  column = table->columns()-1;
640  --row;
641  }
642  cell = table->cellAt(row, column);
643  // note we also continue while we have not reached a cell thats not merged with one above us
644  } while (cell.isValid()
645  && ((op == QTextCursor::PreviousRow && currentRow == cell.row())
646  || cell.row() < row));
647  }
648  if (cell.isValid())
649  newPosition = cell.firstPosition();
650  break;
651  }
652  }
653 
654  if (mode == QTextCursor::KeepAnchor) {
656  if (table && ((op >= QTextCursor::PreviousBlock && op <= QTextCursor::WordLeft)
657  || (op >= QTextCursor::NextBlock && op <= QTextCursor::WordRight))) {
658  int oldColumn = table->cellAt(position).column();
659 
660  const QTextTableCell otherCell = table->cellAt(newPosition);
661  if (!otherCell.isValid())
662  return false;
663 
664  int newColumn = otherCell.column();
665  if ((oldColumn > newColumn && op >= QTextCursor::End)
666  || (oldColumn < newColumn && op <= QTextCursor::WordLeft))
667  return false;
668  }
669  }
670 
671  const bool moved = setPosition(newPosition);
672 
673  if (mode == QTextCursor::MoveAnchor) {
674  anchor = position;
676  } else {
677  adjustCursor(op);
678  }
679 
680  if (adjustX)
681  setX();
682 
683  return moved;
684 }
685 
687 {
688  if (position == anchor)
689  return 0;
690 
692  if (t) {
693  QTextTableCell cell_pos = t->cellAt(position);
694  QTextTableCell cell_anchor = t->cellAt(adjusted_anchor);
695 
696  Q_ASSERT(cell_anchor.isValid());
697 
698  if (cell_pos == cell_anchor)
699  t = 0;
700  }
701  return t;
702 }
703 
704 void QTextCursorPrivate::selectedTableCells(int *firstRow, int *numRows, int *firstColumn, int *numColumns) const
705 {
706  *firstRow = -1;
707  *firstColumn = -1;
708  *numRows = -1;
709  *numColumns = -1;
710 
711  if (position == anchor)
712  return;
713 
715  if (!t)
716  return;
717 
718  QTextTableCell cell_pos = t->cellAt(position);
719  QTextTableCell cell_anchor = t->cellAt(adjusted_anchor);
720 
721  Q_ASSERT(cell_anchor.isValid());
722 
723  if (cell_pos == cell_anchor)
724  return;
725 
726  *firstRow = qMin(cell_pos.row(), cell_anchor.row());
727  *firstColumn = qMin(cell_pos.column(), cell_anchor.column());
728  *numRows = qMax(cell_pos.row() + cell_pos.rowSpan(), cell_anchor.row() + cell_anchor.rowSpan()) - *firstRow;
729  *numColumns = qMax(cell_pos.column() + cell_pos.columnSpan(), cell_anchor.column() + cell_anchor.columnSpan()) - *firstColumn;
730 }
731 
732 static void setBlockCharFormatHelper(QTextDocumentPrivate *priv, int pos1, int pos2,
734 {
735  QTextBlock it = priv->blocksFind(pos1);
736  QTextBlock end = priv->blocksFind(pos2);
737  if (end.isValid())
738  end = end.next();
739 
740  for (; it != end; it = it.next()) {
741  priv->setCharFormat(it.position() - 1, 1, format, changeMode);
742  }
743 }
744 
747 {
748  priv->beginEditBlock();
749 
750  QTextCharFormat format = _format;
752 
754  if (table) {
755  int row_start, col_start, num_rows, num_cols;
756  selectedTableCells(&row_start, &num_rows, &col_start, &num_cols);
757 
758  Q_ASSERT(row_start != -1);
759  for (int r = row_start; r < row_start + num_rows; ++r) {
760  for (int c = col_start; c < col_start + num_cols; ++c) {
761  QTextTableCell cell = table->cellAt(r, c);
762  int rspan = cell.rowSpan();
763  int cspan = cell.columnSpan();
764  if (rspan != 1) {
765  int cr = cell.row();
766  if (cr != r)
767  continue;
768  }
769  if (cspan != 1) {
770  int cc = cell.column();
771  if (cc != c)
772  continue;
773  }
774 
775  int pos1 = cell.firstPosition();
776  int pos2 = cell.lastPosition();
777  setBlockCharFormatHelper(priv, pos1, pos2, format, changeMode);
778  }
779  }
780  } else {
781  int pos1 = position;
782  int pos2 = adjusted_anchor;
783  if (pos1 > pos2) {
784  pos1 = adjusted_anchor;
785  pos2 = position;
786  }
787 
788  setBlockCharFormatHelper(priv, pos1, pos2, format, changeMode);
789  }
790  priv->endEditBlock();
791 }
792 
793 
795 {
797  if (table) {
798  priv->beginEditBlock();
799  int row_start, col_start, num_rows, num_cols;
800  selectedTableCells(&row_start, &num_rows, &col_start, &num_cols);
801 
802  Q_ASSERT(row_start != -1);
803  for (int r = row_start; r < row_start + num_rows; ++r) {
804  for (int c = col_start; c < col_start + num_cols; ++c) {
805  QTextTableCell cell = table->cellAt(r, c);
806  int rspan = cell.rowSpan();
807  int cspan = cell.columnSpan();
808  if (rspan != 1) {
809  int cr = cell.row();
810  if (cr != r)
811  continue;
812  }
813  if (cspan != 1) {
814  int cc = cell.column();
815  if (cc != c)
816  continue;
817  }
818 
819  int pos1 = cell.firstPosition();
820  int pos2 = cell.lastPosition();
821  priv->setBlockFormat(priv->blocksFind(pos1), priv->blocksFind(pos2), format, changeMode);
822  }
823  }
824  priv->endEditBlock();
825  } else {
826  int pos1 = position;
827  int pos2 = adjusted_anchor;
828  if (pos1 > pos2) {
829  pos1 = adjusted_anchor;
830  pos2 = position;
831  }
832 
833  priv->setBlockFormat(priv->blocksFind(pos1), priv->blocksFind(pos2), format, changeMode);
834  }
835 }
836 
838 {
840 
841  QTextCharFormat format = _format;
843 
845  if (table) {
846  priv->beginEditBlock();
847  int row_start, col_start, num_rows, num_cols;
848  selectedTableCells(&row_start, &num_rows, &col_start, &num_cols);
849 
850  Q_ASSERT(row_start != -1);
851  for (int r = row_start; r < row_start + num_rows; ++r) {
852  for (int c = col_start; c < col_start + num_cols; ++c) {
853  QTextTableCell cell = table->cellAt(r, c);
854  int rspan = cell.rowSpan();
855  int cspan = cell.columnSpan();
856  if (rspan != 1) {
857  int cr = cell.row();
858  if (cr != r)
859  continue;
860  }
861  if (cspan != 1) {
862  int cc = cell.column();
863  if (cc != c)
864  continue;
865  }
866 
867  int pos1 = cell.firstPosition();
868  int pos2 = cell.lastPosition();
869  priv->setCharFormat(pos1, pos2-pos1, format, changeMode);
870  }
871  }
872  priv->endEditBlock();
873  } else {
874  int pos1 = position;
875  int pos2 = adjusted_anchor;
876  if (pos1 > pos2) {
877  pos1 = adjusted_anchor;
878  pos2 = position;
879  }
880 
881  priv->setCharFormat(pos1, pos2-pos1, format, changeMode);
882  }
883 }
884 
885 
887  QTextLayout *tl = block.layout();
888  if (!tl->lineCount() && priv->layout())
889  priv->layout()->blockBoundingRect(block);
890  return tl;
891 }
892 
1070  : d(0)
1071 {
1072 }
1073 
1078  : d(new QTextCursorPrivate(document->docHandle()))
1079 {
1080 }
1081 
1086  : d(new QTextCursorPrivate(frame->document()->docHandle()))
1087 {
1088  d->adjusted_anchor = d->anchor = d->position = frame->firstPosition();
1089 }
1090 
1091 
1096  : d(new QTextCursorPrivate(block.docHandle()))
1097 {
1098  d->adjusted_anchor = d->anchor = d->position = block.position();
1099 }
1100 
1101 
1106  : d(new QTextCursorPrivate(p))
1107 {
1108  d->adjusted_anchor = d->anchor = d->position = pos;
1109 
1110  d->setX();
1111 }
1112 
1117 {
1118  Q_ASSERT(d);
1119  this->d = d;
1120 }
1121 
1126 {
1127  d = cursor.d;
1128 }
1129 
1137 {
1138  d = cursor.d;
1139  return *this;
1140 }
1141 
1146 {
1147 }
1148 
1154 {
1155  return !d || !d->priv;
1156 }
1157 
1166 {
1167  if (!d || !d->priv)
1168  return;
1169 
1170  if (pos < 0 || pos >= d->priv->length()) {
1171  qWarning("QTextCursor::setPosition: Position '%d' out of range", pos);
1172  return;
1173  }
1174 
1175  d->setPosition(pos);
1176  if (m == MoveAnchor) {
1177  d->anchor = pos;
1178  d->adjusted_anchor = pos;
1179  } else { // keep anchor
1181  if (pos < d->anchor)
1182  op = QTextCursor::Left;
1183  else
1184  op = QTextCursor::Right;
1185  d->adjustCursor(op);
1186  }
1187  d->setX();
1188 }
1189 
1197 {
1198  if (!d || !d->priv)
1199  return -1;
1200  return d->position;
1201 }
1202 
1216 {
1217  if (!d || !d->priv)
1218  return 0;
1219  return d->position - d->block().position();
1220 }
1221 
1231 {
1232  if (!d || !d->priv)
1233  return -1;
1234  return d->anchor;
1235 }
1236 
1259 {
1260  if (!d || !d->priv)
1261  return false;
1262  switch (op) {
1263  case Start:
1264  case StartOfLine:
1265  case End:
1266  case EndOfLine:
1267  n = 1;
1268  break;
1269  default: break;
1270  }
1271 
1272  int previousPosition = d->position;
1273  for (; n > 0; --n) {
1274  if (!d->movePosition(op, mode))
1275  return false;
1276  }
1277 
1278  if (d->visualNavigation && !d->block().isVisible()) {
1279  QTextBlock b = d->block();
1280  if (previousPosition < d->position) {
1281  while (!b.next().isVisible())
1282  b = b.next();
1283  d->setPosition(b.position() + b.length() - 1);
1284  } else {
1285  while (!b.previous().isVisible())
1286  b = b.previous();
1287  d->setPosition(b.position());
1288  }
1289  if (mode == QTextCursor::MoveAnchor)
1290  d->anchor = d->position;
1291  while (d->movePosition(op, mode)
1292  && !d->block().isVisible())
1293  ;
1294 
1295  }
1296  return true;
1297 }
1298 
1314 {
1315  return d ? d->visualNavigation : false;
1316 }
1317 
1332 {
1333  if (d)
1334  d->visualNavigation = b;
1335 }
1336 
1337 
1356 {
1357  if (d)
1358  d->x = x;
1359 }
1360 
1374 {
1375  return d ? d->x : -1;
1376 }
1377 
1392 {
1393  return d ? d->keepPositionOnInsert : false;
1394 }
1395 
1416 {
1417  if (d)
1418  d->keepPositionOnInsert = b;
1419 }
1420 
1421 
1422 
1440 {
1441  QTextCharFormat fmt = charFormat();
1443  insertText(text, fmt);
1444 }
1445 
1456 {
1457  if (!d || !d->priv)
1458  return;
1459 
1460  Q_ASSERT(_format.isValid());
1461 
1462  QTextCharFormat format = _format;
1464 
1465  bool hasEditBlock = false;
1466 
1467  if (d->anchor != d->position) {
1468  hasEditBlock = true;
1469  d->priv->beginEditBlock();
1470  d->remove();
1471  }
1472 
1473  if (!text.isEmpty()) {
1475  int formatIdx = formats->indexForFormat(format);
1476  Q_ASSERT(formats->format(formatIdx).isCharFormat());
1477 
1478  QTextBlockFormat blockFmt = blockFormat();
1479 
1480 
1481  int textStart = d->priv->text.length();
1482  int blockStart = 0;
1483  d->priv->text += text;
1484  int textEnd = d->priv->text.length();
1485 
1486  for (int i = 0; i < text.length(); ++i) {
1487  QChar ch = text.at(i);
1488 
1489  const int blockEnd = i;
1490 
1491  if (ch == QLatin1Char('\r')
1492  && (i + 1) < text.length()
1493  && text.at(i + 1) == QLatin1Char('\n')) {
1494  ++i;
1495  ch = text.at(i);
1496  }
1497 
1498  if (ch == QLatin1Char('\n')
1499  || ch == QChar::ParagraphSeparator
1500  || ch == QTextBeginningOfFrame
1501  || ch == QTextEndOfFrame
1502  || ch == QLatin1Char('\r')) {
1503 
1504  if (!hasEditBlock) {
1505  hasEditBlock = true;
1506  d->priv->beginEditBlock();
1507  }
1508 
1509  if (blockEnd > blockStart)
1510  d->priv->insert(d->position, textStart + blockStart, blockEnd - blockStart, formatIdx);
1511 
1512  d->insertBlock(blockFmt, format);
1513  blockStart = i + 1;
1514  }
1515  }
1516  if (textStart + blockStart < textEnd)
1517  d->priv->insert(d->position, textStart + blockStart, textEnd - textStart - blockStart, formatIdx);
1518  }
1519  if (hasEditBlock)
1520  d->priv->endEditBlock();
1521  d->setX();
1522 }
1523 
1531 {
1532  if (!d || !d->priv)
1533  return;
1534 
1535  if (d->position != d->anchor) {
1537  return;
1538  }
1539 
1540  if (!d->canDelete(d->position))
1541  return;
1542  d->adjusted_anchor = d->anchor =
1544  d->remove();
1545  d->setX();
1546 }
1547 
1555 {
1556  if (!d || !d->priv)
1557  return;
1558 
1559  if (d->position != d->anchor) {
1561  return;
1562  }
1563 
1564  if (d->anchor < 1 || !d->canDelete(d->anchor-1))
1565  return;
1566  d->anchor--;
1567 
1569  const QTextFragmentData * const frag = fragIt.value();
1570  int fpos = fragIt.position();
1571  QChar uc = d->priv->buffer().at(d->anchor - fpos + frag->stringPosition);
1572  if (d->anchor > fpos && uc.isLowSurrogate()) {
1573  // second half of a surrogate, check if we have the first half as well,
1574  // if yes delete both at once
1575  uc = d->priv->buffer().at(d->anchor - 1 - fpos + frag->stringPosition);
1576  if (uc.isHighSurrogate())
1577  --d->anchor;
1578  }
1579 
1580  d->adjusted_anchor = d->anchor;
1581  d->remove();
1582  d->setX();
1583 }
1584 
1589 {
1590  if (!d || !d->priv)
1591  return;
1592 
1593  clearSelection();
1594 
1595  const QTextBlock block = d->block();
1596 
1597  switch (selection) {
1598  case LineUnderCursor:
1601  break;
1602  case WordUnderCursor:
1605  break;
1606  case BlockUnderCursor:
1607  if (block.length() == 1) // no content
1608  break;
1610  // also select the paragraph separator
1611  if (movePosition(PreviousBlock)) {
1614  }
1616  break;
1617  case Document:
1620  break;
1621  }
1622 }
1623 
1628 {
1629  return !!d && d->position != d->anchor;
1630 }
1631 
1632 
1641 {
1642  if (!d)
1643  return false;
1644 
1645  return d->complexSelectionTable() != 0;
1646 }
1647 
1656 void QTextCursor::selectedTableCells(int *firstRow, int *numRows, int *firstColumn, int *numColumns) const
1657 {
1658  *firstRow = -1;
1659  *firstColumn = -1;
1660  *numRows = -1;
1661  *numColumns = -1;
1662 
1663  if (!d || d->position == d->anchor)
1664  return;
1665 
1666  d->selectedTableCells(firstRow, numRows, firstColumn, numColumns);
1667 }
1668 
1669 
1678 {
1679  if (!d)
1680  return;
1682  d->currentCharFormat = -1;
1683 }
1684 
1692 {
1693  if (!d || !d->priv || d->position == d->anchor)
1694  return;
1695 
1696  d->priv->beginEditBlock();
1697  d->remove();
1698  d->priv->endEditBlock();
1699  d->setX();
1700 }
1701 
1709 {
1710  if (!d || !d->priv)
1711  return -1;
1712  return qMin(d->position, d->adjusted_anchor);
1713 }
1714 
1722 {
1723  if (!d || !d->priv)
1724  return -1;
1725  return qMax(d->position, d->adjusted_anchor);
1726 }
1727 
1728 static void getText(QString &text, QTextDocumentPrivate *priv, const QString &docText, int pos, int end)
1729 {
1730  while (pos < end) {
1731  QTextDocumentPrivate::FragmentIterator fragIt = priv->find(pos);
1732  const QTextFragmentData * const frag = fragIt.value();
1733 
1734  const int offsetInFragment = qMax(0, pos - fragIt.position());
1735  const int len = qMin(int(frag->size_array[0] - offsetInFragment), end - pos);
1736 
1737  text += QString(docText.constData() + frag->stringPosition + offsetInFragment, len);
1738  pos += len;
1739  }
1740 }
1741 
1754 {
1755  if (!d || !d->priv || d->position == d->anchor)
1756  return QString();
1757 
1758  const QString docText = d->priv->buffer();
1759  QString text;
1760 
1761  QTextTable *table = d->complexSelectionTable();
1762  if (table) {
1763  int row_start, col_start, num_rows, num_cols;
1764  selectedTableCells(&row_start, &num_rows, &col_start, &num_cols);
1765 
1766  Q_ASSERT(row_start != -1);
1767  for (int r = row_start; r < row_start + num_rows; ++r) {
1768  for (int c = col_start; c < col_start + num_cols; ++c) {
1769  QTextTableCell cell = table->cellAt(r, c);
1770  int rspan = cell.rowSpan();
1771  int cspan = cell.columnSpan();
1772  if (rspan != 1) {
1773  int cr = cell.row();
1774  if (cr != r)
1775  continue;
1776  }
1777  if (cspan != 1) {
1778  int cc = cell.column();
1779  if (cc != c)
1780  continue;
1781  }
1782 
1783  getText(text, d->priv, docText, cell.firstPosition(), cell.lastPosition());
1784  }
1785  }
1786  } else {
1787  getText(text, d->priv, docText, selectionStart(), selectionEnd());
1788  }
1789 
1790  return text;
1791 }
1792 
1805 {
1806  return QTextDocumentFragment(*this);
1807 }
1808 
1813 {
1814  if (!d || !d->priv)
1815  return QTextBlock();
1816  return d->block();
1817 }
1818 
1825 {
1826  if (!d || !d->priv)
1827  return QTextBlockFormat();
1828 
1829  return d->block().blockFormat();
1830 }
1831 
1839 {
1840  if (!d || !d->priv)
1841  return;
1842 
1844 }
1845 
1854 {
1855  if (!d || !d->priv)
1856  return;
1857 
1859 }
1860 
1870 {
1871  if (!d || !d->priv)
1872  return QTextCharFormat();
1873 
1874  return d->block().charFormat();
1875 }
1876 
1884 {
1885  if (!d || !d->priv)
1886  return;
1887 
1889 }
1890 
1899 {
1900  if (!d || !d->priv)
1901  return;
1902 
1904 }
1905 
1915 {
1916  if (!d || !d->priv)
1917  return QTextCharFormat();
1918 
1919  int idx = d->currentCharFormat;
1920  if (idx == -1) {
1921  QTextBlock block = d->block();
1922 
1923  int pos;
1924  if (d->position == block.position()
1925  && block.length() > 1)
1926  pos = d->position;
1927  else
1928  pos = d->position - 1;
1929 
1930  if (pos == -1) {
1932  } else {
1933  Q_ASSERT(pos >= 0 && pos < d->priv->length());
1934 
1936  Q_ASSERT(!it.atEnd());
1937  idx = it.value()->format;
1938  }
1939  }
1940 
1943 
1944  Q_ASSERT(cfmt.isValid());
1945  return cfmt;
1946 }
1947 
1956 {
1957  if (!d || !d->priv)
1958  return;
1959  if (d->position == d->anchor) {
1961  return;
1962  }
1964 }
1965 
1975 {
1976  if (!d || !d->priv)
1977  return;
1978  if (d->position == d->anchor) {
1980  format.merge(modifier);
1982  return;
1983  }
1984 
1986 }
1987 
1995 {
1996  if (!d || !d->priv)
1997  return false;
1998 
1999  return d->position == d->block().position();
2000 }
2001 
2009 {
2010  if (!d || !d->priv)
2011  return false;
2012 
2013  return d->position == d->block().position() + d->block().length() - 1;
2014 }
2015 
2023 {
2024  if (!d || !d->priv)
2025  return false;
2026 
2027  return d->position == 0;
2028 }
2029 
2042 {
2043  if (!d || !d->priv)
2044  return false;
2045 
2046  return d->position == d->priv->length() - 1;
2047 }
2048 
2056 {
2058 }
2059 
2072 {
2073  QTextCharFormat charFmt = charFormat();
2075  insertBlock(format, charFmt);
2076 }
2077 
2091 {
2092  if (!d || !d->priv)
2093  return;
2094 
2095  QTextCharFormat charFormat = _charFormat;
2097 
2098  d->priv->beginEditBlock();
2099  d->remove();
2100  d->insertBlock(format, charFormat);
2101  d->priv->endEditBlock();
2102  d->setX();
2103 }
2104 
2113 {
2114  insertBlock();
2115  return createList(format);
2116 }
2117 
2131 {
2132  insertBlock();
2133  return createList(style);
2134 }
2135 
2143 {
2144  if (!d || !d->priv)
2145  return 0;
2146 
2147  QTextList *list = static_cast<QTextList *>(d->priv->createObject(format));
2148  QTextBlockFormat modifier;
2149  modifier.setObjectIndex(list->objectIndex());
2150  mergeBlockFormat(modifier);
2151  return list;
2152 }
2153 
2168 {
2169  QTextListFormat fmt;
2170  fmt.setStyle(style);
2171  return createList(fmt);
2172 }
2173 
2181 {
2182  if (!d || !d->priv)
2183  return 0;
2184 
2186  QTextObject *o = d->priv->objectForFormat(b);
2187  return qobject_cast<QTextList *>(o);
2188 }
2189 
2204 {
2205  return insertTable(rows, cols, QTextTableFormat());
2206 }
2207 
2221 {
2222  if(!d || !d->priv || rows == 0 || cols == 0)
2223  return 0;
2224 
2225  int pos = d->position;
2226  QTextTable *t = QTextTablePrivate::createTable(d->priv, d->position, rows, cols, format);
2227  d->setPosition(pos+1);
2228  // ##### what should we do if we have a selection?
2229  d->anchor = d->position;
2230  d->adjusted_anchor = d->anchor;
2231  return t;
2232 }
2233 
2241 {
2242  if(!d || !d->priv)
2243  return 0;
2244 
2245  QTextFrame *frame = d->priv->frameAt(d->position);
2246  while (frame) {
2247  QTextTable *table = qobject_cast<QTextTable *>(frame);
2248  if (table)
2249  return table;
2250  frame = frame->parentFrame();
2251  }
2252  return 0;
2253 }
2254 
2265 {
2266  if (!d || !d->priv)
2267  return 0;
2268 
2269  return d->priv->insertFrame(selectionStart(), selectionEnd(), format);
2270 }
2271 
2278 {
2279  if(!d || !d->priv)
2280  return 0;
2281 
2282  return d->priv->frameAt(d->position);
2283 }
2284 
2285 
2290 {
2291  if (!d || !d->priv || fragment.isEmpty())
2292  return;
2293 
2294  d->priv->beginEditBlock();
2295  d->remove();
2296  fragment.d->insert(*this);
2297  d->priv->endEditBlock();
2298 
2299  if (fragment.d && fragment.d->doc)
2300  d->priv->mergeCachedResources(fragment.d->doc->docHandle());
2301 }
2302 
2317 #ifndef QT_NO_TEXTHTMLPARSER
2318 
2320 {
2321  if (!d || !d->priv)
2322  return;
2324  insertFragment(fragment);
2325 }
2326 
2327 #endif // QT_NO_TEXTHTMLPARSER
2328 
2342 {
2343  if (!d || !d->priv)
2344  return;
2345 
2346  QTextFrameFormat ffmt;
2347  ffmt.setPosition(alignment);
2348  QTextObject *obj = d->priv->createObject(ffmt);
2349 
2350  QTextImageFormat fmt = format;
2351  fmt.setObjectIndex(obj->objectIndex());
2352 
2353  d->priv->beginEditBlock();
2354  d->remove();
2355  const int idx = d->priv->formatCollection()->indexForFormat(fmt);
2357  d->priv->endEditBlock();
2358 }
2359 
2364 {
2366 }
2367 
2380 {
2382  format.setName(name);
2383  insertImage(format);
2384 }
2385 
2396 void QTextCursor::insertImage(const QImage &image, const QString &name)
2397 {
2398  if (image.isNull()) {
2399  qWarning("QTextCursor::insertImage: attempt to add an invalid image");
2400  return;
2401  }
2402  QString imageName = name;
2403  if (name.isEmpty())
2404  imageName = QString::number(image.serialNumber());
2405  d->priv->document()->addResource(QTextDocument::ImageResource, QUrl(imageName), image);
2407  format.setName(imageName);
2408  insertImage(format);
2409 }
2410 
2420 bool QTextCursor::operator!=(const QTextCursor &rhs) const
2421 {
2422  return !operator==(rhs);
2423 }
2424 
2434 bool QTextCursor::operator<(const QTextCursor &rhs) const
2435 {
2436  if (!d)
2437  return !!rhs.d;
2438 
2439  if (!rhs.d)
2440  return false;
2441 
2442  Q_ASSERT_X(d->priv == rhs.d->priv, "QTextCursor::operator<", "cannot compare cursors attached to different documents");
2443 
2444  return d->position < rhs.d->position;
2445 }
2446 
2457 bool QTextCursor::operator<=(const QTextCursor &rhs) const
2458 {
2459  if (!d)
2460  return true;
2461 
2462  if (!rhs.d)
2463  return false;
2464 
2465  Q_ASSERT_X(d->priv == rhs.d->priv, "QTextCursor::operator<=", "cannot compare cursors attached to different documents");
2466 
2467  return d->position <= rhs.d->position;
2468 }
2469 
2479 bool QTextCursor::operator==(const QTextCursor &rhs) const
2480 {
2481  if (!d)
2482  return !rhs.d;
2483 
2484  if (!rhs.d)
2485  return false;
2486 
2487  return d->position == rhs.d->position && d->priv == rhs.d->priv;
2488 }
2489 
2500 bool QTextCursor::operator>=(const QTextCursor &rhs) const
2501 {
2502  if (!d)
2503  return false;
2504 
2505  if (!rhs.d)
2506  return true;
2507 
2508  Q_ASSERT_X(d->priv == rhs.d->priv, "QTextCursor::operator>=", "cannot compare cursors attached to different documents");
2509 
2510  return d->position >= rhs.d->position;
2511 }
2512 
2522 bool QTextCursor::operator>(const QTextCursor &rhs) const
2523 {
2524  if (!d)
2525  return false;
2526 
2527  if (!rhs.d)
2528  return true;
2529 
2530  Q_ASSERT_X(d->priv == rhs.d->priv, "QTextCursor::operator>", "cannot compare cursors attached to different documents");
2531 
2532  return d->position > rhs.d->position;
2533 }
2534 
2553 {
2554  if (!d || !d->priv)
2555  return;
2556 
2557  if (d->priv->editBlock == 0) // we are the initial edit block, store current cursor position for undo
2559 
2560  d->priv->beginEditBlock();
2561 }
2562 
2578 {
2579  if (!d || !d->priv)
2580  return;
2581 
2583 }
2584 
2594 {
2595  if (!d || !d->priv)
2596  return;
2597 
2598  d->priv->endEditBlock();
2599 }
2600 
2608 bool QTextCursor::isCopyOf(const QTextCursor &other) const
2609 {
2610  return d == other.d;
2611 }
2612 
2624 {
2625  if (!d || !d->priv)
2626  return 0;
2627 
2628  return d->block().blockNumber();
2629 }
2630 
2631 
2647 {
2648  if (!d || !d->priv)
2649  return 0;
2650 
2651  QTextBlock block = d->block();
2652  if (!block.isValid())
2653  return 0;
2654 
2655  const QTextLayout *layout = d->blockLayout(block);
2656 
2657  const int relativePos = d->position - block.position();
2658 
2659  if (layout->lineCount() == 0)
2660  return relativePos;
2661 
2662  QTextLine line = layout->lineForTextPosition(relativePos);
2663  if (!line.isValid())
2664  return 0;
2665  return relativePos - line.textStart();
2666 }
2667 
2676 {
2677  if (d->priv)
2678  return d->priv->document();
2679  return 0; // document went away
2680 }
2681 
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: qstring.cpp:6448
int objectIndex() const
Returns the index of the format object, or -1 if the format object is invalid.
T qobject_cast(QObject *object)
Definition: qobject.h:375
int columns() const
Returns the number of columns in the table.
double d
Definition: qnumeric_p.h:62
QTextCharFormat charFormat(int index) const
Definition: qtextformat_p.h:85
QTextTable * insertTable(int rows, int cols, const QTextTableFormat &format)
Creates a new table with the given number of rows and columns in the specified format, inserts it at the current cursor position() in the document, and returns the table object.
QTextTable * complexSelectionTable() const
QTextEngine * engine() const
Definition: qtextlayout.h:180
int anchor() const
Returns the anchor position; this is the same as position() unless there is a selection in which case...
void endEditBlock()
Indicates the end of a block of editing operations on the document that should appear as a single ope...
static void getText(QString &text, QTextDocumentPrivate *priv, const QString &docText, int pos, int end)
QString text() const
Returns the block&#39;s contents as plain text.
bool keepPositionOnInsert() const
Returns whether the cursor should keep its current position when text gets inserted at the position o...
The QTextCharFormat class provides formatting information for characters in a QTextDocument.
Definition: qtextformat.h:372
The QTextListFormat class provides formatting information for lists in a QTextDocument.
Definition: qtextformat.h:642
unsigned char c[8]
Definition: qnumeric_p.h:62
QTextCharFormat charFormat() const
Returns the format of the character immediately before the cursor position().
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
Definition: qglobal.h:1215
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
bool atWordSeparator(int position) const
const QChar at(int i) const
Returns the character at the given index position in the string.
Definition: qstring.h:698
void remove(int pos, int length, QTextUndoCommand::Operation=QTextUndoCommand::MoveCursor)
#define it(className, varName)
QTextBlock block() const
Definition: qtextcursor_p.h:93
The QTextFrame class represents a frame in a QTextDocument.
Definition: qtextobject.h:122
QTextFrame * insertFrame(const QTextFrameFormat &format)
Inserts a frame with the given format at the current cursor position(), moves the cursor position() i...
Position
This enum describes how a frame is located relative to the surrounding text.
Definition: qtextformat.h:734
int selectionEnd() const
Returns the end of the selection or position() if the cursor doesn&#39;t have a selection.
bool isNull() const
Returns true if it is a null image, otherwise returns false.
Definition: qimage.cpp:1542
bool operator!=(const QTextCursor &rhs) const
Returns true if the other cursor is at a different position in the document as this cursor; otherwise...
int length() const
Returns the number of characters in this string.
Definition: qstring.h:696
void setBlockCharFormat(const QTextCharFormat &format)
Sets the block char format of the current block (or all blocks that are contained in the selection) t...
The QTextLine class represents a line of text inside a QTextLayout.
Definition: qtextlayout.h:197
void insertImage(const QTextImageFormat &format, QTextFrameFormat::Position alignment)
Inserts the image defined by the given format at the cursor&#39;s current position with the specified ali...
static qreal position(QGraphicsObject *item, QDeclarativeAnchorLine::AnchorLine anchorLine)
QTextList * createList(const QTextListFormat &format)
Creates and returns a new list with the given format, and makes the current paragraph the cursor is i...
int textLength() const
Returns the length of the text in the line.
bool isLowSurrogate() const
Returns true if the QChar is the low part of a utf16 surrogate (ie.
Definition: qchar.h:279
QTextDocumentFragmentPrivate * d
QTextBlockFormat blockFormat() const
Returns the block format of the block the cursor is in.
QTextDocument * document() const
Returns the document this cursor is associated with.
QTextLayout * blockLayout(QTextBlock &block) const
#define QTextBeginningOfFrame
bool atBlockStart() const
Returns true if the cursor is at the start of a block; otherwise returns false.
void setBlockFormat(const QTextBlock &from, const QTextBlock &to, const QTextBlockFormat &newFormat, FormatChangeMode mode=SetFormat)
void setCharFormat(const QTextCharFormat &format)
Sets the cursor&#39;s current character format to the given format.
QAbstractTextDocumentLayout * layout() const
The QUrl class provides a convenient interface for working with URLs.
Definition: qurl.h:61
The QString class provides a Unicode character string.
Definition: qstring.h:83
QTextFormat format(int idx) const
bool isValid() const
Returns true if this character format is valid; otherwise returns false.
Definition: qtextformat.h:397
bool isHighSurrogate() const
Returns true if the QChar is the high part of a utf16 surrogate (ie.
Definition: qchar.h:276
void setVerticalMovementX(int x)
Sets the visual x position for vertical cursor movements to x.
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
void setBlockFormat(const QTextBlockFormat &format, QTextDocumentPrivate::FormatChangeMode changeMode)
const HB_CharAttributes * attributes() const
int firstPosition() const
Returns the first document position inside the frame.
void mergeBlockFormat(const QTextBlockFormat &modifier)
Modifies the block format of the current block (or all blocks that are contained in the selection) wi...
int blockCharFormatIndex(int node) const
QString selectedText() const
Returns the current selection&#39;s text (which may be empty).
bool isValid() const
Returns true if this text line is valid; otherwise returns false.
Definition: qtextlayout.h:201
void aboutToRemoveCell(int from, int to)
QSharedDataPointer< QTextCursorPrivate > d
Definition: qtextcursor.h:230
The QChar class provides a 16-bit Unicode character.
Definition: qchar.h:72
int insertBlock(int pos, int blockFormat, int charFormat, QTextUndoCommand::Operation=QTextUndoCommand::MoveCursor)
void insertText(const QString &text)
Inserts text at the current position, using the current character format.
void insert(int pos, const QString &text, int format)
void addCursor(QTextCursorPrivate *c)
FragmentMap::ConstIterator FragmentIterator
Q_DECL_CONSTEXPR const T & qMax(const T &a, const T &b)
Definition: qglobal.h:1217
QTextDocumentFragment selection() const
Returns the current selection (which may be empty) with all its formatting information.
QTextCursor & operator=(const QTextCursor &other)
Makes a copy of cursor and assigns it to this QTextCursor.
QTextCursor()
Constructs a null cursor.
QTextBlock next() const
Returns the text block in the document after this block, or an empty text block if this is the last o...
QTextLine lineForTextPosition(int pos) const
Returns the line that contains the cursor position specified by pos.
int rowSpan() const
Returns the number of rows this cell spans.
Definition: qtexttable.cpp:218
bool isInEditBlock() const
int position() const
Returns the index of the block&#39;s first character within the document.
int leftCursorPosition(int position) const
void setPosition(Position f)
Sets the policy for positioning frames with this frame format.
Definition: qtextformat.h:756
QTextFrame * currentFrame() const
Returns a pointer to the current frame.
QTextBlock previous() const
Returns the text block in the document before this block, or an empty text block if this is the first...
bool setPosition(int newPosition)
Definition: qtextcursor_p.h:78
void selectedTableCells(int *firstRow, int *numRows, int *firstColumn, int *numColumns) const
If the selection spans over table cells, firstRow is populated with the number of the first row in th...
QTextTableCell cellAt(int row, int col) const
Returns the table cell at the given row and column in the table.
Definition: qtexttable.cpp:630
qreal cursorToX(int *cursorPos, Edge edge=Leading) const
Converts the cursor position cursorPos to the corresponding x position inside the line...
void setKeepPositionOnInsert(bool b)
Defines whether the cursor should keep its current position when text gets inserted at the current po...
bool isVisible() const
Returns true if the block is visible; otherwise returns false.
The QTextImageFormat class provides formatting information for images in a QTextDocument.
Definition: qtextformat.h:694
void setBlockCharFormat(const QTextCharFormat &format, QTextDocumentPrivate::FormatChangeMode changeMode)
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
FragmentIterator find(int pos) const
MoveMode
If the anchor() is kept where it is and the position() is moved, the text in between will be selected...
Definition: qtextcursor.h:85
int objectType() const
Returns the text format&#39;s object type.
Definition: qtextformat.h:315
int column() const
Returns the number of the column in the table that contains this cell.
Definition: qtexttable.cpp:201
int objectIndex() const
Returns the object index of this object.
QTextFrame * frameAt(int pos) const
QTextBlock blocksBegin() const
int blockNumber() const
Returns the number of the block the cursor is in, or 0 if the cursor is invalid.
int lastPosition() const
Returns the last document position inside the frame.
static QTextDocumentFragment fromHtml(const QString &html)
Returns a QTextDocumentFragment based on the arbitrary piece of HTML in the given text...
bool hasSelection() const
Returns true if the cursor contains a selection; otherwise returns false.
QTextTable * currentTable() const
Returns a pointer to the current table if the cursor position() is inside a block that is part of a t...
Style
This enum describes the symbols used to decorate list items:
Definition: qtextformat.h:649
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
void setBlockFormat(const QTextBlockFormat &format)
Sets the block format of the current block (or all blocks that are contained in the selection) to for...
QTextFrame * parentFrame() const
Returns the frame&#39;s parent frame.
QTextDocumentPrivate * docHandle() const
So that not all classes have to be friends of each other.
The QTextCursor class offers an API to access and modify QTextDocuments.
Definition: qtextcursor.h:70
void setName(const QString &name)
Sets the name of the image.
Definition: qtextformat.h:718
QTextFormatCollection * formatCollection()
const char * name
void prepend(const T &t)
Inserts value at the beginning of the list.
Definition: qlist.h:541
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
int lineNumber() const
Returns the position of the line in the text engine.
Definition: qtextlayout.h:243
QTextObject * objectForFormat(int formatIndex) const
bool visualNavigation() const
Returns true if the cursor does visual navigation; otherwise returns false.
const char * layout
QTextObject * createObject(const QTextFormat &newFormat, int objectIndex=-1)
bool movePosition(QTextCursor::MoveOperation op, QTextCursor::MoveMode mode=QTextCursor::MoveAnchor)
bool operator<=(const QTextCursor &rhs) const
Returns true if the other cursor is positioned later or at the same position in the document as this ...
Q_CORE_EXPORT void qWarning(const char *,...)
bool isEmpty() const
Returns true if the fragment is empty; otherwise returns false.
The QImage class provides a hardware-independent image representation that allows direct access to th...
Definition: qimage.h:87
The QTextBlock class provides a container for text fragments in a QTextDocument.
Definition: qtextobject.h:199
void mergeBlockCharFormat(const QTextCharFormat &modifier)
Modifies the block char format of the current block (or all blocks that are contained in the selectio...
int row() const
Returns the number of the row in the table that contains this cell.
Definition: qtexttable.cpp:184
void select(SelectionType selection)
Selects text in the document according to the given selection.
void insertFragment(const QTextDocumentFragment &fragment)
Inserts the text fragment at the current position().
int position() const
Returns the absolute position of the cursor within the document.
int length() const
Returns the length of the block in characters.
int positionInBlock() const
Returns the relative position of the cursor within the block.
The QTextTable class represents a table in a QTextDocument.
Definition: qtexttable.h:103
const BlockMap & blockMap() const
void mergeCharFormat(const QTextCharFormat &modifier)
Merges the cursor&#39;s current character format with the properties described by format modifier...
QTextLine lineAt(int i) const
Returns the {i}-th line of text in this text layout.
void removeSelectedText()
If there is a selection, its content is deleted; otherwise does nothing.
int rightCursorPosition(int position) const
void insert(QTextCursor &cursor) const
QTextList * currentList() const
Returns the current list if the cursor position() is inside a block that is part of a list; otherwise...
QTextCharFormat charFormat() const
Returns the QTextCharFormat that describes the block&#39;s character format.
bool isCopyOf(const QTextCursor &other) const
Returns true if this cursor and other are copies of each other, i.e.
QTextBlock block() const
Returns the block that contains the cursor.
void qSwap(T &value1, T &value2)
Definition: qglobal.h:2181
void clearSelection()
Clears the current selection by setting the anchor to the cursor position.
QTextCharFormat blockCharFormat() const
Returns the block character format of the block the cursor is in.
bool atStart() const
Returns true if the cursor is at the start of the document; otherwise returns false.
void insertBlock()
Inserts a new empty block at the cursor position() with the current blockFormat() and charFormat()...
void removeCursor(QTextCursorPrivate *c)
#define Q_ASSERT_X(cond, where, what)
Definition: qglobal.h:1837
int serialNumber() const
Returns a number that identifies the contents of this QImage object.
Definition: qimage.cpp:6267
The QTextLayout class is used to lay out and render text.
Definition: qtextlayout.h:105
void insertBlock(const QTextBlockFormat &format, const QTextCharFormat &charFormat)
bool operator>(const QTextCursor &rhs) const
Returns true if the other cursor is positioned earlier in the document than this cursor; otherwise re...
void joinPreviousEditBlock()
Like beginEditBlock() indicates the start of a block of editing operations that should appear as a si...
int previousCursorPosition(int position, QTextLayout::CursorMode mode) const
void beginEditBlock()
Indicates the start of a block of editing operations on the document that should appear as a single o...
virtual QRectF blockBoundingRect(const QTextBlock &block) const =0
Returns the bounding rectangle of block.
SelectionType
This enum describes the types of selection that can be applied with the select() function.
Definition: qtextcursor.h:144
The QSharedData class is a base class for shared data objects.
Definition: qshareddata.h:56
void merge(const QTextFormat &other)
Merges the other format with this format; where there are conflicts the other format takes precedence...
int nextCursorPosition(int position, QTextLayout::CursorMode mode) const
bool operator<(const QTextCursor &rhs) const
Returns true if the other cursor is positioned later in the document than this cursor; otherwise retu...
int firstPosition() const
Returns the first valid position in the document occupied by this cell.
Definition: qtexttable.cpp:273
static QTextTable * createTable(QTextDocumentPrivate *, int pos, int rows, int cols, const QTextTableFormat &tableFormat)
Definition: qtexttable.cpp:364
QString buffer() const
void mergeCachedResources(const QTextDocumentPrivate *priv)
AdjustResult adjustPosition(int positionOfChange, int charsAddedOrRemoved, QTextUndoCommand::Operation op)
Definition: qtextcursor.cpp:94
quint32 size_array[N]
int rows() const
Returns the number of rows in the table.
bool isBlockFormat() const
Returns true if this text format is a BlockFormat; otherwise returns false.
Definition: qtextformat.h:319
The QTextFrameFormat class provides formatting information for frames in a QTextDocument.
Definition: qtextformat.h:727
void deletePreviousChar()
If there is no selected text, deletes the character before the current cursor position; otherwise del...
The QTextTableCell class represents the properties of a cell in a QTextTable.
Definition: qtexttable.h:59
bool hasComplexSelection() const
Returns true if the cursor contains a selection that is not simply a range from selectionStart() to s...
int size() const
Returns the number of items in the list.
Definition: qlist.h:137
The QTextBlockFormat class provides formatting information for blocks of text in a QTextDocument...
Definition: qtextformat.h:545
bool isNull() const
Returns true if the cursor is null; otherwise returns false.
static const QMetaObjectPrivate * priv(const uint *data)
void addResource(int type, const QUrl &name, const QVariant &resource)
Adds the resource resource to the resource cache, using type and name as identifiers.
if(void) toggleToolbarShown
QFactoryLoader * l
QTextDocumentPrivate * priv
int lastPosition() const
Returns the last valid position in the document occupied by this cell.
Definition: qtexttable.cpp:287
bool isCharFormat() const
Returns true if this text format is a CharFormat; otherwise returns false.
Definition: qtextformat.h:318
Qt::LayoutDirection textDirection() const
Returns the resolved text direction.
void adjustCursor(QTextCursor::MoveOperation m)
bool movePosition(MoveOperation op, MoveMode=MoveAnchor, int n=1)
Moves the cursor by performing the given operation n times, using the specified mode, and returns true if all operations were completed successfully; otherwise returns false.
bool operator==(const QTextCursor &rhs) const
Returns true if the other cursor is at the same position in the document as this cursor; otherwise re...
bool isValid() const
Returns true if this is a valid table cell; otherwise returns false.
Definition: qtexttable.h:77
void setVisualNavigation(bool b)
Sets visual navigation to b.
void setPosition(int pos, MoveMode mode=MoveAnchor)
Moves the cursor to the absolute position in the document specified by pos using a MoveMode specified...
The QTextDocument class holds formatted text that can be viewed and edited using a QTextEdit...
bool isValid() const
Returns true if this text block is valid; otherwise returns false.
Definition: qtextobject.h:208
bool canDelete(int pos) const
int verticalMovementX() const
Returns the visual x position for vertical cursor movements.
bool atBlockEnd() const
Returns true if the cursor is at the end of a block; otherwise returns false.
The QTextTableFormat class provides formatting information for tables in a QTextDocument.
Definition: qtextformat.h:842
bool atSpace(int position) const
The QTextList class provides a decorated list of items in a QTextDocument.
Definition: qtextlist.h:57
Qt::CursorMoveStyle defaultCursorMoveStyle
QTextList * insertList(const QTextListFormat &format)
Inserts a new block at the current position and makes it the first list item of a newly created list ...
void clearProperty(int propertyId)
Clears the value of the property given by propertyId.
QTextCursorPrivate(QTextDocumentPrivate *p)
Definition: qtextcursor.cpp:65
QTextFrame * insertFrame(int start, int end, const QTextFrameFormat &format)
QTextBlock blocksFind(int pos) const
int columnSpan() const
Returns the number of columns this cell spans.
Definition: qtexttable.cpp:228
bool atEnd() const
Returns true if the cursor is at the end of the document; otherwise returns false.
static void setBlockCharFormatHelper(QTextDocumentPrivate *priv, int pos1, int pos2, const QTextCharFormat &format, QTextDocumentPrivate::FormatChangeMode changeMode)
void setCharFormat(int pos, int length, const QTextCharFormat &newFormat, FormatChangeMode mode=SetFormat)
void insertHtml(const QString &html)
Inserts the text html at the current position().
void setObjectIndex(int object)
Sets the format object&#39;s object index.
void setCharFormat(const QTextCharFormat &format, QTextDocumentPrivate::FormatChangeMode changeMode)
void deleteChar()
If there is no selected text, deletes the character at the current cursor position; otherwise deletes...
The QTextObject class is a base class for different kinds of objects that can group parts of a QTextD...
Definition: qtextobject.h:64
static const KeyPair *const end
void setStyle(Style style)
Sets the list format&#39;s style.
Definition: qtextformat.h:682
int xToCursor(qreal x, CursorPosition=CursorBetweenCharacters) const
Converts the x-coordinate x, to the nearest matching cursor position, depending on the cursor positio...
int columnNumber() const
Returns the position of the cursor within its containing line.
int indexForFormat(const QTextFormat &f)
~QTextCursor()
Destroys the QTextCursor.
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
bool operator>=(const QTextCursor &rhs) const
Returns true if the other cursor is positioned earlier or at the same position in the document as thi...
QTextBlockFormat blockFormat() const
Returns the QTextBlockFormat that describes block-specific properties.
void selectedTableCells(int *firstRow, int *numRows, int *firstColumn, int *numColumns) const
const QChar * constData() const
Returns a pointer to the data stored in the QString.
Definition: qstring.h:712
The QTextDocumentFragment class represents a piece of formatted text from a QTextDocument.
int selectionStart() const
Returns the start of the selection or position() if the cursor doesn&#39;t have a selection.
int blockNumber() const
Returns the number of this block, or -1 if the block is invalid.
int textStart() const
Returns the start of the line from the beginning of the string passed to the QTextLayout.
#define text
Definition: qobjectdefs.h:80
int lineCount() const
Returns the number of lines in this text layout.
QTextDocument * document()
void clearCells(QTextTable *table, int startRow, int startCol, int numRows, int numCols, QTextUndoCommand::Operation op)
The QList class is a template class that provides lists.
Definition: qdatastream.h:62
#define QTextEndOfFrame
QTextBlock blocksEnd() const
int firstNode() const
QTextLayout * layout() const
Returns the QTextLayout that is used to lay out and display the block&#39;s contents. ...