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