1 | /* |
2 | Copyright (c) 2007 Bruno Virlet <bruno.virlet@gmail.com> |
3 | |
4 | This library is free software; you can redistribute it and/or modify it |
5 | under the terms of the GNU Library General Public License as published by |
6 | the Free Software Foundation; either version 2 of the License, or (at your |
7 | option) any later version. |
8 | |
9 | This library is distributed in the hope that it will be useful, but WITHOUT |
10 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
11 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public |
12 | License for more details. |
13 | |
14 | You should have received a copy of the GNU Library General Public License |
15 | along with this library; see the file COPYING.LIB. If not, write to the |
16 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
17 | 02110-1301, USA. |
18 | */ |
19 | |
20 | #include "collectionfilterproxymodel.h" |
21 | |
22 | #include "collectionmodel.h" |
23 | #include "mimetypechecker.h" |
24 | |
25 | #include <kdebug.h> |
26 | |
27 | #include <QtCore/QString> |
28 | #include <QtCore/QStringList> |
29 | |
30 | using namespace Akonadi; |
31 | |
32 | /** |
33 | * @internal |
34 | */ |
35 | class CollectionFilterProxyModel::Private |
36 | { |
37 | public: |
38 | Private(CollectionFilterProxyModel *parent) |
39 | : mParent(parent) |
40 | , mExcludeVirtualCollections(false) |
41 | { |
42 | mimeChecker.addWantedMimeType(QLatin1String("text/uri-list" )); |
43 | } |
44 | |
45 | bool collectionAccepted(const QModelIndex &index, bool checkResourceVisibility = true); |
46 | |
47 | QVector< QModelIndex > acceptedResources; |
48 | CollectionFilterProxyModel *mParent; |
49 | MimeTypeChecker mimeChecker; |
50 | bool mExcludeVirtualCollections; |
51 | }; |
52 | |
53 | bool CollectionFilterProxyModel::Private::collectionAccepted(const QModelIndex &index, bool checkResourceVisibility) |
54 | { |
55 | // Retrieve supported mimetypes |
56 | const Collection collection = mParent->sourceModel()->data(index, CollectionModel::CollectionRole).value<Collection>(); |
57 | |
58 | if (!collection.isValid()) { |
59 | return false; |
60 | } |
61 | |
62 | if (collection.isVirtual() && mExcludeVirtualCollections) { |
63 | return false; |
64 | } |
65 | |
66 | // If this collection directly contains one valid mimetype, it is accepted |
67 | if (mimeChecker.isWantedCollection(collection)) { |
68 | // The folder will be accepted, but we need to make sure the resource is visible too. |
69 | if (checkResourceVisibility) { |
70 | |
71 | // find the resource |
72 | QModelIndex resource = index; |
73 | while (resource.parent().isValid()) { |
74 | resource = resource.parent(); |
75 | } |
76 | |
77 | // See if that resource is visible, if not, invalidate the filter. |
78 | if (resource != index && !acceptedResources.contains(resource)) { |
79 | kDebug() << "We got a new collection:" << mParent->sourceModel()->data(index).toString() |
80 | << "but the resource is not visible:" << mParent->sourceModel()->data(resource).toString(); |
81 | acceptedResources.clear(); |
82 | // defer reset, the model might still be supplying new items at this point which crashs |
83 | mParent->invalidateFilter(); |
84 | return true; |
85 | } |
86 | } |
87 | |
88 | // Keep track of all the resources that are visible. |
89 | if (!index.parent().isValid()) { |
90 | acceptedResources.append(index); |
91 | } |
92 | |
93 | return true; |
94 | } |
95 | |
96 | // If this collection has a child which contains valid mimetypes, it is accepted |
97 | QModelIndex childIndex = index.child(0, 0); |
98 | while (childIndex.isValid()) { |
99 | if (collectionAccepted(childIndex, false /* don't check visibility of the parent, as we are checking the child now */)) { |
100 | |
101 | // Keep track of all the resources that are visible. |
102 | if (!index.parent().isValid()) { |
103 | acceptedResources.append(index); |
104 | } |
105 | |
106 | return true; |
107 | } |
108 | childIndex = childIndex.sibling(childIndex.row() + 1, 0); |
109 | } |
110 | |
111 | // Or else, no reason to keep this collection. |
112 | return false; |
113 | } |
114 | |
115 | CollectionFilterProxyModel::CollectionFilterProxyModel(QObject *parent) |
116 | : QSortFilterProxyModel(parent) |
117 | , d(new Private(this)) |
118 | { |
119 | } |
120 | |
121 | CollectionFilterProxyModel::~CollectionFilterProxyModel() |
122 | { |
123 | delete d; |
124 | } |
125 | |
126 | void CollectionFilterProxyModel::addMimeTypeFilters(const QStringList &typeList) |
127 | { |
128 | QStringList mimeTypes = d->mimeChecker.wantedMimeTypes() + typeList; |
129 | d->mimeChecker.setWantedMimeTypes(mimeTypes); |
130 | invalidateFilter(); |
131 | } |
132 | |
133 | void CollectionFilterProxyModel::addMimeTypeFilter(const QString &type) |
134 | { |
135 | d->mimeChecker.addWantedMimeType(type); |
136 | invalidateFilter(); |
137 | } |
138 | |
139 | bool CollectionFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const |
140 | { |
141 | return d->collectionAccepted(sourceModel()->index(sourceRow, 0, sourceParent)); |
142 | } |
143 | |
144 | QStringList CollectionFilterProxyModel::mimeTypeFilters() const |
145 | { |
146 | return d->mimeChecker.wantedMimeTypes(); |
147 | } |
148 | |
149 | void CollectionFilterProxyModel::clearFilters() |
150 | { |
151 | d->mimeChecker = MimeTypeChecker(); |
152 | invalidateFilter(); |
153 | } |
154 | |
155 | void CollectionFilterProxyModel::setExcludeVirtualCollections(bool exclude) |
156 | { |
157 | if (exclude != d->mExcludeVirtualCollections) { |
158 | d->mExcludeVirtualCollections = exclude; |
159 | invalidateFilter(); |
160 | } |
161 | } |
162 | |
163 | bool CollectionFilterProxyModel::excludeVirtualCollections() const |
164 | { |
165 | return d->mExcludeVirtualCollections; |
166 | } |
167 | |
168 | Qt::ItemFlags CollectionFilterProxyModel::flags(const QModelIndex &index) const |
169 | { |
170 | if (!index.isValid()) { |
171 | // Don't crash |
172 | return 0; |
173 | } |
174 | |
175 | const Collection collection = sourceModel()->data(mapToSource(index), CollectionModel::CollectionRole).value<Collection>(); |
176 | |
177 | // If this collection directly contains one valid mimetype, it is accepted |
178 | if (d->mimeChecker.isWantedCollection(collection)) { |
179 | return QSortFilterProxyModel::flags(index); |
180 | } else { |
181 | return QSortFilterProxyModel::flags(index) & ~(Qt::ItemIsSelectable); |
182 | } |
183 | } |
184 | |