summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarius Bugge Monsen <mmonsen@trolltech.com>2009-05-29 17:46:44 +0200
committerMarius Bugge Monsen <mmonsen@trolltech.com>2009-05-29 17:46:44 +0200
commit50aa984a068f050c115b985c549419be6874f6b9 (patch)
tree1bb95235d2ae11844519d6bccdaf850a9cb4e2d6
parentd77f9ba2ab3d22ce9d7cde8ee03655cb3fadb43e (diff)
Refactor the QtGraphicsTableView layout function.
-rw-r--r--src/qgraphicstableview.cpp160
-rw-r--r--src/qgraphicstableview.h2
-rw-r--r--src/qgraphicstableview_p.h5
3 files changed, 123 insertions, 44 deletions
diff --git a/src/qgraphicstableview.cpp b/src/qgraphicstableview.cpp
index 643b83a..e7fe534 100644
--- a/src/qgraphicstableview.cpp
+++ b/src/qgraphicstableview.cpp
@@ -25,11 +25,11 @@
#include "qgraphicstableview_p.h"
#include "qtablemodelinterface.h"
-#include "qtableselectionmanager.h"
#include "qgraphicsheader.h"
#include "qtablecontroller.h"
#include <qdebug.h>
+#include <qstack.h>
#include <qpainter.h>
#include <qstyle.h>
#include <qstyleoption.h>
@@ -112,8 +112,8 @@ void QtGraphicsTableViewItem::itemChanged(const QList<int> &roles)
{
Q_UNUSED(roles);
// ### if the size changed, we need to let the layout know
- prepareGeometryChange();
- update();
+ //prepareGeometryChange();
+ //update();
}
QHash<int, QVariant> QtGraphicsTableViewItem::data(const QList<int> &roles) const
@@ -138,19 +138,19 @@ void QtGraphicsTableViewItem::paint(QPainter *painter, const QStyleOptionGraphic
d->view->initStyleOption(&d->option);
d->view->copyStyleOptionState(option, &d->option);
d->view->initStyleOption(&d->option, d->row, d->column);
- d->option.rect = QRectF(QPointF(), size()).toRect();
+ const QRect rect = QRectF(QPointF(), size()).toRect();
+ d->option.rect = rect;
style()->drawControl(QStyle::CE_ItemViewItem, &d->option, painter, widget);
// draw grid
const QColor gridColor = static_cast<QRgb>(style()->styleHint(QStyle::SH_Table_GridLineColor, &d->option, widget));
-// TODO check for option and make the left+top painting ones actually work
// left
- //painter->fillRect(d->option.rect.left(), d->option.rect.bottom(), d->option.rect.width(), 1, gridColor);
+ //painter->fillRect(rect.left(), rect.bottom(), rect.width(), 1, gridColor);
// top
- //painter->fillRect(d->option.rect.right(), d->option.rect.top(), 1, d->option.rect.height(), gridColor);
+ //painter->fillRect(right(), d->option.rect.top(), 1, rect.height(), gridColor);
// right
- painter->fillRect(d->option.rect.left(), d->option.rect.bottom(), d->option.rect.width(), 1, gridColor);
+ painter->fillRect(rect.left(), rect.bottom(), rect.width(), 1, gridColor);
// bottom
- painter->fillRect(d->option.rect.right(), d->option.rect.top(), 1, d->option.rect.height(), gridColor);
+ painter->fillRect(rect.right(), rect.top(), 1, rect.height(), gridColor);
}
/*!
\class QtGraphicsTableViewItemCreatorBase
@@ -241,12 +241,18 @@ void QtGraphicsTableViewPrivate::_q_cellsChanged(int firstRow, int firstColumn,
void QtGraphicsTableViewPrivate::_q_selectionsChanged(const QList<QtTableSelectionRange> &changed)
{
// ### FIXME: naive lookup
- for (int i = 0; i < items.count(); ++i) {
- for (int j = 0; j < changed.count(); ++j) {
- QtGraphicsTableViewItem *item = items.at(i);
- if (changed.at(j).containsCell(item->row(), item->column())) {
- item->update();
- break;
+ // ### FIXME: check header mappings
+ if (!model)
+ return;
+ const int columnCount = model->columnCount();
+ for (int j = 0; j < changed.count(); ++j) {
+ QtTableSelectionRange range = changed.at(j);
+ if (range.intersects(visibleSections)) {
+ for (int row = range.topRow(); row <= range.bottomRow(); ++row) {
+ for (int column = range.leftColumn(); column <= range.rightColumn(); ++column) {
+ if (QtGraphicsTableViewItem *item = items.value((row * columnCount) + column))
+ item->update();
+ }
}
}
}
@@ -254,14 +260,13 @@ void QtGraphicsTableViewPrivate::_q_selectionsChanged(const QList<QtTableSelecti
void QtGraphicsTableViewPrivate::_q_currentChanged(int currentRow, int currentColumn, int previousRow, int previousColumn)
{
- Q_UNUSED(previousColumn);
- Q_UNUSED(previousRow);
- // ### FIXME: naive lookup
- for (int i = 0; i < items.count(); ++i) {
- QtGraphicsTableViewItem *item = items.at(i);
- if (item->row() == currentRow && item->column() == currentColumn)
- item->update();
- }
+ if (!model)
+ return;
+ const int columnCount = model->columnCount();
+ if (QtGraphicsTableViewItem *current = items.value((currentRow * columnCount) + currentColumn))
+ current->update();
+ if (QtGraphicsTableViewItem *previous = items.value((previousRow * columnCount) + previousColumn))
+ previous->update();
}
void QtGraphicsTableViewPrivate::_q_rowsInserted(int row, int count)
@@ -948,6 +953,9 @@ void QtGraphicsTableView::doLayout()
if (area.isEmpty())
return;
+ const int columnCount = d->model->columnCount();
+ const int rowCount = d->model->rowCount();
+
int horizontalCount;
qreal horizontalOffset;
QVector<int> horizontalMapping;
@@ -957,7 +965,7 @@ void QtGraphicsTableView::doLayout()
horizontalOffset = d->horizontalHeader->offset();
horizontalMapping = d->horizontalHeader->indexMapping();
} else {
- horizontalCount = qMin(d->model->columnCount(), int(area.width() / d->defaultColumnWidth));
+ horizontalCount = qMin(columnCount, int(area.width() / d->defaultColumnWidth));
horizontalOffset = d->horizontalOffset;
}
@@ -970,30 +978,93 @@ void QtGraphicsTableView::doLayout()
verticalOffset = d->verticalHeader->offset();
verticalMapping = d->verticalHeader->indexMapping();
} else {
- verticalCount = qMin(d->model->rowCount(), int(area.height() / d->defaultRowHeight));
+ verticalCount = qMin(rowCount, int(area.height() / d->defaultRowHeight));
verticalOffset = d->verticalOffset;
}
- const int lastColumn = qMax(d->firstColumn + horizontalCount - 1, 0);
- const int lastRow = qMax(d->firstRow + verticalCount - 1, 0);
- const int firstIndex = (d->firstRow * horizontalCount) + d->firstColumn;
+ const int firstHorizontalSection = d->firstColumn;
+ const int firstVerticalSection = d->firstRow;
+ const int lastHorizontalSection = qMax(d->firstColumn + horizontalCount - 1, -1);
+ const int lastVerticalSection = qMax(d->firstRow + verticalCount - 1, -1);
+
+ const int oldFirstVerticalSection = d->visibleSections.topRow();
+ const int oldFirstHorizontalSection = d->visibleSections.leftColumn();
+ const int oldLastVerticalSection = d->visibleSections.bottomRow();
+ const int oldLastHorizontalSection = d->visibleSections.rightColumn();
+
+ // find unused items for reassignment
+ QStack<QtGraphicsTableViewItem*> unused;
+
+ /*
+ --------------
+ | |
+ --------------
+ | | | |
+ | | | |
+ | | | |
+ --------------
+ | |
+ --------------
+ */
+
+ // top edge
+ for (int verticalSection = oldFirstVerticalSection; verticalSection < firstVerticalSection; ++verticalSection) {
+ const int row = verticalMapping.value(verticalSection, verticalSection);
+ for (int horizontalSection = oldFirstHorizontalSection; horizontalSection <= oldLastHorizontalSection; ++horizontalSection) {
+ const int column = horizontalMapping.value(horizontalSection, horizontalSection);
+ const int index = (row * columnCount) + column;
+ if (QtGraphicsTableViewItem *item = d->items.take(index))
+ unused.push(item);
+ }
+ }
+ // left edge
+ for (int horizontalSection = oldFirstHorizontalSection; horizontalSection < firstHorizontalSection; ++horizontalSection) {
+ int column = horizontalMapping.value(horizontalSection, horizontalSection);
+ for (int verticalSection = firstVerticalSection; verticalSection <= lastVerticalSection; ++verticalSection) {
+ const int row = verticalMapping.value(verticalSection, verticalSection);
+ const int index = (row * columnCount) + column;
+ if (QtGraphicsTableViewItem *item = d->items.take(index))
+ unused.push(item);
+ }
+ }
+ // bottom edge
+ for (int verticalSection = lastVerticalSection + 1; verticalSection <= oldLastVerticalSection; ++verticalSection) {
+ const int row = verticalMapping.value(verticalSection, verticalSection);
+ for (int horizontalSection = oldFirstHorizontalSection; horizontalSection <= oldLastHorizontalSection; ++horizontalSection) {
+ const int column = horizontalMapping.value(horizontalSection, horizontalSection);
+ const int index = (row * columnCount) + column;
+ if (QtGraphicsTableViewItem *item = d->items.take(index))
+ unused.push(item);
+ }
+ }
+ // right edge
+ for (int horizontalSection = lastHorizontalSection + 1; horizontalSection <= oldLastHorizontalSection; ++horizontalSection) {
+ int column = horizontalMapping.value(horizontalSection, horizontalSection);
+ for (int verticalSection = firstVerticalSection; verticalSection <= lastVerticalSection; ++verticalSection) {
+ const int row = verticalMapping.value(verticalSection, verticalSection);
+ const int index = (row * columnCount) + column;
+ if (QtGraphicsTableViewItem *item = d->items.take(index))
+ unused.push(item);
+ }
+ }
+ // move overlapping items
qreal y = -verticalOffset;
- for (int verticalSection = d->firstRow; verticalSection <= lastRow; ++verticalSection) {
+ for (int verticalSection = firstVerticalSection; verticalSection <= lastVerticalSection; ++verticalSection) {
const int row = verticalMapping.value(verticalSection, verticalSection);
const qreal height = rowHeight(row);
qreal x = -horizontalOffset;
- for (int horizontalSection = d->firstColumn; horizontalSection <= lastColumn; ++horizontalSection) {
+ for (int horizontalSection = firstHorizontalSection; horizontalSection <= lastHorizontalSection; ++horizontalSection) {
const int column = horizontalMapping.value(horizontalSection, horizontalSection);
const qreal width = columnWidth(column);
- const int index = ((verticalSection * horizontalCount) + horizontalSection) - firstIndex;
- QtGraphicsTableViewItem *item = d->items.value(index, 0);
- // ### FIXME: scroll the items properly
- if (item) {
- item = d->creator->reassign(row, column, item);
- } else if (index >= d->items.count()) {
- item = d->creator->create(row, column, this);
- d->items.append(item);
+ const int index = (row * columnCount) + column;
+ QtGraphicsTableViewItem *item = d->items.value(index);
+ if (!item) {
+ if (!unused.isEmpty())
+ item = d->creator->reassign(row, column, unused.pop());
+ else
+ item = d->creator->create(row, column, this);
+ d->items.insert(index, item);
}
item->setGeometry(x, y, width, height);
x += width;
@@ -1001,10 +1072,15 @@ void QtGraphicsTableView::doLayout()
y += height;
}
- const int lastIndex = (lastRow * horizontalCount) + lastColumn;
- const int removeCount = d->items.count() - (lastIndex - firstIndex) - 1;
- for (int i = 0; i < removeCount; ++i)
- d->creator->recycle(d->items.takeLast());
+ // update internal structures
+ d->visibleSections.setRange(firstVerticalSection, firstHorizontalSection, lastVerticalSection, lastHorizontalSection);
+
+ // recycle any unused items left
+ for (int i = 0; i < unused.count(); ++i)
+ d->creator->recycle(unused.at(i));
+
+ Q_ASSERT(d->items.count() == (horizontalCount * verticalCount));
+ //Q_ASSERT(d->items.count() == childItems().count());
}
/*!
diff --git a/src/qgraphicstableview.h b/src/qgraphicstableview.h
index ee3950f..9c561f6 100644
--- a/src/qgraphicstableview.h
+++ b/src/qgraphicstableview.h
@@ -123,7 +123,6 @@ public:
void setTextElideMode(Qt::TextElideMode mode);
bool isGridShown() const;
- void setGridShown(bool show);
qreal rowHeight(int row) const;
void setRowHeight(int row, qreal height);
@@ -183,6 +182,7 @@ public:
void copyStyleOptionState(const QStyleOptionGraphicsItem *source, QStyleOptionViewItemV4 *dest);
public Q_SLOTS:
+ void setGridShown(bool show);
void setFirstRow(int row);
void setFirstColumn(int column);
void setHorizontalOffset(qreal offset);
diff --git a/src/qgraphicstableview_p.h b/src/qgraphicstableview_p.h
index c8e5c61..800f2c7 100644
--- a/src/qgraphicstableview_p.h
+++ b/src/qgraphicstableview_p.h
@@ -39,6 +39,8 @@
#include <qfont.h>
#include <qvariant.h>
+#include <qtableselectionmanager.h>
+
QT_BEGIN_NAMESPACE
class QtTableModelInterface;
@@ -114,7 +116,8 @@ public:
mutable int cachedDataColumn;
// view items
- QList<QtGraphicsTableViewItem*> items;
+ QtTableSelectionRange visibleSections;
+ QHash<int, QtGraphicsTableViewItem*> items;
QtGraphicsTableViewItemCreatorBase *creator;
QtGraphicsTableView *q_ptr;