]> cloud.milkyroute.net Git - dolphin.git/commitdiff
Allow to provide custom widgets for meta data in a generic way.
authorPeter Penz <peter.penz19@gmail.com>
Sat, 13 Mar 2010 19:07:40 +0000 (19:07 +0000)
committerPeter Penz <peter.penz19@gmail.com>
Sat, 13 Mar 2010 19:07:40 +0000 (19:07 +0000)
By this it is possible that other applications like e. g. Gwenview provide custom widgets to change EXIF data directly within the meta data widget.

svn path=/trunk/KDE/kdebase/apps/; revision=1102834

src/panels/information/kmetadatawidget.cpp
src/panels/information/kmetadatawidget.h

index d44637432aeeead2bb746eae3d16b2926adf43f9..5b15b6cef1516b3cd12433091423b9f22aa8e20a 100644 (file)
@@ -65,15 +65,16 @@ public:
     struct Row
     {
         QLabel* label;
-        QWidget* infoWidget;
+        QLabel* defaultValueWidget;
+        QWidget* customValueWidget;
     };
 
     Private(KMetaDataWidget* parent);
     ~Private();
 
-    void addRow(QLabel* label, QWidget* infoWidget);
-    void removeMetaInfoRows();
-    void setRowVisible(QWidget* infoWidget, bool visible);
+    void addRow(QLabel* label, QLabel* valueWidget);
+    void setCustomValueWidget(int rowIndex, QWidget* valueWidget);
+    void setRowVisible(QWidget* valueWidget, bool visible);
 
     /**
      * Initializes the configuration file "kmetainformationrc"
@@ -207,11 +208,12 @@ KMetaDataWidget::Private::~Private()
 {
 }
 
-void KMetaDataWidget::Private::addRow(QLabel* label, QWidget* infoWidget)
+void KMetaDataWidget::Private::addRow(QLabel* label, QLabel* valueWidget)
 {
     Row row;
     row.label = label;
-    row.infoWidget = infoWidget;
+    row.defaultValueWidget = valueWidget;
+    row.customValueWidget = 0;
     m_rows.append(row);
 
     const QFont smallFont = KGlobalSettings::smallestReadableFont();
@@ -227,34 +229,62 @@ void KMetaDataWidget::Private::addRow(QLabel* label, QWidget* infoWidget)
     label->setWordWrap(true);
     label->setAlignment(Qt::AlignTop | Qt::AlignRight);
 
-    infoWidget->setForegroundRole(role);
-    QLabel* infoLabel = qobject_cast<QLabel*>(infoWidget);
-    if (infoLabel != 0) {
-        infoLabel->setFont(smallFont);
-        infoLabel->setWordWrap(true);
-        infoLabel->setAlignment(Qt::AlignTop | Qt::AlignLeft);
-    }
+    valueWidget->setForegroundRole(role);
+    valueWidget->setFont(smallFont);
+    valueWidget->setWordWrap(true);
+    valueWidget->setAlignment(Qt::AlignTop | Qt::AlignLeft);
 
     // add the row to grid layout
-    const int rowIndex = m_rows.count();
+    const int rowIndex = m_rows.count() - 1;
     m_gridLayout->addWidget(label, rowIndex, 0, Qt::AlignRight);
     const int spacerWidth = QFontMetrics(smallFont).size(Qt::TextSingleLine, " ").width();
     m_gridLayout->addItem(new QSpacerItem(spacerWidth, 1), rowIndex, 1);
-    m_gridLayout->addWidget(infoWidget, rowIndex, 2, Qt::AlignLeft);
+    m_gridLayout->addWidget(valueWidget, rowIndex, 2, Qt::AlignLeft);
+}
+
+void KMetaDataWidget::Private::setCustomValueWidget(int rowIndex, QWidget* valueWidget)
+{
+    Row& row = m_rows[rowIndex];
+
+    if (valueWidget == 0) {
+        // remove current custom value widget from the grid and replace it
+        // by the default value widget
+        if (row.customValueWidget != 0) {
+            row.customValueWidget->setVisible(false);
+            m_gridLayout->removeWidget(row.customValueWidget);
+        }
+        m_gridLayout->addWidget(row.defaultValueWidget, rowIndex, 2, Qt::AlignLeft);
+        row.defaultValueWidget->setVisible(true);
+    } else {
+        // remove the default value widget from the grid and replace it
+        // by the custom value widget
+        row.defaultValueWidget->setVisible(false);
+        m_gridLayout->removeWidget(row.defaultValueWidget);
+        m_gridLayout->addWidget(valueWidget, rowIndex, 2, Qt::AlignLeft);
+        valueWidget->setVisible(true);
+    }
+
+    row.customValueWidget = valueWidget;
 }
 
-void KMetaDataWidget::Private::setRowVisible(QWidget* infoWidget, bool visible)
+void KMetaDataWidget::Private::setRowVisible(QWidget* valueWidget, bool visible)
 {
     foreach (const Row& row, m_rows) {
-        if (row.infoWidget == infoWidget) {
+        const bool found = (row.defaultValueWidget == valueWidget) ||
+                           (row.customValueWidget == valueWidget);
+        if (found) {
             row.label->setVisible(visible);
-            row.infoWidget->setVisible(visible);
+            if (row.customValueWidget != 0) {
+                row.customValueWidget->setVisible(visible);
+                row.defaultValueWidget->setVisible(false);
+            } else {
+                row.defaultValueWidget->setVisible(visible);
+            }
             return;
         }
     }
 }
 
-
 void KMetaDataWidget::Private::initMetaInfoSettings()
 {
     const int currentVersion = 3; // increase version, if the blacklist of disabled
@@ -369,7 +399,6 @@ void KMetaDataWidget::Private::slotLoadingFinished()
     // Show the remaining meta information as text. The number
     // of required rows may very. Existing rows are reused to
     // prevent flickering.
-    const KNfoTranslator& nfo = KNfoTranslator::instance();
     int rowIndex = m_fixedRowCount;
 
     const QHash<KUrl, Nepomuk::Variant> data = m_model->data();
@@ -377,57 +406,39 @@ void KMetaDataWidget::Private::slotLoadingFinished()
 
     foreach (const KUrl& key, keys) {
         const Nepomuk::Variant value = data[key];
-        const QString itemLabel = nfo.translation(key);
-
-        bool appliedData = false;
-        if (m_nepomukActivated) {
-            const QString keyString = key.url();
-            if (keyString == QLatin1String("kfileitem#rating")) {
-                m_ratingWidget->setRating(value.toInt());
-                appliedData = true;
-            } else if (keyString == QLatin1String("kfileitem#comment")) {
-                m_commentWidget->setText(value.toString());
-                appliedData = true;
-            } else if (keyString == QLatin1String("kfileitem#tags")) {
-                QList<Nepomuk::Variant> variants = value.toVariantList();
-                QList<Nepomuk::Tag> tags;
-                foreach (const Nepomuk::Variant& variant, variants) {
-                    const Nepomuk::Resource resource = variant.toResource();
-                    tags.append(static_cast<Nepomuk::Tag>(resource));
-                }
-                m_taggingWidget->setTags(tags);
-                appliedData = true;
-            }
+        const QString itemLabel = q->label(key);
+
+        const bool valueApplied = q->setValue(key, value);
+        if (rowIndex >= m_rows.count()) {
+            // a new row must get created
+            QLabel* label = new QLabel(itemLabel, q);
+            QLabel* valueWidget = new QLabel(q);
+            connect(valueWidget, SIGNAL(linkActivated(QString)),
+                    q, SLOT(slotLinkActivated(QString)));
+            addRow(label, valueWidget);
         }
 
-        if (!appliedData) {
-            QString itemValue;
-            if (value.isString()) {
-                itemValue = value.toString();
-            }
+        Q_ASSERT(m_rows[rowIndex].label != 0);
+        Q_ASSERT(m_rows[rowIndex].defaultValueWidget != 0);
 
-            if (rowIndex < m_rows.count()) {
-                // adjust texts of the current row
-                m_rows[rowIndex].label->setText(itemLabel);
-                QLabel* infoValueLabel = qobject_cast<QLabel*>(m_rows[rowIndex].infoWidget);
-                Q_ASSERT(infoValueLabel != 0);
-                infoValueLabel->setText(itemValue);
-            } else {
-                // create new row
-                QLabel* infoLabel = new QLabel(itemLabel, q);
-                QLabel* infoValue = new QLabel(itemValue, q);
-                connect(infoValue, SIGNAL(linkActivated(QString)),
-                        q, SLOT(slotLinkActivated(QString)));
-                addRow(infoLabel, infoValue);
-            }
-            ++rowIndex;
+        // set label
+        m_rows[rowIndex].label->setText(itemLabel);
+
+        // set value
+        if (valueApplied) {
+            setCustomValueWidget(rowIndex, q->valueWidget(key));
+        } else {
+            QLabel* valueWidget = m_rows[rowIndex].defaultValueWidget;
+            valueWidget->setText(value.toString());
+            setCustomValueWidget(rowIndex, 0);
         }
+        ++rowIndex;
     }
 
     // remove rows that are not needed anymore
     for (int i = m_rows.count() - 1; i >= rowIndex; --i) {
         delete m_rows[i].label;
-        delete m_rows[i].infoWidget;
+        delete m_rows[i].defaultValueWidget;
         m_rows.pop_back();
     }
 #endif
@@ -502,8 +513,6 @@ void KMetaDataWidget::Private::startChangeDataJob(KJob* job)
 
 QList<KUrl> KMetaDataWidget::Private::sortedKeys(const QHash<KUrl, Nepomuk::Variant>& data) const
 {
-    const KNfoTranslator& nfo = KNfoTranslator::instance();
-
     // Create a map, where the translated label prefixed with the
     // sort priority acts as key. The data of each entry is the URI
     // of the data. By this the all URIs are sorted by the sort priority
@@ -514,7 +523,7 @@ QList<KUrl> KMetaDataWidget::Private::sortedKeys(const QHash<KUrl, Nepomuk::Vari
         const KUrl uri = hashIt.key();
 
         QString key = q->model()->group(uri);
-        key += nfo.translation(uri);
+        key += q->label(uri);
 
         map.insert(key, uri);
         ++hashIt;
@@ -670,10 +679,15 @@ QSize KMetaDataWidget::sizeHint() const
                  d->m_gridLayout->spacing() * (d->m_rows.count() - 1);
 
     foreach (const Private::Row& row, d->m_rows) {
-        if (row.infoWidget != 0) {
-            int rowHeight = row.infoWidget->heightForWidth(fixedWidth / 2);
+        QWidget* valueWidget = row.defaultValueWidget;
+        if (valueWidget != 0) {
+            if (row.customValueWidget != 0) {
+                valueWidget = row.customValueWidget;
+            }
+
+            int rowHeight = valueWidget->heightForWidth(fixedWidth / 2);
             if (rowHeight <= 0) {
-                rowHeight = row.infoWidget->sizeHint().height();
+                rowHeight = valueWidget->sizeHint().height();
             }
             height += rowHeight;
         }
@@ -682,6 +696,71 @@ QSize KMetaDataWidget::sizeHint() const
     return QSize(fixedWidth, height);
 }
 
+#ifdef HAVE_NEPOMUK
+QString KMetaDataWidget::label(const KUrl& metaDataUri) const
+{
+    QString label;
+    const QString uri = metaDataUri.url();
+    if (uri == QLatin1String("kfileitem#rating")) {
+        label = i18nc("@label", "Rating");
+    } else if (uri == QLatin1String("kfileitem#tags")) {
+        label = i18nc("@label", "Tags");
+    } else if (uri == QLatin1String("kfileitem#comment")) {
+        label = i18nc("@label", "Comment");
+    } else {
+        label = KNfoTranslator::instance().translation(metaDataUri);
+    }
+
+    return label;
+}
+
+QWidget* KMetaDataWidget::valueWidget(const KUrl& metaDataUri) const
+{
+    QWidget* widget = 0;
+
+    if (d->m_nepomukActivated) {
+        const QString uri = metaDataUri.url();
+        if (uri == QLatin1String("kfileitem#rating")) {
+            widget = d->m_ratingWidget;
+        } else if (uri == QLatin1String("kfileitem#tags")) {
+            widget = d->m_taggingWidget;
+        } else if (uri == QLatin1String("kfileitem#comment")) {
+            widget = d->m_commentWidget;
+        }
+    }
+
+    return widget;
+}
+
+bool KMetaDataWidget::setValue(const KUrl& metaDataUri, const Nepomuk::Variant& value)
+{
+    if (d->m_nepomukActivated) {
+        QWidget* widget = valueWidget(metaDataUri);
+        if (widget == d->m_ratingWidget) {
+            d->m_ratingWidget->setRating(value.toInt());
+            return true;
+        }
+
+        if (widget == d->m_taggingWidget) {
+            QList<Nepomuk::Variant> variants = value.toVariantList();
+            QList<Nepomuk::Tag> tags;
+            foreach (const Nepomuk::Variant& variant, variants) {
+                const Nepomuk::Resource resource = variant.toResource();
+                tags.append(static_cast<Nepomuk::Tag>(resource));
+            }
+            d->m_taggingWidget->setTags(tags);
+            return true;
+        }
+
+        if (widget == d->m_commentWidget) {
+            d->m_commentWidget->setText(value.toString());
+            return true;
+        }
+    }
+    return false;
+}
+#endif
+
 bool KMetaDataWidget::event(QEvent* event)
 {
     if (event->type() == QEvent::Polish) {
@@ -695,14 +774,6 @@ bool KMetaDataWidget::event(QEvent* event)
         d->addRow(new QLabel(i18nc("@label", "Owner"), this), d->m_ownerInfo);
         d->addRow(new QLabel(i18nc("@label", "Permissions"), this), d->m_permissionsInfo);
 
-    #ifdef HAVE_NEPOMUK
-        if (d->m_nepomukActivated) {
-            d->addRow(new QLabel(i18nc("@label", "Rating"), this), d->m_ratingWidget);
-            d->addRow(new QLabel(i18nc("@label", "Tags"), this), d->m_taggingWidget);
-            d->addRow(new QLabel(i18nc("@label", "Comment"), this), d->m_commentWidget);
-        }
-    #endif
-
         // The current number of rows represents meta data, that will be shown for
         // all files. Dynamic meta data will be appended after those rows (see
         // slotLoadingFinished()).
index 6f5c66041f4aa0232f397bac4880f295f674393b..27b06a05dc5715f8e1a743227ea5bbf880a15870 100644 (file)
 #include <QList>
 #include <QWidget>
 
+#include <config-nepomuk.h>
+#ifdef HAVE_NEPOMUK
+    #define DISABLE_NEPOMUK_LEGACY
+    #include <nepomuk/variant.h>
+#endif
+
 class KMetaDataModel;
 class KUrl;
 
@@ -41,6 +47,16 @@ class KUrl;
  * To show more than basic meta data, the meta data widget
  * must be provided with a meta data model
  * (see KMetaDataWidget::setModel()).
+ *
+ * Per default most meta data values are shown as labels.
+ * However it is possible to adjust KMetaDataWidget to use
+ * custom widgets for showing and modifying meta data (e. g.
+ * like done already for the rating, tags or comments). The
+ * following steps are necessary:
+ * - Derive a custom widget from KMetaDataWidget.
+ * - Create the custom widgets in the constructor.
+ * - Implement the methods valueWidget(), setValue() and
+ *   (optionally) label() by accessing the custom widgets.
  */
 class KMetaDataWidget : public QWidget
 {
@@ -138,6 +154,33 @@ Q_SIGNALS:
     void urlActivated(const KUrl& url);
 
 protected:
+#ifdef HAVE_NEPOMUK
+    /**
+     * @return Translated string for the label of the meta data represented
+     *         by \p metaDataUri. If no custom translation is provided, the
+     *         base implementation must be invoked.
+     */
+    virtual QString label(const KUrl& metaDataUri) const;
+
+    /**
+     * @return Pointer to the custom value-widget that should be used
+     *         to show the meta data represented by \p metaDataUri. If 0
+     *         is returned, the meta data will be shown inside a label
+     *         as fallback. If no custom value widget is used for the
+     *         given URI, the base implementation must be invoked.
+     */
+    virtual QWidget* valueWidget(const KUrl& metaDataUri) const;
+
+    /**
+     * Sets the value of a custom value-widget to \p value. If the meta data
+     * represented by \p metaDataUri is not shown by a custom value-widget (see
+     * KMetaDataWidget::valueWidget()), then the base implementation must be
+     * invoked.
+     * @return True, if a custom value-widget is available, where the value got applied.
+     */
+    virtual bool setValue(const KUrl& metaDataUri, const Nepomuk::Variant& value);
+#endif
+
     virtual bool event(QEvent* event);
 
 private: