]> cloud.milkyroute.net Git - dolphin.git/blob - src/panels/information/kmetadatawidget.cpp
Allow to provide custom widgets for meta data in a generic way.
[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
192 m_taggingWidget = new KTaggingWidget(parent);
193 connect(m_taggingWidget, SIGNAL(tagsChanged(const QList<Nepomuk::Tag>&)),
194 q, SLOT(slotTagsChanged(const QList<Nepomuk::Tag>&)));
195 connect(m_taggingWidget, SIGNAL(tagActivated(const Nepomuk::Tag&)),
196 q, SLOT(slotTagActivated(const Nepomuk::Tag&)));
197
198 m_commentWidget = new KCommentWidget(parent);
199 connect(m_commentWidget, SIGNAL(commentChanged(const QString&)),
200 q, SLOT(slotCommentChanged(const QString&)));
201 }
202 #endif
203
204 initMetaInfoSettings();
205 }
206
207 KMetaDataWidget::Private::~Private()
208 {
209 }
210
211 void KMetaDataWidget::Private::addRow(QLabel* label, QLabel* valueWidget)
212 {
213 Row row;
214 row.label = label;
215 row.defaultValueWidget = valueWidget;
216 row.customValueWidget = 0;
217 m_rows.append(row);
218
219 const QFont smallFont = KGlobalSettings::smallestReadableFont();
220 // use a brighter color for the label and a small font size
221 QPalette palette = label->palette();
222 const QPalette::ColorRole role = q->foregroundRole();
223 QColor textColor = palette.color(role);
224 textColor.setAlpha(128);
225 palette.setColor(role, textColor);
226 label->setPalette(palette);
227 label->setForegroundRole(role);
228 label->setFont(smallFont);
229 label->setWordWrap(true);
230 label->setAlignment(Qt::AlignTop | Qt::AlignRight);
231
232 valueWidget->setForegroundRole(role);
233 valueWidget->setFont(smallFont);
234 valueWidget->setWordWrap(true);
235 valueWidget->setAlignment(Qt::AlignTop | Qt::AlignLeft);
236
237 // add the row to grid layout
238 const int rowIndex = m_rows.count() - 1;
239 m_gridLayout->addWidget(label, rowIndex, 0, Qt::AlignRight);
240 const int spacerWidth = QFontMetrics(smallFont).size(Qt::TextSingleLine, " ").width();
241 m_gridLayout->addItem(new QSpacerItem(spacerWidth, 1), rowIndex, 1);
242 m_gridLayout->addWidget(valueWidget, rowIndex, 2, Qt::AlignLeft);
243 }
244
245 void KMetaDataWidget::Private::setCustomValueWidget(int rowIndex, QWidget* valueWidget)
246 {
247 Row& row = m_rows[rowIndex];
248
249 if (valueWidget == 0) {
250 // remove current custom value widget from the grid and replace it
251 // by the default value widget
252 if (row.customValueWidget != 0) {
253 row.customValueWidget->setVisible(false);
254 m_gridLayout->removeWidget(row.customValueWidget);
255 }
256 m_gridLayout->addWidget(row.defaultValueWidget, rowIndex, 2, Qt::AlignLeft);
257 row.defaultValueWidget->setVisible(true);
258 } else {
259 // remove the default value widget from the grid and replace it
260 // by the custom value widget
261 row.defaultValueWidget->setVisible(false);
262 m_gridLayout->removeWidget(row.defaultValueWidget);
263 m_gridLayout->addWidget(valueWidget, rowIndex, 2, Qt::AlignLeft);
264 valueWidget->setVisible(true);
265 }
266
267 row.customValueWidget = valueWidget;
268 }
269
270 void KMetaDataWidget::Private::setRowVisible(QWidget* valueWidget, bool visible)
271 {
272 foreach (const Row& row, m_rows) {
273 const bool found = (row.defaultValueWidget == valueWidget) ||
274 (row.customValueWidget == valueWidget);
275 if (found) {
276 row.label->setVisible(visible);
277 if (row.customValueWidget != 0) {
278 row.customValueWidget->setVisible(visible);
279 row.defaultValueWidget->setVisible(false);
280 } else {
281 row.defaultValueWidget->setVisible(visible);
282 }
283 return;
284 }
285 }
286 }
287
288 void KMetaDataWidget::Private::initMetaInfoSettings()
289 {
290 const int currentVersion = 3; // increase version, if the blacklist of disabled
291 // properties should be updated
292
293 KConfig config("kmetainformationrc", KConfig::NoGlobals);
294 if (config.group("Misc").readEntry("version", 0) < currentVersion) {
295 // The resource file is read the first time. Assure
296 // that some meta information is disabled per default.
297
298 // clear old info
299 config.deleteGroup("Show");
300 KConfigGroup settings = config.group("Show");
301
302 static const char* const disabledProperties[] = {
303 "http://www.semanticdesktop.org/ontologies/2007/01/19/nie#comment",
304 "http://www.semanticdesktop.org/ontologies/2007/01/19/nie#contentSize",
305 "http://www.semanticdesktop.org/ontologies/2007/01/19/nie#depends",
306 "http://www.semanticdesktop.org/ontologies/2007/01/19/nie#isPartOf",
307 "http://www.semanticdesktop.org/ontologies/2007/01/19/nie#lastModified",
308 "http://www.semanticdesktop.org/ontologies/2007/01/19/nie#mimeType",
309 "http://www.semanticdesktop.org/ontologies/2007/01/19/nie#plainTextContent",
310 "http://www.semanticdesktop.org/ontologies/2007/01/19/nie#url",
311 "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#averageBitrate",
312 "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#channels",
313 "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#fileName",
314 "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#apertureValue",
315 "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#exposureBiasValue",
316 "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#exposureTime",
317 "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#flash",
318 "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#focalLength",
319 "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#focalLengthIn35mmFilm",
320 "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#isoSpeedRatings",
321 "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#make",
322 "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#meteringMode",
323 "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#model",
324 "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#orientation",
325 "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#whiteBalance",
326 "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#description",
327 "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#hasTag",
328 "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#lastModified",
329 "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#numericRating",
330 "http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
331 "kfileitem#owner",
332 "kfileitem#permissions",
333 0 // mandatory last entry
334 };
335
336 for (int i = 0; disabledProperties[i] != 0; ++i) {
337 settings.writeEntry(disabledProperties[i], false);
338 }
339
340 // mark the group as initialized
341 config.group("Misc").writeEntry("version", currentVersion);
342 }
343 }
344
345 void KMetaDataWidget::Private::updateRowsVisibility()
346 {
347 KConfig config("kmetainformationrc", KConfig::NoGlobals);
348 KConfigGroup settings = config.group("Show");
349
350 setRowVisible(m_typeInfo,
351 (m_visibleDataTypes & KMetaDataWidget::TypeData) &&
352 settings.readEntry("kfileitem#type", true));
353
354 // Cache in m_sizeVisible whether the size should be shown. This
355 // is necessary as the size is temporary hidden when the target
356 // file item is a directory.
357 m_sizeVisible = (m_visibleDataTypes & KMetaDataWidget::SizeData) &&
358 settings.readEntry("kfileitem#size", true);
359 bool visible = m_sizeVisible;
360 if (visible && (m_fileItems.count() == 1)) {
361 // don't show the size information, if one directory is shown
362 const KFileItem item = m_fileItems.first();
363 visible = !item.isNull() && !item.isDir();
364 }
365 setRowVisible(m_sizeInfo, visible);
366
367 setRowVisible(m_modifiedInfo,
368 (m_visibleDataTypes & KMetaDataWidget::ModifiedData) &&
369 settings.readEntry("kfileitem#modified", true));
370
371 setRowVisible(m_ownerInfo,
372 (m_visibleDataTypes & KMetaDataWidget::OwnerData) &&
373 settings.readEntry("kfileitem#owner", true));
374
375 setRowVisible(m_permissionsInfo,
376 (m_visibleDataTypes & KMetaDataWidget::PermissionsData) &&
377 settings.readEntry("kfileitem#permissions", true));
378
379 #ifdef HAVE_NEPOMUK
380 if (m_nepomukActivated) {
381 setRowVisible(m_ratingWidget,
382 (m_visibleDataTypes & KMetaDataWidget::RatingData) &&
383 settings.readEntry("kfileitem#rating", true));
384
385 setRowVisible(m_taggingWidget,
386 (m_visibleDataTypes & KMetaDataWidget::TagsData) &&
387 settings.readEntry("kfileitem#tags", true));
388
389 setRowVisible(m_commentWidget,
390 (m_visibleDataTypes & KMetaDataWidget::CommentData) &&
391 settings.readEntry("kfileitem#comment", true));
392 }
393 #endif
394 }
395
396 void KMetaDataWidget::Private::slotLoadingFinished()
397 {
398 #ifdef HAVE_NEPOMUK
399 // Show the remaining meta information as text. The number
400 // of required rows may very. Existing rows are reused to
401 // prevent flickering.
402 int rowIndex = m_fixedRowCount;
403
404 const QHash<KUrl, Nepomuk::Variant> data = m_model->data();
405 const QList<KUrl> keys = sortedKeys(data);
406
407 foreach (const KUrl& key, keys) {
408 const Nepomuk::Variant value = data[key];
409 const QString itemLabel = q->label(key);
410
411 const bool valueApplied = q->setValue(key, value);
412 if (rowIndex >= m_rows.count()) {
413 // a new row must get created
414 QLabel* label = new QLabel(itemLabel, q);
415 QLabel* valueWidget = new QLabel(q);
416 connect(valueWidget, SIGNAL(linkActivated(QString)),
417 q, SLOT(slotLinkActivated(QString)));
418 addRow(label, valueWidget);
419 }
420
421 Q_ASSERT(m_rows[rowIndex].label != 0);
422 Q_ASSERT(m_rows[rowIndex].defaultValueWidget != 0);
423
424 // set label
425 m_rows[rowIndex].label->setText(itemLabel);
426
427 // set value
428 if (valueApplied) {
429 setCustomValueWidget(rowIndex, q->valueWidget(key));
430 } else {
431 QLabel* valueWidget = m_rows[rowIndex].defaultValueWidget;
432 valueWidget->setText(value.toString());
433 setCustomValueWidget(rowIndex, 0);
434 }
435 ++rowIndex;
436 }
437
438 // remove rows that are not needed anymore
439 for (int i = m_rows.count() - 1; i >= rowIndex; --i) {
440 delete m_rows[i].label;
441 delete m_rows[i].defaultValueWidget;
442 m_rows.pop_back();
443 }
444 #endif
445
446 q->updateGeometry();
447 }
448
449 void KMetaDataWidget::Private::slotRatingChanged(unsigned int rating)
450 {
451 #ifdef HAVE_NEPOMUK
452 Nepomuk::MassUpdateJob* job =
453 Nepomuk::MassUpdateJob::rateResources(resourceList(), rating);
454 startChangeDataJob(job);
455 #else
456 Q_UNUSED(rating);
457 #endif
458 }
459
460 void KMetaDataWidget::Private::slotTagsChanged(const QList<Nepomuk::Tag>& tags)
461 {
462 #ifdef HAVE_NEPOMUK
463 m_taggingWidget->setTags(tags);
464
465 Nepomuk::MassUpdateJob* job =
466 Nepomuk::MassUpdateJob::tagResources(resourceList(), tags);
467 startChangeDataJob(job);
468 #else
469 Q_UNUSED(tags);
470 #endif
471 }
472
473 void KMetaDataWidget::Private::slotCommentChanged(const QString& comment)
474 {
475 #ifdef HAVE_NEPOMUK
476 Nepomuk::MassUpdateJob* job =
477 Nepomuk::MassUpdateJob::commentResources(resourceList(), comment);
478 startChangeDataJob(job);
479 #else
480 Q_UNUSED(comment);
481 #endif
482 }
483
484 void KMetaDataWidget::Private::slotTagActivated(const Nepomuk::Tag& tag)
485 {
486 #ifdef HAVE_NEPOMUK
487 emit q->urlActivated(tag.resourceUri());
488 #else
489 Q_UNUSED(tag);
490 #endif
491 }
492
493 void KMetaDataWidget::Private::slotMetaDataUpdateDone()
494 {
495 #ifdef HAVE_NEPOMUK
496 q->setEnabled(true);
497 #endif
498 }
499
500 void KMetaDataWidget::Private::slotLinkActivated(const QString& link)
501 {
502 emit q->urlActivated(KUrl(link));
503 }
504
505 #ifdef HAVE_NEPOMUK
506 void KMetaDataWidget::Private::startChangeDataJob(KJob* job)
507 {
508 connect(job, SIGNAL(result(KJob*)),
509 q, SLOT(slotMetaDataUpdateDone()));
510 q->setEnabled(false); // no updates during execution
511 job->start();
512 }
513
514 QList<KUrl> KMetaDataWidget::Private::sortedKeys(const QHash<KUrl, Nepomuk::Variant>& data) const
515 {
516 // Create a map, where the translated label prefixed with the
517 // sort priority acts as key. The data of each entry is the URI
518 // of the data. By this the all URIs are sorted by the sort priority
519 // and sub sorted by the translated labels.
520 QMap<QString, KUrl> map;
521 QHash<KUrl, Nepomuk::Variant>::const_iterator hashIt = data.constBegin();
522 while (hashIt != data.constEnd()) {
523 const KUrl uri = hashIt.key();
524
525 QString key = q->model()->group(uri);
526 key += q->label(uri);
527
528 map.insert(key, uri);
529 ++hashIt;
530 }
531
532 // Apply the URIs from the map to the list that will get returned.
533 // The list will then be alphabetically ordered by the translated labels of the URIs.
534 QList<KUrl> list;
535 QMap<QString, KUrl>::const_iterator mapIt = map.constBegin();
536 while (mapIt != map.constEnd()) {
537 list.append(mapIt.value());
538 ++mapIt;
539 }
540
541 return list;
542 }
543
544 QList<Nepomuk::Resource> KMetaDataWidget::Private::resourceList() const
545 {
546 QList<Nepomuk::Resource> list;
547 foreach (const KFileItem& item, m_fileItems) {
548 const KUrl url = item.url();
549 list.append(Nepomuk::Resource(url));
550 }
551 return list;
552 }
553 #endif
554
555 KMetaDataWidget::KMetaDataWidget(QWidget* parent) :
556 QWidget(parent),
557 d(new Private(this))
558 {
559 }
560
561 KMetaDataWidget::~KMetaDataWidget()
562 {
563 delete d;
564 }
565
566 void KMetaDataWidget::setItem(const KFileItem& item)
567 {
568 // update values for "type", "size", "modified",
569 // "owner" and "permissions" synchronously
570 d->m_sizeLabel->setText(i18nc("@label", "Size"));
571 if (item.isDir()) {
572 d->m_typeInfo->setText(i18nc("@label", "Folder"));
573 d->setRowVisible(d->m_sizeInfo, false);
574 } else {
575 d->m_typeInfo->setText(item.mimeComment());
576 d->m_sizeInfo->setText(KIO::convertSize(item.size()));
577 d->setRowVisible(d->m_sizeInfo, d->m_sizeVisible);
578 }
579 d->m_modifiedInfo->setText(KGlobal::locale()->formatDateTime(item.time(KFileItem::ModificationTime), KLocale::FancyLongDate));
580 d->m_ownerInfo->setText(item.user());
581 d->m_permissionsInfo->setText(item.permissionsString());
582
583 setItems(KFileItemList() << item);
584 }
585
586 void KMetaDataWidget::setItems(const KFileItemList& items)
587 {
588 d->m_fileItems = items;
589 if (d->m_model != 0) {
590 d->m_model->setItems(items);
591 }
592
593 if (items.count() > 1) {
594 // calculate the size of all items and show this
595 // information to the user
596 d->m_sizeLabel->setText(i18nc("@label", "Total Size:"));
597 d->setRowVisible(d->m_sizeInfo, d->m_sizeVisible);
598
599 quint64 totalSize = 0;
600 foreach (const KFileItem& item, items) {
601 if (!item.isDir() && !item.isLink()) {
602 totalSize += item.size();
603 }
604 }
605 d->m_sizeInfo->setText(KIO::convertSize(totalSize));
606 }
607 }
608
609 void KMetaDataWidget::setItem(const KUrl& url)
610 {
611 KFileItem item(KFileItem::Unknown, KFileItem::Unknown, url);
612 item.refresh();
613 setItem(item);
614 }
615
616 void KMetaDataWidget::setItems(const QList<KUrl>& urls)
617 {
618 KFileItemList items;
619 foreach (const KUrl& url, urls) {
620 KFileItem item(KFileItem::Unknown, KFileItem::Unknown, url);
621 item.refresh();
622 items.append(item);
623 }
624 setItems(items);
625 }
626
627 KFileItemList KMetaDataWidget::items() const
628 {
629 return d->m_fileItems;
630 }
631
632 void KMetaDataWidget::setModel(KMetaDataModel* model)
633 {
634 if (d->m_model != 0) {
635 disconnect(d->m_model, SIGNAL(loadingFinished()));
636 }
637 d->m_model = model;
638 connect(d->m_model, SIGNAL(loadingFinished()), this, SLOT(slotLoadingFinished()));
639 }
640
641 KMetaDataModel* KMetaDataWidget::model() const
642 {
643 return d->m_model;
644 }
645
646 void KMetaDataWidget::setReadOnly(bool readOnly)
647 {
648 d->m_readOnly = readOnly;
649 #ifdef HAVE_NEPOMUK
650 // TODO: encapsulate this code as part of a metadata-model for KDE 4.5
651 if (d->m_taggingWidget)
652 d->m_taggingWidget->setReadOnly(readOnly);
653 if (d->m_commentWidget)
654 d->m_commentWidget->setReadOnly(readOnly);
655 #endif
656 }
657
658 bool KMetaDataWidget::isReadOnly() const
659 {
660 return d->m_readOnly;
661 }
662
663 void KMetaDataWidget::setVisibleDataTypes(MetaDataTypes data)
664 {
665 d->m_visibleDataTypes = data;
666 d->updateRowsVisibility();
667 }
668
669 KMetaDataWidget::MetaDataTypes KMetaDataWidget::visibleDataTypes() const
670 {
671 return d->m_visibleDataTypes;
672 }
673
674 QSize KMetaDataWidget::sizeHint() const
675 {
676 const int fixedWidth = 200;
677
678 int height = d->m_gridLayout->margin() * 2 +
679 d->m_gridLayout->spacing() * (d->m_rows.count() - 1);
680
681 foreach (const Private::Row& row, d->m_rows) {
682 QWidget* valueWidget = row.defaultValueWidget;
683 if (valueWidget != 0) {
684 if (row.customValueWidget != 0) {
685 valueWidget = row.customValueWidget;
686 }
687
688 int rowHeight = valueWidget->heightForWidth(fixedWidth / 2);
689 if (rowHeight <= 0) {
690 rowHeight = valueWidget->sizeHint().height();
691 }
692 height += rowHeight;
693 }
694 }
695
696 return QSize(fixedWidth, height);
697 }
698
699 #ifdef HAVE_NEPOMUK
700 QString KMetaDataWidget::label(const KUrl& metaDataUri) const
701 {
702 QString label;
703 const QString uri = metaDataUri.url();
704 if (uri == QLatin1String("kfileitem#rating")) {
705 label = i18nc("@label", "Rating");
706 } else if (uri == QLatin1String("kfileitem#tags")) {
707 label = i18nc("@label", "Tags");
708 } else if (uri == QLatin1String("kfileitem#comment")) {
709 label = i18nc("@label", "Comment");
710 } else {
711 label = KNfoTranslator::instance().translation(metaDataUri);
712 }
713
714 return label;
715 }
716
717 QWidget* KMetaDataWidget::valueWidget(const KUrl& metaDataUri) const
718 {
719 QWidget* widget = 0;
720
721 if (d->m_nepomukActivated) {
722 const QString uri = metaDataUri.url();
723 if (uri == QLatin1String("kfileitem#rating")) {
724 widget = d->m_ratingWidget;
725 } else if (uri == QLatin1String("kfileitem#tags")) {
726 widget = d->m_taggingWidget;
727 } else if (uri == QLatin1String("kfileitem#comment")) {
728 widget = d->m_commentWidget;
729 }
730 }
731
732 return widget;
733 }
734
735 bool KMetaDataWidget::setValue(const KUrl& metaDataUri, const Nepomuk::Variant& value)
736 {
737 if (d->m_nepomukActivated) {
738 QWidget* widget = valueWidget(metaDataUri);
739 if (widget == d->m_ratingWidget) {
740 d->m_ratingWidget->setRating(value.toInt());
741 return true;
742 }
743
744 if (widget == d->m_taggingWidget) {
745 QList<Nepomuk::Variant> variants = value.toVariantList();
746 QList<Nepomuk::Tag> tags;
747 foreach (const Nepomuk::Variant& variant, variants) {
748 const Nepomuk::Resource resource = variant.toResource();
749 tags.append(static_cast<Nepomuk::Tag>(resource));
750 }
751 d->m_taggingWidget->setTags(tags);
752 return true;
753 }
754
755 if (widget == d->m_commentWidget) {
756 d->m_commentWidget->setText(value.toString());
757 return true;
758 }
759 }
760 return false;
761 }
762 #endif
763
764 bool KMetaDataWidget::event(QEvent* event)
765 {
766 if (event->type() == QEvent::Polish) {
767 // The adding of rows is not done in the constructor. This allows the
768 // client of KMetaDataWidget to set a proper foreground role which
769 // will be respected by the rows.
770
771 d->addRow(new QLabel(i18nc("@label file type", "Type"), this), d->m_typeInfo);
772 d->addRow(d->m_sizeLabel, d->m_sizeInfo);
773 d->addRow(new QLabel(i18nc("@label", "Modified"), this), d->m_modifiedInfo);
774 d->addRow(new QLabel(i18nc("@label", "Owner"), this), d->m_ownerInfo);
775 d->addRow(new QLabel(i18nc("@label", "Permissions"), this), d->m_permissionsInfo);
776
777 // The current number of rows represents meta data, that will be shown for
778 // all files. Dynamic meta data will be appended after those rows (see
779 // slotLoadingFinished()).
780 d->m_fixedRowCount = d->m_rows.count();
781
782 d->updateRowsVisibility();
783 }
784
785 return QWidget::event(event);
786 }
787
788 #include "kmetadatawidget.moc"