9#include "TreeViewContent.h"
21#include <QtCore/qtextstream.h>
25#include "IException.h"
28#include "AbstractTreeItem.h"
29#include "TableColumn.h"
30#include "AbstractTreeModel.h"
34 TreeViewContent::TreeViewContent(QWidget *parent) :
35 QAbstractScrollArea(parent) {
38 m_parentView = (TreeView *) parent;
41 m_mousePressPos =
new QPoint;
46 verticalScrollBar()->setSingleStep(1);
47 horizontalScrollBar()->setSingleStep(10);
48 m_rowHeight = QFontMetrics(font()).height() + ITEM_PADDING;
51 setMouseTracking(
true);
52 setContextMenuPolicy(Qt::ActionsContextMenu);
53 QAction *alternateRowsAct =
new QAction(
"&Alternate row colors",
this);
54 alternateRowsAct->setCheckable(
true);
55 connect(alternateRowsAct, SIGNAL(toggled(
bool)),
56 this, SLOT(setAlternatingRowColors(
bool)));
57 addAction(alternateRowsAct);
58 alternateRowsAct->setChecked(
true);
62 TreeViewContent::~TreeViewContent() {
66 delete m_mousePressPos;
67 m_mousePressPos = NULL;
75 delete m_lastShiftSelection;
76 m_lastShiftSelection = NULL;
80 QSize TreeViewContent::minimumSizeHint()
const {
81 return QWidget::minimumSizeHint();
85 QSize TreeViewContent::sizeHint()
const {
86 return minimumSizeHint();
90 AbstractTreeModel *TreeViewContent::getModel() {
95 void TreeViewContent::setModel(AbstractTreeModel *someModel) {
97 IString msg =
"Attempted to set a NULL model!";
98 throw IException(IException::Programmer, msg, _FILEINFO_);
102 disconnect(m_model, SIGNAL(modelModified()),
this, SLOT(refresh()));
103 disconnect(m_model, SIGNAL(filterProgressChanged(
int)),
104 this, SLOT(updateItemList()));
114 connect(m_model, SIGNAL(modelModified()),
this, SLOT(refresh()));
115 connect(m_model, SIGNAL(filterProgressChanged(
int)),
116 this, SLOT(updateItemList()));
126 void TreeViewContent::refresh() {
129 if (!m_model->isFiltering()) {
130 QSize modelVisibleSize =
131 m_model->getVisibleSize(ITEM_INDENTATION);
132 int rowCount = modelVisibleSize.height();
133 m_contentWidth = modelVisibleSize.width() + ITEM_INDENTATION;
134 verticalScrollBar()->setRange(0, qMax(rowCount - 1, 0));
135 horizontalScrollBar()->setRange(0, m_contentWidth - viewport()->width()
136 + horizontalScrollBar()->singleStep());
140 viewport()->update();
145 bool TreeViewContent::eventFilter(
QObject *target, QEvent *event) {
146 return QObject::eventFilter(target, event);
150 void TreeViewContent::mouseDoubleClickEvent(QMouseEvent *event) {
151 QPoint pressPos =
event->pos();
152 int index = pressPos.y() / m_rowHeight;
154 if (index < m_items->size()) {
155 AbstractTreeItem *item = (*m_items)[index];
156 item->setExpanded(!item->isExpanded());
161 void TreeViewContent::mousePressEvent(QMouseEvent *event) {
162 QPoint pressPos =
event->pos();
163 int index = pressPos.y() / m_rowHeight;
165 m_pressedItem->first = NULL;
166 m_pressedItem->second =
false;
168 if (index < m_items->size()) {
169 AbstractTreeItem *item = (*m_items)[index];
170 if (item->isSelectable() ||
171 (item->getFirstVisibleChild() &&
172 getArrowRect(item).contains(pressPos))) {
173 m_pressedItem->first = item;
175 if (item->getFirstVisibleChild()) {
176 QRect arrowRect(getArrowRect(item));
177 m_pressedItem->second = arrowRect.contains(pressPos);
181 if (!m_pressedItem->second) {
182 if (event->modifiers() & Qt::ControlModifier) {
183 foreach (AbstractTreeItem * child, item->getChildren()) {
184 child->setSelected(!item->isSelected());
185 if (child->isSelected())
186 newlySelectedItems.append(child);
189 item->setSelected(!item->isSelected());
190 if (item->isSelected())
191 newlySelectedItems.append(item);
193 m_lastDirectlySelectedItem = item;
194 m_lastShiftSelection->clear();
197 if (event->modifiers() & Qt::ShiftModifier) {
198 foreach (AbstractTreeItem * i, *m_lastShiftSelection)
199 i->setSelected(
false);
201 if (m_lastDirectlySelectedItem) {
204 m_model->getItems(m_lastDirectlySelectedItem, item);
208 foreach (AbstractTreeItem * i, tmp) {
209 m_lastShiftSelection->append(i);
212 if (i->getPointerType() == AbstractTreeItem::Point) {
213 foreach (AbstractTreeItem * child, i->getChildren()) {
214 child->setSelected(
true);
215 m_lastShiftSelection->append(child);
221 m_lastShiftSelection->clear();
224 foreach (AbstractTreeItem * i, *m_lastShiftSelection) {
225 i->setSelected(
true);
226 newlySelectedItems.append(i);
230 m_model->setGlobalSelection(
false);
231 item->setSelected(
true);
232 newlySelectedItems.append(item);
233 m_lastDirectlySelectedItem = item;
235 if (item->getPointerType() == AbstractTreeItem::Point) {
236 foreach (AbstractTreeItem * child, item->getChildren()) {
237 child->setSelected(
true);
238 newlySelectedItems.append(child);
242 m_lastShiftSelection->clear();
246 emit treeSelectionChanged(newlySelectedItems);
251 m_model->setGlobalSelection(
false);
254 viewport()->update();
258 void TreeViewContent::mouseReleaseEvent(QMouseEvent *event) {
259 AbstractTreeItem *item = m_pressedItem->first;
260 if (item && getArrowRect(item).contains(event->pos())) {
261 item->setExpanded(!item->isExpanded());
265 m_pressedItem->first = NULL;
266 m_pressedItem->second =
false;
267 viewport()->update();
269 QWidget::mousePressEvent(event);
273 void TreeViewContent::mouseMoveEvent(QMouseEvent *event) {
274 QPoint cursorPos =
event->pos();
275 int index = cursorPos.y() / m_rowHeight;
277 m_hoveredItem->first = NULL;
278 m_hoveredItem->second =
false;
280 if (index < m_items->size() && index >= 0) {
281 AbstractTreeItem *item = (*m_items)[index];
282 if (item->isSelectable() ||
283 (item->getFirstVisibleChild() &&
284 getArrowRect(item).contains(cursorPos))) {
285 m_hoveredItem->first = item;
287 if (item->getFirstVisibleChild()) {
288 QRect arrowRect = getArrowRect(item);
289 m_hoveredItem->second = arrowRect.contains(cursorPos);
294 viewport()->update();
298 void TreeViewContent::leaveEvent(QEvent *event) {
299 m_hoveredItem->first = NULL;
300 m_hoveredItem->second =
false;
301 viewport()->update();
305 void TreeViewContent::keyPressEvent(QKeyEvent *event) {
306 if (event->key() == Qt::Key_A &&
307 event->modifiers() == Qt::ControlModifier) {
308 m_model->setGlobalSelection(
true);
309 viewport()->update();
310 emit treeSelectionChanged();
313 QWidget::keyPressEvent(event);
318 void TreeViewContent::paintEvent(QPaintEvent *event) {
320 int startRow = verticalScrollBar()->value();
321 int rowCount = (int) ceil(viewport()->height() / (
double) m_rowHeight);
323 QPainter painter(viewport());
324 painter.setRenderHints(QPainter::Antialiasing |
325 QPainter::TextAntialiasing);
327 for (
int i = 0; i < rowCount; i++) {
331 QColor backgroundColor = palette().base().color();
333 if (i < m_items->size()) {
334 if (m_alternatingRowColors && (startRow + i) % 2 == 1)
335 backgroundColor = palette().alternateBase().color();
337 if (m_items->at(i)->isSelected())
338 backgroundColor = palette().highlight().color();
342 QPoint relativeTopLeft(0, i * m_rowHeight);
343 QPoint scrollBarPos(horizontalScrollBar()->value(),
344 verticalScrollBar()->value());
345 QPoint absoluteTopLeft(relativeTopLeft + scrollBarPos);
346 QSize rowSize(viewport()->width(), (
int) m_rowHeight);
349 painter.fillRect(QRect(relativeTopLeft, rowSize), backgroundColor);
353 if (i < m_items->size() && m_hoveredItem->first == (*m_items)[i] &&
354 m_hoveredItem->first->isSelectable()) {
355 QPen prevPen(painter.pen());
356 QPen borderPen(prevPen);
357 borderPen.setWidth(1);
358 borderPen.setColor(palette().highlight().color());
359 painter.setPen(borderPen);
360 QPoint borderTopLeft(relativeTopLeft.x() - absoluteTopLeft.x(),
361 relativeTopLeft.y() + 1);
363 int rectWidth = qMax(m_contentWidth +
364 horizontalScrollBar()->singleStep(), viewport()->width());
365 QSize borderSize(rectWidth, rowSize.height() - 2);
366 painter.drawRect(QRect(borderTopLeft, borderSize));
367 painter.setPen(prevPen);
371 if (i < m_items->size())
372 paintItemText(&painter, i, absoluteTopLeft, relativeTopLeft);
376 QWidget::paintEvent(event);
381 void TreeViewContent::resizeEvent(QResizeEvent *event) {
382 QAbstractScrollArea::resizeEvent(event);
383 horizontalScrollBar()->setRange(0, m_contentWidth - viewport()->width()
384 + horizontalScrollBar()->singleStep());
389 void TreeViewContent::scrollContentsBy(
int dx,
int dy) {
390 QAbstractScrollArea::scrollContentsBy(dx, dy);
395 void TreeViewContent::nullify() {
399 m_pressedItem = NULL;
400 m_hoveredItem = NULL;
401 m_lastDirectlySelectedItem = NULL;
402 m_lastShiftSelection = NULL;
403 m_mousePressPos = NULL;
407 void TreeViewContent::paintItemText(QPainter *painter,
408 int index, QPoint absolutePosition, QPoint relativePosition) {
410 QPoint point(-absolutePosition.x(), relativePosition.y());
412 AbstractTreeItem *item = (*m_items)[index];
426 AbstractTreeItem *iteratorItem = item;
427 while (iteratorItem->parent() && iteratorItem->parent()->parent()) {
428 point.setX(point.x() + ITEM_INDENTATION);
429 iteratorItem = iteratorItem->parent();
432 QPen originalPen = painter->pen();
433 if (item->isSelected()) {
434 painter->setPen(QPen(palette().highlightedText().color()));
440 if (item->getFirstVisibleChild()) {
443 QRect itemArrowRect(getArrowRect(item));
444 if (item == m_hoveredItem->first && item == m_pressedItem->first) {
445 if (m_pressedItem->second && m_hoveredItem->second) {
446 QPainter::CompositionMode prevMode = painter->compositionMode();
447 painter->setCompositionMode(QPainter::CompositionMode_SourceOver);
448 QColor color = palette().button().color().darker(160);
450 painter->fillRect(itemArrowRect, color);
451 painter->setCompositionMode(prevMode);
457 if ((item == m_hoveredItem->first && m_hoveredItem->second) ||
458 (item == m_pressedItem->first && m_pressedItem->second)) {
459 if (!m_pressedItem->first ||
460 (item == m_pressedItem->first && m_pressedItem->second)) {
461 painter->drawRect(itemArrowRect);
466 if (item->isExpanded())
467 drawExpandedArrow(painter, itemArrowRect);
469 drawCollapsedArrow(painter, itemArrowRect);
474 point.setX(point.x() + ITEM_INDENTATION);
477 point.setY(point.y() + ITEM_PADDING / 2);
480 int textHeight = m_rowHeight - ITEM_PADDING;
481 QRect rect(point, QSize(viewport()->width() - point.x(), textHeight));
482 painter->drawText(rect, Qt::TextDontClip, item->getData().toString());
483 painter->setPen(originalPen);
488 void TreeViewContent::drawCollapsedArrow(QPainter *painter, QRect rect) {
489 rect.setTopLeft(rect.topLeft() + QPoint(4, 3));
490 rect.setBottomRight(rect.bottomRight() - QPoint(4, 2));
492 QPoint top(rect.topLeft());
493 QPoint bottom(rect.bottomLeft());
494 QPoint right(rect.right(), rect.center().y());
496 QPen prevPen = painter->pen();
497 QPen arrowPen(prevPen);
498 arrowPen.setCapStyle(Qt::RoundCap);
499 arrowPen.setJoinStyle(Qt::RoundJoin);
500 arrowPen.setWidth(2);
501 painter->setPen(arrowPen);
502 painter->drawLine(top, right);
503 painter->drawLine(bottom, right);
504 painter->setPen(prevPen);
508 void TreeViewContent::drawExpandedArrow(QPainter *painter, QRect rect) {
509 rect.setTopLeft(rect.topLeft() + QPoint(3, 4));
510 rect.setBottomRight(rect.bottomRight() - QPoint(2, 4));
512 QPoint left(rect.topLeft());
513 QPoint right(rect.topRight());
514 QPoint bottom(rect.center().x(), rect.bottom());
516 QPen prevPen = painter->pen();
517 QPen arrowPen(prevPen);
518 arrowPen.setCapStyle(Qt::RoundCap);
519 arrowPen.setJoinStyle(Qt::RoundJoin);
520 arrowPen.setWidth(2);
521 painter->setPen(arrowPen);
522 painter->drawLine(left, bottom);
523 painter->drawLine(right, bottom);
524 painter->setPen(prevPen);
528 void TreeViewContent::setAlternatingRowColors(
bool newStatus) {
529 m_alternatingRowColors = newStatus;
530 viewport()->update();
534 void TreeViewContent::updateItemList() {
535 int startRow = verticalScrollBar()->value();
536 int rowCount = (int) ceil(viewport()->height() / (
double) m_rowHeight);
537 *m_items = m_model->getItems(startRow, startRow + rowCount,
538 AbstractTreeModel::AllItems,
false);
540 viewport()->update();
544 QRect TreeViewContent::getArrowRect(AbstractTreeItem *item)
const {
547 int index = m_items->indexOf(item);
548 QPoint centerOfArrow(12 - horizontalScrollBar()->value(),
549 (index * m_rowHeight) + (m_rowHeight / 2));
550 int depth = item->getDepth() - 1;
551 centerOfArrow.setX(centerOfArrow.x() + (depth * ITEM_INDENTATION));
553 arrowRect = QRect(centerOfArrow.x() - 6, centerOfArrow.y() - 6, 12, 12);
559 void TreeViewContent::scrollTo(
561 if (newlySelectedItems.size())
562 scrollTo(newlySelectedItems.last());
566 void TreeViewContent::scrollTo(AbstractTreeItem *newlySelectedItem) {
567 if (newlySelectedItem->getPointerType() == AbstractTreeItem::Measure)
568 newlySelectedItem->parent()->setExpanded(
true);
570 int row = getModel()->indexOfVisibleItem(newlySelectedItem);
573 int topRow = verticalScrollBar()->value();
576 verticalScrollBar()->setValue(row);
579 int wholeVisibleRowCount = viewport()->height() / m_rowHeight;
580 int bottomRow = topRow + wholeVisibleRowCount;
582 verticalScrollBar()->setValue(row - wholeVisibleRowCount + 1);
586 viewport()->update();
This is free and unencumbered software released into the public domain.
This is free and unencumbered software released into the public domain.
This is free and unencumbered software released into the public domain.