File indexing completed on 2024-05-19 04:48:42

0001 /****************************************************************************************
0002  * Copyright (c) 2007-2010 Bart Cerneels <bart.cerneels@kde.org>                        *
0003  *                                                                                      *
0004  * This program is free software; you can redistribute it and/or modify it under        *
0005  * the terms of the GNU General Public License as published by the Free Software        *
0006  * Foundation; either version 2 of the License, or (at your option) any later           *
0007  * version.                                                                             *
0008  *                                                                                      *
0009  * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
0010  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
0011  * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
0012  *                                                                                      *
0013  * You should have received a copy of the GNU General Public License along with         *
0014  * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
0015  ****************************************************************************************/
0016 
0017 #ifndef GROUPINGPROXY_H
0018 #define GROUPINGPROXY_H
0019 
0020 #include <QAbstractProxyModel>
0021 #include <QModelIndex>
0022 #include <QMultiHash>
0023 #include <QStringList>
0024 #include <QIcon>
0025 
0026 typedef QMap<int, QVariant> ItemData;
0027 typedef QMap<int, ItemData> RowData;
0028 
0029 
0030 class QtGroupingProxy : public QAbstractProxyModel
0031 {
0032     Q_OBJECT
0033     public:
0034         explicit QtGroupingProxy( QObject *parent = nullptr );
0035         explicit QtGroupingProxy(QAbstractItemModel *model, const QModelIndex &rootIndex = QModelIndex(),
0036                                   int groupedColumn = -1, QObject *parent = nullptr );
0037         ~QtGroupingProxy() override;
0038 
0039         /* QtGroupingProxy methods */
0040         void setRootIndex( const QModelIndex &rootIndex );
0041         void setGroupedColumn( int groupedColumn );
0042         virtual QModelIndex addEmptyGroup( const RowData &data );
0043         virtual bool removeGroup( const QModelIndex &idx );
0044 
0045         /* QAbstractProxyModel methods */
0046         //re-implemented to connect to source signals
0047         void setSourceModel( QAbstractItemModel *sourceModel ) override;
0048         QModelIndex index( int row, int column = 0,
0049                                    const QModelIndex& parent = QModelIndex() ) const override;
0050         Qt::ItemFlags flags( const QModelIndex &idx ) const override;
0051         QModelIndex buddy( const QModelIndex &index ) const override;
0052         QModelIndex parent( const QModelIndex &idx ) const override;
0053         int rowCount( const QModelIndex &idx = QModelIndex() ) const override;
0054         int columnCount( const QModelIndex &idx ) const override;
0055         QModelIndex mapToSource( const QModelIndex &idx ) const override;
0056         virtual QModelIndexList mapToSource( const QModelIndexList &list ) const;
0057         QModelIndex mapFromSource( const QModelIndex &idx ) const override;
0058         QVariant data( const QModelIndex &idx, int role ) const override;
0059         bool setData( const QModelIndex &index, const QVariant &value,
0060                               int role = Qt::EditRole ) override;
0061         QVariant headerData ( int section, Qt::Orientation orientation,
0062                                       int role ) const override;
0063         bool canFetchMore( const QModelIndex &parent ) const override;
0064         void fetchMore( const QModelIndex &parent ) override;
0065         bool hasChildren( const QModelIndex &parent = QModelIndex() ) const override;
0066 
0067     Q_SIGNALS:
0068         void renameIndex( const QModelIndex &idx );
0069 
0070     protected Q_SLOTS:
0071         virtual void buildTree();
0072 
0073     private Q_SLOTS:
0074         void modelDataChanged( const QModelIndex &, const QModelIndex & );
0075         void modelRowsInserted( const QModelIndex &, int, int );
0076         void modelRowsAboutToBeInserted( const QModelIndex &, int ,int );
0077         void modelRowsRemoved( const QModelIndex &, int, int );
0078         void modelRowsAboutToBeRemoved( const QModelIndex &, int ,int );
0079 
0080     protected:
0081         /** Maps an item to a group.
0082           * The return value is a list because an item can put in multiple groups.
0083           * Inside the list is a 2 dimensional map.
0084           * Mapped to column-number is another map of role-number to QVariant.
0085           * This data prepolulates the group-data cache. The rest is gathered on demand
0086           * from the children of the group.
0087           */
0088         virtual QList<RowData> belongsTo( const QModelIndex &idx );
0089 
0090         /**
0091           * calls belongsTo(), checks cached data and adds the index to existing or new groups.
0092           * @returns the groups this index was added to where -1 means it was added to the root.
0093           */
0094         QList<int> addSourceRow( const QModelIndex &idx );
0095         
0096         bool isGroup( const QModelIndex &index ) const;
0097         bool isAGroupSelected( const QModelIndexList &list ) const;
0098 
0099         /** Maintains the group -> sourcemodel row mapping
0100           * The reason a QList<int> is use instead of a QMultiHash is that the values have to be
0101           * reordered when rows are inserted or removed.
0102           * TODO:use some auto-incrementing container class (steveire's?) for the list
0103           */
0104         QHash<quint32, QList<int> > m_groupHash;
0105         /** The data cache of the groups.
0106           * This can be pre-loaded with data in belongsTo()
0107           */
0108         QList<RowData> m_groupMaps;
0109 
0110         /** "instructions" how to create an item in the tree.
0111           * This is used by parent( QModelIndex )
0112         */
0113         struct ParentCreate
0114         {
0115             quintptr parentCreateIndex;
0116             int row;
0117         };
0118         mutable QList<struct ParentCreate> m_parentCreateList;
0119         /** @returns index of the "instructions" to recreate the parent. Will create new if it doesn't exist yet.
0120         */
0121         int indexOfParentCreate( const QModelIndex &parent ) const;
0122 
0123         QModelIndexList m_selectedGroups;
0124 
0125         QModelIndex m_rootIndex;
0126         int m_groupedColumn;
0127 
0128         /* debug function */
0129         void dumpGroups() const;
0130 };
0131 
0132 #endif //GROUPINGPROXY_H