compile
[kdegraphics.git] / gwenview / lib / semanticinfo / semanticinfodirmodel.cpp
blob6e6d8047e3e7ad61017dc4d9e8b624a00115292a
1 // vim: set tabstop=4 shiftwidth=4 noexpandtab:
2 /*
3 Gwenview: an image viewer
4 Copyright 2008 Aurélien Gâteau <aurelien.gateau@free.fr>
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
11 This program 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
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
21 // Self
22 #include "semanticinfodirmodel.moc"
23 #include <config-gwenview.h>
25 // Qt
26 #include <QHash>
28 // KDE
29 #include <kdebug.h>
31 // Local
32 #include "abstractsemanticinfobackend.h"
33 #include "../archiveutils.h"
35 #ifdef GWENVIEW_SEMANTICINFO_BACKEND_FAKE
36 #include "fakesemanticinfobackend.h"
38 #elif defined(GWENVIEW_SEMANTICINFO_BACKEND_NEPOMUK)
39 #include "nepomuksemanticinfobackend.h"
41 #else
42 #ifdef __GNUC__
43 #error No metadata backend defined
44 #endif
45 #endif
47 namespace Gwenview {
49 struct SemanticInfoCacheItem {
50 SemanticInfoCacheItem()
51 : mValid(false) {}
52 QPersistentModelIndex mIndex;
53 bool mValid;
54 SemanticInfo mInfo;
58 typedef QHash<KUrl, SemanticInfoCacheItem> SemanticInfoCache;
60 struct SemanticInfoDirModelPrivate {
61 SemanticInfoCache mSemanticInfoCache;
62 AbstractSemanticInfoBackEnd* mBackEnd;
66 SemanticInfoDirModel::SemanticInfoDirModel(QObject* parent)
67 : KDirModel(parent)
68 , d(new SemanticInfoDirModelPrivate) {
69 #ifdef GWENVIEW_SEMANTICINFO_BACKEND_FAKE
70 d->mBackEnd = new FakeSemanticInfoBackEnd(this, FakeSemanticInfoBackEnd::InitializeRandom);
71 #elif defined(GWENVIEW_SEMANTICINFO_BACKEND_NEPOMUK)
72 d->mBackEnd = new NepomukSemanticInfoBackEnd(this);
73 #endif
75 connect(d->mBackEnd, SIGNAL(semanticInfoRetrieved(const KUrl&, const SemanticInfo&)),
76 SLOT(slotSemanticInfoRetrieved(const KUrl&, const SemanticInfo&)),
77 Qt::QueuedConnection);
79 connect(this, SIGNAL(modelAboutToBeReset()),
80 SLOT(slotModelAboutToBeReset()) );
82 connect(this, SIGNAL(rowsAboutToBeRemoved(const QModelIndex&, int, int)),
83 SLOT(slotRowsAboutToBeRemoved(const QModelIndex&, int, int)) );
87 SemanticInfoDirModel::~SemanticInfoDirModel() {
88 delete d;
92 void SemanticInfoDirModel::clearSemanticInfoCache() {
93 d->mSemanticInfoCache.clear();
97 bool SemanticInfoDirModel::semanticInfoAvailableForIndex(const QModelIndex& index) const {
98 if (!index.isValid()) {
99 return false;
101 KFileItem item = itemForIndex(index);
102 if (item.isNull()) {
103 return false;
105 SemanticInfoCache::const_iterator it = d->mSemanticInfoCache.constFind(item.targetUrl());
106 if (it == d->mSemanticInfoCache.constEnd()) {
107 return false;
109 return it.value().mValid;
113 SemanticInfo SemanticInfoDirModel::semanticInfoForIndex(const QModelIndex& index) const {
114 if (!index.isValid()) {
115 kWarning() << "invalid index";
116 return SemanticInfo();
118 KFileItem item = itemForIndex(index);
119 if (item.isNull()) {
120 kWarning() << "no item for index";
121 return SemanticInfo();
123 return d->mSemanticInfoCache.value(item.targetUrl()).mInfo;
127 void SemanticInfoDirModel::retrieveSemanticInfoForIndex(const QModelIndex& index) {
128 if (!index.isValid()) {
129 return;
131 KFileItem item = itemForIndex(index);
132 if (item.isNull()) {
133 kWarning() << "invalid item";
134 return;
136 if (ArchiveUtils::fileItemIsDirOrArchive(item)) {
137 return;
139 SemanticInfoCacheItem cacheItem;
140 cacheItem.mIndex = QPersistentModelIndex(index);
141 d->mSemanticInfoCache[item.targetUrl()] = cacheItem;
142 d->mBackEnd->retrieveSemanticInfo(item.targetUrl());
146 QVariant SemanticInfoDirModel::data(const QModelIndex& index, int role) const {
147 if (role == RatingRole || role == DescriptionRole || role == TagsRole) {
148 KFileItem item = itemForIndex(index);
149 if (item.isNull()) {
150 return QVariant();
152 SemanticInfoCache::ConstIterator it = d->mSemanticInfoCache.constFind(item.targetUrl());
153 if (it != d->mSemanticInfoCache.constEnd()) {
154 const SemanticInfo& info = it.value().mInfo;
155 if (role == RatingRole) {
156 return info.mRating;
157 } else if (role == DescriptionRole) {
158 return info.mDescription;
159 } else if (role == TagsRole) {
160 return info.mTags.toVariant();
161 } else {
162 // We should never reach this part
163 Q_ASSERT(0);
164 return QVariant();
166 } else {
167 const_cast<SemanticInfoDirModel*>(this)->retrieveSemanticInfoForIndex(index);
168 return QVariant();
170 } else {
171 return KDirModel::data(index, role);
176 bool SemanticInfoDirModel::setData(const QModelIndex& index, const QVariant& data, int role) {
177 if (role == RatingRole || role == DescriptionRole || role == TagsRole) {
178 KFileItem item = itemForIndex(index);
179 if (item.isNull()) {
180 kWarning() << "no item found for this index";
181 return false;
183 KUrl url = item.targetUrl();
184 SemanticInfoCache::iterator it = d->mSemanticInfoCache.find(url);
185 if (it == d->mSemanticInfoCache.end()) {
186 kWarning() << "No index for" << url;
187 return false;
189 if (!it.value().mValid) {
190 kWarning() << "Semantic info cache for" << url << "is invalid";
191 return false;
193 SemanticInfo& semanticInfo = it.value().mInfo;
194 if (role == RatingRole) {
195 semanticInfo.mRating = data.toInt();
196 } else if (role == DescriptionRole) {
197 semanticInfo.mDescription = data.toString();
198 } else if (role == TagsRole) {
199 semanticInfo.mTags = TagSet::fromVariant(data);
200 } else {
201 // We should never reach this part
202 Q_ASSERT(0);
204 emit dataChanged(index, index);
206 d->mBackEnd->storeSemanticInfo(url, semanticInfo);
207 return true;
208 } else {
209 return KDirModel::setData(index, data, role);
214 void SemanticInfoDirModel::slotSemanticInfoRetrieved(const KUrl& url, const SemanticInfo& semanticInfo) {
215 SemanticInfoCache::iterator it = d->mSemanticInfoCache.find(url);
216 if (it == d->mSemanticInfoCache.end()) {
217 kWarning() << "No index for" << url;
218 return;
220 SemanticInfoCacheItem& cacheItem = it.value();
221 if (!cacheItem.mIndex.isValid()) {
222 kWarning() << "Index for" << url << "is invalid";
223 return;
225 cacheItem.mInfo = semanticInfo;
226 cacheItem.mValid = true;
227 emit dataChanged(cacheItem.mIndex, cacheItem.mIndex);
231 void SemanticInfoDirModel::slotRowsAboutToBeRemoved(const QModelIndex& parent, int start, int end) {
232 for (int pos = start; pos <= end; ++pos) {
233 QModelIndex idx = index(pos, 0, parent);
234 KFileItem item = itemForIndex(idx);
235 if (item.isNull()) {
236 continue;
238 d->mSemanticInfoCache.remove(item.targetUrl());
243 void SemanticInfoDirModel::slotModelAboutToBeReset() {
244 d->mSemanticInfoCache.clear();
248 AbstractSemanticInfoBackEnd* SemanticInfoDirModel::semanticInfoBackEnd() const {
249 return d->mBackEnd;
253 } // namespace