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

0001 /*
0002     SPDX-FileCopyrightText: 2015 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
0003     SPDX-FileContributor: David Faure <david.faure@kdab.com>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #ifndef KEXTRACOLUMNSPROXYMODEL_H
0009 #define KEXTRACOLUMNSPROXYMODEL_H
0010 
0011 #include "kitemmodels_export.h"
0012 #include <QIdentityProxyModel>
0013 
0014 #include <memory>
0015 
0016 class KExtraColumnsProxyModelPrivate;
0017 
0018 /**
0019  * @class KExtraColumnsProxyModel kextracolumnsproxymodel.h KExtraColumnsProxyModel
0020  *
0021  * This proxy appends extra columns (after all existing columns).
0022  *
0023  * The proxy supports source models that have a tree structure.
0024  * It also supports editing, and propagating changes from the source model.
0025  * Row insertion/removal, column insertion/removal in the source model are supported.
0026  *
0027  * Not supported: adding/removing extra columns at runtime; having a different number of columns in subtrees;
0028  * drag-n-drop support in the extra columns; moving columns.
0029  *
0030  * Derive from KExtraColumnsProxyModel, call appendColumn (typically in the constructor) for each extra column,
0031  * and reimplement extraColumnData() to allow KExtraColumnsProxyModel to retrieve the data to show in the extra columns.
0032  *
0033  * If you want your new column(s) to be somewhere else than at the right of the existing columns, you can
0034  * use a KRearrangeColumnsProxyModel on top.
0035  *
0036  * Author: David Faure, KDAB
0037  * @since 5.13
0038  */
0039 class KITEMMODELS_EXPORT KExtraColumnsProxyModel : public QIdentityProxyModel
0040 {
0041     Q_OBJECT
0042 public:
0043     /**
0044      * Base class constructor.
0045      * Remember to call setSourceModel afterwards, and appendColumn.
0046      */
0047     explicit KExtraColumnsProxyModel(QObject *parent = nullptr);
0048     /**
0049      * Destructor.
0050      */
0051     ~KExtraColumnsProxyModel() override;
0052 
0053     // API
0054 
0055     /**
0056      * Appends an extra column.
0057      * @param header an optional text for the horizontal header
0058      * This does not emit any signals - do it in the initial setup phase
0059      */
0060     void appendColumn(const QString &header = QString());
0061 
0062     /**
0063      * Removes an extra column.
0064      * @param idx index of the extra column (starting from 0).
0065      * This does not emit any signals - do it in the initial setup phase
0066      * @since 5.24
0067      */
0068     void removeExtraColumn(int idx);
0069 
0070     /**
0071      * This method is called by data() for extra columns.
0072      * Reimplement this method to return the data for the extra columns.
0073      *
0074      * @param parent the parent model index in the proxy model (only useful in tree models)
0075      * @param row the row number for which the proxy model is querying for data (child of @p parent, if set)
0076      * @param extraColumn the number of the extra column, starting at 0 (this doesn't require knowing how many columns the source model has)
0077      * @param role the role being queried
0078      * @return the data at @p row and @p extraColumn
0079      */
0080     virtual QVariant extraColumnData(const QModelIndex &parent, int row, int extraColumn, int role = Qt::DisplayRole) const = 0;
0081 
0082     // KF6 TODO: add extraColumnFlags() virtual method
0083 
0084     /**
0085      * This method is called by setData() for extra columns.
0086      * Reimplement this method to set the data for the extra columns, if editing is supported.
0087      * Remember to call extraColumnDataChanged() after changing the data storage.
0088      * The default implementation returns false.
0089      */
0090     virtual bool setExtraColumnData(const QModelIndex &parent, int row, int extraColumn, const QVariant &data, int role = Qt::EditRole);
0091 
0092     /**
0093      * This method can be called by your derived class when the data in an extra column has changed.
0094      * The use case is data that changes "by itself", unrelated to setData.
0095      */
0096     void extraColumnDataChanged(const QModelIndex &parent, int row, int extraColumn, const QList<int> &roles);
0097 
0098     /**
0099      * Returns the extra column number (0, 1, ...) for a given column number of the proxymodel.
0100      * This basically means subtracting the amount of columns in the source model.
0101      */
0102     int extraColumnForProxyColumn(int proxyColumn) const;
0103     /**
0104      * Returns the proxy column number for a given extra column number (starting at 0).
0105      * This basically means adding the amount of columns in the source model.
0106      */
0107     int proxyColumnForExtraColumn(int extraColumn) const;
0108 
0109     // Implementation
0110     /// @reimp
0111     void setSourceModel(QAbstractItemModel *model) override;
0112     /// @reimp
0113     QModelIndex mapToSource(const QModelIndex &proxyIndex) const override;
0114     /// @reimp
0115     QItemSelection mapSelectionToSource(const QItemSelection &selection) const override;
0116     /// @reimp
0117     int columnCount(const QModelIndex &parent = QModelIndex()) const override;
0118     /// @reimp
0119     QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
0120     /// @reimp
0121     bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
0122     /// @reimp
0123     QModelIndex sibling(int row, int column, const QModelIndex &idx) const override;
0124     /// @reimp
0125     QModelIndex buddy(const QModelIndex &index) const override;
0126     /// @reimp
0127     Qt::ItemFlags flags(const QModelIndex &index) const override;
0128     /// @reimp
0129     bool hasChildren(const QModelIndex &index) const override;
0130     /// @reimp
0131     QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
0132     /// @reimp
0133     QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
0134     /// @reimp
0135     QModelIndex parent(const QModelIndex &child) const override;
0136 
0137 private:
0138     Q_DECLARE_PRIVATE(KExtraColumnsProxyModel)
0139     Q_PRIVATE_SLOT(d_func(), void _ec_sourceLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &, QAbstractItemModel::LayoutChangeHint))
0140     Q_PRIVATE_SLOT(d_func(), void _ec_sourceLayoutChanged(const QList<QPersistentModelIndex> &, QAbstractItemModel::LayoutChangeHint))
0141     std::unique_ptr<KExtraColumnsProxyModelPrivate> const d_ptr;
0142 };
0143 
0144 #endif