1 /**************************************************************************
2 ** This file is part of LiteIDE
3 **
4 ** Copyright (c) 2011-2017 LiteIDE. All rights reserved.
5 **
6 ** This library is free software; you can redistribute it and/or
7 ** modify it under the terms of the GNU Lesser General Public
8 ** License as published by the Free Software Foundation; either
9 ** version 2.1 of the License, or (at your option) any later version.
10 **
11 ** This library is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ** Lesser General Public License for more details.
15 **
16 ** In addition, as a special exception, that plugins developed for LiteIDE,
17 ** are allowed to remain closed sourced and can be distributed under any license .
18 ** These rights are included in the file LGPL_EXCEPTION.txt in this package.
19 **
20 **************************************************************************/
21 // Module: abstractmultiproxymodel.cpp
22 // Creator: visualfc <visualfc@gmail.com>
23
24 #include "abstractmultiproxymodel.h"
25 #include "abstractmultiproxymodel_p.h"
26
27 #include <QSize>
28 #include <QStringList>
29 #include <QDebug>
30
31 //detects the deletion of the source model
_q_sourceModelDestroyed()32 void AbstractMultiProxyModelPrivate::_q_sourceModelDestroyed()
33 {
34 //model = QAbstractItemModelPrivate::staticEmptyModel();
35 Q_Q(AbstractMultiProxyModel);
36 QAbstractItemModel *sourceModel = (QAbstractItemModel*)sender();
37 q->removeSourceModel(sourceModel);
38 }
39
40 /*!
41 Constructs a proxy model with the given \a parent.
42 */
43
AbstractMultiProxyModel(QObject * parent)44 AbstractMultiProxyModel::AbstractMultiProxyModel(QObject *parent)
45 :QAbstractItemModel(parent)
46 {
47 d_ptr = new AbstractMultiProxyModelPrivate;
48 d_ptr->q_ptr = this;
49 //setSourceModel(QAbstractItemModelPrivate::staticEmptyModel());
50 }
51
52 /*!
53 \internal
54 */
55
AbstractMultiProxyModel(AbstractMultiProxyModelPrivate & dd,QObject * parent)56 AbstractMultiProxyModel::AbstractMultiProxyModel(AbstractMultiProxyModelPrivate &dd, QObject *parent)
57 : QAbstractItemModel(parent), d_ptr(&dd)
58 {
59 d_ptr->q_ptr = this;
60
61 }
62
63 /*!
64 Destroys the proxy model.
65 */
~AbstractMultiProxyModel()66 AbstractMultiProxyModel::~AbstractMultiProxyModel()
67 {
68
69 }
70
71 /*!
72 Sets the given \a sourceModel to be processed by the proxy model.
73 */
74
addSourceModel(QAbstractItemModel * sourceModel,const QModelIndex & sourceIndex)75 bool AbstractMultiProxyModel::addSourceModel(QAbstractItemModel *sourceModel, const QModelIndex &sourceIndex)
76 {
77 Q_D(AbstractMultiProxyModel);
78 if (d->containsModel(sourceModel)) {
79 return false;
80 }
81 // if (sourceModel) {
82 // connect(sourceModel,SIGNAL(destroyed(QObject*)),d,SLOT(_q_sourceModelDestroyed()));
83 // }
84 d->indexList.push_back(SourceModelIndex(sourceModel,sourceIndex));
85 return true;
86 }
87
removeSourceModel(QAbstractItemModel * sourceModel)88 bool AbstractMultiProxyModel::removeSourceModel(QAbstractItemModel *sourceModel)
89 {
90 Q_D(AbstractMultiProxyModel);
91 QMutableListIterator<SourceModelIndex> i(d->indexList);
92 int n = 0;
93 while (i.hasNext()) {
94 SourceModelIndex index = i.next();
95 if (index.model == sourceModel) {
96 this->beginRemoveRows(QModelIndex(),n,n);
97 disconnect(sourceModel,0,this,0);
98 i.remove();
99 this->endRemoveRows();
100 return true;
101 }
102 n++;
103 }
104 return false;
105 }
106
removeAllSourceModel()107 void AbstractMultiProxyModel::removeAllSourceModel()
108 {
109 this->beginResetModel();
110 Q_D(AbstractMultiProxyModel);
111 foreach (SourceModelIndex si, d->indexList) {
112 disconnect(si.model,0,this,0);
113 }
114 d->indexList.clear();
115 this->endResetModel();
116 }
117
sourceModelIndexlList() const118 QList<SourceModelIndex> AbstractMultiProxyModel::sourceModelIndexlList() const
119 {
120 Q_D(const AbstractMultiProxyModel);
121 return d->indexList;
122 }
123
sourceModelList() const124 QList<QAbstractItemModel *> AbstractMultiProxyModel::sourceModelList() const
125 {
126 Q_D(const AbstractMultiProxyModel);
127 QList<QAbstractItemModel*> modelList;
128 foreach (SourceModelIndex i, d->indexList) {
129 modelList.push_back(i.model);
130 }
131 return modelList;
132 }
133
134 /*!
135 \reimp
136 */
submit()137 bool AbstractMultiProxyModel::submit()
138 {
139 Q_D(AbstractMultiProxyModel);
140 if (d->indexList.isEmpty()) {
141 return false;
142 }
143 foreach (SourceModelIndex source, d->indexList) {
144 source.model->submit();
145 }
146 return true;
147 }
148
149 /*!
150 \reimp
151 */
revert()152 void AbstractMultiProxyModel::revert()
153 {
154 Q_D(AbstractMultiProxyModel);
155 foreach (SourceModelIndex source, d->indexList) {
156 source.model->revert();
157 }
158 }
159
160
161 /*!
162 \fn QModelIndex AbstractMultiProxyModel::mapToSource(const QModelIndex &proxyIndex) const
163
164 Reimplement this function to return the model index in the source model that
165 corresponds to the \a proxyIndex in the proxy model.
166
167 \sa mapFromSource()
168 */
169
170 /*!
171 \fn QModelIndex AbstractMultiProxyModel::mapFromSource(const QModelIndex &sourceIndex) const
172
173 Reimplement this function to return the model index in the proxy model that
174 corresponds to the \a sourceIndex from the source model.
175
176 \sa mapToSource()
177 */
178
179 /*!
180 Returns a source selection mapped from the specified \a proxySelection.
181
182 Reimplement this method to map proxy selections to source selections.
183 */
mapSelectionToSource(const QItemSelection & proxySelection) const184 QItemSelection AbstractMultiProxyModel::mapSelectionToSource(const QItemSelection &proxySelection) const
185 {
186 QModelIndexList proxyIndexes = proxySelection.indexes();
187 QItemSelection sourceSelection;
188 for (int i = 0; i < proxyIndexes.size(); ++i) {
189 const QModelIndex proxyIdx = mapToSource(proxyIndexes.at(i));
190 if (!proxyIdx.isValid())
191 continue;
192 sourceSelection << QItemSelectionRange(proxyIdx);
193 }
194 return sourceSelection;
195 }
196
197 /*!
198 Returns a proxy selection mapped from the specified \a sourceSelection.
199
200 Reimplement this method to map source selections to proxy selections.
201 */
mapSelectionFromSource(const QItemSelection & sourceSelection) const202 QItemSelection AbstractMultiProxyModel::mapSelectionFromSource(const QItemSelection &sourceSelection) const
203 {
204 QModelIndexList sourceIndexes = sourceSelection.indexes();
205 QItemSelection proxySelection;
206 for (int i = 0; i < sourceIndexes.size(); ++i) {
207 const QModelIndex srcIdx = mapFromSource(sourceIndexes.at(i));
208 if (!srcIdx.isValid())
209 continue;
210 proxySelection << QItemSelectionRange(srcIdx);
211 }
212 return proxySelection;
213 }
214
215 /*!
216 \reimp
217 */
data(const QModelIndex & proxyIndex,int role) const218 QVariant AbstractMultiProxyModel::data(const QModelIndex &proxyIndex, int role) const
219 {
220 // Q_D(const AbstractMultiProxyModel);
221 SourceModelIndex source = mapToSourceEx(proxyIndex);
222 if (!source.index.isValid() && proxyIndex.column() == 0 && role == Qt::DisplayRole) {
223 return "Root";
224 }
225 return source.model->data(source.index,role);
226 }
227
228 /*!
229 \reimp
230 */
headerData(int section,Qt::Orientation orientation,int role) const231 QVariant AbstractMultiProxyModel::headerData(int section, Qt::Orientation orientation, int role) const
232 {
233 Q_D(const AbstractMultiProxyModel);
234 if (d->indexList.isEmpty()) {
235 return QVariant();
236 }
237 return d->indexList[0].model->headerData(section,orientation,role);
238 // int sourceSection;
239 // SourceIndex si;
240 // if (orientation == Qt::Horizontal) {
241 // const QModelIndex proxyIndex = index(0, section);
242 // si = mapToSourceEx(proxyIndex);
243 // sourceSection = si.index.column();
244 // } else {
245 // const QModelIndex proxyIndex = index(section, 0);
246 // si = mapToSourceEx(proxyIndex);
247 // sourceSection = si.index.row();
248 // }
249 // if (si.model == 0) {
250 // qDebug() << "error";
251 // return d->modelList[0]->headerData(section,orientation,role);
252 // }
253 // return si.model->headerData(sourceSection, orientation, role);
254 }
255
256 /*!
257 \reimp
258 */
itemData(const QModelIndex & proxyIndex) const259 QMap<int, QVariant> AbstractMultiProxyModel::itemData(const QModelIndex &proxyIndex) const
260 {
261 return QAbstractItemModel::itemData(proxyIndex);
262 }
263
264 /*!
265 \reimp
266 */
flags(const QModelIndex & index) const267 Qt::ItemFlags AbstractMultiProxyModel::flags(const QModelIndex &index) const
268 {
269 //Q_D(const AbstractMultiProxyModel);
270 if (!index.isValid()) {
271 return Qt::NoItemFlags;
272 }
273 SourceModelIndex source = mapToSourceEx(index);
274 return source.model->flags(source.index);
275 }
276
277 /*!
278 \reimp
279 */
setData(const QModelIndex & index,const QVariant & value,int role)280 bool AbstractMultiProxyModel::setData(const QModelIndex &index, const QVariant &value, int role)
281 {
282 //Q_D(AbstractMultiProxyModel);
283 SourceModelIndex source = mapToSourceEx(index);
284 return source.model->setData(source.index,value,role);
285 }
286
287 /*!
288 \reimp
289 */
setItemData(const QModelIndex & index,const QMap<int,QVariant> & roles)290 bool AbstractMultiProxyModel::setItemData(const QModelIndex &index, const QMap< int, QVariant >& roles)
291 {
292 return QAbstractItemModel::setItemData(index, roles);
293 }
294
295 /*!
296 \reimp
297 */
setHeaderData(int section,Qt::Orientation orientation,const QVariant & value,int role)298 bool AbstractMultiProxyModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role)
299 {
300 //Q_D(AbstractMultiProxyModel);
301 int sourceSection;
302 SourceModelIndex source;
303 if (orientation == Qt::Horizontal) {
304 const QModelIndex proxyIndex = index(0, section);
305 source = mapToSourceEx(proxyIndex);
306 sourceSection = source.index.column();
307 } else {
308 const QModelIndex proxyIndex = index(section, 0);
309 source = mapToSourceEx(proxyIndex);
310 sourceSection = source.index.row();
311 }
312 return source.model->setHeaderData(sourceSection, orientation, value, role);
313 //return d->model->setHeaderData(sourceSection, orientation, value, role);
314 }
315
316 /*!
317 \reimp
318 \since 4.8
319 */
buddy(const QModelIndex & index) const320 QModelIndex AbstractMultiProxyModel::buddy(const QModelIndex &index) const
321 {
322 //Q_D(const AbstractMultiProxyModel);
323 SourceModelIndex source = mapToSourceEx(index);
324 return mapFromSourceEx(source.model,source.model->buddy(source.index));
325 }
326
327 /*!
328 \reimp
329 \since 4.8
330 */
canFetchMore(const QModelIndex & parent) const331 bool AbstractMultiProxyModel::canFetchMore(const QModelIndex &parent) const
332 {
333 //Q_D(const AbstractMultiProxyModel);
334 SourceModelIndex source = mapToSourceEx(parent);
335 if (source.model == 0) {
336 return false;
337 }
338 return source.model->canFetchMore(source.index);
339 }
340
341 /*!
342 \reimp
343 \since 4.8
344 */
fetchMore(const QModelIndex & parent)345 void AbstractMultiProxyModel::fetchMore(const QModelIndex &parent)
346 {
347 //Q_D(AbstractMultiProxyModel);
348 SourceModelIndex source = mapToSourceEx(parent);
349 source.model->fetchMore(source.index);
350 //d->model->fetchMore(mapToSource(parent));
351 }
352
353 /*!
354 \reimp
355 \since 4.8
356 */
sort(int column,Qt::SortOrder order)357 void AbstractMultiProxyModel::sort(int column, Qt::SortOrder order)
358 {
359 Q_D(AbstractMultiProxyModel);
360 //d->model->sort(column, order);
361 foreach (SourceModelIndex source, d->indexList) {
362 source.model->sort(column,order);
363 }
364 }
365
366 /*!
367 \reimp
368 \since 4.8
369 */
span(const QModelIndex & index) const370 QSize AbstractMultiProxyModel::span(const QModelIndex &index) const
371 {
372 //Q_D(const AbstractMultiProxyModel);
373 SourceModelIndex source = mapToSourceEx(index);
374 return source.model->span(source.index);
375 }
376
377 /*!
378 \reimp
379 \since 4.8
380 */
hasChildren(const QModelIndex & parent) const381 bool AbstractMultiProxyModel::hasChildren(const QModelIndex &parent) const
382 {
383 //Q_D(const AbstractMultiProxyModel);
384 SourceModelIndex source = mapToSourceEx(parent);
385 return source.model->hasChildren(source.index);
386 }
387
388 /*!
389 \reimp
390 \since 4.8
391 */
mimeData(const QModelIndexList & indexes) const392 QMimeData* AbstractMultiProxyModel::mimeData(const QModelIndexList &indexes) const
393 {
394 Q_D(const AbstractMultiProxyModel);
395 if (d->indexList.isEmpty()) {
396 return QAbstractItemModel::mimeData(indexes);
397 }
398
399 QModelIndexList list;
400 foreach(const QModelIndex &index, indexes)
401 list << mapToSource(index);
402
403 return d->indexList[0].model->mimeData(list);
404 }
405
406 /*!
407 \reimp
408 \since 4.8
409 */
mimeTypes() const410 QStringList AbstractMultiProxyModel::mimeTypes() const
411 {
412 Q_D(const AbstractMultiProxyModel);
413 if (d->indexList.isEmpty()) {
414 return QAbstractItemModel::mimeTypes();
415 }
416 return d->indexList[0].model->mimeTypes();
417 }
418
419 /*!
420 \reimp
421 \since 4.8
422 */
supportedDropActions() const423 Qt::DropActions AbstractMultiProxyModel::supportedDropActions() const
424 {
425 Q_D(const AbstractMultiProxyModel);
426 if (d->indexList.isEmpty()) {
427 return QAbstractItemModel::supportedDropActions();
428 }
429 return d->indexList[0].model->supportedDropActions();
430 }
431
432 #include "moc_abstractmultiproxymodel.cpp"
433 //lite_memory_check_begin
434 #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG)
435 #define _CRTDBG_MAP_ALLOC
436 #include <stdlib.h>
437 #include <crtdbg.h>
438 #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ )
439 #define new DEBUG_NEW
440 #endif
441 //lite_memory_check_end
442