File indexing completed on 2024-07-21 06:38:22

0001 /*
0002     SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
0003     SPDX-FileContributor: Stephen Kelly <stephen@kdab.com>
0004     SPDX-FileCopyrightText: 2016 Ableton AG <info@ableton.com>
0005     SPDX-FileContributor: Stephen Kelly <stephen.kelly@ableton.com>
0006 
0007     SPDX-License-Identifier: LGPL-2.0-or-later
0008 */
0009 
0010 #ifndef KMODELINDEXPROXYMAPPER_H
0011 #define KMODELINDEXPROXYMAPPER_H
0012 
0013 #include <QObject>
0014 
0015 #include "kitemmodels_export.h"
0016 
0017 #include <memory>
0018 
0019 class QAbstractItemModel;
0020 class QModelIndex;
0021 class QItemSelection;
0022 class KModelIndexProxyMapperPrivate;
0023 
0024 /**
0025  * @class KModelIndexProxyMapper kmodelindexproxymapper.h KModelIndexProxyMapper
0026  *
0027  * @brief This class facilitates easy mapping of indexes and selections through proxy models.
0028  *
0029  * In a complex system of proxy models there can be a need to map indexes and selections between them,
0030  * and sometimes to do so without knowledge of the path from one model to another.
0031  *
0032  * For example,
0033  *
0034  * @verbatim
0035  *     Root model
0036  *         |
0037  *       /    \
0038  *   Proxy 1   Proxy 3
0039  *      |       |
0040  *   Proxy 2   Proxy 4
0041  * @endverbatim
0042  *
0043  * If there is a need to map indexes between proxy 2 and proxy 4, a KModelIndexProxyMapper can be created
0044  * to facilitate mapping of indexes between them.
0045  *
0046  * @code
0047  *   m_indexMapper = new KModelIndexProxyMapper(proxy2, proxy4, this);
0048  *
0049  *  ...
0050  *
0051  *   const QModelIndex proxy4Index = m_mapLeftToRight(proxy2->index(0, 0));
0052  *   Q_ASSERT(proxy4Index.model() == proxy4);
0053  * @endcode
0054  *
0055  * Note that the aim is to achieve black box connections so that there is no need for application code to
0056  * know the structure of proxy models in the path between left and right and attempt to manually map them.
0057  *
0058  * @verbatim
0059  *     Root model
0060  *         |
0061  *   ---------------
0062  *   |  Black Box  |
0063  *   ---------------
0064  *      |       |
0065  *   Proxy 2   Proxy 4
0066  * @endverbatim
0067  *
0068  * The isConnected property indicates whether there is a
0069  * path from the left side to the right side.
0070  *
0071  * @author Stephen Kelly <steveire@gmail.com>
0072  *
0073  */
0074 class KITEMMODELS_EXPORT KModelIndexProxyMapper : public QObject
0075 {
0076     Q_OBJECT
0077 
0078     /**
0079      * Indicates whether there is a chain that can be followed from leftModel to rightModel.
0080      *
0081      * This value can change if the sourceModel of an intermediate proxy is changed.
0082      */
0083     Q_PROPERTY(bool isConnected READ isConnected NOTIFY isConnectedChanged)
0084 public:
0085     /**
0086      * Constructor
0087      */
0088     KModelIndexProxyMapper(const QAbstractItemModel *leftModel, const QAbstractItemModel *rightModel, QObject *parent = nullptr);
0089 
0090     ~KModelIndexProxyMapper() override;
0091 
0092     /**
0093      * Maps the @p index from the left model to the right model.
0094      */
0095     QModelIndex mapLeftToRight(const QModelIndex &index) const;
0096 
0097     /**
0098      * Maps the @p index from the right model to the left model.
0099      */
0100     QModelIndex mapRightToLeft(const QModelIndex &index) const;
0101 
0102     /**
0103      * Maps the @p selection from the left model to the right model.
0104      */
0105     QItemSelection mapSelectionLeftToRight(const QItemSelection &selection) const;
0106 
0107     /**
0108      * Maps the @p selection from the right model to the left model.
0109      */
0110     QItemSelection mapSelectionRightToLeft(const QItemSelection &selection) const;
0111 
0112     bool isConnected() const;
0113 
0114 Q_SIGNALS:
0115     void isConnectedChanged();
0116 
0117 private:
0118     //@cond PRIVATE
0119     Q_DECLARE_PRIVATE(KModelIndexProxyMapper)
0120     std::unique_ptr<KModelIndexProxyMapperPrivate> const d_ptr;
0121     //@endcond
0122 };
0123 
0124 #endif