]> cloud.milkyroute.net Git - dolphin.git/blob - src/panels/information/metadatawidget.cpp
The complexity of the class InformationPanel has grown a lot from KDE 4.0 to KDE...
[dolphin.git] / src / panels / information / metadatawidget.cpp
1 /***************************************************************************
2 * Copyright (C) 2007 by Sebastian Trueg <trueg@kde.org> *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
18 ***************************************************************************/
19
20 #include "metadatawidget.h"
21
22 #include "commentwidget.h"
23
24 #include <config-nepomuk.h>
25
26 #include <klocale.h>
27 #include <KMessageBox>
28
29 #include <QtCore/QEvent>
30 #include <QtCore/QMutex>
31 #include <QtCore/QMutexLocker>
32 #include <QtCore/QThread>
33 #include <QtGui/QLabel>
34 #include <QtGui/QGridLayout>
35 #include <QtGui/QTextEdit>
36
37 #ifdef HAVE_NEPOMUK
38 #include "nepomukmassupdatejob.h"
39 #include <nepomuk/kmetadatatagwidget.h>
40 #include <nepomuk/resourcemanager.h>
41 #include <nepomuk/resource.h>
42 #include <nepomuk/variant.h>
43 #include <nepomuk/kratingwidget.h>
44 #include <Soprano/Vocabulary/Xesam>
45 #include "resourcetaggingwidget.h"
46 #endif
47
48
49 bool MetaDataWidget::metaDataAvailable()
50 {
51 #ifdef HAVE_NEPOMUK
52 return !Nepomuk::ResourceManager::instance()->init();
53 #else
54 return false;
55 #endif
56 }
57
58
59 class MetaDataWidget::Private
60 {
61 public:
62 #ifdef HAVE_NEPOMUK
63 CommentWidget* commentWidget;
64 KRatingWidget* ratingWidget;
65 Nepomuk::ResourceTaggingWidget* tagWidget;
66
67 // shared data between the GUI-thread and
68 // the loader-thread (see LoadFilesThread):
69 QMutex mutex;
70 struct SharedData
71 {
72 int rating;
73 QString comment;
74 QList<Nepomuk::Resource> fileRes;
75 QMap<KUrl, Nepomuk::Resource> files;
76 } sharedData;
77
78 /**
79 * Loads the meta data of files and writes
80 * the result into a shared data pool that
81 * can be used by the widgets in the GUI thread.
82 */
83 class LoadFilesThread : public QThread
84 {
85 public:
86 LoadFilesThread(SharedData* sharedData, QMutex* mutex);
87 ~LoadFilesThread();
88 void loadFiles(const KUrl::List& urls);
89 virtual void run();
90
91 private:
92 SharedData* m_sharedData;
93 QMutex* m_mutex;
94 KUrl::List m_urls;
95 bool m_canceled;
96 };
97
98 LoadFilesThread* loadFilesThread;
99 #endif
100 };
101
102 #ifdef HAVE_NEPOMUK
103
104 MetaDataWidget::Private::LoadFilesThread::LoadFilesThread(
105 MetaDataWidget::Private::SharedData* sharedData,
106 QMutex* mutex) :
107 m_sharedData(sharedData),
108 m_mutex(mutex),
109 m_urls(),
110 m_canceled(false)
111 {
112 }
113
114 MetaDataWidget::Private::LoadFilesThread::~LoadFilesThread()
115 {
116 // this thread may very well be deleted during execution. We need
117 // to protect it from crashes here
118 m_canceled = true;
119 wait();
120 }
121
122 void MetaDataWidget::Private::LoadFilesThread::loadFiles(const KUrl::List& urls)
123 {
124 QMutexLocker locker( m_mutex );
125 m_urls = urls;
126 m_canceled = false;
127 start();
128 }
129
130 void MetaDataWidget::Private::LoadFilesThread::run()
131 {
132 QMutexLocker locker( m_mutex );
133 const KUrl::List urls = m_urls;
134 locker.unlock();
135
136 bool first = true;
137 QList<Nepomuk::Resource> fileRes;
138 QMap<KUrl, Nepomuk::Resource> files;
139 unsigned int rating = 0;
140 QString comment;
141 Q_FOREACH( const KUrl &url, urls ) {
142 if ( m_canceled )
143 return;
144 Nepomuk::Resource file( url, Soprano::Vocabulary::Xesam::File() );
145 files.insert( url, file );
146 fileRes.append( file );
147
148 if ( !first && rating != file.rating() ) {
149 rating = 0; // reset rating
150 }
151 else if ( first ) {
152 rating = file.rating();
153 }
154
155 if ( !first && comment != file.description() ) {
156 comment.clear();
157 }
158 else if ( first ) {
159 comment = file.description();
160 }
161 first = false;
162 }
163
164 locker.relock();
165 m_sharedData->rating = rating;
166 m_sharedData->comment = comment;
167 m_sharedData->fileRes = fileRes;
168 m_sharedData->files = files;
169 }
170 #endif
171
172 MetaDataWidget::MetaDataWidget(QWidget* parent) :
173 QWidget(parent)
174 {
175 #ifdef HAVE_NEPOMUK
176 d = new Private;
177 d->commentWidget = new CommentWidget(this);
178 d->commentWidget->setFocusPolicy(Qt::ClickFocus);
179 d->ratingWidget = new KRatingWidget(this);
180 d->ratingWidget->setAlignment( Qt::AlignCenter );
181 d->tagWidget = new Nepomuk::ResourceTaggingWidget(this);
182 connect(d->ratingWidget, SIGNAL(ratingChanged(unsigned int)), this, SLOT(slotRatingChanged(unsigned int)));
183 connect(d->commentWidget, SIGNAL(commentChanged(const QString&)), this, SLOT(slotCommentChanged(const QString&)));
184 connect(d->tagWidget, SIGNAL(tagClicked(const Nepomuk::Tag&)), this, SLOT(slotTagClicked( const Nepomuk::Tag&)));
185
186 d->sharedData.rating = 0;
187 d->loadFilesThread = new Private::LoadFilesThread(&d->sharedData, &d->mutex);
188 connect(d->loadFilesThread, SIGNAL(finished()), this, SLOT(slotLoadingFinished()));
189
190 QVBoxLayout* lay = new QVBoxLayout(this);
191 lay->setMargin(0);
192 lay->addWidget(d->ratingWidget);
193 lay->addWidget(d->commentWidget);
194 lay->addWidget( d->tagWidget );
195 #else
196 d = 0;
197 #endif
198 }
199
200
201 MetaDataWidget::~MetaDataWidget()
202 {
203 #ifdef HAVE_NEPOMUK
204 delete d->loadFilesThread;
205 #endif
206 delete d;
207 }
208
209 void MetaDataWidget::setRatingVisible(bool visible)
210 {
211 #ifdef HAVE_NEPOMUK
212 d->ratingWidget->setVisible(visible);
213 #else
214 Q_UNUSED(visible);
215 #endif
216 }
217
218
219 bool MetaDataWidget::isRatingVisible() const
220 {
221 #ifdef HAVE_NEPOMUK
222 return d->ratingWidget->isVisible();
223 #else
224 return false;
225 #endif
226 }
227
228
229 void MetaDataWidget::setCommentVisible(bool visible)
230 {
231 #ifdef HAVE_NEPOMUK
232 d->commentWidget->setVisible(visible);
233 #else
234 Q_UNUSED(visible);
235 #endif
236 }
237
238
239 bool MetaDataWidget::isCommentVisible() const
240 {
241 #ifdef HAVE_NEPOMUK
242 return d->commentWidget->isVisible();
243 #else
244 return false;
245 #endif
246 }
247
248
249 void MetaDataWidget::setTagsVisible(bool visible)
250 {
251 #ifdef HAVE_NEPOMUK
252 d->tagWidget->setVisible(visible);
253 #else
254 Q_UNUSED(visible);
255 #endif
256 }
257
258
259 bool MetaDataWidget::areTagsVisible() const
260 {
261 #ifdef HAVE_NEPOMUK
262 return d->tagWidget->isVisible();
263 #else
264 return false;
265 #endif
266 }
267
268
269 void MetaDataWidget::setFile(const KUrl& url)
270 {
271 KUrl::List urls;
272 urls.append( url );
273 setFiles( urls );
274 }
275
276 void MetaDataWidget::setFiles(const KUrl::List& urls)
277 {
278 #ifdef HAVE_NEPOMUK
279 // Assure that the currently edited text is stored before
280 // loading the meta data for new files.
281 const QString currentComment = d->commentWidget->editorText();
282 if ( currentComment != d->commentWidget->comment() ) {
283 slotCommentChanged( currentComment );
284 }
285
286 d->loadFilesThread->loadFiles( urls );
287 #else
288 Q_UNUSED( urls );
289 #endif
290 }
291
292
293 void MetaDataWidget::slotCommentChanged( const QString& s )
294 {
295 #ifdef HAVE_NEPOMUK
296 disconnect(d->commentWidget, SIGNAL(commentChanged(const QString&)), this, SLOT(slotCommentChanged(const QString&)));
297
298 QMutexLocker locker( &d->mutex );
299 Nepomuk::MassUpdateJob* job = Nepomuk::MassUpdateJob::commentResources( d->sharedData.files.values(), s );
300 connect( job, SIGNAL( result( KJob* ) ),
301 this, SLOT( metadataUpdateDone() ) );
302 setEnabled( false ); // no updates during execution
303 job->start();
304
305 connect(d->commentWidget, SIGNAL(commentChanged(const QString&)), this, SLOT(slotCommentChanged(const QString&)));
306 #else
307 Q_UNUSED( s );
308 #endif
309 }
310
311
312 void MetaDataWidget::slotRatingChanged(unsigned int rating)
313 {
314 #ifdef HAVE_NEPOMUK
315 QMutexLocker locker( &d->mutex );
316 Nepomuk::MassUpdateJob* job = Nepomuk::MassUpdateJob::rateResources( d->sharedData.files.values(), rating );
317 connect( job, SIGNAL( result( KJob* ) ),
318 this, SLOT( metadataUpdateDone() ) );
319 setEnabled( false ); // no updates during execution
320 job->start();
321 #else
322 Q_UNUSED( rating );
323 #endif
324 }
325
326
327 void MetaDataWidget::metadataUpdateDone()
328 {
329 setEnabled( true );
330 }
331
332
333 bool MetaDataWidget::eventFilter(QObject* obj, QEvent* event)
334 {
335 return QWidget::eventFilter(obj, event);
336 }
337
338
339 void MetaDataWidget::slotTagClicked( const Nepomuk::Tag& tag )
340 {
341 Q_UNUSED( tag );
342 #ifdef HAVE_NEPOMUK
343 d->tagWidget->showTagPopup( QCursor::pos() );
344 #endif
345 }
346
347 void MetaDataWidget::slotLoadingFinished()
348 {
349 #ifdef HAVE_NEPOMUK
350 QMutexLocker locker( &d->mutex );
351 d->ratingWidget->setRating( d->sharedData.rating );
352 d->commentWidget->setComment( d->sharedData.comment );
353 d->tagWidget->setResources( d->sharedData.fileRes );
354 #endif
355 }
356
357 #include "metadatawidget.moc"