diff options
Diffstat (limited to 'tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractitemview.cpp')
-rw-r--r-- | tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractitemview.cpp | 425 |
1 files changed, 425 insertions, 0 deletions
diff --git a/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractitemview.cpp b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractitemview.cpp new file mode 100644 index 0000000000..961cf4e03c --- /dev/null +++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractitemview.cpp @@ -0,0 +1,425 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $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)); + m_container->setListItemCaching(listItemCaching(), i); + } + + 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(); +} |