]> cloud.milkyroute.net Git - dolphin.git/blob - src/panels/information/kmetadatawidget.cpp
Remove connection to non-existent slot.
[dolphin.git] / src / panels / information / kmetadatawidget.cpp
1 /*****************************************************************************
2 * Copyright (C) 2008 by Sebastian Trueg <trueg@kde.org> *
3 * Copyright (C) 2009-2010 by Peter Penz <peter.penz@gmx.at> *
4 * *
5 * This library is free software; you can redistribute it and/or *
6 * modify it under the terms of the GNU Library General Public *
7 * License version 2 as published by the Free Software Foundation. *
8 * *
9 * This library 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 GNU *
12 * Library General Public 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 *
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *
17 * Boston, MA 02110-1301, USA. *
18 *****************************************************************************/
19
20 #include "kmetadatawidget.h"
21
22 #include <kconfig.h>
23 #include <kconfiggroup.h>
24 #include <kfileitem.h>
25 #include <kglobalsettings.h>
26 #include <kglobal.h>
27 #include <klocale.h>
28 #include "kmetadatamodel.h"
29 #include "knfotranslator_p.h"
30
31 #include <QEvent>
32 #include <QFontMetrics>
33 #include <QGridLayout>
34 #include <QLabel>
35 #include <QList>
36 #include <QString>
37
38 #include <config-nepomuk.h>
39 #ifdef HAVE_NEPOMUK
40 #define DISABLE_NEPOMUK_LEGACY
41
42 #include "kcommentwidget_p.h"
43 #include "ktaggingwidget_p.h"
44
45 #include <nepomuk/kratingwidget.h>
46 #include <nepomuk/resource.h>
47 #include <nepomuk/resourcemanager.h>
48 #include <nepomuk/property.h>
49 #include <nepomuk/tag.h>
50 #include "nepomukmassupdatejob_p.h"
51
52 #include <QMutex>
53 #include <QSpacerItem>
54 #include <QThread>
55 #else
56 namespace Nepomuk
57 {
58 typedef int Tag;
59 }
60 #endif
61
62 class KMetaDataWidget::Private
63 {
64 public:
65 struct Row
66 {
67 QLabel* label;
68 QLabel* defaultValueWidget;
69 QWidget* customValueWidget;
70 };
71
72 Private(KMetaDataWidget* parent);
73 ~Private();
74
75 void addRow(QLabel* label, QLabel* valueWidget);
76 void setCustomValueWidget(int rowIndex, QWidget* valueWidget);
77 void setRowVisible(QWidget* valueWidget, bool visible);
78
79 /**
80 * Initializes the configuration file "kmetainformationrc"
81 * with proper default settings for the first start in
82 * an uninitialized environment.
83 */
84 void initMetaInfoSettings();
85
86 /**
87 * Parses the configuration file "kmetainformationrc" and
88 * updates the visibility of all rows.
89 */
90 void updateRowsVisibility();
91
92 void slotLoadingFinished();
93
94 void slotRatingChanged(unsigned int rating);
95 void slotTagsChanged(const QList<Nepomuk::Tag>& tags);
96 void slotCommentChanged(const QString& comment);
97
98 void slotMetaDataUpdateDone();
99 void slotLinkActivated(const QString& link);
100
101 void slotTagActivated(const Nepomuk::Tag& tag);
102
103 #ifdef HAVE_NEPOMUK
104 /**
105 * Disables the metadata widget and starts the job that
106 * changes the meta data asynchronously. After the job
107 * has been finished, the metadata widget gets enabled again.
108 */
109 void startChangeDataJob(KJob* job);
110
111 QList<KUrl> sortedKeys(const QHash<KUrl, Nepomuk::Variant>& data) const;
112 QList<Nepomuk::Resource> resourceList() const;
113 #endif
114
115 bool m_sizeVisible;
116 bool m_readOnly;
117 bool m_nepomukActivated;
118 int m_fixedRowCount;
119 MetaDataTypes m_visibleDataTypes;
120 QList<KFileItem> m_fileItems;
121 QList<Row> m_rows;
122
123 KMetaDataModel* m_model;
124
125 QGridLayout* m_gridLayout;
126
127 QLabel* m_typeInfo;
128 QLabel* m_sizeLabel;
129 QLabel* m_sizeInfo;
130 QLabel* m_modifiedInfo;
131 QLabel* m_ownerInfo;
132 QLabel* m_permissionsInfo;
133
134 #ifdef HAVE_NEPOMUK
135 KRatingWidget* m_ratingWidget;
136 KTaggingWidget* m_taggingWidget;
137 KCommentWidget* m_commentWidget;
138 #endif
139
140 private:
141 KMetaDataWidget* const q;
142 };
143
144 KMetaDataWidget::Private::Private(KMetaDataWidget* parent) :
145 m_sizeVisible(true),
146 m_readOnly(false),
147 m_nepomukActivated(false),
148 m_fixedRowCount(0),
149 m_visibleDataTypes(TypeData | SizeData | ModifiedData | OwnerData |
150 PermissionsData | RatingData | TagsData | CommentData),
151 m_fileItems(),
152 m_rows(),
153 m_model(0),
154 m_gridLayout(0),
155 m_typeInfo(0),
156 m_sizeLabel(0),
157 m_sizeInfo(0),
158 m_modifiedInfo(0),
159 m_ownerInfo(0),
160 m_permissionsInfo(0),
161 #ifdef HAVE_NEPOMUK
162 m_ratingWidget(0),
163 m_taggingWidget(0),
164 m_commentWidget(0),
165 #endif
166 q(parent)
167 {
168 const QFontMetrics fontMetrics(KGlobalSettings::smallestReadableFont());
169
170 m_gridLayout = new QGridLayout(parent);
171 m_gridLayout->setMargin(0);
172 m_gridLayout->setSpacing(fontMetrics.height() / 4);
173
174 m_typeInfo = new QLabel(parent);
175 m_sizeLabel = new QLabel(parent);
176 m_sizeInfo = new QLabel(parent);
177 m_modifiedInfo = new QLabel(parent);
178 m_ownerInfo = new QLabel(parent);
179 m_permissionsInfo = new QLabel(parent);
180
181 #ifdef HAVE_NEPOMUK
182 m_nepomukActivated = (Nepomuk::ResourceManager::instance()->init() == 0);
183 if (m_nepomukActivated) {
184 m_ratingWidget = new KRatingWidget(parent);
185 m_ratingWidget->setFixedHeight(fontMetrics.height());
186 const Qt::Alignment align = (parent->layoutDirection() == Qt::LeftToRight) ?
187 Qt::AlignLeft : Qt::AlignRight;
188 m_ratingWidget->setAlignment(align);
189 connect(m_ratingWidget, SIGNAL(ratingChanged(unsigned int)),
190 q, SLOT(slotRatingChanged(unsigned int)));
191 m_ratingWidget->setVisible(false);
192
193 m_taggingWidget = new KTaggingWidget(parent);
194 connect(m_taggingWidget, SIGNAL(tagsChanged(const QList<Nepomuk::Tag>&)),
195 q, SLOT(slotTagsChanged(const QList<Nepomuk::Tag>&)));
196 connect(m_taggingWidget, SIGNAL(tagActivated(const Nepomuk::Tag&)),
197 q, SLOT(slotTagActivated(const Nepomuk::Tag&)));
198 m_taggingWidget->setVisible(false);
199
200 m_commentWidget = new KCommentWidget(parent);
201 connect(m_commentWidget, SIGNAL(commentChanged(const QString&)),
202 q, SLOT(slotCommentChanged(const QString&)));
203 m_commentWidget->setVisible(false);
204 }
205 #endif
206
207 initMetaInfoSettings();
208 }
209
210 KMetaDataWidget::Private::~Private()
211 {
212 }
213
214 void KMetaDataWidget::Private::addRow(QLabel* label, QLabel* valueWidget)
215 {
216 Row row;
217 row.label = label;
218 row.defaultValueWidget = valueWidget;
219 row.customValueWidget = 0;
220 m_rows.append(row);
221
222 const QFont smallFont = KGlobalSettings::smallestReadableFont();
223 // use a brighter color for the label and a small font size
224 QPalette palette = label->palette();
225 const QPalette::ColorRole role = q->foregroundRole();
226 QColor textColor = palette.color(role);
227 textColor.setAlpha(128);
228 palette.setColor(role, textColor);
229 label->setPalette(palette);
230 label->setForegroundRole(role);
231 label->setFont(smallFont);
232 label->setWordWrap(true);
233 label->setAlignment(Qt::AlignTop | Qt::AlignRight);
234
235 valueWidget->setForegroundRole(role);
236 valueWidget->setFont(smallFont);
237 valueWidget->setWordWrap(true);
238 valueWidget->setAlignment(Qt::AlignTop | Qt::AlignLeft);
239
240 // add the row to grid layout
241 const int rowIndex = m_rows.count() - 1;
242 m_gridLayout->addWidget(label, rowIndex, 0, Qt::AlignRight);
243 const int spacerWidth = QFontMetrics(smallFont).size(Qt::TextSingleLine, " ").width();
244 m_gridLayout->addItem(new QSpacerItem(spacerWidth, 1), rowIndex, 1);
245 m_gridLayout->addWidget(valueWidget, rowIndex, 2, Qt::AlignLeft);
246 }
247
248 void KMetaDataWidget::Private::setCustomValueWidget(int rowIndex, QWidget* valueWidget)
249 {
250 Row& row = m_rows[rowIndex];
251
252 if (valueWidget == 0) {
253 // remove current custom value widget from the grid and replace it
254 // by the default value widget
255 if (row.customValueWidget != 0) {
256 row.customValueWidget->setVisible(false);
257 m_gridLayout->removeWidget(row.customValueWidget);
258 }
259 m_gridLayout->addWidget(row.defaultValueWidget, rowIndex, 2, Qt::AlignLeft);
260 row.defaultValueWidget->setVisible(true);
261 } else {
262 // remove the default value widget from the grid and replace it
263 // by the custom value widget
264 row.defaultValueWidget->setVisible(false);
265 m_gridLayout->removeWidget(row.defaultValueWidget);
266 m_gridLayout->addWidget(valueWidget, rowIndex, 2, Qt::AlignLeft);
267 valueWidget->setVisible(true);
268 }
269
270 row.customValueWidget = valueWidget;
271 }
272
273 void KMetaDataWidget::Private::setRowVisible(QWidget* valueWidget, bool visible)
274 {
275 foreach (const Row& row, m_rows) {
276 const bool found = (row.defaultValueWidget == valueWidget) ||
277 (row.customValueWidget == valueWidget);
278 if (found) {
279 row.label->setVisible(visible);
280 if (row.customValueWidget != 0) {
281 row.customValueWidget->setVisible(visible);
282 row.defaultValueWidget->setVisible(false);
283 } else {
284 row.defaultValueWidget->setVisible(visible);
285 }
286 return;
287 }
288 }
289 }
290
291 void KMetaDataWidget::Private::initMetaInfoSettings()
292 {
293 const int currentVersion = 3; // increase version, if the blacklist of disabled
294 // properties should be updated
295
296 KConfig config("kmetainformationrc", KConfig::NoGlobals);
297 if (config.group("Misc").readEntry("version", 0) < currentVersion) {
298 // The resource file is read the first time. Assure
299 // that some meta information is disabled per default.
300
301 // clear old info
302 config.deleteGroup("Show");
303 KConfigGroup settings = config.group("Show");
304
305 static const char* const disabledProperties[] = {
306 "http://www.semanticdesktop.org/ontologies/2007/01/19/nie#comment",
307 "http://www.semanticdesktop.org/ontologies/2007/01/19/nie#contentSize",
308 "http://www.semanticdesktop.org/ontologies/2007/01/19/nie#depends",
309 "http://www.semanticdesktop.org/ontologies/2007/01/19/nie#isPartOf",
310 "http://www.semanticdesktop.org/ontologies/2007/01/19/nie#lastModified",
311 "http://www.semanticdesktop.org/ontologies/2007/01/19/nie#mimeType",
312 "http://www.semanticdesktop.org/ontologies/2007/01/19/nie#plainTextContent",
313 "http://www.semanticdesktop.org/ontologies/2007/01/19/nie#url",
314 "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#averageBitrate",
315 "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#channels",
316 "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#fileName",
317 "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#apertureValue",
318 "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#exposureBiasValue",
319 "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#exposureTime",
320 "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#flash",
321 "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#focalLength",
322 "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#focalLengthIn35mmFilm",
323 "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#isoSpeedRatings",
324 "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#make",
325 "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#meteringMode",
326 "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#model",
327 "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#orientation",
328 "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#whiteBalance",
329 "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#description",
330 "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#hasTag",
331 "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#lastModified",
332 "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#numericRating",
333 "http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
334 "kfileitem#owner",
335 "kfileitem#permissions",
336 0 // mandatory last entry
337 };
338
339 for (int i = 0; disabledProperties[i] != 0; ++i) {
340 settings.writeEntry(disabledProperties[i], false);
341 }
342
343 // mark the group as initialized
344 config.group("Misc").writeEntry("version", currentVersion);
345 }
346 }
347
348 void KMetaDataWidget::Private::updateRowsVisibility()
349 {
350 KConfig config("kmetainformationrc", KConfig::NoGlobals);
351 KConfigGroup settings = config.group("Show");
352
353 setRowVisible(m_typeInfo,
354 (m_visibleDataTypes & KMetaDataWidget::TypeData) &&
355 settings.readEntry("kfileitem#type", true));
356
357 // Cache in m_sizeVisible whether the size should be shown. This
358 // is necessary as the size is temporary hidden when the target
359 // file item is a directory.
360 m_sizeVisible = (m_visibleDataTypes & KMetaDataWidget::SizeData) &&
361 settings.readEntry("kfileitem#size", true);
362 bool visible = m_sizeVisible;
363 if (visible && (m_fileItems.count() == 1)) {
364 // don't show the size information, if one directory is shown
365 const KFileItem item = m_fileItems.first();
366 visible = !item.isNull() && !item.isDir();
367 }
368 setRowVisible(m_sizeInfo, visible);
369
370 setRowVisible(m_modifiedInfo,
371 (m_visibleDataTypes & KMetaDataWidget::ModifiedData) &&
372 settings.readEntry("kfileitem#modified", true));
373
374 setRowVisible(m_ownerInfo,
375 (m_visibleDataTypes & KMetaDataWidget::OwnerData) &&
376 settings.readEntry("kfileitem#owner", true));
377
378 setRowVisible(m_permissionsInfo,
379 (m_visibleDataTypes & KMetaDataWidget::PermissionsData) &&
380 settings.readEntry("kfileitem#permissions", true));
381
382 #ifdef HAVE_NEPOMUK
383 if (m_nepomukActivated) {
384 setRowVisible(m_ratingWidget,
385 (m_visibleDataTypes & KMetaDataWidget::RatingData) &&
386 settings.readEntry("kfileitem#rating", true));
387
388 setRowVisible(m_taggingWidget,
389 (m_visibleDataTypes & KMetaDataWidget::TagsData) &&
390 settings.readEntry("kfileitem#tags", true));
391
392 setRowVisible(m_commentWidget,
393 (m_visibleDataTypes & KMetaDataWidget::CommentData) &&
394 settings.readEntry("kfileitem#comment", true));
395 }
396 #endif
397 }
398
399 void KMetaDataWidget::Private::slotLoadingFinished()
400 {
401 #ifdef HAVE_NEPOMUK
402 // Show the remaining meta information as text. The number
403 // of required rows may very. Existing rows are reused to
404 // prevent flickering and to increase the performance.
405 int rowIndex = m_fixedRowCount;
406
407 const QHash<KUrl, Nepomuk::Variant> data = m_model->data();
408 const QList<KUrl> keys = sortedKeys(data);
409
410 foreach (const KUrl& key, keys) {
411 const Nepomuk::Variant value = data[key];
412 const QString itemLabel = q->label(key);
413
414 const bool valueApplied = q->setValue(key, value);
415 if (rowIndex >= m_rows.count()) {
416 // a new row must get created
417 QLabel* label = new QLabel(itemLabel, q);
418 QLabel* valueWidget = new QLabel(q);
419 connect(valueWidget, SIGNAL(linkActivated(QString)),
420 q, SLOT(slotLinkActivated(QString)));
421 addRow(label, valueWidget);
422 }
423
424 Q_ASSERT(m_rows[rowIndex].label != 0);
425 Q_ASSERT(m_rows[rowIndex].defaultValueWidget != 0);
426
427 // set label
428 m_rows[rowIndex].label->setText(itemLabel);
429
430 // set value
431 if (valueApplied) {
432 setCustomValueWidget(rowIndex, q->valueWidget(key));
433 } else {
434 QLabel* valueWidget = m_rows[rowIndex].defaultValueWidget;
435 valueWidget->setText(value.toString());
436 setCustomValueWidget(rowIndex, 0);
437 }
438 ++rowIndex;
439 }
440
441 // remove rows that are not needed anymore
442 for (int i = m_rows.count() - 1; i >= rowIndex; --i) {
443 delete m_rows[i].label;
444 delete m_rows[i].defaultValueWidget;
445 m_rows.pop_back();
446 }
447 #endif
448
449 q->updateGeometry();
450 }
451
452 void KMetaDataWidget::Private::slotRatingChanged(unsigned int rating)
453 {
454 #ifdef HAVE_NEPOMUK
455 Nepomuk::MassUpdateJob* job =
456 Nepomuk::MassUpdateJob::rateResources(resourceList(), rating);
457 startChangeDataJob(job);
458 #else
459 Q_UNUSED(rating);
460 #endif
461 }
462
463 void KMetaDataWidget::Private::slotTagsChanged(const QList<Nepomuk::Tag>& tags)
464 {
465 #ifdef HAVE_NEPOMUK
466 m_taggingWidget->setTags(tags);
467
468 Nepomuk::MassUpdateJob* job =
469 Nepomuk::MassUpdateJob::tagResources(resourceList(), tags);
470 startChangeDataJob(job);
471 #else
472 Q_UNUSED(tags);
473 #endif
474 }
475
476 void KMetaDataWidget::Private::slotCommentChanged(const QString& comment)
477 {
478 #ifdef HAVE_NEPOMUK
479 Nepomuk::MassUpdateJob* job =
480 Nepomuk::MassUpdateJob::commentResources(resourceList(), comment);
481 startChangeDataJob(job);
482 #else
483 Q_UNUSED(comment);
484 #endif
485 }
486
487 void KMetaDataWidget::Private::slotTagActivated(const Nepomuk::Tag& tag)
488 {
489 #ifdef HAVE_NEPOMUK
490 emit q->urlActivated(tag.resourceUri());
491 #else
492 Q_UNUSED(tag);
493 #endif
494 }
495
496 void KMetaDataWidget::Private::slotMetaDataUpdateDone()
497 {
498 #ifdef HAVE_NEPOMUK
499 q->setEnabled(true);
500 #endif
501 }
502
503 void KMetaDataWidget::Private::slotLinkActivated(const QString& link)
504 {
505 emit q->urlActivated(KUrl(link));
506 }
507
508 #ifdef HAVE_NEPOMUK
509 void KMetaDataWidget::Private::startChangeDataJob(KJob* job)
510 {
511 connect(job, SIGNAL(result(KJob*)),
512 q, SLOT(slotMetaDataUpdateDone()));
513 q->setEnabled(false); // no updates during execution
514 job->start();
515 }
516
517 QList<KUrl> KMetaDataWidget::Private::sortedKeys(const QHash<KUrl, Nepomuk::Variant>& data) const
518 {
519 // Create a map, where the translated label prefixed with the
520 // sort priority acts as key. The data of each entry is the URI
521 // of the data. By this the all URIs are sorted by the sort priority
522 // and sub sorted by the translated labels.
523 QMap<QString, KUrl> map;
524 QHash<KUrl, Nepomuk::Variant>::const_iterator hashIt = data.constBegin();
525 while (hashIt != data.constEnd()) {
526 const KUrl uri = hashIt.key();
527
528 QString key = q->model()->group(uri);
529 key += q->label(uri);
530
531 map.insert(key, uri);
532 ++hashIt;
533 }
534
535 // Apply the URIs from the map to the list that will get returned.
536 // The list will then be alphabetically ordered by the translated labels of the URIs.
537 QList<KUrl> list;
538 QMap<QString, KUrl>::const_iterator mapIt = map.constBegin();
539 while (mapIt != map.constEnd()) {
540 list.append(mapIt.value());
541 ++mapIt;
542 }
543
544 return list;
545 }
546
547 QList<Nepomuk::Resource> KMetaDataWidget::Private::resourceList() const
548 {
549 QList<Nepomuk::Resource> list;
550 foreach (const KFileItem& item, m_fileItems) {
551 const KUrl url = item.url();
552 list.append(Nepomuk::Resource(url));
553 }
554 return list;
555 }
556 #endif
557
558 KMetaDataWidget::KMetaDataWidget(QWidget* parent) :
559 QWidget(parent),
560 d(new Private(this))
561 {
562 }
563
564 KMetaDataWidget::~KMetaDataWidget()
565 {
566 delete d;
567 }
568
569 void KMetaDataWidget::setItem(const KFileItem& item)
570 {
571 // update values for "type", "size", "modified",
572 // "owner" and "permissions" synchronously
573 d->m_sizeLabel->setText(i18nc("@label", "Size"));
574 if (item.isDir()) {
575 d->m_typeInfo->setText(i18nc("@label", "Folder"));
576 d->setRowVisible(d->m_sizeInfo, false);
577 } else {
578 d->m_typeInfo->setText(item.mimeComment());
579 d->m_sizeInfo->setText(KIO::convertSize(item.size()));
580 d->setRowVisible(d->m_sizeInfo, d->m_sizeVisible);
581 }
582 d->m_modifiedInfo->setText(KGlobal::locale()->formatDateTime(item.time(KFileItem::ModificationTime), KLocale::FancyLongDate));
583 d->m_ownerInfo->setText(item.user());
584 d->m_permissionsInfo->setText(item.permissionsString());
585
586 setItems(KFileItemList() << item);
587 }
588
589 void KMetaDataWidget::setItems(const KFileItemList& items)
590 {
591 d->m_fileItems = items;
592 if (d->m_model != 0) {
593 d->m_model->setItems(items);
594 }
595
596 if (items.count() > 1) {
597 // calculate the size of all items and show this
598 // information to the user
599 d->m_sizeLabel->setText(i18nc("@label", "Total Size:"));
600 d->setRowVisible(d->m_sizeInfo, d->m_sizeVisible);
601
602 quint64 totalSize = 0;
603 foreach (const KFileItem& item, items) {
604 if (!item.isDir() && !item.isLink()) {
605 totalSize += item.size();
606 }
607 }
608 d->m_sizeInfo->setText(KIO::convertSize(totalSize));
609 }
610 }
611
612 void KMetaDataWidget::setItem(const KUrl& url)
613 {
614 KFileItem item(KFileItem::Unknown, KFileItem::Unknown, url);
615 item.refresh();
616 setItem(item);
617 }
618
619 void KMetaDataWidget::setItems(const QList<KUrl>& urls)
620 {
621 KFileItemList items;
622 foreach (const KUrl& url, urls) {
623 KFileItem item(KFileItem::Unknown, KFileItem::Unknown, url);
624 item.refresh();
625 items.append(item);
626 }
627 setItems(items);
628 }
629
630 KFileItemList KMetaDataWidget::items() const
631 {
632 return d->m_fileItems;
633 }
634
635 void KMetaDataWidget::setModel(KMetaDataModel* model)
636 {
637 if (d->m_model != 0) {
638 disconnect(d->m_model, SIGNAL(loadingFinished()));
639 }
640 d->m_model = model;
641 connect(d->m_model, SIGNAL(loadingFinished()), this, SLOT(slotLoadingFinished()));
642 }
643
644 KMetaDataModel* KMetaDataWidget::model() const
645 {
646 return d->m_model;
647 }
648
649 void KMetaDataWidget::setReadOnly(bool readOnly)
650 {
651 d->m_readOnly = readOnly;
652 #ifdef HAVE_NEPOMUK
653 // TODO: encapsulate this code as part of a metadata-model for KDE 4.5
654 if (d->m_taggingWidget)
655 d->m_taggingWidget->setReadOnly(readOnly);
656 if (d->m_commentWidget)
657 d->m_commentWidget->setReadOnly(readOnly);
658 #endif
659 }
660
661 bool KMetaDataWidget::isReadOnly() const
662 {
663 return d->m_readOnly;
664 }
665
666 void KMetaDataWidget::setVisibleDataTypes(MetaDataTypes data)
667 {
668 d->m_visibleDataTypes = data;
669 d->updateRowsVisibility();
670 }
671
672 KMetaDataWidget::MetaDataTypes KMetaDataWidget::visibleDataTypes() const
673 {
674 return d->m_visibleDataTypes;
675 }
676
677 QSize KMetaDataWidget::sizeHint() const
678 {
679 const int fixedWidth = 200;
680
681 int height = d->m_gridLayout->margin() * 2 +
682 d->m_gridLayout->spacing() * (d->m_rows.count() - 1);
683
684 foreach (const Private::Row& row, d->m_rows) {
685 QWidget* valueWidget = row.defaultValueWidget;
686 if (valueWidget != 0) {
687 if (row.customValueWidget != 0) {
688 valueWidget = row.customValueWidget;
689 }
690
691 int rowHeight = valueWidget->heightForWidth(fixedWidth / 2);
692 if (rowHeight <= 0) {
693 rowHeight = valueWidget->sizeHint().height();
694 }
695 height += rowHeight;
696 }
697 }
698
699 return QSize(fixedWidth, height);
700 }
701
702 QString KMetaDataWidget::label(const KUrl& metaDataUri) const
703 {
704 QString label;
705 const QString uri = metaDataUri.url();
706 if (uri == QLatin1String("kfileitem#rating")) {
707 label = i18nc("@label", "Rating");
708 } else if (uri == QLatin1String("kfileitem#tags")) {
709 label = i18nc("@label", "Tags");
710 } else if (uri == QLatin1String("kfileitem#comment")) {
711 label = i18nc("@label", "Comment");
712 } else {
713 label = KNfoTranslator::instance().translation(metaDataUri);
714 }
715
716 return label;
717 }
718
719 #ifdef HAVE_NEPOMUK
720 QWidget* KMetaDataWidget::valueWidget(const KUrl& metaDataUri) const
721 {
722 QWidget* widget = 0;
723
724 if (d->m_nepomukActivated) {
725 const QString uri = metaDataUri.url();
726 if (uri == QLatin1String("kfileitem#rating")) {
727 widget = d->m_ratingWidget;
728 } else if (uri == QLatin1String("kfileitem#tags")) {
729 widget = d->m_taggingWidget;
730 } else if (uri == QLatin1String("kfileitem#comment")) {
731 widget = d->m_commentWidget;
732 }
733 }
734
735 return widget;
736 }
737
738 bool KMetaDataWidget::setValue(const KUrl& metaDataUri, const Nepomuk::Variant& value)
739 {
740 if (d->m_nepomukActivated) {
741 QWidget* widget = valueWidget(metaDataUri);
742 if (widget == d->m_ratingWidget) {
743 d->m_ratingWidget->setRating(value.toInt());
744 return true;
745 }
746
747 if (widget == d->m_taggingWidget) {
748 QList<Nepomuk::Variant> variants = value.toVariantList();
749 QList<Nepomuk::Tag> tags;
750 foreach (const Nepomuk::Variant& variant, variants) {
751 const Nepomuk::Resource resource = variant.toResource();
752 tags.append(static_cast<Nepomuk::Tag>(resource));
753 }
754 d->m_taggingWidget->setTags(tags);
755 return true;
756 }
757
758 if (widget == d->m_commentWidget) {
759 d->m_commentWidget->setText(value.toString());
760 return true;
761 }
762 }
763 return false;
764 }
765 #endif
766
767 bool KMetaDataWidget::event(QEvent* event)
768 {
769 if (event->type() == QEvent::Polish) {
770 // The adding of rows is not done in the constructor. This allows the
771 // client of KMetaDataWidget to set a proper foreground role which
772 // will be respected by the rows.
773
774 d->addRow(new QLabel(i18nc("@label file type", "Type"), this), d->m_typeInfo);
775 d->addRow(d->m_sizeLabel, d->m_sizeInfo);
776 d->addRow(new QLabel(i18nc("@label", "Modified"), this), d->m_modifiedInfo);
777 d->addRow(new QLabel(i18nc("@label", "Owner"), this), d->m_ownerInfo);
778 d->addRow(new QLabel(i18nc("@label", "Permissions"), this), d->m_permissionsInfo);
779
780 // The current number of rows represents meta data, that will be shown for
781 // all files. Dynamic meta data will be appended after those rows (see
782 // slotLoadingFinished()).
783 d->m_fixedRowCount = d->m_rows.count();
784
785 d->updateRowsVisibility();
786 }
787
788 return QWidget::event(event);
789 }
790
791 #include "kmetadatawidget.moc"