maxLibQt
GroupedItemsProxyModel.h
Go to the documentation of this file.
1 /*
2  GroupedItemsProxyModel
3  https://github.com/mpaperno/maxLibQt
4 
5  COPYRIGHT: (c)2017 Maxim Paperno; All Right Reserved.
6  Contact: http://www.WorldDesign.com/contact
7 
8  LICENSE:
9 
10  Commercial License Usage
11  Licensees holding valid commercial licenses may use this file in
12  accordance with the terms contained in a written agreement between
13  you and the copyright holder.
14 
15  GNU General Public License Usage
16  Alternatively, this file may be used under the terms of the GNU
17  General Public License as published by the Free Software Foundation,
18  either version 3 of the License, or (at your option) any later version.
19 
20  This program is distributed in the hope that it will be useful,
21  but WITHOUT ANY WARRANTY; without even the implied warranty of
22  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23  GNU General Public License for more details.
24 
25  A copy of the GNU General Public License is available at <http://www.gnu.org/licenses/>.
26 */
27 
28 #ifndef GROUPEDITEMSPROXYMODEL_H
29 #define GROUPEDITEMSPROXYMODEL_H
30 
31 #include <QIdentityProxyModel>
32 #include <QSize>
33 #include <QDebug>
34 #include <QMetaMethod>
35 
65 {
66  Q_OBJECT
67  Q_PROPERTY(int groupMatchRole READ groupMatchRole WRITE setGroupMatchRole)
73  Q_PROPERTY (int count READ count NOTIFY countChanged)
74 
75  public:
77 
78  explicit GroupedItemsProxyModel(QObject *parent = Q_NULLPTR, QAbstractItemModel *sourceModel = Q_NULLPTR, const QVector<int> &groupColumns = QVector<int>());
80 
81  // QAbstractItemModel interface
82  void setSourceModel(QAbstractItemModel *newSourceModel) Q_DECL_OVERRIDE;
83  QModelIndex index(int row, int column, const QModelIndex &parent) const Q_DECL_OVERRIDE;
84  QModelIndex parent(const QModelIndex &child) const Q_DECL_OVERRIDE;
85  int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
86  int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
87  bool hasChildren(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
88  QVariant data(const QModelIndex &index, int role = Qt::EditRole) const Q_DECL_OVERRIDE;
89  QMap<int, QVariant> itemData(const QModelIndex &index) const Q_DECL_OVERRIDE;
90  QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE;
91  Qt::ItemFlags flags(const QModelIndex &index) const Q_DECL_OVERRIDE;
92  QSize span(const QModelIndex &index) const Q_DECL_OVERRIDE;
93  QHash<int, QByteArray> roleNames() const;
94 
95  // QAbstractProxyModel interface
96  QModelIndex mapToSource(const QModelIndex &proxyIndex) const Q_DECL_OVERRIDE;
97  QModelIndex mapFromSource(const QModelIndex &sourceIndex) const Q_DECL_OVERRIDE;
98 
99  // Qml API
100  inline int count() { return rowCount(); }
101  Q_INVOKABLE void move (int idx, int pos, int parent = -1);
102 
103  Q_INVOKABLE int mapToSourceRow(int idx) const { return mapToSource(index(idx, 0, indexForItem(m_defaultParent))).row(); }
104  Q_INVOKABLE int mapFromSourceRow(int idx) const { return mapFromSource(sourceModel()->index(idx, 0)).row(); }
105 
106  Q_INVOKABLE QObject *get (int idx) const {
107  const static int getIdx = sourceModel()->metaObject()->indexOfMethod(QMetaObject::normalizedSignature("get(int)"));
108  if (getIdx > -1) {
109  QObject *ret;
110  sourceModel()->metaObject()->invokeMethod(sourceModel(), "get", Qt::DirectConnection, Q_RETURN_ARG(QObject *, ret), Q_ARG(int, mapToSourceRow(idx)));
111  return ret;
112  }
113  qWarning() << "Can't get(int), source model not compatible";
114  return nullptr;
115  }
116 
117  Q_INVOKABLE QObject *get (const QString &uid) const {
118  const static int getIdx = sourceModel()->metaObject()->indexOfMethod(QMetaObject::normalizedSignature("get(QString)"));
119  if (getIdx > -1) {
120  QObject *ret;
121  sourceModel()->metaObject()->invokeMethod(sourceModel(), "get", Qt::DirectConnection, Q_RETURN_ARG(QObject *, ret), Q_ARG(const QString &, uid));
122  return ret;
123  }
124  qWarning() << "Can't get(QString), source model not compatible";
125  return nullptr;
126  }
127 
128  // GroupedItemProxyModel interface
129 
131  inline int groupMatchRole() const { return m_groupMatchRole; }
133  inline int groupColumnVisible() const { return m_groupColumnVisible; }
135  inline int groupColumnIsProxy() const { return m_groupColumnIsProxy; }
137  inline int groupColumnProxySrc() const { return m_groupColumnProxySrc; }
139  inline int groupRowSelectable() const { return m_groupRowSelectable; }
142 
143  signals:
144  void countChanged();
145 
146  public slots:
148  inline void addGroup(int column) { addGroups(QVector<int>() << column); }
150  virtual void addGroups(const QVector<int> & columns);
152  virtual void setGroups(const QVector<int> & columns);
154  virtual void insertGroup(int index, int column);
156  virtual void removeGroup(int column);
158  virtual void clearGroups();
160  virtual void setRootGroup(int column = -1, const QVariant &value = QVariant());
161  // properties
162  virtual void setGroupMatchRole(int role);
163  virtual void setGroupColumnVisible(bool visible) { m_groupColumnVisible = visible; }
164  virtual void setGroupColumnIsProxy(bool enable) { m_groupColumnIsProxy = enable; }
165  virtual void setGroupColumnProxySrc(int column) { m_groupColumnProxySrc = column; }
166  virtual void setGroupRowSelectable(bool selectable) { m_groupRowSelectable = selectable; }
167  virtual void setGroupHeaderTitle(const QString &title, const QString &tooltip = QString());
168 
169  protected:
170  class GroupedProxyItem; // forward
171 
172  virtual uint extraColumns() const { return (!m_groups.isEmpty() && groupColumnVisible() ? 1 : 0); }
173  virtual QModelIndex indexForItem(GroupedProxyItem *item, const int col = 0) const;
174  virtual GroupedProxyItem * itemForIndex(const QModelIndex &index, const bool rootDefault = false) const;
175  virtual GroupedProxyItem * findGroupItem(const int group, const QVariant &value = QVariant(), GroupedProxyItem *parent = NULL) const;
176  virtual QModelIndex sourceIndexForProxy(GroupedProxyItem *item) const;
177  virtual bool isProxyColumn(const QModelIndex &index) const { return (index.isValid() && extraColumns() && index.column() == 0 && groupColumnIsProxy()); }
178  int totalRowCount(GroupedProxyItem *parent = NULL) const;
179  GroupedProxyItem * itemForRow(int row, GroupedProxyItem *parent = NULL) const;
180 
181  protected slots:
182  virtual GroupedProxyItem * placeSourceRow(const int row);
183  virtual void removeItem(GroupedProxyItem *item);
184  virtual void removeUnusedGroups(GroupedProxyItem *parent = NULL);
185  virtual void reloadSourceModel();
186  virtual void modelResetHandler();
187  virtual void dataChangedHandler(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles = QVector<int>());
188  virtual void rowsInsertedHandler(const QModelIndex &parent, int first, int last);
189  virtual void rowsRemovedHandler(const QModelIndex &parent, int first, int last);
190  virtual void rowsMovedHandler(const QModelIndex &parent, int start, int end, const QModelIndex &destination, int row);
191 
192  protected:
204 
205  private:
206  bool setReloadSuspended(bool enable) { bool prev = m_reloadSuspended; m_reloadSuspended = enable; return prev; }
207  bool reloadSuspended() const { return m_reloadSuspended; }
208 
209  bool m_reloadSuspended;
210 
211 
212  protected:
214  {
215  public:
216  explicit GroupedProxyItem(const QModelIndex &srcIndex, const bool isSrcItem = false, GroupedProxyItem *parent = NULL);
217  explicit GroupedProxyItem(GroupedProxyItem *parent = NULL);
218  virtual ~GroupedProxyItem();
219 
220  int row() const;
221  QVariant data(int role = Qt::EditRole) const { return m_itemData.value(role, QVariant()); }
223  int rowCount() const { return m_childItems.size(); }
225  GroupedProxyItem * child(const int row) const { return m_childItems.value(row, NULL); }
226  int childRow(GroupedProxyItem * child) const { return m_childItems.indexOf(child); }
227  GroupedProxyItem * parent() const { return m_parentItem; }
228 
230  bool isSourceItem() const { return m_isSourceItem; }
231  bool isGroupItem() const { return !isSourceItem(); }
232 
233  void clear();
234  GroupedProxyItem * addChild(const QModelIndex &srcIndex, const bool isSrcItem = true);
235  void removeChild(GroupedProxyItem * item);
236  void removeChild(const int row) { removeChild(child(row)); }
237  bool setData(const QVariant &data, int role = Qt::EditRole);
238  bool setItemData(const QMap<int, QVariant> &roles);
239 
240  protected:
246 
248  }; // GroupedProxyItem
249  \
250 }; // GroupedItemsProxyModel
251 
252 #endif // GROUPEDITEMSPROXYMODEL_H
GroupedProxyItem(const QModelIndex &srcIndex, const bool isSrcItem=false, GroupedProxyItem *parent=NULL)
GroupedProxyItem.
int rowCount(const QModelIndex &parent=QModelIndex()) const override
QModelIndex mapToSource(const QModelIndex &proxyIndex) const override
QByteArray normalizedSignature(const char *method)
virtual GroupedProxyItem * findGroupItem(const int group, const QVariant &value=QVariant(), GroupedProxyItem *parent=NULL) const
QVariant data(const QModelIndex &index, int role=Qt::EditRole) const override
virtual void dataChangedHandler(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector< int > &roles=QVector< int >())
QModelIndex index(int row, int column, const QModelIndex &parent) const override
int indexOfMethod(const char *method) const const
virtual void setGroupMatchRole(int role)
virtual QModelIndex sourceIndexForProxy(GroupedProxyItem *item) const
virtual void clearGroups()
Remove the previously-added groupings.
bool setData(const QVariant &data, int role=Qt::EditRole)
bool isValid() const const
void setSourceModel(QAbstractItemModel *newSourceModel) override
virtual void removeUnusedGroups(GroupedProxyItem *parent=NULL)
virtual GroupedProxyItem * itemForIndex(const QModelIndex &index, const bool rootDefault=false) const
GroupedItemsProxyModel(QObject *parent=Q_NULLPTR, QAbstractItemModel *sourceModel=Q_NULLPTR, const QVector< int > &groupColumns=QVector< int >())
GroupedItemProxyModel.
void move(int idx, int pos, int parent=-1)
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
UserRole
int row() const const
Qt::ItemFlags flags(const QModelIndex &index) const override
virtual void setGroupColumnIsProxy(bool enable)
QObject * get(const QString &uid) const
virtual const QMetaObject * metaObject() const const
virtual uint extraColumns() const
virtual void removeGroup(int column)
Remove the previously-added column grouping.
int mapToSourceRow(int idx) const
bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType type, QGenericReturnArgument ret, QGenericArgument val0, QGenericArgument val1, QGenericArgument val2, QGenericArgument val3, QGenericArgument val4, QGenericArgument val5, QGenericArgument val6, QGenericArgument val7, QGenericArgument val8, QGenericArgument val9)
QVariant data(int role=Qt::EditRole) const
int childRow(GroupedProxyItem *child) const
GroupedItemsProxyModel allows a grouped item presentation of a flat table data model.
QAbstractItemModel * sourceModel() const const
virtual void removeItem(GroupedProxyItem *item)
QVector< GroupedProxyItem * > children() const
virtual void addGroups(const QVector< int > &columns)
Add multiple groupings based on columns.
GroupedProxyItem * child(const int row) const
void addGroup(int column)
Add a new grouping based on column.
bool isEmpty() const const
virtual void setGroupRowSelectable(bool selectable)
virtual void setGroupHeaderTitle(const QString &title, const QString &tooltip=QString())
virtual QModelIndex indexForItem(GroupedProxyItem *item, const int col=0) const
virtual void setGroups(const QVector< int > &columns)
Add multiple groupings based on columns.
QHash< int, GroupedProxyItem * > m_sourceMap
int column() const const
virtual void setGroupColumnVisible(bool visible)
virtual void rowsRemovedHandler(const QModelIndex &parent, int first, int last)
int totalRowCount(GroupedProxyItem *parent=NULL) const
GroupedProxyItem * m_defaultParent
int mapFromSourceRow(int idx) const
QObject * get(int idx) const
virtual void insertGroup(int index, int column)
Insert a new grouping at index based on column.
GroupedProxyItem * addChild(const QModelIndex &srcIndex, const bool isSrcItem=true)
virtual void setRootGroup(int column=-1, const QVariant &value=QVariant())
Sets parent group.
virtual void rowsMovedHandler(const QModelIndex &parent, int start, int end, const QModelIndex &destination, int row)
virtual bool isProxyColumn(const QModelIndex &index) const
DirectConnection
QObject * parent() const const
virtual void rowsInsertedHandler(const QModelIndex &parent, int first, int last)
int columnCount(const QModelIndex &parent=QModelIndex()) const override
QString toString() const const
bool hasChildren(const QModelIndex &parent=QModelIndex()) const override
QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override
bool setItemData(const QMap< int, QVariant > &roles)
virtual GroupedProxyItem * placeSourceRow(const int row)
QMap< int, QVariant > itemData(const QModelIndex &index) const override
virtual void setGroupColumnProxySrc(int column)
QHash< int, QByteArray > roleNames() const
const T value(const Key &key, const T &defaultValue) const const
GroupedProxyItem * itemForRow(int row, GroupedProxyItem *parent=NULL) const
QSize span(const QModelIndex &index) const override