1 // vim: set tabstop=4 shiftwidth=4 noexpandtab:
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.
22 #include "semanticinfodirmodel.moc"
23 #include <config-gwenview.h>
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"
43 #error No metadata backend defined
49 struct SemanticInfoCacheItem
{
50 SemanticInfoCacheItem()
52 QPersistentModelIndex mIndex
;
58 typedef QHash
<KUrl
, SemanticInfoCacheItem
> SemanticInfoCache
;
60 struct SemanticInfoDirModelPrivate
{
61 SemanticInfoCache mSemanticInfoCache
;
62 AbstractSemanticInfoBackEnd
* mBackEnd
;
66 SemanticInfoDirModel::SemanticInfoDirModel(QObject
* 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);
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() {
92 void SemanticInfoDirModel::clearSemanticInfoCache() {
93 d
->mSemanticInfoCache
.clear();
97 bool SemanticInfoDirModel::semanticInfoAvailableForIndex(const QModelIndex
& index
) const {
98 if (!index
.isValid()) {
101 KFileItem item
= itemForIndex(index
);
105 SemanticInfoCache::const_iterator it
= d
->mSemanticInfoCache
.constFind(item
.targetUrl());
106 if (it
== d
->mSemanticInfoCache
.constEnd()) {
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
);
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()) {
131 KFileItem item
= itemForIndex(index
);
133 kWarning() << "invalid item";
136 if (ArchiveUtils::fileItemIsDirOrArchive(item
)) {
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
);
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
) {
157 } else if (role
== DescriptionRole
) {
158 return info
.mDescription
;
159 } else if (role
== TagsRole
) {
160 return info
.mTags
.toVariant();
162 // We should never reach this part
167 const_cast<SemanticInfoDirModel
*>(this)->retrieveSemanticInfoForIndex(index
);
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
);
180 kWarning() << "no item found for this index";
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
;
189 if (!it
.value().mValid
) {
190 kWarning() << "Semantic info cache for" << url
<< "is invalid";
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
);
201 // We should never reach this part
204 emit
dataChanged(index
, index
);
206 d
->mBackEnd
->storeSemanticInfo(url
, semanticInfo
);
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
;
220 SemanticInfoCacheItem
& cacheItem
= it
.value();
221 if (!cacheItem
.mIndex
.isValid()) {
222 kWarning() << "Index for" << url
<< "is invalid";
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
);
238 d
->mSemanticInfoCache
.remove(item
.targetUrl());
243 void SemanticInfoDirModel::slotModelAboutToBeReset() {
244 d
->mSemanticInfoCache
.clear();
248 AbstractSemanticInfoBackEnd
* SemanticInfoDirModel::semanticInfoBackEnd() const {