1 | /****************************************************************************
|
---|
2 | **
|
---|
3 | ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
---|
4 | ** All rights reserved.
|
---|
5 | ** Contact: Nokia Corporation (qt-info@nokia.com)
|
---|
6 | **
|
---|
7 | ** This file is part of the examples of the Qt Toolkit.
|
---|
8 | **
|
---|
9 | ** $QT_BEGIN_LICENSE:LGPL$
|
---|
10 | ** Commercial Usage
|
---|
11 | ** Licensees holding valid Qt Commercial licenses may use this file in
|
---|
12 | ** accordance with the Qt Commercial License Agreement provided with the
|
---|
13 | ** Software or, alternatively, in accordance with the terms contained in
|
---|
14 | ** a written agreement between you and Nokia.
|
---|
15 | **
|
---|
16 | ** GNU Lesser General Public License Usage
|
---|
17 | ** Alternatively, this file may be used under the terms of the GNU Lesser
|
---|
18 | ** General Public License version 2.1 as published by the Free Software
|
---|
19 | ** Foundation and appearing in the file LICENSE.LGPL included in the
|
---|
20 | ** packaging of this file. Please review the following information to
|
---|
21 | ** ensure the GNU Lesser General Public License version 2.1 requirements
|
---|
22 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
---|
23 | **
|
---|
24 | ** In addition, as a special exception, Nokia gives you certain additional
|
---|
25 | ** rights. These rights are described in the Nokia Qt LGPL Exception
|
---|
26 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
---|
27 | **
|
---|
28 | ** GNU General Public License Usage
|
---|
29 | ** Alternatively, this file may be used under the terms of the GNU
|
---|
30 | ** General Public License version 3.0 as published by the Free Software
|
---|
31 | ** Foundation and appearing in the file LICENSE.GPL included in the
|
---|
32 | ** packaging of this file. Please review the following information to
|
---|
33 | ** ensure the GNU General Public License version 3.0 requirements will be
|
---|
34 | ** met: http://www.gnu.org/copyleft/gpl.html.
|
---|
35 | **
|
---|
36 | ** If you have questions regarding the use of this file, please contact
|
---|
37 | ** Nokia at qt-info@nokia.com.
|
---|
38 | ** $QT_END_LICENSE$
|
---|
39 | **
|
---|
40 | ****************************************************************************/
|
---|
41 |
|
---|
42 | #include <math.h>
|
---|
43 | #include <QtGui>
|
---|
44 |
|
---|
45 | #ifndef M_PI
|
---|
46 | #define M_PI 3.1415927
|
---|
47 | #endif
|
---|
48 |
|
---|
49 | #include "pieview.h"
|
---|
50 |
|
---|
51 | PieView::PieView(QWidget *parent)
|
---|
52 | : QAbstractItemView(parent)
|
---|
53 | {
|
---|
54 | horizontalScrollBar()->setRange(0, 0);
|
---|
55 | verticalScrollBar()->setRange(0, 0);
|
---|
56 |
|
---|
57 | margin = 8;
|
---|
58 | totalSize = 300;
|
---|
59 | pieSize = totalSize - 2*margin;
|
---|
60 | validItems = 0;
|
---|
61 | totalValue = 0.0;
|
---|
62 | rubberBand = 0;
|
---|
63 | }
|
---|
64 |
|
---|
65 | void PieView::dataChanged(const QModelIndex &topLeft,
|
---|
66 | const QModelIndex &bottomRight)
|
---|
67 | {
|
---|
68 | QAbstractItemView::dataChanged(topLeft, bottomRight);
|
---|
69 |
|
---|
70 | validItems = 0;
|
---|
71 | totalValue = 0.0;
|
---|
72 |
|
---|
73 | for (int row = 0; row < model()->rowCount(rootIndex()); ++row) {
|
---|
74 |
|
---|
75 | QModelIndex index = model()->index(row, 1, rootIndex());
|
---|
76 | double value = model()->data(index).toDouble();
|
---|
77 |
|
---|
78 | if (value > 0.0) {
|
---|
79 | totalValue += value;
|
---|
80 | validItems++;
|
---|
81 | }
|
---|
82 | }
|
---|
83 | viewport()->update();
|
---|
84 | }
|
---|
85 |
|
---|
86 | bool PieView::edit(const QModelIndex &index, EditTrigger trigger, QEvent *event)
|
---|
87 | {
|
---|
88 | if (index.column() == 0)
|
---|
89 | return QAbstractItemView::edit(index, trigger, event);
|
---|
90 | else
|
---|
91 | return false;
|
---|
92 | }
|
---|
93 |
|
---|
94 | /*
|
---|
95 | Returns the item that covers the coordinate given in the view.
|
---|
96 | */
|
---|
97 |
|
---|
98 | QModelIndex PieView::indexAt(const QPoint &point) const
|
---|
99 | {
|
---|
100 | if (validItems == 0)
|
---|
101 | return QModelIndex();
|
---|
102 |
|
---|
103 | // Transform the view coordinates into contents widget coordinates.
|
---|
104 | int wx = point.x() + horizontalScrollBar()->value();
|
---|
105 | int wy = point.y() + verticalScrollBar()->value();
|
---|
106 |
|
---|
107 | if (wx < totalSize) {
|
---|
108 | double cx = wx - totalSize/2;
|
---|
109 | double cy = totalSize/2 - wy; // positive cy for items above the center
|
---|
110 |
|
---|
111 | // Determine the distance from the center point of the pie chart.
|
---|
112 | double d = pow(pow(cx, 2) + pow(cy, 2), 0.5);
|
---|
113 |
|
---|
114 | if (d == 0 || d > pieSize/2)
|
---|
115 | return QModelIndex();
|
---|
116 |
|
---|
117 | // Determine the angle of the point.
|
---|
118 | double angle = (180 / M_PI) * acos(cx/d);
|
---|
119 | if (cy < 0)
|
---|
120 | angle = 360 - angle;
|
---|
121 |
|
---|
122 | // Find the relevant slice of the pie.
|
---|
123 | double startAngle = 0.0;
|
---|
124 |
|
---|
125 | for (int row = 0; row < model()->rowCount(rootIndex()); ++row) {
|
---|
126 |
|
---|
127 | QModelIndex index = model()->index(row, 1, rootIndex());
|
---|
128 | double value = model()->data(index).toDouble();
|
---|
129 |
|
---|
130 | if (value > 0.0) {
|
---|
131 | double sliceAngle = 360*value/totalValue;
|
---|
132 |
|
---|
133 | if (angle >= startAngle && angle < (startAngle + sliceAngle))
|
---|
134 | return model()->index(row, 1, rootIndex());
|
---|
135 |
|
---|
136 | startAngle += sliceAngle;
|
---|
137 | }
|
---|
138 | }
|
---|
139 | } else {
|
---|
140 | double itemHeight = QFontMetrics(viewOptions().font).height();
|
---|
141 | int listItem = int((wy - margin) / itemHeight);
|
---|
142 | int validRow = 0;
|
---|
143 |
|
---|
144 | for (int row = 0; row < model()->rowCount(rootIndex()); ++row) {
|
---|
145 |
|
---|
146 | QModelIndex index = model()->index(row, 1, rootIndex());
|
---|
147 | if (model()->data(index).toDouble() > 0.0) {
|
---|
148 |
|
---|
149 | if (listItem == validRow)
|
---|
150 | return model()->index(row, 0, rootIndex());
|
---|
151 |
|
---|
152 | // Update the list index that corresponds to the next valid row.
|
---|
153 | validRow++;
|
---|
154 | }
|
---|
155 | }
|
---|
156 | }
|
---|
157 |
|
---|
158 | return QModelIndex();
|
---|
159 | }
|
---|
160 |
|
---|
161 | bool PieView::isIndexHidden(const QModelIndex & /*index*/) const
|
---|
162 | {
|
---|
163 | return false;
|
---|
164 | }
|
---|
165 |
|
---|
166 | /*
|
---|
167 | Returns the rectangle of the item at position \a index in the
|
---|
168 | model. The rectangle is in contents coordinates.
|
---|
169 | */
|
---|
170 |
|
---|
171 | QRect PieView::itemRect(const QModelIndex &index) const
|
---|
172 | {
|
---|
173 | if (!index.isValid())
|
---|
174 | return QRect();
|
---|
175 |
|
---|
176 | // Check whether the index's row is in the list of rows represented
|
---|
177 | // by slices.
|
---|
178 | QModelIndex valueIndex;
|
---|
179 |
|
---|
180 | if (index.column() != 1)
|
---|
181 | valueIndex = model()->index(index.row(), 1, rootIndex());
|
---|
182 | else
|
---|
183 | valueIndex = index;
|
---|
184 |
|
---|
185 | if (model()->data(valueIndex).toDouble() > 0.0) {
|
---|
186 |
|
---|
187 | int listItem = 0;
|
---|
188 | for (int row = index.row()-1; row >= 0; --row) {
|
---|
189 | if (model()->data(model()->index(row, 1, rootIndex())).toDouble() > 0.0)
|
---|
190 | listItem++;
|
---|
191 | }
|
---|
192 |
|
---|
193 | double itemHeight;
|
---|
194 |
|
---|
195 | switch (index.column()) {
|
---|
196 | case 0:
|
---|
197 | itemHeight = QFontMetrics(viewOptions().font).height();
|
---|
198 |
|
---|
199 | return QRect(totalSize,
|
---|
200 | int(margin + listItem*itemHeight),
|
---|
201 | totalSize - margin, int(itemHeight));
|
---|
202 | case 1:
|
---|
203 | return viewport()->rect();
|
---|
204 | }
|
---|
205 |
|
---|
206 | }
|
---|
207 | return QRect();
|
---|
208 | }
|
---|
209 |
|
---|
210 | QRegion PieView::itemRegion(const QModelIndex &index) const
|
---|
211 | {
|
---|
212 | if (!index.isValid())
|
---|
213 | return QRegion();
|
---|
214 |
|
---|
215 | if (index.column() != 1)
|
---|
216 | return itemRect(index);
|
---|
217 |
|
---|
218 | if (model()->data(index).toDouble() <= 0.0)
|
---|
219 | return QRegion();
|
---|
220 |
|
---|
221 | double startAngle = 0.0;
|
---|
222 | for (int row = 0; row < model()->rowCount(rootIndex()); ++row) {
|
---|
223 |
|
---|
224 | QModelIndex sliceIndex = model()->index(row, 1, rootIndex());
|
---|
225 | double value = model()->data(sliceIndex).toDouble();
|
---|
226 |
|
---|
227 | if (value > 0.0) {
|
---|
228 | double angle = 360*value/totalValue;
|
---|
229 |
|
---|
230 | if (sliceIndex == index) {
|
---|
231 | QPainterPath slicePath;
|
---|
232 | slicePath.moveTo(totalSize/2, totalSize/2);
|
---|
233 | slicePath.arcTo(margin, margin, margin+pieSize, margin+pieSize,
|
---|
234 | startAngle, angle);
|
---|
235 | slicePath.closeSubpath();
|
---|
236 |
|
---|
237 | return QRegion(slicePath.toFillPolygon().toPolygon());
|
---|
238 | }
|
---|
239 |
|
---|
240 | startAngle += angle;
|
---|
241 | }
|
---|
242 | }
|
---|
243 |
|
---|
244 | return QRegion();
|
---|
245 | }
|
---|
246 |
|
---|
247 | int PieView::horizontalOffset() const
|
---|
248 | {
|
---|
249 | return horizontalScrollBar()->value();
|
---|
250 | }
|
---|
251 |
|
---|
252 | void PieView::mousePressEvent(QMouseEvent *event)
|
---|
253 | {
|
---|
254 | QAbstractItemView::mousePressEvent(event);
|
---|
255 | origin = event->pos();
|
---|
256 | if (!rubberBand)
|
---|
257 | rubberBand = new QRubberBand(QRubberBand::Rectangle, viewport());
|
---|
258 | rubberBand->setGeometry(QRect(origin, QSize()));
|
---|
259 | rubberBand->show();
|
---|
260 | }
|
---|
261 |
|
---|
262 | void PieView::mouseMoveEvent(QMouseEvent *event)
|
---|
263 | {
|
---|
264 | if (rubberBand)
|
---|
265 | rubberBand->setGeometry(QRect(origin, event->pos()).normalized());
|
---|
266 | QAbstractItemView::mouseMoveEvent(event);
|
---|
267 | }
|
---|
268 |
|
---|
269 | void PieView::mouseReleaseEvent(QMouseEvent *event)
|
---|
270 | {
|
---|
271 | QAbstractItemView::mouseReleaseEvent(event);
|
---|
272 | if (rubberBand)
|
---|
273 | rubberBand->hide();
|
---|
274 | viewport()->update();
|
---|
275 | }
|
---|
276 |
|
---|
277 | QModelIndex PieView::moveCursor(QAbstractItemView::CursorAction cursorAction,
|
---|
278 | Qt::KeyboardModifiers /*modifiers*/)
|
---|
279 | {
|
---|
280 | QModelIndex current = currentIndex();
|
---|
281 |
|
---|
282 | switch (cursorAction) {
|
---|
283 | case MoveLeft:
|
---|
284 | case MoveUp:
|
---|
285 | if (current.row() > 0)
|
---|
286 | current = model()->index(current.row() - 1, current.column(),
|
---|
287 | rootIndex());
|
---|
288 | else
|
---|
289 | current = model()->index(0, current.column(), rootIndex());
|
---|
290 | break;
|
---|
291 | case MoveRight:
|
---|
292 | case MoveDown:
|
---|
293 | if (current.row() < rows(current) - 1)
|
---|
294 | current = model()->index(current.row() + 1, current.column(),
|
---|
295 | rootIndex());
|
---|
296 | else
|
---|
297 | current = model()->index(rows(current) - 1, current.column(),
|
---|
298 | rootIndex());
|
---|
299 | break;
|
---|
300 | default:
|
---|
301 | break;
|
---|
302 | }
|
---|
303 |
|
---|
304 | viewport()->update();
|
---|
305 | return current;
|
---|
306 | }
|
---|
307 |
|
---|
308 | void PieView::paintEvent(QPaintEvent *event)
|
---|
309 | {
|
---|
310 | QItemSelectionModel *selections = selectionModel();
|
---|
311 | QStyleOptionViewItem option = viewOptions();
|
---|
312 | QStyle::State state = option.state;
|
---|
313 |
|
---|
314 | QBrush background = option.palette.base();
|
---|
315 | QPen foreground(option.palette.color(QPalette::WindowText));
|
---|
316 | QPen textPen(option.palette.color(QPalette::Text));
|
---|
317 | QPen highlightedPen(option.palette.color(QPalette::HighlightedText));
|
---|
318 |
|
---|
319 | QPainter painter(viewport());
|
---|
320 | painter.setRenderHint(QPainter::Antialiasing);
|
---|
321 |
|
---|
322 | painter.fillRect(event->rect(), background);
|
---|
323 | painter.setPen(foreground);
|
---|
324 |
|
---|
325 | // Viewport rectangles
|
---|
326 | QRect pieRect = QRect(margin, margin, pieSize, pieSize);
|
---|
327 | QPoint keyPoint = QPoint(totalSize - horizontalScrollBar()->value(),
|
---|
328 | margin - verticalScrollBar()->value());
|
---|
329 |
|
---|
330 | if (validItems > 0) {
|
---|
331 |
|
---|
332 | painter.save();
|
---|
333 | painter.translate(pieRect.x() - horizontalScrollBar()->value(),
|
---|
334 | pieRect.y() - verticalScrollBar()->value());
|
---|
335 | painter.drawEllipse(0, 0, pieSize, pieSize);
|
---|
336 | double startAngle = 0.0;
|
---|
337 | int row;
|
---|
338 |
|
---|
339 | for (row = 0; row < model()->rowCount(rootIndex()); ++row) {
|
---|
340 |
|
---|
341 | QModelIndex index = model()->index(row, 1, rootIndex());
|
---|
342 | double value = model()->data(index).toDouble();
|
---|
343 |
|
---|
344 | if (value > 0.0) {
|
---|
345 | double angle = 360*value/totalValue;
|
---|
346 |
|
---|
347 | QModelIndex colorIndex = model()->index(row, 0, rootIndex());
|
---|
348 | QColor color = QColor(model()->data(colorIndex,
|
---|
349 | Qt::DecorationRole).toString());
|
---|
350 |
|
---|
351 | if (currentIndex() == index)
|
---|
352 | painter.setBrush(QBrush(color, Qt::Dense4Pattern));
|
---|
353 | else if (selections->isSelected(index))
|
---|
354 | painter.setBrush(QBrush(color, Qt::Dense3Pattern));
|
---|
355 | else
|
---|
356 | painter.setBrush(QBrush(color));
|
---|
357 |
|
---|
358 | painter.drawPie(0, 0, pieSize, pieSize, int(startAngle*16),
|
---|
359 | int(angle*16));
|
---|
360 |
|
---|
361 | startAngle += angle;
|
---|
362 | }
|
---|
363 | }
|
---|
364 | painter.restore();
|
---|
365 |
|
---|
366 | int keyNumber = 0;
|
---|
367 |
|
---|
368 | for (row = 0; row < model()->rowCount(rootIndex()); ++row) {
|
---|
369 |
|
---|
370 | QModelIndex index = model()->index(row, 1, rootIndex());
|
---|
371 | double value = model()->data(index).toDouble();
|
---|
372 |
|
---|
373 | if (value > 0.0) {
|
---|
374 | QModelIndex labelIndex = model()->index(row, 0, rootIndex());
|
---|
375 |
|
---|
376 | QStyleOptionViewItem option = viewOptions();
|
---|
377 | option.rect = visualRect(labelIndex);
|
---|
378 | if (selections->isSelected(labelIndex))
|
---|
379 | option.state |= QStyle::State_Selected;
|
---|
380 | if (currentIndex() == labelIndex)
|
---|
381 | option.state |= QStyle::State_HasFocus;
|
---|
382 | itemDelegate()->paint(&painter, option, labelIndex);
|
---|
383 |
|
---|
384 | keyNumber++;
|
---|
385 | }
|
---|
386 | }
|
---|
387 | }
|
---|
388 | }
|
---|
389 |
|
---|
390 | void PieView::resizeEvent(QResizeEvent * /* event */)
|
---|
391 | {
|
---|
392 | updateGeometries();
|
---|
393 | }
|
---|
394 |
|
---|
395 | int PieView::rows(const QModelIndex &index) const
|
---|
396 | {
|
---|
397 | return model()->rowCount(model()->parent(index));
|
---|
398 | }
|
---|
399 |
|
---|
400 | void PieView::rowsInserted(const QModelIndex &parent, int start, int end)
|
---|
401 | {
|
---|
402 | for (int row = start; row <= end; ++row) {
|
---|
403 |
|
---|
404 | QModelIndex index = model()->index(row, 1, rootIndex());
|
---|
405 | double value = model()->data(index).toDouble();
|
---|
406 |
|
---|
407 | if (value > 0.0) {
|
---|
408 | totalValue += value;
|
---|
409 | validItems++;
|
---|
410 | }
|
---|
411 | }
|
---|
412 |
|
---|
413 | QAbstractItemView::rowsInserted(parent, start, end);
|
---|
414 | }
|
---|
415 |
|
---|
416 | void PieView::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
|
---|
417 | {
|
---|
418 | for (int row = start; row <= end; ++row) {
|
---|
419 |
|
---|
420 | QModelIndex index = model()->index(row, 1, rootIndex());
|
---|
421 | double value = model()->data(index).toDouble();
|
---|
422 | if (value > 0.0) {
|
---|
423 | totalValue -= value;
|
---|
424 | validItems--;
|
---|
425 | }
|
---|
426 | }
|
---|
427 |
|
---|
428 | QAbstractItemView::rowsAboutToBeRemoved(parent, start, end);
|
---|
429 | }
|
---|
430 |
|
---|
431 | void PieView::scrollContentsBy(int dx, int dy)
|
---|
432 | {
|
---|
433 | viewport()->scroll(dx, dy);
|
---|
434 | }
|
---|
435 |
|
---|
436 | void PieView::scrollTo(const QModelIndex &index, ScrollHint)
|
---|
437 | {
|
---|
438 | QRect area = viewport()->rect();
|
---|
439 | QRect rect = visualRect(index);
|
---|
440 |
|
---|
441 | if (rect.left() < area.left())
|
---|
442 | horizontalScrollBar()->setValue(
|
---|
443 | horizontalScrollBar()->value() + rect.left() - area.left());
|
---|
444 | else if (rect.right() > area.right())
|
---|
445 | horizontalScrollBar()->setValue(
|
---|
446 | horizontalScrollBar()->value() + qMin(
|
---|
447 | rect.right() - area.right(), rect.left() - area.left()));
|
---|
448 |
|
---|
449 | if (rect.top() < area.top())
|
---|
450 | verticalScrollBar()->setValue(
|
---|
451 | verticalScrollBar()->value() + rect.top() - area.top());
|
---|
452 | else if (rect.bottom() > area.bottom())
|
---|
453 | verticalScrollBar()->setValue(
|
---|
454 | verticalScrollBar()->value() + qMin(
|
---|
455 | rect.bottom() - area.bottom(), rect.top() - area.top()));
|
---|
456 |
|
---|
457 | update();
|
---|
458 | }
|
---|
459 |
|
---|
460 | /*
|
---|
461 | Find the indices corresponding to the extent of the selection.
|
---|
462 | */
|
---|
463 |
|
---|
464 | void PieView::setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags command)
|
---|
465 | {
|
---|
466 | // Use content widget coordinates because we will use the itemRegion()
|
---|
467 | // function to check for intersections.
|
---|
468 |
|
---|
469 | QRect contentsRect = rect.translated(
|
---|
470 | horizontalScrollBar()->value(),
|
---|
471 | verticalScrollBar()->value()).normalized();
|
---|
472 |
|
---|
473 | int rows = model()->rowCount(rootIndex());
|
---|
474 | int columns = model()->columnCount(rootIndex());
|
---|
475 | QModelIndexList indexes;
|
---|
476 |
|
---|
477 | for (int row = 0; row < rows; ++row) {
|
---|
478 | for (int column = 0; column < columns; ++column) {
|
---|
479 | QModelIndex index = model()->index(row, column, rootIndex());
|
---|
480 | QRegion region = itemRegion(index);
|
---|
481 | if (!region.intersect(contentsRect).isEmpty())
|
---|
482 | indexes.append(index);
|
---|
483 | }
|
---|
484 | }
|
---|
485 |
|
---|
486 | if (indexes.size() > 0) {
|
---|
487 | int firstRow = indexes[0].row();
|
---|
488 | int lastRow = indexes[0].row();
|
---|
489 | int firstColumn = indexes[0].column();
|
---|
490 | int lastColumn = indexes[0].column();
|
---|
491 |
|
---|
492 | for (int i = 1; i < indexes.size(); ++i) {
|
---|
493 | firstRow = qMin(firstRow, indexes[i].row());
|
---|
494 | lastRow = qMax(lastRow, indexes[i].row());
|
---|
495 | firstColumn = qMin(firstColumn, indexes[i].column());
|
---|
496 | lastColumn = qMax(lastColumn, indexes[i].column());
|
---|
497 | }
|
---|
498 |
|
---|
499 | QItemSelection selection(
|
---|
500 | model()->index(firstRow, firstColumn, rootIndex()),
|
---|
501 | model()->index(lastRow, lastColumn, rootIndex()));
|
---|
502 | selectionModel()->select(selection, command);
|
---|
503 | } else {
|
---|
504 | QModelIndex noIndex;
|
---|
505 | QItemSelection selection(noIndex, noIndex);
|
---|
506 | selectionModel()->select(selection, command);
|
---|
507 | }
|
---|
508 |
|
---|
509 | update();
|
---|
510 | }
|
---|
511 |
|
---|
512 | void PieView::updateGeometries()
|
---|
513 | {
|
---|
514 | horizontalScrollBar()->setPageStep(viewport()->width());
|
---|
515 | horizontalScrollBar()->setRange(0, qMax(0, 2*totalSize - viewport()->width()));
|
---|
516 | verticalScrollBar()->setPageStep(viewport()->height());
|
---|
517 | verticalScrollBar()->setRange(0, qMax(0, totalSize - viewport()->height()));
|
---|
518 | }
|
---|
519 |
|
---|
520 | int PieView::verticalOffset() const
|
---|
521 | {
|
---|
522 | return verticalScrollBar()->value();
|
---|
523 | }
|
---|
524 |
|
---|
525 | /*
|
---|
526 | Returns the position of the item in viewport coordinates.
|
---|
527 | */
|
---|
528 |
|
---|
529 | QRect PieView::visualRect(const QModelIndex &index) const
|
---|
530 | {
|
---|
531 | QRect rect = itemRect(index);
|
---|
532 | if (rect.isValid())
|
---|
533 | return QRect(rect.left() - horizontalScrollBar()->value(),
|
---|
534 | rect.top() - verticalScrollBar()->value(),
|
---|
535 | rect.width(), rect.height());
|
---|
536 | else
|
---|
537 | return rect;
|
---|
538 | }
|
---|
539 |
|
---|
540 | /*
|
---|
541 | Returns a region corresponding to the selection in viewport coordinates.
|
---|
542 | */
|
---|
543 |
|
---|
544 | QRegion PieView::visualRegionForSelection(const QItemSelection &selection) const
|
---|
545 | {
|
---|
546 | int ranges = selection.count();
|
---|
547 |
|
---|
548 | if (ranges == 0)
|
---|
549 | return QRect();
|
---|
550 |
|
---|
551 | QRegion region;
|
---|
552 | for (int i = 0; i < ranges; ++i) {
|
---|
553 | QItemSelectionRange range = selection.at(i);
|
---|
554 | for (int row = range.top(); row <= range.bottom(); ++row) {
|
---|
555 | for (int col = range.left(); col <= range.right(); ++col) {
|
---|
556 | QModelIndex index = model()->index(row, col, rootIndex());
|
---|
557 | region += visualRect(index);
|
---|
558 | }
|
---|
559 | }
|
---|
560 | }
|
---|
561 | return region;
|
---|
562 | }
|
---|