From: Peter Penz Date: Sat, 13 Mar 2010 19:07:40 +0000 (+0000) Subject: Allow to provide custom widgets for meta data in a generic way. X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/commitdiff_plain/5f542389124512e01ec05a4c939d902a5dcbd5a7 Allow to provide custom widgets for meta data in a generic way. 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 --- diff --git a/src/panels/information/kmetadatawidget.cpp b/src/panels/information/kmetadatawidget.cpp index d44637432..5b15b6cef 100644 --- a/src/panels/information/kmetadatawidget.cpp +++ b/src/panels/information/kmetadatawidget.cpp @@ -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(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 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 variants = value.toVariantList(); - QList tags; - foreach (const Nepomuk::Variant& variant, variants) { - const Nepomuk::Resource resource = variant.toResource(); - tags.append(static_cast(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(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 KMetaDataWidget::Private::sortedKeys(const QHash& 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 KMetaDataWidget::Private::sortedKeys(const QHashmodel()->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 variants = value.toVariantList(); + QList tags; + foreach (const Nepomuk::Variant& variant, variants) { + const Nepomuk::Resource resource = variant.toResource(); + tags.append(static_cast(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()). diff --git a/src/panels/information/kmetadatawidget.h b/src/panels/information/kmetadatawidget.h index 6f5c66041..27b06a05d 100644 --- a/src/panels/information/kmetadatawidget.h +++ b/src/panels/information/kmetadatawidget.h @@ -25,6 +25,12 @@ #include #include +#include +#ifdef HAVE_NEPOMUK + #define DISABLE_NEPOMUK_LEGACY + #include +#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: