OpenCoverage

qtexttable.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/gui/text/qtexttable.cpp
Source codeSwitch to Preprocessed file
LineSourceCount
1/****************************************************************************-
2**-
3** Copyright (C) 2016 The Qt Company Ltd.-
4** Contact: https://www.qt.io/licensing/-
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 The Qt Company. For licensing terms-
14** and conditions see https://www.qt.io/terms-conditions. For further-
15** information use the contact form at https://www.qt.io/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 3 as published by the Free Software-
20** Foundation and appearing in the file LICENSE.LGPL3 included in the-
21** packaging of this file. Please review the following information to-
22** ensure the GNU Lesser General Public License version 3 requirements-
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.-
24**-
25** GNU General Public License Usage-
26** Alternatively, this file may be used under the terms of the GNU-
27** General Public License version 2.0 or (at your option) the GNU General-
28** Public license version 3 or any later version approved by the KDE Free-
29** Qt Foundation. The licenses are as published by the Free Software-
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3-
31** included in the packaging of this file. Please review the following-
32** information to ensure the GNU General Public License requirements will-
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and-
34** https://www.gnu.org/licenses/gpl-3.0.html.-
35**-
36** $QT_END_LICENSE$-
37**-
38****************************************************************************/-
39-
40#include "qtexttable.h"-
41#include "qtextcursor.h"-
42#include "qtextformat.h"-
43#include <qdebug.h>-
44#include "qtextcursor_p.h"-
45#include "qtexttable_p.h"-
46#include "qvarlengtharray.h"-
47-
48#include <algorithm>-
49#include <stdlib.h>-
50-
51QT_BEGIN_NAMESPACE-
52-
53/*!-
54 \class QTextTableCell-
55 \reentrant-
56-
57 \brief The QTextTableCell class represents the properties of a-
58 cell in a QTextTable.-
59 \inmodule QtGui-
60-
61 \ingroup richtext-processing-
62-
63 Table cells are pieces of document structure that belong to a table.-
64 The table orders cells into particular rows and columns; cells can-
65 also span multiple columns and rows.-
66-
67 Cells are usually created when a table is inserted into a document with-
68 QTextCursor::insertTable(), but they are also created and destroyed when-
69 a table is resized.-
70-
71 Cells contain information about their location in a table; you can-
72 obtain the row() and column() numbers of a cell, and its rowSpan()-
73 and columnSpan().-
74-
75 The format() of a cell describes the default character format of its-
76 contents. The firstCursorPosition() and lastCursorPosition() functions-
77 are used to obtain the extent of the cell in the document.-
78-
79 \sa QTextTable, QTextTableFormat-
80*/-
81-
82/*!-
83 \fn QTextTableCell::QTextTableCell()-
84-
85 Constructs an invalid table cell.-
86-
87 \sa isValid()-
88*/-
89-
90/*!-
91 \fn QTextTableCell::QTextTableCell(const QTextTableCell &other)-
92-
93 Copy constructor. Creates a new QTextTableCell object based on the-
94 \a other cell.-
95*/-
96-
97/*!-
98 \fn QTextTableCell& QTextTableCell::operator=(const QTextTableCell &other)-
99-
100 Assigns the \a other table cell to this table cell.-
101*/-
102-
103/*!-
104 \since 4.2-
105-
106 Sets the cell's character format to \a format. This can for example be used to change-
107 the background color of the entire cell:-
108-
109 QTextTableCell cell = table->cellAt(2, 3);-
110 QTextCharFormat format = cell.format();-
111 format.setBackground(Qt::blue);-
112 cell.setFormat(format);-
113-
114 Note that the cell's row or column span cannot be changed through this function. You have-
115 to use QTextTable::mergeCells and QTextTable::splitCell instead.-
116-
117 \sa format()-
118*/-
119void QTextTableCell::setFormat(const QTextCharFormat &format)-
120{-
121 QTextCharFormat fmt = format;-
122 fmt.clearProperty(QTextFormat::ObjectIndex);-
123 fmt.setObjectType(QTextFormat::TableCellObject);-
124 QTextDocumentPrivate *p = table->docHandle();-
125 QTextDocumentPrivate::FragmentIterator frag(&p->fragmentMap(), fragment);-
126-
127 QTextFormatCollection *c = p->formatCollection();-
128 QTextCharFormat oldFormat = c->charFormat(frag->format);-
129 fmt.setTableCellRowSpan(oldFormat.tableCellRowSpan());-
130 fmt.setTableCellColumnSpan(oldFormat.tableCellColumnSpan());-
131-
132 p->setCharFormat(frag.position(), 1, fmt, QTextDocumentPrivate::SetFormatAndPreserveObjectIndices);-
133}
never executed: end of block
0
134-
135/*!-
136 Returns the cell's character format.-
137*/-
138QTextCharFormat QTextTableCell::format() const-
139{-
140 QTextDocumentPrivate *p = table->docHandle();-
141 QTextFormatCollection *c = p->formatCollection();-
142-
143 QTextCharFormat fmt = c->charFormat(tableCellFormatIndex());-
144 fmt.setObjectType(QTextFormat::TableCellObject);-
145 return fmt;
never executed: return fmt;
0
146}-
147-
148/*!-
149 \since 4.5-
150-
151 Returns the index of the tableCell's format in the document's internal list of formats.-
152-
153 \sa QTextDocument::allFormats()-
154*/-
155int QTextTableCell::tableCellFormatIndex() const-
156{-
157 QTextDocumentPrivate *p = table->docHandle();-
158 return QTextDocumentPrivate::FragmentIterator(&p->fragmentMap(), fragment)->format;
never executed: return QTextDocumentPrivate::FragmentIterator(&p->fragmentMap(), fragment)->format;
0
159}-
160-
161/*!-
162 Returns the number of the row in the table that contains this cell.-
163-
164 \sa column()-
165*/-
166int QTextTableCell::row() const-
167{-
168 const QTextTablePrivate *tp = table->d_func();-
169 if (tp->dirty)
tp->dirtyDescription
TRUEnever evaluated
FALSEnever evaluated
0
170 tp->update();
never executed: tp->update();
0
171-
172 int idx = tp->findCellIndex(fragment);-
173 if (idx == -1)
idx == -1Description
TRUEnever evaluated
FALSEnever evaluated
0
174 return idx;
never executed: return idx;
0
175 return tp->cellIndices.at(idx) / tp->nCols;
never executed: return tp->cellIndices.at(idx) / tp->nCols;
0
176}-
177-
178/*!-
179 Returns the number of the column in the table that contains this cell.-
180-
181 \sa row()-
182*/-
183int QTextTableCell::column() const-
184{-
185 const QTextTablePrivate *tp = table->d_func();-
186 if (tp->dirty)
tp->dirtyDescription
TRUEnever evaluated
FALSEnever evaluated
0
187 tp->update();
never executed: tp->update();
0
188-
189 int idx = tp->findCellIndex(fragment);-
190 if (idx == -1)
idx == -1Description
TRUEnever evaluated
FALSEnever evaluated
0
191 return idx;
never executed: return idx;
0
192 return tp->cellIndices.at(idx) % tp->nCols;
never executed: return tp->cellIndices.at(idx) % tp->nCols;
0
193}-
194-
195/*!-
196 Returns the number of rows this cell spans. The default is 1.-
197-
198 \sa columnSpan()-
199*/-
200int QTextTableCell::rowSpan() const-
201{-
202 return format().tableCellRowSpan();
never executed: return format().tableCellRowSpan();
0
203}-
204-
205/*!-
206 Returns the number of columns this cell spans. The default is 1.-
207-
208 \sa rowSpan()-
209*/-
210int QTextTableCell::columnSpan() const-
211{-
212 return format().tableCellColumnSpan();
never executed: return format().tableCellColumnSpan();
0
213}-
214-
215/*!-
216 \fn bool QTextTableCell::isValid() const-
217-
218 Returns \c true if this is a valid table cell; otherwise returns-
219 false.-
220*/-
221-
222-
223/*!-
224 Returns the first valid cursor position in this cell.-
225-
226 \sa lastCursorPosition()-
227*/-
228QTextCursor QTextTableCell::firstCursorPosition() const-
229{-
230 return QTextCursorPrivate::fromPosition(table->d_func()->pieceTable, firstPosition());
never executed: return QTextCursorPrivate::fromPosition(table->d_func()->pieceTable, firstPosition());
0
231}-
232-
233/*!-
234 Returns the last valid cursor position in this cell.-
235-
236 \sa firstCursorPosition()-
237*/-
238QTextCursor QTextTableCell::lastCursorPosition() const-
239{-
240 return QTextCursorPrivate::fromPosition(table->d_func()->pieceTable, lastPosition());
never executed: return QTextCursorPrivate::fromPosition(table->d_func()->pieceTable, lastPosition());
0
241}-
242-
243-
244/*!-
245 \internal-
246-
247 Returns the first valid position in the document occupied by this cell.-
248*/-
249int QTextTableCell::firstPosition() const-
250{-
251 QTextDocumentPrivate *p = table->docHandle();-
252 return p->fragmentMap().position(fragment) + 1;
never executed: return p->fragmentMap().position(fragment) + 1;
0
253}-
254-
255/*!-
256 \internal-
257-
258 Returns the last valid position in the document occupied by this cell.-
259*/-
260int QTextTableCell::lastPosition() const-
261{-
262 QTextDocumentPrivate *p = table->docHandle();-
263 const QTextTablePrivate *td = table->d_func();-
264 int index = table->d_func()->findCellIndex(fragment);-
265 int f;-
266 if (index != -1)
index != -1Description
TRUEnever evaluated
FALSEnever evaluated
0
267 f = td->cells.value(index + 1, td->fragment_end);
never executed: f = td->cells.value(index + 1, td->fragment_end);
0
268 else-
269 f = td->fragment_end;
never executed: f = td->fragment_end;
0
270 return p->fragmentMap().position(f);
never executed: return p->fragmentMap().position(f);
0
271}-
272-
273-
274/*!-
275 Returns a frame iterator pointing to the beginning of the table's cell.-
276-
277 \sa end()-
278*/-
279QTextFrame::iterator QTextTableCell::begin() const-
280{-
281 QTextDocumentPrivate *p = table->docHandle();-
282 int b = p->blockMap().findNode(firstPosition());-
283 int e = p->blockMap().findNode(lastPosition()+1);-
284 return QTextFrame::iterator(const_cast<QTextTable *>(table), b, b, e);
never executed: return QTextFrame::iterator(const_cast<QTextTable *>(table), b, b, e);
0
285}-
286-
287/*!-
288 Returns a frame iterator pointing to the end of the table's cell.-
289-
290 \sa begin()-
291*/-
292QTextFrame::iterator QTextTableCell::end() const-
293{-
294 QTextDocumentPrivate *p = table->docHandle();-
295 int b = p->blockMap().findNode(firstPosition());-
296 int e = p->blockMap().findNode(lastPosition()+1);-
297 return QTextFrame::iterator(const_cast<QTextTable *>(table), e, b, e);
never executed: return QTextFrame::iterator(const_cast<QTextTable *>(table), e, b, e);
0
298}-
299-
300-
301/*!-
302 \fn QTextCursor QTextTableCell::operator==(const QTextTableCell &other) const-
303-
304 Returns \c true if this cell object and the \a other cell object-
305 describe the same cell; otherwise returns \c false.-
306*/-
307-
308/*!-
309 \fn QTextCursor QTextTableCell::operator!=(const QTextTableCell &other) const-
310-
311 Returns \c true if this cell object and the \a other cell object-
312 describe different cells; otherwise returns \c false.-
313*/-
314-
315/*!-
316 \fn QTextTableCell::~QTextTableCell()-
317-
318 Destroys the table cell.-
319*/-
320-
321QTextTablePrivate::~QTextTablePrivate()-
322{-
323 if (grid)
gridDescription
TRUEnever evaluated
FALSEnever evaluated
0
324 free(grid);
never executed: free(grid);
0
325}
never executed: end of block
0
326-
327-
328QTextTable *QTextTablePrivate::createTable(QTextDocumentPrivate *pieceTable, int pos, int rows, int cols, const QTextTableFormat &tableFormat)-
329{-
330 QTextTableFormat fmt = tableFormat;-
331 fmt.setColumns(cols);-
332 QTextTable *table = qobject_cast<QTextTable *>(pieceTable->createObject(fmt));-
333 Q_ASSERT(table);-
334-
335 pieceTable->beginEditBlock();-
336-
337// qDebug("---> createTable: rows=%d, cols=%d at %d", rows, cols, pos);-
338 // add block after table-
339 QTextCharFormat charFmt;-
340 charFmt.setObjectIndex(table->objectIndex());-
341 charFmt.setObjectType(QTextFormat::TableCellObject);-
342-
343-
344 int charIdx = pieceTable->formatCollection()->indexForFormat(charFmt);-
345 int cellIdx = pieceTable->formatCollection()->indexForFormat(QTextBlockFormat());-
346-
347 QTextTablePrivate *d = table->d_func();-
348 d->blockFragmentUpdates = true;-
349-
350 d->fragment_start = pieceTable->insertBlock(QTextBeginningOfFrame, pos, cellIdx, charIdx);-
351 d->cells.append(d->fragment_start);-
352 ++pos;-
353-
354 for (int i = 1; i < rows*cols; ++i) {
i < rows*colsDescription
TRUEnever evaluated
FALSEnever evaluated
0
355 d->cells.append(pieceTable->insertBlock(QTextBeginningOfFrame, pos, cellIdx, charIdx));-
356// qDebug(" addCell at %d", pos);-
357 ++pos;-
358 }
never executed: end of block
0
359-
360 d->fragment_end = pieceTable->insertBlock(QTextEndOfFrame, pos, cellIdx, charIdx);-
361// qDebug(" addEOR at %d", pos);-
362 ++pos;-
363-
364 d->blockFragmentUpdates = false;-
365 d->dirty = true;-
366-
367 pieceTable->endEditBlock();-
368-
369 return table;
never executed: return table;
0
370}-
371-
372struct QFragmentFindHelper-
373{-
374 inline QFragmentFindHelper(int _pos, const QTextDocumentPrivate::FragmentMap &map)-
375 : pos(_pos), fragmentMap(map) {}
never executed: end of block
0
376 uint pos;-
377 const QTextDocumentPrivate::FragmentMap &fragmentMap;-
378};-
379-
380static inline bool operator<(int fragment, const QFragmentFindHelper &helper)-
381{-
382 return helper.fragmentMap.position(fragment) < helper.pos;
never executed: return helper.fragmentMap.position(fragment) < helper.pos;
0
383}-
384-
385static inline bool operator<(const QFragmentFindHelper &helper, int fragment)-
386{-
387 return helper.pos < helper.fragmentMap.position(fragment);
never executed: return helper.pos < helper.fragmentMap.position(fragment);
0
388}-
389-
390int QTextTablePrivate::findCellIndex(int fragment) const-
391{-
392 QFragmentFindHelper helper(pieceTable->fragmentMap().position(fragment),-
393 pieceTable->fragmentMap());-
394 const auto it = std::lower_bound(cells.constBegin(), cells.constEnd(), helper);-
395 if ((it == cells.constEnd()) || (helper < *it))
(it == cells.constEnd())Description
TRUEnever evaluated
FALSEnever evaluated
(helper < *it)Description
TRUEnever evaluated
FALSEnever evaluated
0
396 return -1;
never executed: return -1;
0
397 return it - cells.constBegin();
never executed: return it - cells.constBegin();
0
398}-
399-
400void QTextTablePrivate::fragmentAdded(QChar type, uint fragment)-
401{-
402 dirty = true;-
403 if (blockFragmentUpdates)
blockFragmentUpdatesDescription
TRUEnever evaluated
FALSEnever evaluated
0
404 return;
never executed: return;
0
405 if (type == QTextBeginningOfFrame) {
type == QChar(0xfdd0)Description
TRUEnever evaluated
FALSEnever evaluated
0
406 Q_ASSERT(cells.indexOf(fragment) == -1);-
407 const uint pos = pieceTable->fragmentMap().position(fragment);-
408 QFragmentFindHelper helper(pos, pieceTable->fragmentMap());-
409 auto it = std::lower_bound(cells.begin(), cells.end(), helper);-
410 cells.insert(it, fragment);-
411 if (!fragment_start || pos < pieceTable->fragmentMap().position(fragment_start))
!fragment_startDescription
TRUEnever evaluated
FALSEnever evaluated
pos < pieceTab...ragment_start)Description
TRUEnever evaluated
FALSEnever evaluated
0
412 fragment_start = fragment;
never executed: fragment_start = fragment;
0
413 return;
never executed: return;
0
414 }-
415 QTextFramePrivate::fragmentAdded(type, fragment);-
416}
never executed: end of block
0
417-
418void QTextTablePrivate::fragmentRemoved(QChar type, uint fragment)-
419{-
420 dirty = true;-
421 if (blockFragmentUpdates)
blockFragmentUpdatesDescription
TRUEnever evaluated
FALSEnever evaluated
0
422 return;
never executed: return;
0
423 if (type == QTextBeginningOfFrame) {
type == QChar(0xfdd0)Description
TRUEnever evaluated
FALSEnever evaluated
0
424 Q_ASSERT(cells.indexOf(fragment) != -1);-
425 cells.removeAll(fragment);-
426 if (fragment_start == fragment && cells.size()) {
fragment_start == fragmentDescription
TRUEnever evaluated
FALSEnever evaluated
cells.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
427 fragment_start = cells.at(0);-
428 }
never executed: end of block
0
429 if (fragment_start != fragment)
fragment_start != fragmentDescription
TRUEnever evaluated
FALSEnever evaluated
0
430 return;
never executed: return;
0
431 }
never executed: end of block
0
432 QTextFramePrivate::fragmentRemoved(type, fragment);-
433}
never executed: end of block
0
434-
435/*!-
436 /fn void QTextTablePrivate::update() const-
437-
438 This function is usually called when the table is "dirty".-
439 It seems to update all kind of table information.-
440-
441*/-
442void QTextTablePrivate::update() const-
443{-
444 Q_Q(const QTextTable);-
445 nCols = q->format().columns();-
446 nRows = (cells.size() + nCols-1)/nCols;-
447// qDebug(">>>> QTextTablePrivate::update, nRows=%d, nCols=%d", nRows, nCols);-
448-
449 grid = q_check_ptr((int *)realloc(grid, nRows*nCols*sizeof(int)));-
450 memset(grid, 0, nRows*nCols*sizeof(int));-
451-
452 QTextDocumentPrivate *p = pieceTable;-
453 QTextFormatCollection *c = p->formatCollection();-
454-
455 cellIndices.resize(cells.size());-
456-
457 int cell = 0;-
458 for (int i = 0; i < cells.size(); ++i) {
i < cells.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
459 int fragment = cells.at(i);-
460 QTextCharFormat fmt = c->charFormat(QTextDocumentPrivate::FragmentIterator(&p->fragmentMap(), fragment)->format);-
461 int rowspan = fmt.tableCellRowSpan();-
462 int colspan = fmt.tableCellColumnSpan();-
463-
464 // skip taken cells-
465 while (cell < nRows*nCols && grid[cell])
cell < nRows*nColsDescription
TRUEnever evaluated
FALSEnever evaluated
grid[cell]Description
TRUEnever evaluated
FALSEnever evaluated
0
466 ++cell;
never executed: ++cell;
0
467-
468 int r = cell/nCols;-
469 int c = cell%nCols;-
470 cellIndices[i] = cell;-
471-
472 if (r + rowspan > nRows) {
r + rowspan > nRowsDescription
TRUEnever evaluated
FALSEnever evaluated
0
473 grid = q_check_ptr((int *)realloc(grid, sizeof(int)*(r + rowspan)*nCols));-
474 memset(grid + (nRows*nCols), 0, sizeof(int)*(r+rowspan-nRows)*nCols);-
475 nRows = r + rowspan;-
476 }
never executed: end of block
0
477-
478 Q_ASSERT(c + colspan <= nCols);-
479 for (int ii = 0; ii < rowspan; ++ii) {
ii < rowspanDescription
TRUEnever evaluated
FALSEnever evaluated
0
480 for (int jj = 0; jj < colspan; ++jj) {
jj < colspanDescription
TRUEnever evaluated
FALSEnever evaluated
0
481 Q_ASSERT(grid[(r+ii)*nCols + c+jj] == 0);-
482 grid[(r+ii)*nCols + c+jj] = fragment;-
483// qDebug(" setting cell %d span=%d/%d at %d/%d", fragment, rowspan, colspan, r+ii, c+jj);-
484 }
never executed: end of block
0
485 }
never executed: end of block
0
486 }
never executed: end of block
0
487// qDebug("<<<< end: nRows=%d, nCols=%d", nRows, nCols);-
488-
489 dirty = false;-
490}
never executed: end of block
0
491-
492-
493-
494-
495-
496/*!-
497 \class QTextTable-
498 \reentrant-
499-
500 \brief The QTextTable class represents a table in a QTextDocument.-
501 \inmodule QtGui-
502-
503 \ingroup richtext-processing-
504-
505 A table is a group of cells ordered into rows and columns. Each table-
506 contains at least one row and one column. Each cell contains a block, and-
507 is surrounded by a frame.-
508-
509 Tables are usually created and inserted into a document with the-
510 QTextCursor::insertTable() function.-
511 For example, we can insert a table with three rows and two columns at the-
512 current cursor position in an editor using the following lines of code:-
513-
514 \snippet textdocument-tables/mainwindow.cpp 1-
515 \codeline-
516 \snippet textdocument-tables/mainwindow.cpp 3-
517-
518 The table format is either defined when the table is created or changed-
519 later with setFormat().-
520-
521 The table currently being edited by the cursor is found with-
522 QTextCursor::currentTable(). This allows its format or dimensions to be-
523 changed after it has been inserted into a document.-
524-
525 A table's size can be changed with resize(), or by using-
526 insertRows(), insertColumns(), removeRows(), or removeColumns().-
527 Use cellAt() to retrieve table cells.-
528-
529 The starting and ending positions of table rows can be found by moving-
530 a cursor within a table, and using the rowStart() and rowEnd() functions-
531 to obtain cursors at the start and end of each row.-
532-
533 Rows and columns within a QTextTable can be merged and split using-
534 the mergeCells() and splitCell() functions. However, only cells that span multiple-
535 rows or columns can be split. (Merging or splitting does not increase or decrease-
536 the number of rows and columns.)-
537-
538 Note that if you have merged multiple columns and rows into one cell, you will not-
539 be able to split the merged cell into new cells spanning over more than one row-
540 or column. To be able to split cells spanning over several rows and columns you-
541 need to do this over several iterations.-
542-
543 \table 80%-
544 \row-
545 \li \inlineimage texttable-split.png Original Table-
546 \li Suppose we have a 2x3 table of names and addresses. To merge both-
547 columns in the first row we invoke mergeCells() with \a row = 0,-
548 \a column = 0, \a numRows = 1 and \a numColumns = 2.-
549 \snippet textdocument-texttable/main.cpp 0-
550-
551 \row-
552 \li \inlineimage texttable-merge.png-
553 \li This gives us the following table. To split the first row of the table-
554 back into two cells, we invoke the splitCell() function with \a numRows-
555 and \a numCols = 1.-
556 \snippet textdocument-texttable/main.cpp 1-
557-
558 \row-
559 \li \inlineimage texttable-split.png Split Table-
560 \li This results in the original table.-
561 \endtable-
562-
563 \sa QTextTableFormat-
564*/-
565-
566/*! \internal-
567 */-
568QTextTable::QTextTable(QTextDocument *doc)-
569 : QTextFrame(*new QTextTablePrivate(doc), doc)-
570{-
571}
never executed: end of block
0
572-
573/*! \internal-
574-
575Destroys the table.-
576 */-
577QTextTable::~QTextTable()-
578{-
579}-
580-
581-
582/*!-
583 \fn QTextTableCell QTextTable::cellAt(int row, int column) const-
584-
585 Returns the table cell at the given \a row and \a column in the table.-
586-
587 \sa columns(), rows()-
588*/-
589QTextTableCell QTextTable::cellAt(int row, int col) const-
590{-
591 Q_D(const QTextTable);-
592 if (d->dirty)
d->dirtyDescription
TRUEnever evaluated
FALSEnever evaluated
0
593 d->update();
never executed: d->update();
0
594-
595 if (row < 0 || row >= d->nRows || col < 0 || col >= d->nCols)
row < 0Description
TRUEnever evaluated
FALSEnever evaluated
row >= d->nRowsDescription
TRUEnever evaluated
FALSEnever evaluated
col < 0Description
TRUEnever evaluated
FALSEnever evaluated
col >= d->nColsDescription
TRUEnever evaluated
FALSEnever evaluated
0
596 return QTextTableCell();
never executed: return QTextTableCell();
0
597-
598 return QTextTableCell(this, d->grid[row*d->nCols + col]);
never executed: return QTextTableCell(this, d->grid[row*d->nCols + col]);
0
599}-
600-
601/*!-
602 \overload-
603-
604 Returns the table cell that contains the character at the given \a position-
605 in the document.-
606*/-
607QTextTableCell QTextTable::cellAt(int position) const-
608{-
609 Q_D(const QTextTable);-
610 if (d->dirty)
d->dirtyDescription
TRUEnever evaluated
FALSEnever evaluated
0
611 d->update();
never executed: d->update();
0
612-
613 uint pos = (uint)position;-
614 const QTextDocumentPrivate::FragmentMap &map = d->pieceTable->fragmentMap();-
615 if (position < 0 || map.position(d->fragment_start) >= pos || map.position(d->fragment_end) < pos)
position < 0Description
TRUEnever evaluated
FALSEnever evaluated
map.position(d..._start) >= posDescription
TRUEnever evaluated
FALSEnever evaluated
map.position(d...ent_end) < posDescription
TRUEnever evaluated
FALSEnever evaluated
0
616 return QTextTableCell();
never executed: return QTextTableCell();
0
617-
618 QFragmentFindHelper helper(position, map);-
619 auto it = std::lower_bound(d->cells.begin(), d->cells.end(), helper);-
620 if (it != d->cells.begin())
it != d->cells.begin()Description
TRUEnever evaluated
FALSEnever evaluated
0
621 --it;
never executed: --it;
0
622-
623 return QTextTableCell(this, *it);
never executed: return QTextTableCell(this, *it);
0
624}-
625-
626/*!-
627 \fn QTextTableCell QTextTable::cellAt(const QTextCursor &cursor) const-
628-
629 \overload-
630-
631 Returns the table cell containing the given \a cursor.-
632*/-
633QTextTableCell QTextTable::cellAt(const QTextCursor &c) const-
634{-
635 return cellAt(c.position());
never executed: return cellAt(c.position());
0
636}-
637-
638/*!-
639 \fn void QTextTable::resize(int rows, int columns)-
640-
641 Resizes the table to contain the required number of \a rows and \a columns.-
642-
643 \sa insertRows(), insertColumns(), removeRows(), removeColumns()-
644*/-
645void QTextTable::resize(int rows, int cols)-
646{-
647 Q_D(QTextTable);-
648 if (d->dirty)
d->dirtyDescription
TRUEnever evaluated
FALSEnever evaluated
0
649 d->update();
never executed: d->update();
0
650-
651 int nRows = this->rows();-
652 int nCols = this->columns();-
653-
654 if (rows == nRows && cols == nCols)
rows == nRowsDescription
TRUEnever evaluated
FALSEnever evaluated
cols == nColsDescription
TRUEnever evaluated
FALSEnever evaluated
0
655 return;
never executed: return;
0
656-
657 d->pieceTable->beginEditBlock();-
658-
659 if (nCols < cols)
nCols < colsDescription
TRUEnever evaluated
FALSEnever evaluated
0
660 insertColumns(nCols, cols - nCols);
never executed: insertColumns(nCols, cols - nCols);
0
661 else if (nCols > cols)
nCols > colsDescription
TRUEnever evaluated
FALSEnever evaluated
0
662 removeColumns(cols, nCols - cols);
never executed: removeColumns(cols, nCols - cols);
0
663-
664 if (nRows < rows)
nRows < rowsDescription
TRUEnever evaluated
FALSEnever evaluated
0
665 insertRows(nRows, rows-nRows);
never executed: insertRows(nRows, rows-nRows);
0
666 else if (nRows > rows)
nRows > rowsDescription
TRUEnever evaluated
FALSEnever evaluated
0
667 removeRows(rows, nRows-rows);
never executed: removeRows(rows, nRows-rows);
0
668-
669 d->pieceTable->endEditBlock();-
670}
never executed: end of block
0
671-
672/*!-
673 \fn void QTextTable::insertRows(int index, int rows)-
674-
675 Inserts a number of \a rows before the row with the specified \a index.-
676-
677 \sa resize(), insertColumns(), removeRows(), removeColumns(), appendRows(), appendColumns()-
678*/-
679void QTextTable::insertRows(int pos, int num)-
680{-
681 Q_D(QTextTable);-
682 if (num <= 0)
num <= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
683 return;
never executed: return;
0
684-
685 if (d->dirty)
d->dirtyDescription
TRUEnever evaluated
FALSEnever evaluated
0
686 d->update();
never executed: d->update();
0
687-
688 if (pos > d->nRows || pos < 0)
pos > d->nRowsDescription
TRUEnever evaluated
FALSEnever evaluated
pos < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
689 pos = d->nRows;
never executed: pos = d->nRows;
0
690-
691// qDebug() << "-------- insertRows" << pos << num;-
692 QTextDocumentPrivate *p = d->pieceTable;-
693 QTextFormatCollection *c = p->formatCollection();-
694 p->beginEditBlock();-
695-
696 int extended = 0;-
697 int insert_before = 0;-
698 if (pos > 0 && pos < d->nRows) {
pos > 0Description
TRUEnever evaluated
FALSEnever evaluated
pos < d->nRowsDescription
TRUEnever evaluated
FALSEnever evaluated
0
699 for (int i = 0; i < d->nCols; ++i) {
i < d->nColsDescription
TRUEnever evaluated
FALSEnever evaluated
0
700 int cell = d->grid[pos*d->nCols + i];-
701 if (cell == d->grid[(pos-1)*d->nCols+i]) {
cell == d->gri...1)*d->nCols+i]Description
TRUEnever evaluated
FALSEnever evaluated
0
702 // cell spans the insertion place, extend it-
703 QTextDocumentPrivate::FragmentIterator it(&p->fragmentMap(), cell);-
704 QTextCharFormat fmt = c->charFormat(it->format);-
705 fmt.setTableCellRowSpan(fmt.tableCellRowSpan() + num);-
706 p->setCharFormat(it.position(), 1, fmt);-
707 extended++;-
708 } else if (!insert_before) {
never executed: end of block
!insert_beforeDescription
TRUEnever evaluated
FALSEnever evaluated
0
709 insert_before = cell;-
710 }
never executed: end of block
0
711 }
never executed: end of block
0
712 } else {
never executed: end of block
0
713 insert_before = (pos == 0 ? d->grid[0] : d->fragment_end);
pos == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
714 }
never executed: end of block
0
715 if (extended < d->nCols) {
extended < d->nColsDescription
TRUEnever evaluated
FALSEnever evaluated
0
716 Q_ASSERT(insert_before);-
717 QTextDocumentPrivate::FragmentIterator it(&p->fragmentMap(), insert_before);-
718 QTextCharFormat fmt = c->charFormat(it->format);-
719 fmt.setTableCellRowSpan(1);-
720 fmt.setTableCellColumnSpan(1);-
721 Q_ASSERT(fmt.objectIndex() == objectIndex());-
722 int pos = it.position();-
723 int cfmt = p->formatCollection()->indexForFormat(fmt);-
724 int bfmt = p->formatCollection()->indexForFormat(QTextBlockFormat());-
725// qDebug("inserting %d cells, nCols=%d extended=%d", num*(d->nCols-extended), d->nCols, extended);-
726 for (int i = 0; i < num*(d->nCols-extended); ++i)
i < num*(d->nCols-extended)Description
TRUEnever evaluated
FALSEnever evaluated
0
727 p->insertBlock(QTextBeginningOfFrame, pos, bfmt, cfmt, QTextUndoCommand::MoveCursor);
never executed: p->insertBlock(QChar(0xfdd0), pos, bfmt, cfmt, QTextUndoCommand::MoveCursor);
0
728 }
never executed: end of block
0
729-
730// qDebug() << "-------- end insertRows" << pos << num;-
731 p->endEditBlock();-
732}
never executed: end of block
0
733-
734/*!-
735 \fn void QTextTable::insertColumns(int index, int columns)-
736-
737 Inserts a number of \a columns before the column with the specified \a index.-
738-
739 \sa insertRows(), resize(), removeRows(), removeColumns(), appendRows(), appendColumns()-
740*/-
741void QTextTable::insertColumns(int pos, int num)-
742{-
743 Q_D(QTextTable);-
744 if (num <= 0)
num <= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
745 return;
never executed: return;
0
746-
747 if (d->dirty)
d->dirtyDescription
TRUEnever evaluated
FALSEnever evaluated
0
748 d->update();
never executed: d->update();
0
749-
750 if (pos > d->nCols || pos < 0)
pos > d->nColsDescription
TRUEnever evaluated
FALSEnever evaluated
pos < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
751 pos = d->nCols;
never executed: pos = d->nCols;
0
752-
753// qDebug() << "-------- insertCols" << pos << num;-
754 QTextDocumentPrivate *p = d->pieceTable;-
755 QTextFormatCollection *c = p->formatCollection();-
756 p->beginEditBlock();-
757-
758 QVector<int> extendedSpans;-
759 for (int i = 0; i < d->nRows; ++i) {
i < d->nRowsDescription
TRUEnever evaluated
FALSEnever evaluated
0
760 int cell;-
761 if (i == d->nRows - 1 && pos == d->nCols) {
i == d->nRows - 1Description
TRUEnever evaluated
FALSEnever evaluated
pos == d->nColsDescription
TRUEnever evaluated
FALSEnever evaluated
0
762 cell = d->fragment_end;-
763 } else {
never executed: end of block
0
764 int logicalGridIndexBeforePosition = pos > 0
pos > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
765 ? d->findCellIndex(d->grid[i*d->nCols + pos - 1])-
766 : -1;-
767-
768 // Search for the logical insertion point by skipping past cells which are not the first-
769 // cell in a rowspan. This means any cell for which the logical grid index is-
770 // less than the logical cell index of the cell before the insertion.-
771 int logicalGridIndex;-
772 int gridArrayOffset = i*d->nCols + pos;-
773 do {-
774 cell = d->grid[gridArrayOffset];-
775 logicalGridIndex = d->findCellIndex(cell);-
776 gridArrayOffset++;-
777 } while (logicalGridIndex < logicalGridIndexBeforePosition
never executed: end of block
logicalGridInd...BeforePositionDescription
TRUEnever evaluated
FALSEnever evaluated
0
778 && gridArrayOffset < d->nRows*d->nCols);
gridArrayOffse...nRows*d->nColsDescription
TRUEnever evaluated
FALSEnever evaluated
0
779-
780 if (logicalGridIndex < logicalGridIndexBeforePosition
logicalGridInd...BeforePositionDescription
TRUEnever evaluated
FALSEnever evaluated
0
781 && gridArrayOffset == d->nRows*d->nCols)
gridArrayOffse...nRows*d->nColsDescription
TRUEnever evaluated
FALSEnever evaluated
0
782 cell = d->fragment_end;
never executed: cell = d->fragment_end;
0
783 }
never executed: end of block
0
784-
785 if (pos > 0 && pos < d->nCols && cell == d->grid[i*d->nCols + pos - 1]) {
pos > 0Description
TRUEnever evaluated
FALSEnever evaluated
pos < d->nColsDescription
TRUEnever evaluated
FALSEnever evaluated
cell == d->gri...ols + pos - 1]Description
TRUEnever evaluated
FALSEnever evaluated
0
786 // cell spans the insertion place, extend it-
787 if (!extendedSpans.contains(cell)) {
!extendedSpans.contains(cell)Description
TRUEnever evaluated
FALSEnever evaluated
0
788 QTextDocumentPrivate::FragmentIterator it(&p->fragmentMap(), cell);-
789 QTextCharFormat fmt = c->charFormat(it->format);-
790 fmt.setTableCellColumnSpan(fmt.tableCellColumnSpan() + num);-
791 p->setCharFormat(it.position(), 1, fmt);-
792 d->dirty = true;-
793 extendedSpans << cell;-
794 }
never executed: end of block
0
795 } else {
never executed: end of block
0
796 /* If the next cell is spanned from the row above, we need to find the right position-
797 to insert to */-
798 if (i > 0 && pos < d->nCols && cell == d->grid[(i-1) * d->nCols + pos]) {
i > 0Description
TRUEnever evaluated
FALSEnever evaluated
pos < d->nColsDescription
TRUEnever evaluated
FALSEnever evaluated
cell == d->gri...->nCols + pos]Description
TRUEnever evaluated
FALSEnever evaluated
0
799 int gridIndex = i*d->nCols + pos;-
800 const int gridEnd = d->nRows * d->nCols - 1;-
801 while (gridIndex < gridEnd && cell == d->grid[gridIndex]) {
gridIndex < gridEndDescription
TRUEnever evaluated
FALSEnever evaluated
cell == d->grid[gridIndex]Description
TRUEnever evaluated
FALSEnever evaluated
0
802 ++gridIndex;-
803 }
never executed: end of block
0
804 if (gridIndex == gridEnd)
gridIndex == gridEndDescription
TRUEnever evaluated
FALSEnever evaluated
0
805 cell = d->fragment_end;
never executed: cell = d->fragment_end;
0
806 else-
807 cell = d->grid[gridIndex];
never executed: cell = d->grid[gridIndex];
0
808 }-
809 QTextDocumentPrivate::FragmentIterator it(&p->fragmentMap(), cell);-
810 QTextCharFormat fmt = c->charFormat(it->format);-
811 fmt.setTableCellRowSpan(1);-
812 fmt.setTableCellColumnSpan(1);-
813 Q_ASSERT(fmt.objectIndex() == objectIndex());-
814 int position = it.position();-
815 int cfmt = p->formatCollection()->indexForFormat(fmt);-
816 int bfmt = p->formatCollection()->indexForFormat(QTextBlockFormat());-
817 for (int i = 0; i < num; ++i)
i < numDescription
TRUEnever evaluated
FALSEnever evaluated
0
818 p->insertBlock(QTextBeginningOfFrame, position, bfmt, cfmt, QTextUndoCommand::MoveCursor);
never executed: p->insertBlock(QChar(0xfdd0), position, bfmt, cfmt, QTextUndoCommand::MoveCursor);
0
819 }
never executed: end of block
0
820 }-
821-
822 QTextTableFormat tfmt = format();-
823 tfmt.setColumns(tfmt.columns()+num);-
824 QVector<QTextLength> columnWidths = tfmt.columnWidthConstraints();-
825 if (! columnWidths.isEmpty()) {
! columnWidths.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
826 for (int i = num; i > 0; --i)
i > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
827 columnWidths.insert(pos, columnWidths.at(qMax(0, pos - 1)));
never executed: columnWidths.insert(pos, columnWidths.at(qMax(0, pos - 1)));
0
828 }
never executed: end of block
0
829 tfmt.setColumnWidthConstraints (columnWidths);-
830 QTextObject::setFormat(tfmt);-
831-
832// qDebug() << "-------- end insertCols" << pos << num;-
833 p->endEditBlock();-
834}
never executed: end of block
0
835-
836/*!-
837 \since 4.5-
838 Appends \a count rows at the bottom of the table.-
839-
840 \sa insertColumns(), insertRows(), resize(), removeRows(), removeColumns(), appendColumns()-
841*/-
842void QTextTable::appendRows(int count)-
843{-
844 insertRows(rows(), count);-
845}
never executed: end of block
0
846-
847/*!-
848 \since 4.5-
849 Appends \a count columns at the right side of the table.-
850-
851 \sa insertColumns(), insertRows(), resize(), removeRows(), removeColumns(), appendRows()-
852*/-
853void QTextTable::appendColumns(int count)-
854{-
855 insertColumns(columns(), count);-
856}
never executed: end of block
0
857-
858/*!-
859 \fn void QTextTable::removeRows(int index, int rows)-
860-
861 Removes a number of \a rows starting with the row at the specified \a index.-
862-
863 \sa insertRows(), insertColumns(), resize(), removeColumns(), appendRows(), appendColumns()-
864*/-
865void QTextTable::removeRows(int pos, int num)-
866{-
867 Q_D(QTextTable);-
868// qDebug() << "-------- removeRows" << pos << num;-
869-
870 if (num <= 0 || pos < 0)
num <= 0Description
TRUEnever evaluated
FALSEnever evaluated
pos < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
871 return;
never executed: return;
0
872 if (d->dirty)
d->dirtyDescription
TRUEnever evaluated
FALSEnever evaluated
0
873 d->update();
never executed: d->update();
0
874 if (pos >= d->nRows)
pos >= d->nRowsDescription
TRUEnever evaluated
FALSEnever evaluated
0
875 return;
never executed: return;
0
876 if (pos+num > d->nRows)
pos+num > d->nRowsDescription
TRUEnever evaluated
FALSEnever evaluated
0
877 num = d->nRows - pos;
never executed: num = d->nRows - pos;
0
878-
879 QTextDocumentPrivate *p = d->pieceTable;-
880 QTextFormatCollection *collection = p->formatCollection();-
881 p->beginEditBlock();-
882-
883 // delete whole table?-
884 if (pos == 0 && num == d->nRows) {
pos == 0Description
TRUEnever evaluated
FALSEnever evaluated
num == d->nRowsDescription
TRUEnever evaluated
FALSEnever evaluated
0
885 const int pos = p->fragmentMap().position(d->fragment_start);-
886 p->remove(pos, p->fragmentMap().position(d->fragment_end) - pos + 1);-
887 p->endEditBlock();-
888 return;
never executed: return;
0
889 }-
890-
891 p->aboutToRemoveCell(cellAt(pos, 0).firstPosition(), cellAt(pos + num - 1, d->nCols - 1).lastPosition());-
892-
893 QVector<int> touchedCells;-
894 for (int r = pos; r < pos + num; ++r) {
r < pos + numDescription
TRUEnever evaluated
FALSEnever evaluated
0
895 for (int c = 0; c < d->nCols; ++c) {
c < d->nColsDescription
TRUEnever evaluated
FALSEnever evaluated
0
896 int cell = d->grid[r*d->nCols + c];-
897 if (touchedCells.contains(cell))
touchedCells.contains(cell)Description
TRUEnever evaluated
FALSEnever evaluated
0
898 continue;
never executed: continue;
0
899 touchedCells << cell;-
900 QTextDocumentPrivate::FragmentIterator it(&p->fragmentMap(), cell);-
901 QTextCharFormat fmt = collection->charFormat(it->format);-
902 int span = fmt.tableCellRowSpan();-
903 if (span > 1) {
span > 1Description
TRUEnever evaluated
FALSEnever evaluated
0
904 fmt.setTableCellRowSpan(span - 1);-
905 p->setCharFormat(it.position(), 1, fmt);-
906 } else {
never executed: end of block
0
907 // remove cell-
908 int index = d->cells.indexOf(cell) + 1;-
909 int f_end = index < d->cells.size() ? d->cells.at(index) : d->fragment_end;
index < d->cells.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
910 p->remove(it.position(), p->fragmentMap().position(f_end) - it.position());-
911 }
never executed: end of block
0
912 }-
913 }
never executed: end of block
0
914-
915 p->endEditBlock();-
916// qDebug() << "-------- end removeRows" << pos << num;-
917}
never executed: end of block
0
918-
919/*!-
920 \fn void QTextTable::removeColumns(int index, int columns)-
921-
922 Removes a number of \a columns starting with the column at the specified-
923 \a index.-
924-
925 \sa insertRows(), insertColumns(), removeRows(), resize(), appendRows(), appendColumns()-
926*/-
927void QTextTable::removeColumns(int pos, int num)-
928{-
929 Q_D(QTextTable);-
930// qDebug() << "-------- removeCols" << pos << num;-
931-
932 if (num <= 0 || pos < 0)
num <= 0Description
TRUEnever evaluated
FALSEnever evaluated
pos < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
933 return;
never executed: return;
0
934 if (d->dirty)
d->dirtyDescription
TRUEnever evaluated
FALSEnever evaluated
0
935 d->update();
never executed: d->update();
0
936 if (pos >= d->nCols)
pos >= d->nColsDescription
TRUEnever evaluated
FALSEnever evaluated
0
937 return;
never executed: return;
0
938 if (pos + num > d->nCols)
pos + num > d->nColsDescription
TRUEnever evaluated
FALSEnever evaluated
0
939 pos = d->nCols - num;
never executed: pos = d->nCols - num;
0
940-
941 QTextDocumentPrivate *p = d->pieceTable;-
942 QTextFormatCollection *collection = p->formatCollection();-
943 p->beginEditBlock();-
944-
945 // delete whole table?-
946 if (pos == 0 && num == d->nCols) {
pos == 0Description
TRUEnever evaluated
FALSEnever evaluated
num == d->nColsDescription
TRUEnever evaluated
FALSEnever evaluated
0
947 const int pos = p->fragmentMap().position(d->fragment_start);-
948 p->remove(pos, p->fragmentMap().position(d->fragment_end) - pos + 1);-
949 p->endEditBlock();-
950 return;
never executed: return;
0
951 }-
952-
953 p->aboutToRemoveCell(cellAt(0, pos).firstPosition(), cellAt(d->nRows - 1, pos + num - 1).lastPosition());-
954-
955 QVector<int> touchedCells;-
956 for (int r = 0; r < d->nRows; ++r) {
r < d->nRowsDescription
TRUEnever evaluated
FALSEnever evaluated
0
957 for (int c = pos; c < pos + num; ++c) {
c < pos + numDescription
TRUEnever evaluated
FALSEnever evaluated
0
958 int cell = d->grid[r*d->nCols + c];-
959 QTextDocumentPrivate::FragmentIterator it(&p->fragmentMap(), cell);-
960 QTextCharFormat fmt = collection->charFormat(it->format);-
961 int span = fmt.tableCellColumnSpan();-
962 if (touchedCells.contains(cell) && span <= 1)
touchedCells.contains(cell)Description
TRUEnever evaluated
FALSEnever evaluated
span <= 1Description
TRUEnever evaluated
FALSEnever evaluated
0
963 continue;
never executed: continue;
0
964 touchedCells << cell;-
965-
966 if (span > 1) {
span > 1Description
TRUEnever evaluated
FALSEnever evaluated
0
967 fmt.setTableCellColumnSpan(span - 1);-
968 p->setCharFormat(it.position(), 1, fmt);-
969 } else {
never executed: end of block
0
970 // remove cell-
971 int index = d->cells.indexOf(cell) + 1;-
972 int f_end = index < d->cells.size() ? d->cells.at(index) : d->fragment_end;
index < d->cells.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
973 p->remove(it.position(), p->fragmentMap().position(f_end) - it.position());-
974 }
never executed: end of block
0
975 }-
976 }
never executed: end of block
0
977-
978 QTextTableFormat tfmt = format();-
979 tfmt.setColumns(tfmt.columns()-num);-
980 QVector<QTextLength> columnWidths = tfmt.columnWidthConstraints();-
981 if (columnWidths.count() > pos) {
columnWidths.count() > posDescription
TRUEnever evaluated
FALSEnever evaluated
0
982 columnWidths.remove(pos, num);-
983 tfmt.setColumnWidthConstraints (columnWidths);-
984 }
never executed: end of block
0
985 QTextObject::setFormat(tfmt);-
986-
987 p->endEditBlock();-
988// qDebug() << "-------- end removeCols" << pos << num;-
989}
never executed: end of block
0
990-
991/*!-
992 \since 4.1-
993-
994 Merges the cell at the specified \a row and \a column with the adjacent cells-
995 into one cell. The new cell will span \a numRows rows and \a numCols columns.-
996 This method does nothing if \a numRows or \a numCols is less than the current-
997 number of rows or columns spanned by the cell.-
998-
999 \sa splitCell()-
1000*/-
1001void QTextTable::mergeCells(int row, int column, int numRows, int numCols)-
1002{-
1003 Q_D(QTextTable);-
1004-
1005 if (d->dirty)
d->dirtyDescription
TRUEnever evaluated
FALSEnever evaluated
0
1006 d->update();
never executed: d->update();
0
1007-
1008 QTextDocumentPrivate *p = d->pieceTable;-
1009 QTextFormatCollection *fc = p->formatCollection();-
1010-
1011 const QTextTableCell cell = cellAt(row, column);-
1012 if (!cell.isValid() || row != cell.row() || column != cell.column())
!cell.isValid()Description
TRUEnever evaluated
FALSEnever evaluated
row != cell.row()Description
TRUEnever evaluated
FALSEnever evaluated
column != cell.column()Description
TRUEnever evaluated
FALSEnever evaluated
0
1013 return;
never executed: return;
0
1014-
1015 QTextCharFormat fmt = cell.format();-
1016 const int rowSpan = fmt.tableCellRowSpan();-
1017 const int colSpan = fmt.tableCellColumnSpan();-
1018-
1019 numRows = qMin(numRows, rows() - cell.row());-
1020 numCols = qMin(numCols, columns() - cell.column());-
1021-
1022 // nothing to merge?-
1023 if (numRows < rowSpan || numCols < colSpan)
numRows < rowSpanDescription
TRUEnever evaluated
FALSEnever evaluated
numCols < colSpanDescription
TRUEnever evaluated
FALSEnever evaluated
0
1024 return;
never executed: return;
0
1025-
1026 // check the edges of the merge rect to make sure no cell spans the edge-
1027 for (int r = row; r < row + numRows; ++r) {
r < row + numRowsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1028 if (cellAt(r, column) == cellAt(r, column - 1))
cellAt(r, colu...r, column - 1)Description
TRUEnever evaluated
FALSEnever evaluated
0
1029 return;
never executed: return;
0
1030 if (cellAt(r, column + numCols) == cellAt(r, column + numCols - 1))
cellAt(r, colu...+ numCols - 1)Description
TRUEnever evaluated
FALSEnever evaluated
0
1031 return;
never executed: return;
0
1032 }
never executed: end of block
0
1033-
1034 for (int c = column; c < column + numCols; ++c) {
c < column + numColsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1035 if (cellAt(row, c) == cellAt(row - 1, c))
cellAt(row, c)...At(row - 1, c)Description
TRUEnever evaluated
FALSEnever evaluated
0
1036 return;
never executed: return;
0
1037 if (cellAt(row + numRows, c) == cellAt(row + numRows - 1, c))
cellAt(row + n...umRows - 1, c)Description
TRUEnever evaluated
FALSEnever evaluated
0
1038 return;
never executed: return;
0
1039 }
never executed: end of block
0
1040-
1041 p->beginEditBlock();-
1042-
1043 const int origCellPosition = cell.firstPosition() - 1;-
1044-
1045 const int cellFragment = d->grid[row * d->nCols + column];-
1046-
1047 // find the position at which to insert the contents of the merged cells-
1048 QFragmentFindHelper helper(origCellPosition, p->fragmentMap());-
1049 const auto begin = d->cells.cbegin();-
1050 const auto it = std::lower_bound(begin, d->cells.cend(), helper);-
1051 Q_ASSERT(it != d->cells.end());-
1052 Q_ASSERT(!(helper < *it));-
1053 Q_ASSERT(*it == cellFragment);-
1054 const int insertCellIndex = it - begin;-
1055 int insertFragment = d->cells.value(insertCellIndex + 1, d->fragment_end);-
1056 uint insertPos = p->fragmentMap().position(insertFragment);-
1057-
1058 d->blockFragmentUpdates = true;-
1059-
1060 bool rowHasText = cell.firstCursorPosition().block().length();-
1061 bool needsParagraph = rowHasText && colSpan == numCols;
rowHasTextDescription
TRUEnever evaluated
FALSEnever evaluated
colSpan == numColsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1062-
1063 // find all cells that will be erased by the merge-
1064 for (int r = row; r < row + numRows; ++r) {
r < row + numRowsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1065 int firstColumn = r < row + rowSpan ? column + colSpan : column;
r < row + rowSpanDescription
TRUEnever evaluated
FALSEnever evaluated
0
1066-
1067 // don't recompute the cell index for the first row-
1068 int firstCellIndex = r == row ? insertCellIndex + 1 : -1;
r == rowDescription
TRUEnever evaluated
FALSEnever evaluated
0
1069 int cellIndex = firstCellIndex;-
1070-
1071 for (int c = firstColumn; c < column + numCols; ++c) {
c < column + numColsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1072 const int fragment = d->grid[r * d->nCols + c];-
1073-
1074 // already handled?-
1075 if (fragment == cellFragment)
fragment == cellFragmentDescription
TRUEnever evaluated
FALSEnever evaluated
0
1076 continue;
never executed: continue;
0
1077-
1078 QTextDocumentPrivate::FragmentIterator it(&p->fragmentMap(), fragment);-
1079 uint pos = it.position();-
1080-
1081 if (firstCellIndex == -1) {
firstCellIndex == -1Description
TRUEnever evaluated
FALSEnever evaluated
0
1082 QFragmentFindHelper helper(pos, p->fragmentMap());-
1083 const auto begin = d->cells.cbegin();-
1084 const auto it = std::lower_bound(begin, d->cells.cend(), helper);-
1085 Q_ASSERT(it != d->cells.end());-
1086 Q_ASSERT(!(helper < *it));-
1087 Q_ASSERT(*it == fragment);-
1088 firstCellIndex = cellIndex = it - begin;-
1089 }
never executed: end of block
0
1090-
1091 ++cellIndex;-
1092-
1093 QTextCharFormat fmt = fc->charFormat(it->format);-
1094-
1095 const int cellRowSpan = fmt.tableCellRowSpan();-
1096 const int cellColSpan = fmt.tableCellColumnSpan();-
1097-
1098 // update the grid for this cell-
1099 for (int i = r; i < r + cellRowSpan; ++i)
i < r + cellRowSpanDescription
TRUEnever evaluated
FALSEnever evaluated
0
1100 for (int j = c; j < c + cellColSpan; ++j)
j < c + cellColSpanDescription
TRUEnever evaluated
FALSEnever evaluated
0
1101 d->grid[i * d->nCols + j] = cellFragment;
never executed: d->grid[i * d->nCols + j] = cellFragment;
0
1102-
1103 // erase the cell marker-
1104 p->remove(pos, 1);-
1105-
1106 const int nextFragment = d->cells.value(cellIndex, d->fragment_end);-
1107 const uint nextPos = p->fragmentMap().position(nextFragment);-
1108-
1109 Q_ASSERT(nextPos >= pos);-
1110-
1111 // merge the contents of the cell (if not empty)-
1112 if (nextPos > pos) {
nextPos > posDescription
TRUEnever evaluated
FALSEnever evaluated
0
1113 if (needsParagraph) {
needsParagraphDescription
TRUEnever evaluated
FALSEnever evaluated
0
1114 needsParagraph = false;-
1115 QTextCursorPrivate::fromPosition(p, insertPos++).insertBlock();-
1116 p->move(pos + 1, insertPos, nextPos - pos);-
1117 } else if (rowHasText) {
never executed: end of block
rowHasTextDescription
TRUEnever evaluated
FALSEnever evaluated
0
1118 QTextCursorPrivate::fromPosition(p, insertPos++).insertText(QLatin1String(" "));-
1119 p->move(pos + 1, insertPos, nextPos - pos);-
1120 } else {
never executed: end of block
0
1121 p->move(pos, insertPos, nextPos - pos);-
1122 }
never executed: end of block
0
1123-
1124 insertPos += nextPos - pos;-
1125 rowHasText = true;-
1126 }
never executed: end of block
0
1127 }
never executed: end of block
0
1128-
1129 if (rowHasText) {
rowHasTextDescription
TRUEnever evaluated
FALSEnever evaluated
0
1130 needsParagraph = true;-
1131 rowHasText = false;-
1132 }
never executed: end of block
0
1133-
1134 // erase cells from last row-
1135 if (firstCellIndex >= 0) {
firstCellIndex >= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1136 d->cellIndices.remove(firstCellIndex, cellIndex - firstCellIndex);-
1137 d->cells.erase(d->cells.begin() + firstCellIndex, d->cells.begin() + cellIndex);-
1138 }
never executed: end of block
0
1139 }
never executed: end of block
0
1140-
1141 d->fragment_start = d->cells.constFirst();-
1142-
1143 fmt.setTableCellRowSpan(numRows);-
1144 fmt.setTableCellColumnSpan(numCols);-
1145 p->setCharFormat(origCellPosition, 1, fmt);-
1146-
1147 d->blockFragmentUpdates = false;-
1148 d->dirty = false;-
1149-
1150 p->endEditBlock();-
1151}
never executed: end of block
0
1152-
1153/*!-
1154 \overload-
1155 \since 4.1-
1156-
1157 Merges the cells selected by the provided \a cursor.-
1158-
1159 \sa splitCell()-
1160*/-
1161void QTextTable::mergeCells(const QTextCursor &cursor)-
1162{-
1163 if (!cursor.hasComplexSelection())
!cursor.hasComplexSelection()Description
TRUEnever evaluated
FALSEnever evaluated
0
1164 return;
never executed: return;
0
1165-
1166 int firstRow, numRows, firstColumn, numColumns;-
1167 cursor.selectedTableCells(&firstRow, &numRows, &firstColumn, &numColumns);-
1168 mergeCells(firstRow, firstColumn, numRows, numColumns);-
1169}
never executed: end of block
0
1170-
1171/*!-
1172 \since 4.1-
1173-
1174 Splits the specified cell at \a row and \a column into an array of multiple-
1175 cells with dimensions specified by \a numRows and \a numCols.-
1176-
1177 \note It is only possible to split cells that span multiple rows or columns, such as rows-
1178 that have been merged using mergeCells().-
1179-
1180 \sa mergeCells()-
1181*/-
1182void QTextTable::splitCell(int row, int column, int numRows, int numCols)-
1183{-
1184 Q_D(QTextTable);-
1185-
1186 if (d->dirty)
d->dirtyDescription
TRUEnever evaluated
FALSEnever evaluated
0
1187 d->update();
never executed: d->update();
0
1188-
1189 QTextDocumentPrivate *p = d->pieceTable;-
1190 QTextFormatCollection *c = p->formatCollection();-
1191-
1192 const QTextTableCell cell = cellAt(row, column);-
1193 if (!cell.isValid())
!cell.isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
1194 return;
never executed: return;
0
1195 row = cell.row();-
1196 column = cell.column();-
1197-
1198 QTextCharFormat fmt = cell.format();-
1199 const int rowSpan = fmt.tableCellRowSpan();-
1200 const int colSpan = fmt.tableCellColumnSpan();-
1201-
1202 // nothing to split?-
1203 if (numRows > rowSpan || numCols > colSpan)
numRows > rowSpanDescription
TRUEnever evaluated
FALSEnever evaluated
numCols > colSpanDescription
TRUEnever evaluated
FALSEnever evaluated
0
1204 return;
never executed: return;
0
1205-
1206 p->beginEditBlock();-
1207-
1208 const int origCellPosition = cell.firstPosition() - 1;-
1209-
1210 QVarLengthArray<int> rowPositions(rowSpan);-
1211-
1212 rowPositions[0] = cell.lastPosition();-
1213-
1214 for (int r = row + 1; r < row + rowSpan; ++r) {
r < row + rowSpanDescription
TRUEnever evaluated
FALSEnever evaluated
0
1215 // find the cell before which to insert the new cell markers-
1216 int gridIndex = r * d->nCols + column;-
1217 const auto begin = d->cellIndices.cbegin();-
1218 const auto it = std::upper_bound(begin, d->cellIndices.cend(), gridIndex);-
1219 int fragment = d->cells.value(it - begin, d->fragment_end);-
1220 rowPositions[r - row] = p->fragmentMap().position(fragment);-
1221 }
never executed: end of block
0
1222-
1223 fmt.setTableCellColumnSpan(1);-
1224 fmt.setTableCellRowSpan(1);-
1225 const int fmtIndex = c->indexForFormat(fmt);-
1226 const int blockIndex = p->blockMap().find(cell.lastPosition())->format;-
1227-
1228 int insertAdjustement = 0;-
1229 for (int i = 0; i < numRows; ++i) {
i < numRowsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1230 for (int c = 0; c < colSpan - numCols; ++c)
c < colSpan - numColsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1231 p->insertBlock(QTextBeginningOfFrame, rowPositions[i] + insertAdjustement + c, blockIndex, fmtIndex);
never executed: p->insertBlock(QChar(0xfdd0), rowPositions[i] + insertAdjustement + c, blockIndex, fmtIndex);
0
1232 insertAdjustement += colSpan - numCols;-
1233 }
never executed: end of block
0
1234-
1235 for (int i = numRows; i < rowSpan; ++i) {
i < rowSpanDescription
TRUEnever evaluated
FALSEnever evaluated
0
1236 for (int c = 0; c < colSpan; ++c)
c < colSpanDescription
TRUEnever evaluated
FALSEnever evaluated
0
1237 p->insertBlock(QTextBeginningOfFrame, rowPositions[i] + insertAdjustement + c, blockIndex, fmtIndex);
never executed: p->insertBlock(QChar(0xfdd0), rowPositions[i] + insertAdjustement + c, blockIndex, fmtIndex);
0
1238 insertAdjustement += colSpan;-
1239 }
never executed: end of block
0
1240-
1241 fmt.setTableCellRowSpan(numRows);-
1242 fmt.setTableCellColumnSpan(numCols);-
1243 p->setCharFormat(origCellPosition, 1, fmt);-
1244-
1245 p->endEditBlock();-
1246}
never executed: end of block
0
1247-
1248/*!-
1249 Returns the number of rows in the table.-
1250-
1251 \sa columns()-
1252*/-
1253int QTextTable::rows() const-
1254{-
1255 Q_D(const QTextTable);-
1256 if (d->dirty)
d->dirtyDescription
TRUEnever evaluated
FALSEnever evaluated
0
1257 d->update();
never executed: d->update();
0
1258-
1259 return d->nRows;
never executed: return d->nRows;
0
1260}-
1261-
1262/*!-
1263 Returns the number of columns in the table.-
1264-
1265 \sa rows()-
1266*/-
1267int QTextTable::columns() const-
1268{-
1269 Q_D(const QTextTable);-
1270 if (d->dirty)
d->dirtyDescription
TRUEnever evaluated
FALSEnever evaluated
0
1271 d->update();
never executed: d->update();
0
1272-
1273 return d->nCols;
never executed: return d->nCols;
0
1274}-
1275-
1276/*!-
1277 \fn QTextCursor QTextTable::rowStart(const QTextCursor &cursor) const-
1278-
1279 Returns a cursor pointing to the start of the row that contains the-
1280 given \a cursor.-
1281-
1282 \sa rowEnd()-
1283*/-
1284QTextCursor QTextTable::rowStart(const QTextCursor &c) const-
1285{-
1286 Q_D(const QTextTable);-
1287 QTextTableCell cell = cellAt(c);-
1288 if (!cell.isValid())
!cell.isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
1289 return QTextCursor();
never executed: return QTextCursor();
0
1290-
1291 int row = cell.row();-
1292 QTextDocumentPrivate *p = d->pieceTable;-
1293 QTextDocumentPrivate::FragmentIterator it(&p->fragmentMap(), d->grid[row*d->nCols]);-
1294 return QTextCursorPrivate::fromPosition(p, it.position());
never executed: return QTextCursorPrivate::fromPosition(p, it.position());
0
1295}-
1296-
1297/*!-
1298 \fn QTextCursor QTextTable::rowEnd(const QTextCursor &cursor) const-
1299-
1300 Returns a cursor pointing to the end of the row that contains the given-
1301 \a cursor.-
1302-
1303 \sa rowStart()-
1304*/-
1305QTextCursor QTextTable::rowEnd(const QTextCursor &c) const-
1306{-
1307 Q_D(const QTextTable);-
1308 QTextTableCell cell = cellAt(c);-
1309 if (!cell.isValid())
!cell.isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
1310 return QTextCursor();
never executed: return QTextCursor();
0
1311-
1312 int row = cell.row() + 1;-
1313 int fragment = row < d->nRows ? d->grid[row*d->nCols] : d->fragment_end;
row < d->nRowsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1314 QTextDocumentPrivate *p = d->pieceTable;-
1315 QTextDocumentPrivate::FragmentIterator it(&p->fragmentMap(), fragment);-
1316 return QTextCursorPrivate::fromPosition(p, it.position() - 1);
never executed: return QTextCursorPrivate::fromPosition(p, it.position() - 1);
0
1317}-
1318-
1319/*!-
1320 \fn void QTextTable::setFormat(const QTextTableFormat &format)-
1321-
1322 Sets the table's \a format.-
1323-
1324 \sa format()-
1325*/-
1326void QTextTable::setFormat(const QTextTableFormat &format)-
1327{-
1328 QTextTableFormat fmt = format;-
1329 // don't try to change the number of table columns from here-
1330 fmt.setColumns(columns());-
1331 QTextObject::setFormat(fmt);-
1332}
never executed: end of block
0
1333-
1334/*!-
1335 \fn QTextTableFormat QTextTable::format() const-
1336-
1337 Returns the table's format.-
1338-
1339 \sa setFormat()-
1340*/-
1341-
1342QT_END_NAMESPACE-
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9