summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarius Bugge Monsen <mmonsen@trolltech.com>2009-06-07 20:11:21 +0200
committerMarius Bugge Monsen <mmonsen@trolltech.com>2009-06-07 20:11:21 +0200
commit897c2092bcd5044f6f1fdffc0dedd51850eba5bd (patch)
tree300fd35ce3f68ac54e446b818c412fa38c855e6d
parent9770e8fc6b85e0180cdc94a9398d419173e07e3e (diff)
Add QtGraphicsListView::itemGeometry(int). This enables us to implement setOffsetToEnsureIndexIsVisible(int).
Subclasses of QtGraphicsListView that implement a different layout should reimplement itemGeometry(int).
-rw-r--r--src/experimental/qgraphicsflowview.cpp6
-rw-r--r--src/experimental/qgraphicsflowview.h1
-rw-r--r--src/experimental/qgraphicsgridview.cpp27
-rw-r--r--src/experimental/qgraphicsgridview.h1
-rw-r--r--src/experimental/qgraphicspathview.cpp11
-rw-r--r--src/experimental/qgraphicspathview.h1
-rw-r--r--src/qgraphicslistview.cpp126
-rw-r--r--src/qgraphicslistview.h1
-rw-r--r--src/qgraphicslistview_p.h4
-rw-r--r--src/qgraphicstreeview.cpp48
10 files changed, 189 insertions, 37 deletions
diff --git a/src/experimental/qgraphicsflowview.cpp b/src/experimental/qgraphicsflowview.cpp
index 68d4a6a..56da1f8 100644
--- a/src/experimental/qgraphicsflowview.cpp
+++ b/src/experimental/qgraphicsflowview.cpp
@@ -128,6 +128,12 @@ QtGraphicsFlowView::~QtGraphicsFlowView()
{
}
+QRectF QtGraphicsFlowView::itemGeometry(int index) const
+{
+ Q_UNUSED(index);
+ return QRectF(); // ### FIXME: implement
+}
+
int QtGraphicsFlowView::itemAt(const QPointF &position) const
{
Q_D(const QtGraphicsFlowView);
diff --git a/src/experimental/qgraphicsflowview.h b/src/experimental/qgraphicsflowview.h
index 3195e0f..8c71e79 100644
--- a/src/experimental/qgraphicsflowview.h
+++ b/src/experimental/qgraphicsflowview.h
@@ -33,6 +33,7 @@ public:
QtGraphicsFlowView(Qt::Orientation orientation = Qt::Vertical, QGraphicsWidget *parent = 0);
virtual ~QtGraphicsFlowView();
+ virtual QRectF itemGeometry(int index) const;
virtual int itemAt(const QPointF &position) const;
virtual int maximumFirstIndex() const;
virtual void doLayout();
diff --git a/src/experimental/qgraphicsgridview.cpp b/src/experimental/qgraphicsgridview.cpp
index 839fa75..db1991e 100644
--- a/src/experimental/qgraphicsgridview.cpp
+++ b/src/experimental/qgraphicsgridview.cpp
@@ -195,7 +195,7 @@ QPointF QtGraphicsGridViewPrivate::gridPosition(int index) const
y = (index % sectionCount) * s;
x -= firstIndex * s; // scrolling
}
- return QPointF(x, y);
+ return QPointF(x - horizontalOffset, y - verticalOffset);
}
int QtGraphicsGridViewPrivate::firstVisibleIndex(const QRectF &area) const
@@ -295,6 +295,7 @@ void QtGraphicsGridView::setSectionCount(int count)
}
/*!
+ \reimp
*/
int QtGraphicsGridView::maximumFirstIndex() const
{
@@ -304,6 +305,7 @@ int QtGraphicsGridView::maximumFirstIndex() const
}
/*!
+ \reimp
*/
qreal QtGraphicsGridView::maximumHorizontalOffset() const
{
@@ -315,6 +317,7 @@ qreal QtGraphicsGridView::maximumHorizontalOffset() const
}
/*!
+ \reimp
*/
qreal QtGraphicsGridView::maximumVerticalOffset() const
{
@@ -326,6 +329,7 @@ qreal QtGraphicsGridView::maximumVerticalOffset() const
}
/*!
+ \reimp
*/
void QtGraphicsGridView::doLayout()
{
@@ -338,12 +342,11 @@ void QtGraphicsGridView::doLayout()
const int count = d->model ? d->model->count() : 0;
const qreal gridSize = d->gridSize();
- const QPointF offset(-horizontalOffset(), -verticalOffset());
- //const QPointF currentPos = d->gridPosition(current) + offset;
- //const QPointF previousPos = d->gridPosition(previous) + offset;
+ //const QPointF currentPos = d->gridPosition(current);
+ //const QPointF previousPos = d->gridPosition(previous);
// update item geometry
- const QRectF viewport(QPointF(-offset.x(), -offset.y()), size());
+ const QRectF viewport(QPointF(horizontalOffset(), verticalOffset()), size());
const int firstVisibleIndex = d->firstVisibleIndex(viewport);
const int lastVisibleIndex = qMin(d->lastVisibleIndex(viewport), count - 1);
d->scrollItems(firstVisibleIndex);
@@ -354,7 +357,7 @@ void QtGraphicsGridView::doLayout()
if (i >= d->items.count())
d->items.append(d->creator->create(index, this));
QtGraphicsListViewItem *item = d->items.at(i);
- const QPointF pos = d->gridPosition(index) + offset;
+ const QPointF pos = d->gridPosition(index);
const QSizeF size = item->sizeHint(index, &option, Qt::PreferredSize, QSizeF(gridSize, gridSize));
const QRectF grid(pos.x(), pos.y(), gridSize, gridSize);
const QRectF aligned = QStyle::alignedRect(option.direction,
@@ -370,6 +373,18 @@ void QtGraphicsGridView::doLayout()
}
/*!
+ \reimp
+ */
+QRectF QtGraphicsGridView::itemGeometry(int index) const
+{
+ Q_D(const QtGraphicsGridView);
+ const QPointF position = d->gridPosition(index);
+ const qreal size = d->gridSize();
+ return QRectF(position, QSizeF(size, size));
+}
+
+/*!
+ \reimp
*/
int QtGraphicsGridView::itemAt(const QPointF &position) const
{
diff --git a/src/experimental/qgraphicsgridview.h b/src/experimental/qgraphicsgridview.h
index 8c869a0..2980fbc 100644
--- a/src/experimental/qgraphicsgridview.h
+++ b/src/experimental/qgraphicsgridview.h
@@ -50,6 +50,7 @@ public:
virtual qreal maximumVerticalOffset() const;
virtual void doLayout();
+ virtual QRectF itemGeometry(int index) const;
virtual int itemAt(const QPointF &position) const;
virtual void initStyleOption(QStyleOptionViewItemV4 *option) const;
virtual void initStyleOption(QStyleOptionViewItemV4 *option, int index) const;
diff --git a/src/experimental/qgraphicspathview.cpp b/src/experimental/qgraphicspathview.cpp
index 75edf2f..469206a 100644
--- a/src/experimental/qgraphicspathview.cpp
+++ b/src/experimental/qgraphicspathview.cpp
@@ -58,6 +58,8 @@ QtGraphicsPathViewPrivate::QtGraphicsPathViewPrivate()
void QtGraphicsPathViewPrivate::_q_currentChanged(int current, int previous)
{
+ Q_UNUSED(current);
+ Q_UNUSED(previous);
/*
QTimeLine::Direction direction = current > previous ? QTimeLine::Backward : QTimeLine::Forward;
if (previous == 0 && current == model->count() - 1)
@@ -117,10 +119,17 @@ qreal QtGraphicsPathView::maximumVerticalOffset() const
return 0;
}
+QRectF QtGraphicsPathView::itemGeometry(int index) const
+{
+ Q_UNUSED(index);
+ // ### FIXME: implementation goes here
+ return QRectF();
+}
+
int QtGraphicsPathView::itemAt(const QPointF &position) const
{
Q_UNUSED(position);
- // ### implementation goes here
+ // ### FIXME: implementation goes here
return -1;
}
diff --git a/src/experimental/qgraphicspathview.h b/src/experimental/qgraphicspathview.h
index 7c33696..7b49d0c 100644
--- a/src/experimental/qgraphicspathview.h
+++ b/src/experimental/qgraphicspathview.h
@@ -50,6 +50,7 @@ public:
virtual qreal maximumHorizontalOffset() const;
virtual qreal maximumVerticalOffset() const;
+ virtual QRectF itemGeometry(int index) const;
virtual int itemAt(const QPointF &position) const;
virtual void doLayout();
diff --git a/src/qgraphicslistview.cpp b/src/qgraphicslistview.cpp
index 15d798d..38f495b 100644
--- a/src/qgraphicslistview.cpp
+++ b/src/qgraphicslistview.cpp
@@ -61,7 +61,7 @@
as they are needed based on how many items are visible. It is possible for an
item to be reused. When this happens the itemChanged() method will be called
to make the item aware of this change. The default implmentation will make sure
- that paint() will be called.
+ that update() will be called.
The default QtGraphicsListView::itemContentsSizeHint() will first ask the model for a
Qt::SizeHintRole and then request the effectiveSizeHint() from the item to
@@ -89,6 +89,11 @@ QtGraphicsListViewItem::~QtGraphicsListViewItem()
delete d_ptr;
}
+/*!
+ Returns the index of the list model item this
+ view tem represents.
+ \sa setIndex()
+ */
int QtGraphicsListViewItem::index() const
{
Q_D(const QtGraphicsListViewItem);
@@ -96,6 +101,8 @@ int QtGraphicsListViewItem::index() const
}
/*!
+ Sets the index of list model item this
+ view item will represent.
*/
void QtGraphicsListViewItem::setIndex(int index)
{
@@ -107,6 +114,7 @@ void QtGraphicsListViewItem::setIndex(int index)
}
/*!
+ \reimp
*/
QSizeF QtGraphicsListViewItem::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
{
@@ -117,6 +125,8 @@ QSizeF QtGraphicsListViewItem::sizeHint(Qt::SizeHint which, const QSizeF &constr
}
/*!
+ Returns \a which size hint for the item indicated by the given \a index,
+ using the given \a option and \a constrainst.
*/
QSizeF QtGraphicsListViewItem::sizeHint(int index, const QStyleOptionViewItemV4 *option, Qt::SizeHint which, const QSizeF &constraint) const
{
@@ -139,12 +149,13 @@ QSizeF QtGraphicsListViewItem::sizeHint(int index, const QStyleOptionViewItemV4
}
/*!
+ \reimp
*/
void QtGraphicsListViewItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_D(QtGraphicsListViewItem);
// ### this code is less than optimal, but we will hopefully get rid of the style calls
- // ### (by moving to a purely scene-graph based approach for items)
+ // ### by moving to a purely scene-graph based approach for items
d->view->copyStyleOptionState(option, &d->option);
d->view->initStyleOption(&d->option);
d->view->initStyleOption(&d->option, d->index);
@@ -168,6 +179,10 @@ void QtGraphicsListViewItem::itemChanged(const QList<int> &roles)
update();
}
+/*!
+ Returns the data for the given \a roles, for the list model
+ item this view item represents.
+ */
QHash<int, QVariant> QtGraphicsListViewItem::data(const QList<int> &roles) const
{
Q_D(const QtGraphicsListViewItem);
@@ -176,6 +191,9 @@ QHash<int, QVariant> QtGraphicsListViewItem::data(const QList<int> &roles) const
return QHash<int, QVariant>();
}
+/*!
+ Returns the view where this item is shown.
+ */
QtGraphicsListView *QtGraphicsListViewItem::view() const
{
Q_D(const QtGraphicsListViewItem);
@@ -184,12 +202,21 @@ QtGraphicsListView *QtGraphicsListViewItem::view() const
/*!
\class QtGraphicsListViewItemCreatorBase
+ \brief Creates, reassignes and recycles view items.
*/
+/*!
+ */
QtGraphicsListViewItemCreatorBase::~QtGraphicsListViewItemCreatorBase()
{
}
+/*!
+ \fn QtGraphicsListViewItemCreatorBase::create(int index, QtGraphicsListView *view)
+ */
+
+/*!
+ */
QtGraphicsListViewItem *QtGraphicsListViewItemCreatorBase::reassign(int index, QtGraphicsListViewItem *item)
{
Q_ASSERT(item);
@@ -197,6 +224,8 @@ QtGraphicsListViewItem *QtGraphicsListViewItemCreatorBase::reassign(int index, Q
return item;
}
+/*!
+ */
void QtGraphicsListViewItemCreatorBase::recycle(QtGraphicsListViewItem *item)
{
delete item;
@@ -215,8 +244,11 @@ QtGraphicsListViewPrivate::QtGraphicsListViewPrivate()
: q_ptr(0), controller(0), model(0), selectionManager(0),
orientation(Qt::Horizontal), textElideMode(Qt::ElideMiddle),
firstIndex(0), horizontalOffset(0), verticalOffset(0),
- cachedIndexOffset(0), cachedCoordinateOffset(0), cachedDataIndex(-1),
- layoutsBlocked(false), creator(new QtGraphicsListViewItemCreator<QtGraphicsListViewItem>())
+#if CACHING_ENABLED
+ cachedIndexOffset(0), cachedCoordinateOffset(0),
+#endif
+ cachedDataIndex(-1), layoutsBlocked(false),
+ creator(new QtGraphicsListViewItemCreator<QtGraphicsListViewItem>())
{
}
@@ -351,10 +383,12 @@ void QtGraphicsListViewPrivate::checkCache(int index, int count)
cachedDataHash.clear();
cachedDataIndex = -1;
}
+#if CACHING_ENABLED
if (cachedIndexOffset >= index) {
cachedIndexOffset = 0;
cachedCoordinateOffset = 0;
}
+#endif
}
/*!
@@ -595,6 +629,45 @@ QtGraphicsListView::~QtGraphicsListView()
}
/*!
+ Returns the geometry given to the item
+ referred to by the given \a index.
+
+ \sa updateLayout()
+ */
+QRectF QtGraphicsListView::itemGeometry(int index) const
+{
+ Q_D(const QtGraphicsListView);
+ if (!d->model)
+ return QRectF();
+ if (QtGraphicsListViewItem *item = itemForIndex(index))
+ return item->geometry();
+ const QSizeF constraint = size();
+ const int count = d->model->count();
+ QStyleOptionViewItemV4 option;
+ initStyleOption(&option);
+ qreal x = -d->horizontalOffset;
+ qreal y = -d->verticalOffset;
+ if (d->orientation == Qt::Vertical) {
+ for (int i = d->firstIndex; i < count; ++i) {
+ initStyleOption(&option, i);
+ const QSizeF size = d->itemSizeHint(&option, i, constraint);
+ if (i == index)
+ return QRectF(QPointF(x, y), size);
+ y += size.height();
+ }
+ } else {
+ for (int i = d->firstIndex; i < count; ++i) {
+ initStyleOption(&option, i);
+ const QSizeF size = d->itemSizeHint(&option, i, constraint);
+ if (i == index)
+ return QRectF(QPointF(x, y), size);
+ x += size.width();
+ }
+ }
+ return QRectF();
+}
+
+/*!
Returns the index of the item at the
given \a position.
@@ -605,16 +678,17 @@ int QtGraphicsListView::itemAt(const QPointF &position) const
Q_D(const QtGraphicsListView);
if (!d->model)
return -1;
+ // ### FIXME: check the visible items first
const QSizeF constraint = size();
+ const int count = d->model->count();
QStyleOptionViewItemV4 option;
initStyleOption(&option);
int index = d->firstIndex;
- int count = d->model->count();
if (d->orientation == Qt::Vertical) {
qreal y = -d->verticalOffset;
while (y <= position.y() && index < count) {
initStyleOption(&option, index);
- QSizeF size = d->itemSizeHint(&option, index, constraint);
+ const QSizeF size = d->itemSizeHint(&option, index, constraint);
y += size.height();
if (y >= position.y())
return index;
@@ -624,7 +698,7 @@ int QtGraphicsListView::itemAt(const QPointF &position) const
qreal x = -d->horizontalOffset;
while (x <= position.x() && index < count) {
initStyleOption(&option, index);
- QSizeF size = d->itemSizeHint(&option, index, constraint);
+ const QSizeF size = d->itemSizeHint(&option, index, constraint);
x += size.width();
if (x >= position.x())
return index;
@@ -671,10 +745,10 @@ void QtGraphicsListView::doLayout()
// find the visible items; caching helps us skip this most of the time
if (coordinate <= 0 && !d->items.isEmpty()) {
+#if CACHING_ENABLED
// optimization: use the cached index and offset as starting points
// The cached values are offsets from the start of the _contents_
// and the to index found at that offset.
-#if 0 // enable or disable the caching
index += d->cachedIndexOffset;
coordinate += d->cachedCoordinateOffset;
#endif
@@ -698,7 +772,7 @@ void QtGraphicsListView::doLayout()
--index;
}
}
-#if 0 // enable or disable the caching
+#if CACHING_ENABLED
d->cachedIndexOffset = index - d->firstIndex;
d->cachedCoordinateOffset = coordinate + offset;
#endif
@@ -921,19 +995,32 @@ int QtGraphicsListView::firstIndex() const
}
/*!
+ Sets the horizonal and vertical offset to ensure that
+ the item represented by the given \a index is visible
+ in the view.
+ Note that this function is potentially slow.
+
+ \sa setHorizontalOffset(), setVerticalOffset()
*/
void QtGraphicsListView::setOffsetToEnsureIndexIsVisible(int index)
{
- Q_UNUSED(index);
- // ### TODO
+ Q_D(QtGraphicsListView);
+ if (itemForIndex(index))
+ return; // the item was already visible
+ const QRectF geometry = itemGeometry(index); // ### potentially slow
+ if (d->orientation == Qt::Vertical)
+ setVerticalOffset(geometry.y() + d->verticalOffset); // ### FIXME: not always correct
+ else
+ setHorizontalOffset(geometry.x() + d->horizontalOffset); // ### FIXME: not always correct
}
/*!
*/
void QtGraphicsListView::setFirstIndexToEnsureIndexIsVisible(int index)
{
+ // ### this breaks views with a different layout
+#if 0
Q_D(QtGraphicsListView);
- return; // ### this breaks views with a different layout
// ### cache
if (index > d->firstIndex) {
const QSizeF constraint = size();
@@ -959,6 +1046,9 @@ void QtGraphicsListView::setFirstIndexToEnsureIndexIsVisible(int index)
}
if (index > -1)
setFirstIndex(index);
+#else
+ Q_UNUSED(index);
+#endif
}
/*!
@@ -1130,6 +1220,7 @@ bool QtGraphicsListView::event(QEvent *event)
event->accept();
return true;
}
+ // delayed layout mechanism
if (event->type() == QEvent::Timer && static_cast<QTimerEvent*>(event)->timerId() == d->layoutTimer.timerId())
doLayout();
return QGraphicsWidget::event(event);
@@ -1162,10 +1253,15 @@ void QtGraphicsListView::setItemCreator(QtGraphicsListViewItemCreatorBase *creat
QtGraphicsListViewItem* QtGraphicsListView::itemForIndex(int index) const
{
Q_D(const QtGraphicsListView);
- for (int i = 0; i < d->items.count(); ++i) {
- QtGraphicsListViewItem *item = d->items.at(i);
- if (item->index() == index)
+ if (!d->items.isEmpty()) {
+ const int firstIndex = d->items.first()->index();
+ const int lastIndex = d->items.last()->index();
+ if (firstIndex <= index && index <= lastIndex) {
+ QtGraphicsListViewItem *item = d->items.at(index - firstIndex);
+ Q_ASSERT(item);
+ Q_ASSERT(item->index() == index);
return item;
+ }
}
return 0;
}
diff --git a/src/qgraphicslistview.h b/src/qgraphicslistview.h
index edce53d..5dd65a5 100644
--- a/src/qgraphicslistview.h
+++ b/src/qgraphicslistview.h
@@ -110,6 +110,7 @@ public:
void setTextElideMode(Qt::TextElideMode mode);
virtual int itemAt(const QPointF &position) const;
+ virtual QRectF itemGeometry(int index) const;
virtual void doLayout();
int firstIndex() const;
diff --git a/src/qgraphicslistview_p.h b/src/qgraphicslistview_p.h
index 7365ff1..9b3382f 100644
--- a/src/qgraphicslistview_p.h
+++ b/src/qgraphicslistview_p.h
@@ -40,6 +40,8 @@
#include <qtimer.h>
#include <qhash.h>
+#define CACHING_ENABLED 0
+
QT_BEGIN_NAMESPACE
class QtGraphicsListViewItemPrivate
@@ -95,8 +97,10 @@ public:
qreal horizontalOffset;
qreal verticalOffset;
+#if CACHING_ENABLED
mutable int cachedIndexOffset;
mutable qreal cachedCoordinateOffset;
+#endif
mutable QHash<int, QVariant> cachedDataHash;
mutable int cachedDataIndex;
diff --git a/src/qgraphicstreeview.cpp b/src/qgraphicstreeview.cpp
index 305dd65..4def7ed 100644
--- a/src/qgraphicstreeview.cpp
+++ b/src/qgraphicstreeview.cpp
@@ -1067,6 +1067,16 @@ void QtGraphicsTreeView::setItemCreator(QtGraphicsTreeViewItemCreatorBase *creat
}
/*!
+ Returns the visible item representing the given \a it, if that item exists and is visible.
+ Otherwise returns null.
+ */
+QtGraphicsTreeViewItem *QtGraphicsTreeView::itemForIterator(const QtTreeModelIterator &it) const
+{
+ Q_D(const QtGraphicsTreeView);
+ return d->items.value(it);
+}
+
+/*!
*/
void QtGraphicsTreeView::updateLayout()
{
@@ -1094,27 +1104,35 @@ void QtGraphicsTreeView::doLayout()
QtTreeModelIterator it;
int index = 0;
#if 0
- if (y == cachedVerticalOffset) {
- it = d->cachedFirstVisibleItem;
- index = d->cachedVisibleIndex;
- syncStack(it, stack);
- } else
+ y = d->cachedVerticalOffset;
+ it = d->cachedFirstVisibleItem;
+ index = d->cachedVisibleIndex;
+ syncStack(it, stack);
#endif
// this handles caching too
it = d->firstItem(stack, &index);
- while (y < area.y() && it.isValid()) {
- y += d->itemHeight(option, it); // ####
- d->next(it, stack);
- ++index;
+ // offset-based scrolling
+ /*
+ if (y < area.y()) {
+ while (y < area.y() && it.isValid()) {
+ y += d->itemHeight(option, it);
+ d->next(it, stack);
+ ++index;
+ }
+ } else if (y > area.y()) {
+ while (y > area.y() && it.isValid()) {
+ y -= d->itemHeight(option, it);
+ d->previous(it, stack);
+ --index;
+ }
}
+ */
#if 0
- // TODO: will be used for pixel-based scrolling
- if (y != 0) {
- d->cachedVerticalOffset = d->verticalOffset;
- d->cachedFirstVisibleItem = it;
- d->cachedVisibleIndex = index;
- }
+ d->cachedVerticalOffset = d->verticalOffset;
+ d->cachedFirstVisibleItem = it;
+ d->cachedVisibleIndex = index;
#endif
+
if (!it.isValid())
return;