diff options
Diffstat (limited to 'tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractitemview.cpp')
-rw-r--r-- | tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractitemview.cpp | 444 |
1 files changed, 444 insertions, 0 deletions
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractitemview.cpp b/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractitemview.cpp new file mode 100644 index 0000000..ba958ca --- /dev/null +++ b/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractitemview.cpp @@ -0,0 +1,444 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QGraphicsLayout> + +#include "abstractitemview.h" +#include "abstractviewitem.h" +#include "scrollbar.h" + +AbstractItemView::AbstractItemView(QGraphicsWidget *parent) + : AbstractScrollArea(parent), + m_model(0), + m_rootIndex(), + m_container(0), + m_selectionModel(0), + m_currentIndex(), + m_scroller() +{ + setRootIndex(QModelIndex()); +} + +/*virtual*/ +AbstractItemView::~AbstractItemView() +{ +} + +/*virtual*/ +void AbstractItemView::setModel(QAbstractItemModel *model, AbstractViewItem *prototype) +{ + if( m_model == model || !model) + return; + + if (m_model) { + disconnect(m_model, SIGNAL(destroyed()), + this, SLOT(_q_modelDestroyed())); + disconnect(m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), + this, SLOT( dataChanged(QModelIndex,QModelIndex))); + disconnect(m_model, SIGNAL(rowsInserted(QModelIndex,int,int)), + this, SLOT(rowsInserted(QModelIndex,int,int))); + disconnect(m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)), + this, SLOT(rowsRemoved(QModelIndex,int,int))); + disconnect(m_model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), + this, SLOT(rowsAboutToBeRemoved(QModelIndex,int,int))); + disconnect(m_model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), + this, SLOT(rowsAboutToBeInserted(QModelIndex,int,int))); + disconnect(m_model, SIGNAL(columnsInserted(QModelIndex,int,int)), + this, SLOT(columnsInserted(QModelIndex,int,int))); + disconnect(m_model, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)), + this, SLOT(columnsAboutToBeInserted(QModelIndex,int,int))); + disconnect(m_model, SIGNAL(columnsRemoved(QModelIndex,int,int)), + this, SLOT(columnsRemoved(QModelIndex,int,int))); + disconnect(m_model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)), + this, SLOT(columnsAboutToBeRemoved(QModelIndex,int,int))); + disconnect(m_model, SIGNAL(modelReset()), this, SLOT(reset())); + disconnect(m_model, SIGNAL(layoutChanged()), this, SLOT(_q_layoutChanged())); + + m_model = 0; + } + + setSelectionModel(0); + + m_currentIndex = QModelIndex(); + m_rootIndex = QModelIndex(); + + m_model = model; + + Q_ASSERT_X(m_model->index(0,0) == m_model->index(0,0), + "AbstractItemView::setModel", + "A model should return the exact same index " + "(including its internal id/pointer) when asked for it twice in a row."); + Q_ASSERT_X(m_model->index(0,0).parent() == QModelIndex(), + "AbstractItemView::setModel", + "The parent of a top level index should be invalid"); + + + connect(m_model, SIGNAL(destroyed()), this, SLOT(modelDestroyed())); + connect(m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), + this, SLOT( dataChanged(QModelIndex,QModelIndex))); + connect(m_model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), + this, SLOT(rowsAboutToBeInserted(QModelIndex,int,int))); + connect(m_model, SIGNAL(rowsInserted(QModelIndex,int,int)), + this, SLOT(rowsInserted(QModelIndex,int,int))); + connect(m_model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), + this, SLOT(rowsAboutToBeRemoved(QModelIndex,int,int))); + connect(m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)), + this, SLOT(rowsRemoved(QModelIndex,int,int))); + connect(m_model, SIGNAL(modelReset()), this, SLOT(reset())); + connect(m_model, SIGNAL(layoutChanged()), this, SLOT(layoutChanged())); + + setSelectionModel(new QItemSelectionModel(m_model)); + + if (prototype && m_container) { + m_container->setItemPrototype(prototype); + m_container->reset(); + } +} + +/*virtual*/ +void AbstractItemView::setContainer(AbstractItemContainer *container) +{ + m_container = container; + m_container->setItemView(this); + m_container->setParentItem(viewport()); + + viewport()->setFlag( + QGraphicsItem::ItemClipsChildrenToShape, true); + m_scroller.setScrollable(this); + installEventFilter(&m_scroller); +} + +/*virtual*/ +void AbstractItemView::setRootIndex(const QModelIndex &index) +{ + m_rootIndex = index; + // TODO fix this if we change index, container should be updated? Or do we need root index? +} + +/*virtual*/ +int AbstractItemView::indexCount() const +{ + if (m_model) + return m_model->rowCount(m_rootIndex); + return 0; +} + +/*virtual*/ +QAbstractItemModel* AbstractItemView::model() const +{ + return m_model; +} + +/*virtual*/ +QModelIndex AbstractItemView::nextIndex(const QModelIndex &index) const +{ + if (!m_model) + return QModelIndex(); + + if (index.isValid()) + return m_model->index(index.row() + 1, 0, m_rootIndex); + else + return m_model->index(0, 0, m_rootIndex); +} + +/*virtual*/ +QModelIndex AbstractItemView::previousIndex(const QModelIndex &index) const +{ + if (!m_model) + return QModelIndex(); + + if (index.isValid()) + return m_model->index(index.row() - 1, 0, m_rootIndex); + else + return m_model->index(m_model->rowCount(m_rootIndex) - 1, 0, m_rootIndex); +} + +/*virtual*/ +void AbstractItemView::setItemPrototype(AbstractViewItem* prototype) +{ + if (prototype && m_container) { + m_container->setItemPrototype(prototype); + m_container->reset(); + } +} + +void AbstractItemView::setSelectionModel(QItemSelectionModel *smodel) +{ + if (smodel && smodel->model() != m_model) { + return; + } + if (m_selectionModel) { + disconnect(m_selectionModel, SIGNAL(selectionChanged(QItemSelection, QItemSelection)), + this, SLOT(currentSelectionChanged(QItemSelection, QItemSelection))); + + disconnect(m_selectionModel, SIGNAL(currentChanged(QModelIndex, QModelIndex)), + this, SLOT(currentIndexChanged(QModelIndex, QModelIndex))); + + delete m_selectionModel; + m_selectionModel = 0; + } + + m_selectionModel = smodel; + + if (m_selectionModel) { + connect(m_selectionModel, SIGNAL(selectionChanged(QItemSelection, QItemSelection)), + this, SLOT(currentSelectionChanged(QItemSelection, QItemSelection))); + connect(m_selectionModel, SIGNAL(currentChanged(QModelIndex, QModelIndex)), + this, SLOT(currentIndexChanged(QModelIndex, QModelIndex))); + } +} + +/*virtual*/ +void AbstractItemView::currentIndexChanged(const QModelIndex ¤t, const QModelIndex &previous) +{ + Q_UNUSED(previous) + + if (current != m_currentIndex) + m_currentIndex = current; +} + +/*virtual*/ +void AbstractItemView::currentSelectionChanged(const QItemSelection &selected, + const QItemSelection &deselected) +{ + Q_UNUSED(selected) + Q_UNUSED(deselected) +} + +/*virtual*/ +void AbstractItemView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) +{ + Q_UNUSED(topLeft) + Q_UNUSED(bottomRight) + // TODO implement if we like to edit view items. +} + +/*virtual*/ +void AbstractItemView::rowsAboutToBeInserted(const QModelIndex &index, int start, int end) +{ + Q_UNUSED(index) + Q_UNUSED(start) + Q_UNUSED(end) + + // TODO implement +} + + +/*virtual*/ +void AbstractItemView::rowsAboutToBeRemoved(const QModelIndex &index,int start, int end) +{ + Q_UNUSED(index) + Q_UNUSED(start) + Q_UNUSED(end) +} + +/*virtual*/ +void AbstractItemView::rowsRemoved(const QModelIndex &parent,int start, int end) +{ + Q_UNUSED(parent) + Q_UNUSED(start) + Q_UNUSED(end) + + if (start <= m_currentIndex.row() && m_currentIndex.row() <= end) { + QModelIndex newCurrentIndex = m_model->index(start, 0, m_rootIndex); + if (!newCurrentIndex.isValid()) { + newCurrentIndex = m_model->index(qMax(0,start - 1), 0, m_rootIndex); + } + + if (m_selectionModel) { + m_selectionModel->setCurrentIndex(newCurrentIndex, QItemSelectionModel::NoUpdate); + } + } + for (int i = end; i >= start; --i) //The items are already removed from the model. + m_container->removeItem(QModelIndex()); // Indexes are already invalid. +} + +/*virtual*/ +void AbstractItemView::reset() +{ + m_rootIndex = QModelIndex(); + + if (m_container) + m_container->reset(); + + setCurrentIndex(QModelIndex()); + + ScrollBar *sb = verticalScrollBar(); + + if (sb) + sb->setSliderSize(0); +} + +/*virtual*/ +void AbstractItemView::rowsInserted(const QModelIndex &parent, int start, int end) +{ + if (!m_container) + return; + + for (int i = start; i <= end; ++i) + m_container->addItem(m_model->index(i, 0, parent)); + + refreshContainerGeometry(); +} + +/*virtual*/ +void AbstractItemView::modelDestroyed() +{ + m_model = 0; + setSelectionModel(0); + reset(); +} + +/*virtual*/ +void AbstractItemView::layoutChanged() +{ + m_container->reset(); +} + +bool AbstractItemView::event(QEvent *e) +{ + bool result = AbstractScrollArea::event(e); + if (e && e->type()==QEvent::LayoutRequest) { + refreshContainerGeometry(); + result = true; + } + if (e && e->type()==QEvent::GraphicsSceneResize) { + m_scroller.stopScrolling(); + refreshContainerGeometry(); + + m_container->resize(this->size().width()-verticalScrollBar()->size().width(), + m_container->preferredHeight()); + + if(verticalScrollBar()->sliderPosition() > verticalScrollBar()->sliderSize()) + verticalScrollBar()->setSliderPosition(verticalScrollBar()->sliderSize()); + + result = true; + } + return result; +} + +void AbstractItemView::setCurrentIndex(const QModelIndex &index, QItemSelectionModel::SelectionFlags selectionFlag) +{ + if (m_selectionModel) + m_selectionModel->setCurrentIndex(index, selectionFlag); +} + +void AbstractItemView::refreshContainerGeometry() +{ + if (!m_container || !m_model) + return; + + if (m_container->layout() && !m_container->layout()->isActivated()) + m_container->layout()->activate(); + + ScrollBar *sb = verticalScrollBar(); + + if (sb) { + AbstractViewItem *item = m_container->itemAt(0); + if (item) { + qreal oneItemH = item->size().height(); + sb->setSliderSize(oneItemH*m_model->rowCount(m_rootIndex)-size().height()); + } + if (!sb->isVisible() && verticalScrollBarPolicy() != Qt::ScrollBarAlwaysOff && + contentsRect().height() < m_container->boundingRect().height()) + sb->show(); + } +} + +void AbstractItemView::scrollContentsBy(qreal dx, qreal dy) +{ + AbstractScrollArea::scrollContentsBy(dx, dy); + + if (!viewport() || !m_container || (m_container && m_container->itemCount() <= 0) || + !m_model || (m_model && m_model->rowCount() <= 0) || + (viewport() && viewport()->boundingRect().height() < contentsRect().height())) + return; + + qreal itemH = 1; + + AbstractViewItem *item = m_container->itemAt(0); + if(item && item->size().height() > 1) { + itemH = item->size().height(); + } + else if(item && item->preferredHeight() > 1) { + itemH = item->preferredHeight(); + } + + qreal vpx = m_container->pos().x(); + qreal vpy = m_container->pos().y(); + + if ((vpy+m_container->size().height()-dy > pos().y()+size().height()) && + (qAbs(dy) < itemH) && (vpy-dy <= 0)) { + m_container->setPos(vpx, vpy-dy); + } + else { + qreal vPos = verticalScrollBar()->sliderPosition(); + int startRow = m_model->index(vPos/itemH, 0).row(); + int itemsInContainer = m_container->itemCount(); + + for (int i = 0; i<itemsInContainer; ++i) { + AbstractViewItem *changedItem = m_container->itemAt(i); + changedItem->setModelIndex(m_model->index(startRow+i,0)); +#if (QT_VERSION >= 0x040600) + m_container->setListItemCaching(listItemCaching(), i); +#endif + } + + qreal diff = vPos-startRow*itemH; + + if (diff < 0) + m_container->setPos(vpx, diff); + else + m_container->setPos(vpx, -diff); + } +} + +void AbstractItemView::changeTheme() +{ + if (m_container) + m_container->themeChange(); +} + +void AbstractItemView::updateViewContent() +{ + if (m_container) + m_container->updateContent(); +} |