3 #include "TableViewHeader.h"
7 #include <QAbstractItemModel>
8 #include <QFontMetrics>
10 #include <QLinearGradient>
12 #include <QMessageBox>
13 #include <QMouseEvent>
18 #include <QVBoxLayout>
20 #include "TableColumn.h"
21 #include "TableColumnList.h"
22 #include "TableView.h"
23 #include "AbstractTreeModel.h"
24 #include "AbstractTableModel.h"
29 TableViewHeader::TableViewHeader(AbstractTableModel *someModel) {
32 m_horizontalOffset = 0;
34 m_filterProgressMin = 0;
35 m_filterProgressMax = 0;
36 m_rebuildProgress = 0;
37 m_rebuildProgressMin = 0;
38 m_rebuildProgressMax = 0;
40 m_sortProgressMin = 0;
41 m_sortProgressMax = 0;
45 m_clickedColumnEdge = -1;
48 setMouseTracking(
true);
57 TableViewHeader::~TableViewHeader() {
62 void TableViewHeader::setColumns(TableColumnList *cols) {
67 QSize TableViewHeader::minimumSizeHint()
const {
68 return QSize(0, QFontMetrics(font()).height() + 6);
74 QSize TableViewHeader::sizeHint()
const {
75 return minimumSizeHint();
79 void TableViewHeader::setModel(AbstractTableModel *someModel) {
81 disconnect(m_model, SIGNAL(filterProgressChanged(
int)),
82 this, SLOT(updateFilterProgress(
int)));
83 disconnect(m_model, SIGNAL(rebuildProgressChanged(
int)),
84 this, SLOT(updateRebuildProgress(
int)));
85 disconnect(m_model, SIGNAL(sortProgressChanged(
int)),
86 this, SLOT(updateSortProgress(
int)));
87 disconnect(m_model, SIGNAL(filterProgressRangeChanged(
int,
int)),
88 this, SLOT(updateFilterProgressRange(
int,
int)));
89 disconnect(m_model, SIGNAL(rebuildProgressRangeChanged(
int,
int)),
90 this, SLOT(updateRebuildProgressRange(
int,
int)));
91 disconnect(m_model, SIGNAL(sortProgressRangeChanged(
int,
int)),
92 this, SLOT(updateSortProgressRange(
int,
int)));
93 disconnect(m_model, SIGNAL(filterCountsChanged(
int,
int)),
94 this, SLOT(handleFilterCountsChanged(
int,
int)));
95 disconnect(
this, SIGNAL(requestedGlobalSelection(
bool)),
96 m_model, SLOT(setGlobalSelection(
bool)));
97 disconnect(m_model, SIGNAL(m_modelModified()),
98 this, SLOT(update()));
103 connect(m_model, SIGNAL(filterProgressChanged(
int)),
104 this, SLOT(updateFilterProgress(
int)));
105 connect(m_model, SIGNAL(rebuildProgressChanged(
int)),
106 this, SLOT(updateRebuildProgress(
int)));
107 connect(m_model, SIGNAL(sortProgressChanged(
int)),
108 this, SLOT(updateSortProgress(
int)));
109 connect(m_model, SIGNAL(filterProgressRangeChanged(
int,
int)),
110 this, SLOT(updateFilterProgressRange(
int,
int)));
111 connect(m_model, SIGNAL(rebuildProgressRangeChanged(
int,
int)),
112 this, SLOT(updateRebuildProgressRange(
int,
int)));
113 connect(m_model, SIGNAL(sortProgressRangeChanged(
int,
int)),
114 this, SLOT(updateSortProgressRange(
int,
int)));
115 connect(m_model, SIGNAL(filterCountsChanged(
int,
int)),
116 this, SLOT(handleFilterCountsChanged(
int,
int)));
117 connect(
this, SIGNAL(requestedGlobalSelection(
bool)),
118 m_model, SLOT(setGlobalSelection(
bool)));
119 connect(m_model, SIGNAL(modelModified()),
this, SLOT(update()));
123 for (
int i = 0; i < m_columns->size(); i++) {
124 disconnect((*m_columns)[i], SIGNAL(visibilityChanged()),
125 this, SLOT(update()));
129 m_columns = m_model->getColumns();
131 for (
int i = 0; i < m_columns->size(); i++)
132 connect((*m_columns)[i], SIGNAL(visibilityChanged()),
this, SLOT(update()));
136 void TableViewHeader::handleFilterCountsChanged(
137 int visibleTopLevelItemCount,
int topLevelItemCount) {
138 m_visibleCount = visibleTopLevelItemCount;
139 m_totalCount = topLevelItemCount;
141 if (m_visibleCount >= 0) {
142 TableColumnList visibleCols = m_columns->getVisibleColumns();
143 for (
int i = 0; i < visibleCols.size(); i++) {
144 TableColumn *& col = visibleCols[i];
146 if (col->getTitle().isEmpty())
147 col->setWidth(QFontMetrics(font()).width(
148 QString::number(m_visibleCount)) + 22);
157 void TableViewHeader::updateHeaderOffset(
int newOffset) {
158 m_horizontalOffset = newOffset;
163 void TableViewHeader::mousePressEvent(QMouseEvent *event) {
164 QPoint mousePos =
event->pos();
166 m_clickedColumn = getMousedColumn(mousePos);
172 if (event->buttons() == Qt::LeftButton) {
173 m_clickedColumnEdge = getMousedColumnEdge(mousePos);
174 if (m_clickedColumnEdge == -1 && m_clickedColumn != -1) {
176 if (m_columns->getVisibleColumns()[m_clickedColumn]->getTitle().isEmpty()) {
177 emit requestedGlobalSelection(
true);
191 void TableViewHeader::mouseMoveEvent(QMouseEvent *event) {
192 QPoint mousePos =
event->pos();
194 if (m_clickedColumnEdge >= 0) {
196 QRect columnToResizeRect(getColumnRect(m_clickedColumnEdge));
197 columnToResizeRect.setRight(mousePos.x());
199 TableColumn *col = m_columns->getVisibleColumns()[m_clickedColumnEdge];
202 if (columnToResizeRect.width() > 1) {
203 newWidth = columnToResizeRect.width();
204 if (m_columns->getSortingOrder()[0] == col)
205 newWidth = qMax(newWidth, ARROW_WIDTH + SORT_ARROW_MARGIN * 2);
208 m_columns->getVisibleColumns()[m_clickedColumnEdge]->setWidth(newWidth);
211 if (mouseAtResizableColumnEdge(mousePos)) {
212 setCursor(Qt::SizeHorCursor);
215 setCursor(Qt::ArrowCursor);
222 void TableViewHeader::mouseReleaseEvent(QMouseEvent *event) {
224 m_clickedColumnEdge >= m_columns->getVisibleColumns().size() - 2;
225 if (m_clickedColumnEdge != -1) {
226 emit columnResized(wasLastCol);
229 if (m_clickedColumn == getMousedColumn(event->pos())) {
230 TableColumn *col = m_columns->getVisibleColumns()[m_clickedColumn];
232 TableColumn
const *sortCol =
233 m_columns->getVisibleColumns().getSortingOrder()[0];
236 col->setSortAscending(!col->sortAscending());
238 m_columns->raiseToTop(col);
240 if (!m_model->sortingOn()) {
241 QMessageBox::information(
this, tr(
"Sorting Disabled"),
242 tr(
"Sorting is currently disabled for this table. Please configure your sorting "
243 "options before trying to sort by [<font color='red'>%1</font>].")
244 .arg(col->getTitle()),
250 m_clickedColumnEdge = -1;
251 m_clickedColumn = -1;
257 void TableViewHeader::paintEvent(QPaintEvent *event) {
258 QPainter painter(
this);
259 painter.setRenderHints(QPainter::Antialiasing |
260 QPainter::TextAntialiasing);
262 ARROW_HEIGHT = qMax(height() / 5, 3);
263 ASSERT(height() > 8);
264 ARROW_WIDTH = ARROW_HEIGHT * 2 - 1;
266 paintHeader(&painter, height());
272 void TableViewHeader::nullify() {
278 QRect TableViewHeader::getColumnRect(
int column)
const {
281 TableColumnList visibleCols = m_columns->getVisibleColumns();
283 if (column < visibleCols.size() && column >= 0) {
286 for (
int i = 0; i < column; i++)
287 indent += visibleCols[i]->getWidth() - 1;
289 colRect = QRect(indent - m_horizontalOffset, 0,
290 visibleCols[column]->getWidth(), height());
297 int TableViewHeader::getMousedColumn(QPoint mousePos) {
298 int mousedColumn = -1;
301 i < m_columns->getVisibleColumns().size() && mousedColumn < 0;
303 QRect columnRect(getColumnRect(i));
304 if (columnRect.contains(mousePos))
312 int TableViewHeader::getMousedColumnEdge(QPoint mousePos) {
315 if (mouseAtResizableColumnEdge(mousePos)) {
316 int mousedColumn = getMousedColumn(mousePos);
318 QRect columnRect(getColumnRect(mousedColumn));
322 if (mousePos.x() - columnRect.left() < TableColumn::EDGE_WIDTH)
323 edge = mousedColumn - 1;
332 bool TableViewHeader::mouseAtResizableColumnEdge(QPoint mousePos) {
333 int columnNum = getMousedColumn(mousePos);
335 QRect columnRect(getColumnRect(columnNum));
337 bool isAtColumnEdge =
false;
339 if (!columnRect.isNull()) {
341 mousePos.x() - columnRect.left() < TableColumn::EDGE_WIDTH;
343 columnRect.right() - mousePos.x() < TableColumn::EDGE_WIDTH;
344 bool isResizable =
false;
346 TableColumnList visCols = m_columns->getVisibleColumns();
347 if (isOnLeft && columnNum > 0)
348 isResizable = visCols[columnNum - 1]->getTitle().size();
350 isResizable = visCols[columnNum]->getTitle().size();
352 isAtColumnEdge = (isOnLeft || isOnRight) && isResizable;
355 return isAtColumnEdge;
359 void TableViewHeader::paintHeader(QPainter *painter,
int rowHeight) {
360 int visibleColWidth = -m_horizontalOffset;
361 TableColumnList visibleCols = m_columns->getVisibleColumns();
363 for (
int i = 0; i < visibleCols.size(); i++)
364 visibleColWidth += visibleCols[i]->getWidth() - 1;
366 QRect rect(0, 0, qMin(width(), visibleColWidth), rowHeight);
368 int x = rect.center().x();
369 QLinearGradient gradient(x, rect.top(), x, rect.bottom());
372 bool selected =
false;
373 QColor color = selected ? palette().highlight().color() :
374 palette().button().color();
377 int adjustment = 110;
378 gradient.setColorAt(0, color.lighter(adjustment));
379 gradient.setColorAt(1, color.darker(adjustment));
380 painter->fillRect(rect, gradient);
384 QBrush brush = painter->brush();
385 QPainter::CompositionMode compMode = painter->compositionMode();
386 painter->setCompositionMode(QPainter::CompositionMode_SourceOver);
389 painter->setBrush(QBrush(QColor(0, 70, 100, 30)));
390 paintProgress(painter, rect, m_filterProgressMin, m_filterProgressMax,
391 m_filterProgress,
false);
394 painter->setBrush(QBrush(QColor(100, 70, 0, 30)));
395 paintProgress(painter, rect, m_rebuildProgressMin, m_rebuildProgressMax,
396 m_rebuildProgress,
false);
399 painter->setBrush(QBrush(QColor(0, 100, 0, 30)));
400 paintProgress(painter, rect, m_sortProgressMin, m_sortProgressMax,
401 m_sortProgress,
true);
405 painter->setBrush(brush);
406 painter->setCompositionMode(compMode);
408 for (
int i = 0; i < visibleCols.size(); i++) {
409 TableColumn *visibleCol = visibleCols[i];
411 QString columnText = visibleCol->getTitle();
412 QRect columnRect(getColumnRect(visibleCols.indexOf(visibleCol)));
413 QPen pen(palette().dark().color().darker(150));
414 pen.setCapStyle(Qt::RoundCap);
415 painter->setPen(pen);
416 painter->drawLine(columnRect.topLeft() + QPoint(0, 1),
417 columnRect.bottomLeft() + QPoint(0, 1));
419 painter->drawLine(columnRect.topLeft() + QPoint(1, 0),
420 columnRect.topRight() - QPoint(0, 0));
422 painter->drawLine(columnRect.topLeft() + QPoint(1, 1),
423 columnRect.topRight() + QPoint(0, 1));
425 painter->drawLine(columnRect.bottomLeft() + QPoint(1, 1),
426 columnRect.bottomRight() + QPoint(0, 1));
428 painter->drawLine(columnRect.bottomLeft() + QPoint(1, 1),
429 columnRect.bottomRight() + QPoint(0, 1));
431 painter->drawLine(columnRect.topRight() + QPoint(0, 1),
432 columnRect.bottomRight() - QPoint(0, 0));
434 painter->setPen(selected ? palette().highlightedText().color() :
435 palette().buttonText().color());
437 QRect textRect(columnRect.x(),
439 columnRect.width() - (SORT_ARROW_MARGIN * 2 + ARROW_WIDTH),
440 columnRect.height());
441 painter->drawText(textRect , Qt::AlignCenter | Qt::TextSingleLine,
444 if (visibleCol == visibleCols.getSortingOrder()[0] &&
445 visibleCol->getWidth() >= SORT_ARROW_MARGIN * 2 + ARROW_WIDTH) {
446 ASSERT(SORT_ARROW_MARGIN > 0);
448 QRect arrowRect(textRect.right() + 1,
450 SORT_ARROW_MARGIN * 2 + ARROW_WIDTH,
453 ASSERT(arrowRect.width() + textRect.width() == columnRect.width());
454 ASSERT(arrowRect.right() == columnRect.right());
458 QPoint left(arrowRect.left() + SORT_ARROW_MARGIN,
459 arrowRect.center().y() - ((ARROW_HEIGHT - 1) / 2));
461 int yOffSet = ((ARROW_HEIGHT - 1) / 2);
462 if (ARROW_HEIGHT % 2 == 0)
464 QPoint center(left.x() + ((ARROW_WIDTH - 1) / 2),
465 arrowRect.center().y() + yOffSet);
467 QPoint right(center.x() + ((ARROW_WIDTH - 1) / 2),
468 arrowRect.center().y() - ((ARROW_HEIGHT - 1) / 2));
470 ASSERT(right.x() == arrowRect.right() - SORT_ARROW_MARGIN);
471 ASSERT(right.x() - center.x() == center.x() - left.x());
473 if (!visibleCol->sortAscending()) {
475 left.setY(center.y());
476 center.setY(right.y());
477 right.setY(left.y());
480 if (m_model->sortingOn()) {
481 painter->drawLine(left, center);
482 painter->drawLine(center, right);
487 columnRect.moveLeft(columnRect.right());
492 void TableViewHeader::paintProgress(QPainter *painter,
493 const QRect &rect,
int min,
int max,
int value,
bool over100) {
494 double progressPercent = 1.0;
495 int progressRange = max - min;
497 if (progressRange > 0)
498 progressPercent = ((double)(value - min)) / progressRange;
499 else if (progressRange == 0)
502 if (progressPercent < 1.0 || over100) {
503 QRect progressRect(rect);
504 progressRect.setWidth((
int)(progressRect.width() * progressPercent));
505 painter->fillRect(progressRect, painter->brush());
510 void TableViewHeader::updateFilterProgress(
int newProgress) {
511 m_filterProgress = newProgress;
516 void TableViewHeader::updateFilterProgressRange(
int min,
int max) {
517 m_filterProgressMin = min;
518 m_filterProgressMax = max;
523 void TableViewHeader::updateRebuildProgress(
int newProgress) {
524 m_rebuildProgress = newProgress;
529 void TableViewHeader::updateRebuildProgressRange(
int min,
int max) {
530 m_rebuildProgressMin = min;
531 m_rebuildProgressMax = max;
536 void TableViewHeader::updateSortProgress(
int newProgress) {
537 m_sortProgress = newProgress;
542 void TableViewHeader::updateSortProgressRange(
int min,
int max) {
543 m_sortProgressMin = min;
544 m_sortProgressMax = max;