File indexing completed on 2025-04-20 06:44:16
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 KLINKITEMSELECTIONMODEL_H 0011 #define KLINKITEMSELECTIONMODEL_H 0012 0013 #include <QItemSelectionModel> 0014 0015 #include "kitemmodels_export.h" 0016 0017 #include <memory> 0018 0019 class KLinkItemSelectionModelPrivate; 0020 0021 /** 0022 @class KLinkItemSelectionModel klinkitemselectionmodel.h KLinkItemSelectionModel 0023 0024 @brief Makes it possible to share a selection in multiple views which do not have the same source model 0025 0026 Although <a href="https://doc.qt.io/qt-5/model-view-programming.html#handling-selections-of-items">multiple views can share the same QItemSelectionModel</a>, 0027 the views then need to have the same source model. 0028 0029 If there is a proxy model between the model and one of the views, or different proxy models in each, this class makes 0030 it possible to share the selection between the views. 0031 0032 @image html kproxyitemselectionmodel-simple.png "Sharing a QItemSelectionModel between views on the same model is trivial" 0033 @image html kproxyitemselectionmodel-error.png "If a proxy model is used, it is no longer possible to share the QItemSelectionModel directly" 0034 @image html kproxyitemselectionmodel-solution.png "A KLinkItemSelectionModel can be used to map the selection through the proxy model" 0035 0036 @code 0037 QAbstractItemModel *model = getModel(); 0038 0039 QSortFilterProxyModel *proxy = new QSortFilterProxyModel(); 0040 proxy->setSourceModel(model); 0041 0042 QTreeView *view1 = new QTreeView(splitter); 0043 view1->setModel(model); 0044 0045 KLinkItemSelectionModel *view2SelectionModel = new KLinkItemSelectionModel( proxy, view1->selectionModel()); 0046 0047 QTreeView *view2 = new QTreeView(splitter); 0048 // Note that the QAbstractItemModel passed to KLinkItemSelectionModel must be the same as what is used in the view 0049 view2->setModel(proxy); 0050 view2->setSelectionModel( view2SelectionModel ); 0051 @endcode 0052 0053 @image html kproxyitemselectionmodel-complex.png "Arbitrarily complex proxy configurations on the same root model can be used" 0054 0055 @code 0056 QAbstractItemModel *model = getModel(); 0057 0058 QSortFilterProxyModel *proxy1 = new QSortFilterProxyModel(); 0059 proxy1->setSourceModel(model); 0060 QSortFilterProxyModel *proxy2 = new QSortFilterProxyModel(); 0061 proxy2->setSourceModel(proxy1); 0062 QSortFilterProxyModel *proxy3 = new QSortFilterProxyModel(); 0063 proxy3->setSourceModel(proxy2); 0064 0065 QTreeView *view1 = new QTreeView(splitter); 0066 view1->setModel(proxy3); 0067 0068 QSortFilterProxyModel *proxy4 = new QSortFilterProxyModel(); 0069 proxy4->setSourceModel(model); 0070 QSortFilterProxyModel *proxy5 = new QSortFilterProxyModel(); 0071 proxy5->setSourceModel(proxy4); 0072 0073 KLinkItemSelectionModel *view2SelectionModel = new KLinkItemSelectionModel( proxy5, view1->selectionModel()); 0074 0075 QTreeView *view2 = new QTreeView(splitter); 0076 // Note that the QAbstractItemModel passed to KLinkItemSelectionModel must be the same as what is used in the view 0077 view2->setModel(proxy5); 0078 view2->setSelectionModel( view2SelectionModel ); 0079 @endcode 0080 0081 See also <a href="https://commits.kde.org/kitemmodels?path=tests/proxymodeltestapp/proxyitemselectionwidget.cpp">kitemmodels: 0082 tests/proxymodeltestapp/proxyitemselectionwidget.cpp</a>. 0083 0084 @since 4.5 0085 @author Stephen Kelly <steveire@gmail.com> 0086 0087 */ 0088 class KITEMMODELS_EXPORT KLinkItemSelectionModel : public QItemSelectionModel 0089 { 0090 Q_OBJECT 0091 Q_PROPERTY( 0092 QItemSelectionModel *linkedItemSelectionModel READ linkedItemSelectionModel WRITE setLinkedItemSelectionModel NOTIFY linkedItemSelectionModelChanged) 0093 public: 0094 /** 0095 Constructor. 0096 */ 0097 KLinkItemSelectionModel(QAbstractItemModel *targetModel, QItemSelectionModel *linkedItemSelectionModel, QObject *parent = nullptr); 0098 0099 explicit KLinkItemSelectionModel(QObject *parent = nullptr); 0100 0101 ~KLinkItemSelectionModel() override; 0102 0103 QItemSelectionModel *linkedItemSelectionModel() const; 0104 void setLinkedItemSelectionModel(QItemSelectionModel *selectionModel); 0105 0106 void select(const QModelIndex &index, QItemSelectionModel::SelectionFlags command) override; 0107 void select(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command) override; 0108 0109 Q_SIGNALS: 0110 void linkedItemSelectionModelChanged(); 0111 0112 protected: 0113 std::unique_ptr<KLinkItemSelectionModelPrivate> const d_ptr; 0114 0115 private: 0116 Q_DECLARE_PRIVATE(KLinkItemSelectionModel) 0117 Q_PRIVATE_SLOT(d_func(), void sourceSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected)) 0118 Q_PRIVATE_SLOT(d_func(), void sourceCurrentChanged(const QModelIndex ¤t)) 0119 Q_PRIVATE_SLOT(d_func(), void slotCurrentChanged(const QModelIndex ¤t)) 0120 }; 0121 0122 #endif