1 /*
2 * Copyright (C) 2008 Emweb bv, Herent, Belgium.
3 *
4 * See the LICENSE file for terms of use.
5 */
6
7 #include "Wt/WAbstractProxyModel.h"
8
9 namespace Wt {
10
11 #ifndef DOXYGEN_ONLY
12
~BaseItem()13 WAbstractProxyModel::BaseItem::~BaseItem()
14 { }
15
WAbstractProxyModel()16 WAbstractProxyModel::WAbstractProxyModel()
17 : sourceModel_(nullptr)
18 { }
19
20 void WAbstractProxyModel
setSourceModel(const std::shared_ptr<WAbstractItemModel> & sourceModel)21 ::setSourceModel(const std::shared_ptr<WAbstractItemModel>& sourceModel)
22 {
23 sourceModel_ = sourceModel;
24 }
25
data(const WModelIndex & index,ItemDataRole role)26 cpp17::any WAbstractProxyModel::data(const WModelIndex& index, ItemDataRole role) const
27 {
28 return sourceModel_->data(mapToSource(index), role);
29 }
30
setData(const WModelIndex & index,const cpp17::any & value,ItemDataRole role)31 bool WAbstractProxyModel::setData(const WModelIndex& index,
32 const cpp17::any& value, ItemDataRole role)
33 {
34 return sourceModel_->setData(mapToSource(index), value, role);
35 }
36
setItemData(const WModelIndex & index,const DataMap & values)37 bool WAbstractProxyModel::setItemData(const WModelIndex& index,
38 const DataMap& values)
39 {
40 return sourceModel_->setItemData(mapToSource(index), values);
41 }
42
flags(const WModelIndex & index)43 WFlags<ItemFlag> WAbstractProxyModel::flags(const WModelIndex& index) const
44 {
45 return sourceModel_->flags(mapToSource(index));
46 }
47
insertColumns(int column,int count,const WModelIndex & parent)48 bool WAbstractProxyModel::insertColumns(int column, int count,
49 const WModelIndex& parent)
50 {
51 return sourceModel_->insertColumns(column, count, parent);
52 }
53
removeColumns(int column,int count,const WModelIndex & parent)54 bool WAbstractProxyModel::removeColumns(int column, int count,
55 const WModelIndex& parent)
56 {
57 return sourceModel_->removeColumns(column, count, parent);
58 }
59
mimeType()60 std::string WAbstractProxyModel::mimeType() const
61 {
62 return sourceModel_->mimeType();
63 }
64
acceptDropMimeTypes()65 std::vector<std::string> WAbstractProxyModel::acceptDropMimeTypes() const
66 {
67 return sourceModel_->acceptDropMimeTypes();
68 }
69
dropEvent(const WDropEvent & e,DropAction action,int row,int column,const WModelIndex & parent)70 void WAbstractProxyModel::dropEvent(const WDropEvent& e, DropAction action,
71 int row, int column,
72 const WModelIndex& parent)
73 {
74 WModelIndex sourceParent = mapToSource(parent);
75
76 int sourceRow = row;
77 int sourceColumn = column;
78
79 if (sourceRow != -1)
80 sourceRow = mapToSource(index(row, 0, parent)).row();
81
82 sourceModel_->dropEvent(e, action, sourceRow, sourceColumn, sourceParent);
83 }
84
toRawIndex(const WModelIndex & index)85 void *WAbstractProxyModel::toRawIndex(const WModelIndex& index) const
86 {
87 return sourceModel_->toRawIndex(mapToSource(index));
88 }
89
fromRawIndex(void * rawIndex)90 WModelIndex WAbstractProxyModel::fromRawIndex(void *rawIndex) const
91 {
92 return mapFromSource(sourceModel_->fromRawIndex(rawIndex));
93 }
94
headerFlags(int section,Orientation orientation)95 WFlags<HeaderFlag> WAbstractProxyModel::headerFlags(int section,
96 Orientation orientation) const
97 {
98 if (orientation == Wt::Orientation::Horizontal) {
99 section = mapToSource(index(0, section, Wt::WModelIndex())).column();
100 } else {
101 section = mapToSource(index(section, 0, Wt::WModelIndex())).row();
102 }
103 return sourceModel_->headerFlags(section, orientation);
104 }
105
headerData(int section,Orientation orientation,ItemDataRole role)106 cpp17::any WAbstractProxyModel::headerData(int section, Orientation orientation,
107 ItemDataRole role) const
108 {
109 if (orientation == Wt::Orientation::Horizontal) {
110 section = mapToSource(index(0, section, Wt::WModelIndex())).column();
111 } else {
112 section = mapToSource(index(section, 0, Wt::WModelIndex())).row();
113 }
114 return sourceModel_->headerData(section, orientation, role);
115 }
116
createSourceIndex(int row,int column,void * ptr)117 WModelIndex WAbstractProxyModel::createSourceIndex(int row, int column,
118 void *ptr) const
119 {
120 return sourceModel_->createIndex(row, column, ptr);
121 }
122
startShiftModelIndexes(const WModelIndex & sourceParent,int start,int count,ItemMap & items)123 void WAbstractProxyModel::startShiftModelIndexes(const WModelIndex& sourceParent,
124 int start, int count,
125 ItemMap& items)
126 {
127 /*
128 * We must shift all indexes within sourceParent >= start with count
129 * and delete items when count < 0.
130 */
131 std::vector<BaseItem *> erased;
132
133 WModelIndex startIndex;
134 if (sourceModel()->rowCount(sourceParent) == 0)
135 startIndex = sourceParent;
136 else if (start >= sourceModel()->rowCount(sourceParent))
137 return;
138 else
139 startIndex = sourceModel()->index(start, 0, sourceParent);
140
141 #ifdef WT_TARGET_JAVA
142 if (!startIndex.isValid())
143 return;
144 #endif
145
146 for (ItemMap::iterator it = items.lower_bound(startIndex);
147 it != items.end();) {
148 #ifndef WT_TARGET_JAVA
149 ItemMap::iterator n = it;
150 ++n;
151 #endif
152 WModelIndex i = it->first;
153 if (i == sourceParent) {
154 #ifndef WT_TARGET_JAVA
155 it = n;
156 #endif
157 continue;
158 }
159
160 if (i.isValid()) {
161 WModelIndex p = i.parent();
162 if (p != sourceParent && !WModelIndex::isAncestor(p, sourceParent))
163 break;
164
165 if (p == sourceParent) { /* Child of source parent: shift or remove */
166 if (count < 0 &&
167 i.row() >= start &&
168 i.row() < start + (-count))
169 erased.push_back(it->second);
170 else {
171 itemsToShift_.push_back(it->second);
172 }
173 } else if (count < 0) { /* Other descendent: remove if necessary */
174 // delete indexes that are about to be deleted, if they are within
175 // the range of deleted indexes
176 do {
177 if (p.parent() == sourceParent
178 && p.row() >= start
179 && p.row() < start + (-count)) {
180 erased.push_back(it->second);
181 break;
182 } else
183 p = p.parent();
184 } while (p != sourceParent);
185 }
186 }
187
188 #ifndef WT_TARGET_JAVA
189 it = n;
190 #endif
191 }
192
193 for (unsigned i = 0; i < itemsToShift_.size(); ++i) {
194 BaseItem *item = itemsToShift_[i];
195 items.erase(item->sourceIndex_);
196 item->sourceIndex_ = sourceModel()->index
197 (item->sourceIndex_.row() + count,
198 item->sourceIndex_.column(),
199 sourceParent);
200 }
201
202 for (unsigned i = 0; i < erased.size(); ++i) {
203 items.erase(erased[i]->sourceIndex_);
204 delete erased[i];
205 }
206
207 if (count > 0)
208 endShiftModelIndexes(sourceParent, start, count, items);
209 }
210
endShiftModelIndexes(const WModelIndex & sourceParent,int start,int count,ItemMap & items)211 void WAbstractProxyModel::endShiftModelIndexes(const WModelIndex& sourceParent,
212 int start, int count,
213 ItemMap& items)
214 {
215 for (unsigned i = 0; i < itemsToShift_.size(); ++i)
216 items[itemsToShift_[i]->sourceIndex_] = itemsToShift_[i];
217
218 itemsToShift_.clear();
219 }
220
221
222 #endif // DOXYGEN_ONLY
223
224 }
225