-
Notifications
You must be signed in to change notification settings - Fork 388
Expand file tree
/
Copy pathWAggregateProxyModel.h
More file actions
246 lines (205 loc) · 7.64 KB
/
WAggregateProxyModel.h
File metadata and controls
246 lines (205 loc) · 7.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
// This may look like C code, but it's really -*- C++ -*-
/*
* Copyright (C) 2008 Emweb bv, Herent, Belgium.
*
* See the LICENSE file for terms of use.
*/
#ifndef WAGGREGATE_PROXY_MODEL_H_
#define WAGGREGATE_PROXY_MODEL_H_
#include <Wt/WAbstractProxyModel.h>
namespace Wt {
class WRegExp;
/*! \class WAggregateProxyModel Wt/WAggregateProxyModel.h Wt/WAggregateProxyModel.h
* \brief A proxy model for %Wt's item models that provides column aggregation.
*
* This proxy model does not store data itself, but presents data from
* a source model, and presents methods to organize columns using aggregation,
* through which a user may navigate (usually to obtain more detailed results
* related to a single aggregate quantity).
*
* To use this proxy model, you should provide a source model using
* setSourceModel(), and define column ranges that can be aggregated
* using addAggregate().
*
* \if cpp
* Example:
* \code
int COLS = 18;
int ROWS = 20;
// set up the source model
model_ = std::make_shared<WStandardItemModel>(0, COLS);
std::string columns[] = {
"Supplier",
"2004",
"Q1",
"January",
"February",
"March",
"Q2",
"April",
"May",
"June",
"Q3",
"July",
"August",
"September",
"Q4",
"October",
"November",
"December"
};
for (unsigned i = 0; i < COLS; ++i) {
model_->setHeaderData(i, Orientation::Horizontal, columns[i]);
}
for (unsigned i = 0; i < ROWS; ++i) {
model_->insertRow(i);
for (unsigned j = 0; j < COLS; ++j)
model_->setData(i, j, "col " + std::to_string(j));
}
// set up the proxy model
auto proxy = std::make_shared<WAggregateProxyModel>();
proxy->setSourceModel(model_);
proxy->addAggregate(1, 2, 17);
proxy->addAggregate(2, 3, 5);
proxy->addAggregate(6, 7, 9);
proxy->addAggregate(10, 11, 13);
proxy->addAggregate(14, 15, 17);
proxy->expandColumn(1); // expand 2004 -> Q1 Q2 Q3 Q4
// define a view
treeView_ = root()->addWidget(std::make_unique<WTreeView>());
treeView_->setColumnBorder(Wt::StandardColor::Black);
treeView_->setModel(proxy);
treeView_->setColumnWidth(0, 160);
treeView_->setColumnResizeEnabled(true);
treeView_->setSortingEnabled(true);
\endcode
* \endif
*
* This example would render like this:
*
* \image html WAggregateProxyModel-1.png "A WTreeView using a WAggregateProxyModel"
*
* \note This model does not support dynamic changes to the column
* definition of the source model (i.e. insertions or deletions of
* source model columns).
*
* \ingroup modelview
*/
class WT_API WAggregateProxyModel : public WAbstractProxyModel
{
public:
/*! \brief Constructor.
*
* Sets up the proxy without aggregation functionality.
*/
WAggregateProxyModel();
/*! \brief Destructor.
*/
virtual ~WAggregateProxyModel();
/*! \brief Adds a new column aggregation definition.
*
* The \p parentColumn is the column index in the source model that
* acts as an aggregate for columns \p firstColumn to \p
* lastColumn. \p parentColumn must border the range defined by
* \p firstColumn to \p lastColumn:
* \code
* parentColumn == firstColumn - 1 || parentColumn == lastColumn + 1
* \endcode
*
* Note that column parameters reference column indexes in the
* source model.
*
* Aggregation definitions can be nested, but should be strictly
* hierarchical.
*
* The aggregate column will initially be collapsed.
*
* Only one aggregate can be defined per \p parentColumn.
*/
void addAggregate(int parentColumn, int firstColumn, int lastColumn);
virtual WModelIndex mapFromSource(const WModelIndex& sourceIndex)
const override;
virtual WModelIndex mapToSource(const WModelIndex& proxyIndex)
const override;
virtual void setSourceModel(const std::shared_ptr<WAbstractItemModel>&
sourceModel) override;
virtual void expandColumn(int column) override;
virtual void collapseColumn(int column) override;
virtual int columnCount(const WModelIndex& parent = WModelIndex())
const override;
virtual int rowCount(const WModelIndex& parent = WModelIndex())
const override;
virtual WFlags<HeaderFlag> headerFlags
(int section, Orientation orientation = Orientation::Horizontal)
const override;
virtual bool setHeaderData
(int section, Orientation orientation, const cpp17::any& value,
ItemDataRole role = ItemDataRole::Edit) override;
virtual cpp17::any headerData
(int section, Orientation orientation = Orientation::Horizontal,
ItemDataRole role = ItemDataRole::Display) const override;
virtual WModelIndex parent(const WModelIndex& index) const override;
virtual WModelIndex index(int row, int column,
const WModelIndex& parent = WModelIndex())
const override;
virtual void sort(int column,
SortOrder order = SortOrder::Ascending) override;
private:
struct Aggregate {
int parentSrc_;
int firstChildSrc_, lastChildSrc_;
int level_;
bool collapsed_;
std::vector<Aggregate> nestedAggregates_;
Aggregate();
Aggregate(int parentColumn, int firstColumn, int lastColumn);
bool contains(const Aggregate& other) const;
bool contains(int column) const;
Aggregate *add(const Aggregate& other);
int mapFromSource(int sourceColumn) const;
int mapToSource(int column) const;
bool before(const Aggregate& other) const;
bool after(int column) const;
bool before(int column) const;
int collapsedCount() const;
Aggregate *findAggregate(int parentColumn);
const Aggregate *findAggregate(int parentColumn) const;
const Aggregate *findEnclosingAggregate(int column) const;
int firstVisibleNotBefore(int column) const;
int lastVisibleNotAfter(int column) const;
};
Aggregate topLevel_;
std::vector<Wt::Signals::connection> modelConnections_;
void expand(Aggregate& aggregate);
void collapse(Aggregate& aggregate);
void propagateBeginRemove(const WModelIndex& proxyIndex,
int start, int end);
void propagateEndRemove(const WModelIndex& proxyIndex,
int start, int end);
void propagateBeginInsert(const WModelIndex& proxyIndex,
int start, int end);
void propagateEndInsert(const WModelIndex& proxyIndex,
int start, int end);
int lastVisibleSourceNotAfter(int sourceColumn) const;
int firstVisibleSourceNotBefore(int sourceColumn) const;
void sourceColumnsAboutToBeInserted(const WModelIndex& parent,
int start, int end);
void sourceColumnsInserted(const WModelIndex& parent, int start, int end);
void sourceColumnsAboutToBeRemoved(const WModelIndex& parent,
int start, int end);
void sourceColumnsRemoved(const WModelIndex& parent, int start, int end);
void sourceRowsAboutToBeInserted(const WModelIndex& parent,
int start, int end);
void sourceRowsInserted(const WModelIndex& parent, int start, int end);
void sourceRowsAboutToBeRemoved(const WModelIndex& parent,
int start, int end);
void sourceRowsRemoved(const WModelIndex& parent, int start, int end);
void sourceDataChanged(const WModelIndex& topLeft,
const WModelIndex& bottomRight);
void sourceHeaderDataChanged(Orientation orientation, int start, int end);
void sourceLayoutAboutToBeChanged();
void sourceLayoutChanged();
void sourceModelReset();
};
}
#endif // WAGGREGATE_PROXY_MODEL_H_