/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Data Visualization module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:GPL$ ** 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 or (at your option) any later version ** approved by the KDE Free Qt Foundation. The licenses are as published by ** the Free Software Foundation and appearing in the file LICENSE.GPL3 ** 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 "abstractitemmodelhandler_p.h" QT_BEGIN_NAMESPACE_DATAVISUALIZATION AbstractItemModelHandler::AbstractItemModelHandler(QObject *parent) : QObject(parent), resolvePending(0), m_fullReset(true) { m_resolveTimer.setSingleShot(true); QObject::connect(&m_resolveTimer, &QTimer::timeout, this, &AbstractItemModelHandler::handlePendingResolve); } AbstractItemModelHandler::~AbstractItemModelHandler() { } void AbstractItemModelHandler::setItemModel(QAbstractItemModel *itemModel) { if (itemModel != m_itemModel.data()) { if (!m_itemModel.isNull()) QObject::disconnect(m_itemModel, 0, this, 0); m_itemModel = itemModel; if (!m_itemModel.isNull()) { QObject::connect(m_itemModel.data(), &QAbstractItemModel::columnsInserted, this, &AbstractItemModelHandler::handleColumnsInserted); QObject::connect(m_itemModel.data(), &QAbstractItemModel::columnsMoved, this, &AbstractItemModelHandler::handleColumnsMoved); QObject::connect(m_itemModel.data(), &QAbstractItemModel::columnsRemoved, this, &AbstractItemModelHandler::handleColumnsRemoved); QObject::connect(m_itemModel.data(), &QAbstractItemModel::dataChanged, this, &AbstractItemModelHandler::handleDataChanged); QObject::connect(m_itemModel.data(), &QAbstractItemModel::layoutChanged, this, &AbstractItemModelHandler::handleLayoutChanged); QObject::connect(m_itemModel.data(), &QAbstractItemModel::modelReset, this, &AbstractItemModelHandler::handleModelReset); QObject::connect(m_itemModel.data(), &QAbstractItemModel::rowsInserted, this, &AbstractItemModelHandler::handleRowsInserted); QObject::connect(m_itemModel.data(), &QAbstractItemModel::rowsMoved, this, &AbstractItemModelHandler::handleRowsMoved); QObject::connect(m_itemModel.data(), &QAbstractItemModel::rowsRemoved, this, &AbstractItemModelHandler::handleRowsRemoved); } if (!m_resolveTimer.isActive()) m_resolveTimer.start(0); emit itemModelChanged(itemModel); } } QAbstractItemModel *AbstractItemModelHandler::itemModel() const { return m_itemModel.data(); } void AbstractItemModelHandler::handleColumnsInserted(const QModelIndex &parent, int start, int end) { Q_UNUSED(parent) Q_UNUSED(start) Q_UNUSED(end) // Manipulating columns changes all rows in proxies that map rows/columns directly, // and its effects are not clearly defined in others -> always do full reset. if (!m_resolveTimer.isActive()) { m_fullReset = true; m_resolveTimer.start(0); } } void AbstractItemModelHandler::handleColumnsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationColumn) { Q_UNUSED(sourceParent) Q_UNUSED(sourceStart) Q_UNUSED(sourceEnd) Q_UNUSED(destinationParent) Q_UNUSED(destinationColumn) // Manipulating columns changes all rows in proxies that map rows/columns directly, // and its effects are not clearly defined in others -> always do full reset. if (!m_resolveTimer.isActive()) { m_fullReset = true; m_resolveTimer.start(0); } } void AbstractItemModelHandler::handleColumnsRemoved(const QModelIndex &parent, int start, int end) { Q_UNUSED(parent) Q_UNUSED(start) Q_UNUSED(end) // Manipulating columns changes all rows in proxies that map rows/columns directly, // and its effects are not clearly defined in others -> always do full reset. if (!m_resolveTimer.isActive()) { m_fullReset = true; m_resolveTimer.start(0); } } void AbstractItemModelHandler::handleDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector &roles) { Q_UNUSED(topLeft) Q_UNUSED(bottomRight) Q_UNUSED(roles) // Default handling for dataChanged is to do full reset, as it cannot be optimized // in a general case, where we do not know which row/column/index the item model item // actually ended up to in the proxy. if (!m_resolveTimer.isActive()) { m_fullReset = true; m_resolveTimer.start(0); } } void AbstractItemModelHandler::handleLayoutChanged(const QList &parents, QAbstractItemModel::LayoutChangeHint hint) { Q_UNUSED(parents) Q_UNUSED(hint) // Resolve entire model if layout changes if (!m_resolveTimer.isActive()) { m_fullReset = true; m_resolveTimer.start(0); } } void AbstractItemModelHandler::handleModelReset() { // Data cleared, reset array if (!m_resolveTimer.isActive()) { m_fullReset = true; m_resolveTimer.start(0); } } void AbstractItemModelHandler::handleRowsInserted(const QModelIndex &parent, int start, int end) { Q_UNUSED(parent) Q_UNUSED(start) Q_UNUSED(end) // Default handling for rowsInserted is to do full reset, as it cannot be optimized // in a general case, where we do not know which row/column/index the item model item // actually ended up to in the proxy. if (!m_resolveTimer.isActive()) { m_fullReset = true; m_resolveTimer.start(0); } } void AbstractItemModelHandler::handleRowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow) { Q_UNUSED(sourceParent) Q_UNUSED(sourceStart) Q_UNUSED(sourceEnd) Q_UNUSED(destinationParent) Q_UNUSED(destinationRow) // Default handling for rowsMoved is to do full reset, as it cannot be optimized // in a general case, where we do not know which row/column/index the item model item // actually ended up to in the proxy. if (!m_resolveTimer.isActive()) { m_fullReset = true; m_resolveTimer.start(0); } } void AbstractItemModelHandler::handleRowsRemoved(const QModelIndex &parent, int start, int end) { Q_UNUSED(parent) Q_UNUSED(start) Q_UNUSED(end) // Default handling for rowsRemoved is to do full reset, as it cannot be optimized // in a general case, where we do not know which row/column/index the item model item // actually ended up to in the proxy. if (!m_resolveTimer.isActive()) { m_fullReset = true; m_resolveTimer.start(0); } } void AbstractItemModelHandler::handleMappingChanged() { if (!m_resolveTimer.isActive()) m_resolveTimer.start(0); } void AbstractItemModelHandler::handlePendingResolve() { resolveModel(); m_fullReset = false; } QT_END_NAMESPACE_DATAVISUALIZATION