11 #include "TreeViewContent.h"
20 #include <QPaintEvent>
23 #include <QtCore/qtextstream.h>
25 #include <QVBoxLayout>
27 #include "IException.h"
30 #include "AbstractTreeItem.h"
31 #include "TableColumn.h"
32 #include "AbstractTreeModel.h"
36 TreeViewContent::TreeViewContent(
QWidget *parent) :
40 m_parentView = (TreeView *) parent;
43 m_mousePressPos =
new QPoint;
48 verticalScrollBar()->setSingleStep(1);
49 horizontalScrollBar()->setSingleStep(10);
50 m_rowHeight = QFontMetrics(font()).height() + ITEM_PADDING;
52 ASSERT(m_rowHeight > 0);
54 setMouseTracking(
true);
55 setContextMenuPolicy(Qt::ActionsContextMenu);
56 QAction *alternateRowsAct =
new QAction(
"&Alternate row colors",
this);
57 alternateRowsAct->setCheckable(
true);
58 connect(alternateRowsAct, SIGNAL(toggled(
bool)),
59 this, SLOT(setAlternatingRowColors(
bool)));
60 addAction(alternateRowsAct);
61 alternateRowsAct->setChecked(
true);
65 TreeViewContent::~TreeViewContent() {
69 delete m_mousePressPos;
70 m_mousePressPos = NULL;
78 delete m_lastShiftSelection;
79 m_lastShiftSelection = NULL;
83 QSize TreeViewContent::minimumSizeHint()
const {
84 return QWidget::minimumSizeHint();
88 QSize TreeViewContent::sizeHint()
const {
89 return minimumSizeHint();
93 AbstractTreeModel *TreeViewContent::getModel() {
98 void TreeViewContent::setModel(AbstractTreeModel *someModel) {
100 IString msg =
"Attempted to set a NULL model!";
105 disconnect(m_model, SIGNAL(modelModified()),
this, SLOT(refresh()));
106 disconnect(m_model, SIGNAL(filterProgressChanged(
int)),
107 this, SLOT(updateItemList()));
117 connect(m_model, SIGNAL(modelModified()),
this, SLOT(refresh()));
118 connect(m_model, SIGNAL(filterProgressChanged(
int)),
119 this, SLOT(updateItemList()));
129 void TreeViewContent::refresh() {
132 if (!m_model->isFiltering()) {
133 QSize modelVisibleSize =
135 int rowCount = modelVisibleSize.height();
136 m_contentWidth = modelVisibleSize.width() + ITEM_INDENTATION;
137 verticalScrollBar()->setRange(0, qMax(rowCount - 1, 0));
138 horizontalScrollBar()->setRange(0, m_contentWidth - viewport()->width()
139 + horizontalScrollBar()->singleStep());
143 viewport()->update();
148 bool TreeViewContent::eventFilter(
QObject *target, QEvent *event) {
149 return QObject::eventFilter(target, event);
153 void TreeViewContent::mouseDoubleClickEvent(QMouseEvent *event) {
154 QPoint pressPos =
event->pos();
155 int index = pressPos.y() / m_rowHeight;
157 if (index < m_items->size()) {
158 AbstractTreeItem *item = (*m_items)[index];
159 item->setExpanded(!item->isExpanded());
164 void TreeViewContent::mousePressEvent(QMouseEvent *event) {
165 QPoint pressPos =
event->pos();
166 int index = pressPos.y() / m_rowHeight;
171 if (index < m_items->size()) {
172 AbstractTreeItem *item = (*m_items)[index];
173 if (item->isSelectable() ||
174 (item->getFirstVisibleChild() &&
175 getArrowRect(item).contains(pressPos))) {
178 if (item->getFirstVisibleChild()) {
179 QRect arrowRect(getArrowRect(item));
185 if (event->modifiers() & Qt::ControlModifier) {
186 foreach (AbstractTreeItem * child, item->getChildren()) {
187 child->setSelected(!item->isSelected());
188 if (child->isSelected())
189 newlySelectedItems.append(child);
192 item->setSelected(!item->isSelected());
193 if (item->isSelected())
194 newlySelectedItems.append(item);
196 m_lastDirectlySelectedItem = item;
197 m_lastShiftSelection->clear();
200 if (event->modifiers() & Qt::ShiftModifier) {
201 foreach (AbstractTreeItem * i, *m_lastShiftSelection)
202 i->setSelected(
false);
204 if (m_lastDirectlySelectedItem) {
207 m_model->getItems(m_lastDirectlySelectedItem, item);
211 foreach (AbstractTreeItem * i, tmp) {
212 m_lastShiftSelection->append(i);
215 if (i->getPointerType() == AbstractTreeItem::Point) {
216 foreach (AbstractTreeItem * child, i->getChildren()) {
217 child->setSelected(
true);
218 m_lastShiftSelection->append(child);
224 m_lastShiftSelection->clear();
227 foreach (AbstractTreeItem * i, *m_lastShiftSelection) {
228 i->setSelected(
true);
229 newlySelectedItems.append(i);
233 m_model->setGlobalSelection(
false);
234 item->setSelected(
true);
235 newlySelectedItems.append(item);
236 m_lastDirectlySelectedItem = item;
238 if (item->getPointerType() == AbstractTreeItem::Point) {
239 foreach (AbstractTreeItem * child, item->getChildren()) {
240 child->setSelected(
true);
241 newlySelectedItems.append(child);
245 m_lastShiftSelection->clear();
249 emit treeSelectionChanged(newlySelectedItems);
254 m_model->setGlobalSelection(
false);
257 viewport()->update();
261 void TreeViewContent::mouseReleaseEvent(QMouseEvent *event) {
263 if (item && getArrowRect(item).contains(event->pos())) {
264 item->setExpanded(!item->isExpanded());
270 viewport()->update();
272 QWidget::mousePressEvent(event);
276 void TreeViewContent::mouseMoveEvent(QMouseEvent *event) {
277 QPoint cursorPos =
event->pos();
278 int index = cursorPos.y() / m_rowHeight;
283 if (index < m_items->size() && index >= 0) {
284 AbstractTreeItem *item = (*m_items)[index];
285 if (item->isSelectable() ||
286 (item->getFirstVisibleChild() &&
287 getArrowRect(item).contains(cursorPos))) {
290 if (item->getFirstVisibleChild()) {
291 QRect arrowRect = getArrowRect(item);
297 viewport()->update();
301 void TreeViewContent::leaveEvent(QEvent *event) {
304 viewport()->update();
308 void TreeViewContent::keyPressEvent(QKeyEvent *event) {
309 if (event->key() == Qt::Key_A &&
310 event->modifiers() == Qt::ControlModifier) {
311 m_model->setGlobalSelection(
true);
312 viewport()->update();
313 emit treeSelectionChanged();
316 QWidget::keyPressEvent(event);
321 void TreeViewContent::paintEvent(QPaintEvent *event) {
323 int startRow = verticalScrollBar()->value();
324 int rowCount = (int) ceil(viewport()->height() / (double) m_rowHeight);
326 QPainter painter(viewport());
327 painter.setRenderHints(QPainter::Antialiasing |
328 QPainter::TextAntialiasing);
330 for (
int i = 0; i < rowCount; i++) {
334 QColor backgroundColor = palette().base().color();
336 if (i < m_items->size()) {
337 if (m_alternatingRowColors && (startRow + i) % 2 == 1)
338 backgroundColor = palette().alternateBase().color();
340 ASSERT(m_items->at(i));
341 if (m_items->at(i)->isSelected())
342 backgroundColor = palette().highlight().color();
346 QPoint relativeTopLeft(0, i * m_rowHeight);
347 QPoint scrollBarPos(horizontalScrollBar()->value(),
348 verticalScrollBar()->value());
349 QPoint absoluteTopLeft(relativeTopLeft + scrollBarPos);
350 QSize rowSize(viewport()->width(), (
int) m_rowHeight);
353 painter.fillRect(QRect(relativeTopLeft, rowSize), backgroundColor);
357 if (i < m_items->size() &&
m_hoveredItem->first == (*m_items)[i] &&
359 QPen prevPen(painter.pen());
360 QPen borderPen(prevPen);
361 borderPen.setWidth(1);
362 borderPen.setColor(palette().highlight().color());
363 painter.setPen(borderPen);
364 QPoint borderTopLeft(relativeTopLeft.x() - absoluteTopLeft.x(),
365 relativeTopLeft.y() + 1);
367 int rectWidth = qMax(m_contentWidth +
368 horizontalScrollBar()->singleStep(), viewport()->width());
369 QSize borderSize(rectWidth, rowSize.height() - 2);
370 painter.drawRect(QRect(borderTopLeft, borderSize));
371 painter.setPen(prevPen);
375 if (i < m_items->size())
376 paintItemText(&painter, i, absoluteTopLeft, relativeTopLeft);
380 QWidget::paintEvent(event);
385 void TreeViewContent::resizeEvent(QResizeEvent *event) {
386 QAbstractScrollArea::resizeEvent(event);
387 horizontalScrollBar()->setRange(0, m_contentWidth - viewport()->width()
388 + horizontalScrollBar()->singleStep());
393 void TreeViewContent::scrollContentsBy(
int dx,
int dy) {
394 QAbstractScrollArea::scrollContentsBy(dx, dy);
399 void TreeViewContent::nullify() {
405 m_lastDirectlySelectedItem = NULL;
406 m_lastShiftSelection = NULL;
407 m_mousePressPos = NULL;
411 void TreeViewContent::paintItemText(QPainter *painter,
412 int index, QPoint absolutePosition, QPoint relativePosition) {
414 ASSERT(index >= 0 && index < m_items->size());
416 QPoint point(-absolutePosition.x(), relativePosition.y());
418 AbstractTreeItem *item = (*m_items)[index];
432 AbstractTreeItem *iteratorItem = item;
433 while (iteratorItem->parent() && iteratorItem->parent()->parent()) {
434 point.setX(point.x() + ITEM_INDENTATION);
435 iteratorItem = iteratorItem->parent();
438 QPen originalPen = painter->pen();
439 if (item->isSelected()) {
440 painter->setPen(QPen(palette().highlightedText().color()));
446 if (item->getFirstVisibleChild()) {
449 QRect itemArrowRect(getArrowRect(item));
452 QPainter::CompositionMode prevMode = painter->compositionMode();
453 painter->setCompositionMode(QPainter::CompositionMode_SourceOver);
454 QColor color = palette().button().color().darker(160);
456 painter->fillRect(itemArrowRect, color);
457 painter->setCompositionMode(prevMode);
467 painter->drawRect(itemArrowRect);
472 if (item->isExpanded())
473 drawExpandedArrow(painter, itemArrowRect);
475 drawCollapsedArrow(painter, itemArrowRect);
480 point.setX(point.x() + ITEM_INDENTATION);
483 point.setY(point.y() + ITEM_PADDING / 2);
486 int textHeight = m_rowHeight - ITEM_PADDING;
487 QRect rect(point, QSize(viewport()->width() - point.x(), textHeight));
488 painter->drawText(rect, Qt::TextDontClip, item->getData().toString());
489 painter->setPen(originalPen);
494 void TreeViewContent::drawCollapsedArrow(QPainter *painter, QRect rect) {
495 rect.setTopLeft(rect.topLeft() + QPoint(4, 3));
496 rect.setBottomRight(rect.bottomRight() - QPoint(4, 2));
498 QPoint top(rect.topLeft());
499 QPoint bottom(rect.bottomLeft());
500 QPoint right(rect.right(), rect.center().y());
502 QPen prevPen = painter->pen();
503 QPen arrowPen(prevPen);
504 arrowPen.setCapStyle(Qt::RoundCap);
505 arrowPen.setJoinStyle(Qt::RoundJoin);
506 arrowPen.setWidth(2);
507 painter->setPen(arrowPen);
508 painter->drawLine(top, right);
509 painter->drawLine(bottom, right);
510 painter->setPen(prevPen);
514 void TreeViewContent::drawExpandedArrow(QPainter *painter, QRect rect) {
515 rect.setTopLeft(rect.topLeft() + QPoint(3, 4));
516 rect.setBottomRight(rect.bottomRight() - QPoint(2, 4));
518 QPoint left(rect.topLeft());
519 QPoint right(rect.topRight());
520 QPoint bottom(rect.center().x(), rect.bottom());
522 QPen prevPen = painter->pen();
523 QPen arrowPen(prevPen);
524 arrowPen.setCapStyle(Qt::RoundCap);
525 arrowPen.setJoinStyle(Qt::RoundJoin);
526 arrowPen.setWidth(2);
527 painter->setPen(arrowPen);
528 painter->drawLine(left, bottom);
529 painter->drawLine(right, bottom);
530 painter->setPen(prevPen);
534 void TreeViewContent::setAlternatingRowColors(
bool newStatus) {
535 m_alternatingRowColors = newStatus;
536 viewport()->update();
540 void TreeViewContent::updateItemList() {
541 int startRow = verticalScrollBar()->value();
542 int rowCount = (int) ceil(viewport()->height() / (double) m_rowHeight);
543 *m_items = m_model->getItems(startRow, startRow + rowCount,
544 AbstractTreeModel::AllItems,
false);
546 viewport()->update();
550 QRect TreeViewContent::getArrowRect(AbstractTreeItem *item)
const {
553 int index = m_items->indexOf(item);
554 QPoint centerOfArrow(12 - horizontalScrollBar()->value(),
555 (index * m_rowHeight) + (m_rowHeight / 2));
556 int depth = item->getDepth() - 1;
557 centerOfArrow.setX(centerOfArrow.x() + (depth * ITEM_INDENTATION));
559 arrowRect = QRect(centerOfArrow.x() - 6, centerOfArrow.y() - 6, 12, 12);
565 void TreeViewContent::scrollTo(
567 if (newlySelectedItems.size())
568 scrollTo(newlySelectedItems.last());
572 void TreeViewContent::scrollTo(AbstractTreeItem *newlySelectedItem) {
573 if (newlySelectedItem->getPointerType() == AbstractTreeItem::Measure)
574 newlySelectedItem->parent()->setExpanded(
true);
576 int row = getModel()->indexOfVisibleItem(newlySelectedItem);
579 int topRow = verticalScrollBar()->value();
582 verticalScrollBar()->setValue(row);
585 int wholeVisibleRowCount = viewport()->height() / m_rowHeight;
586 int bottomRow = topRow + wholeVisibleRowCount;
588 verticalScrollBar()->setValue(row - wholeVisibleRowCount + 1);
592 viewport()->update();