mirror of
https://invent.kde.org/system/dolphin
synced 2024-11-05 18:47:12 +00:00
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
This commit is contained in:
parent
6b9c4f7b45
commit
5f54238912
2 changed files with 189 additions and 75 deletions
|
@ -65,15 +65,16 @@ public:
|
||||||
struct Row
|
struct Row
|
||||||
{
|
{
|
||||||
QLabel* label;
|
QLabel* label;
|
||||||
QWidget* infoWidget;
|
QLabel* defaultValueWidget;
|
||||||
|
QWidget* customValueWidget;
|
||||||
};
|
};
|
||||||
|
|
||||||
Private(KMetaDataWidget* parent);
|
Private(KMetaDataWidget* parent);
|
||||||
~Private();
|
~Private();
|
||||||
|
|
||||||
void addRow(QLabel* label, QWidget* infoWidget);
|
void addRow(QLabel* label, QLabel* valueWidget);
|
||||||
void removeMetaInfoRows();
|
void setCustomValueWidget(int rowIndex, QWidget* valueWidget);
|
||||||
void setRowVisible(QWidget* infoWidget, bool visible);
|
void setRowVisible(QWidget* valueWidget, bool visible);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the configuration file "kmetainformationrc"
|
* 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 row;
|
||||||
row.label = label;
|
row.label = label;
|
||||||
row.infoWidget = infoWidget;
|
row.defaultValueWidget = valueWidget;
|
||||||
|
row.customValueWidget = 0;
|
||||||
m_rows.append(row);
|
m_rows.append(row);
|
||||||
|
|
||||||
const QFont smallFont = KGlobalSettings::smallestReadableFont();
|
const QFont smallFont = KGlobalSettings::smallestReadableFont();
|
||||||
|
@ -227,34 +229,62 @@ void KMetaDataWidget::Private::addRow(QLabel* label, QWidget* infoWidget)
|
||||||
label->setWordWrap(true);
|
label->setWordWrap(true);
|
||||||
label->setAlignment(Qt::AlignTop | Qt::AlignRight);
|
label->setAlignment(Qt::AlignTop | Qt::AlignRight);
|
||||||
|
|
||||||
infoWidget->setForegroundRole(role);
|
valueWidget->setForegroundRole(role);
|
||||||
QLabel* infoLabel = qobject_cast<QLabel*>(infoWidget);
|
valueWidget->setFont(smallFont);
|
||||||
if (infoLabel != 0) {
|
valueWidget->setWordWrap(true);
|
||||||
infoLabel->setFont(smallFont);
|
valueWidget->setAlignment(Qt::AlignTop | Qt::AlignLeft);
|
||||||
infoLabel->setWordWrap(true);
|
|
||||||
infoLabel->setAlignment(Qt::AlignTop | Qt::AlignLeft);
|
|
||||||
}
|
|
||||||
|
|
||||||
// add the row to grid layout
|
// 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);
|
m_gridLayout->addWidget(label, rowIndex, 0, Qt::AlignRight);
|
||||||
const int spacerWidth = QFontMetrics(smallFont).size(Qt::TextSingleLine, " ").width();
|
const int spacerWidth = QFontMetrics(smallFont).size(Qt::TextSingleLine, " ").width();
|
||||||
m_gridLayout->addItem(new QSpacerItem(spacerWidth, 1), rowIndex, 1);
|
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::setRowVisible(QWidget* infoWidget, bool visible)
|
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* valueWidget, bool visible)
|
||||||
{
|
{
|
||||||
foreach (const Row& row, m_rows) {
|
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.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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void KMetaDataWidget::Private::initMetaInfoSettings()
|
void KMetaDataWidget::Private::initMetaInfoSettings()
|
||||||
{
|
{
|
||||||
const int currentVersion = 3; // increase version, if the blacklist of disabled
|
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
|
// Show the remaining meta information as text. The number
|
||||||
// of required rows may very. Existing rows are reused to
|
// of required rows may very. Existing rows are reused to
|
||||||
// prevent flickering.
|
// prevent flickering.
|
||||||
const KNfoTranslator& nfo = KNfoTranslator::instance();
|
|
||||||
int rowIndex = m_fixedRowCount;
|
int rowIndex = m_fixedRowCount;
|
||||||
|
|
||||||
const QHash<KUrl, Nepomuk::Variant> data = m_model->data();
|
const QHash<KUrl, Nepomuk::Variant> data = m_model->data();
|
||||||
|
@ -377,57 +406,39 @@ void KMetaDataWidget::Private::slotLoadingFinished()
|
||||||
|
|
||||||
foreach (const KUrl& key, keys) {
|
foreach (const KUrl& key, keys) {
|
||||||
const Nepomuk::Variant value = data[key];
|
const Nepomuk::Variant value = data[key];
|
||||||
const QString itemLabel = nfo.translation(key);
|
const QString itemLabel = q->label(key);
|
||||||
|
|
||||||
bool appliedData = false;
|
const bool valueApplied = q->setValue(key, value);
|
||||||
if (m_nepomukActivated) {
|
if (rowIndex >= m_rows.count()) {
|
||||||
const QString keyString = key.url();
|
// a new row must get created
|
||||||
if (keyString == QLatin1String("kfileitem#rating")) {
|
QLabel* label = new QLabel(itemLabel, q);
|
||||||
m_ratingWidget->setRating(value.toInt());
|
QLabel* valueWidget = new QLabel(q);
|
||||||
appliedData = true;
|
connect(valueWidget, SIGNAL(linkActivated(QString)),
|
||||||
} else if (keyString == QLatin1String("kfileitem#comment")) {
|
q, SLOT(slotLinkActivated(QString)));
|
||||||
m_commentWidget->setText(value.toString());
|
addRow(label, valueWidget);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!appliedData) {
|
Q_ASSERT(m_rows[rowIndex].label != 0);
|
||||||
QString itemValue;
|
Q_ASSERT(m_rows[rowIndex].defaultValueWidget != 0);
|
||||||
if (value.isString()) {
|
|
||||||
itemValue = value.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rowIndex < m_rows.count()) {
|
// set label
|
||||||
// adjust texts of the current row
|
m_rows[rowIndex].label->setText(itemLabel);
|
||||||
m_rows[rowIndex].label->setText(itemLabel);
|
|
||||||
QLabel* infoValueLabel = qobject_cast<QLabel*>(m_rows[rowIndex].infoWidget);
|
// set value
|
||||||
Q_ASSERT(infoValueLabel != 0);
|
if (valueApplied) {
|
||||||
infoValueLabel->setText(itemValue);
|
setCustomValueWidget(rowIndex, q->valueWidget(key));
|
||||||
} else {
|
} else {
|
||||||
// create new row
|
QLabel* valueWidget = m_rows[rowIndex].defaultValueWidget;
|
||||||
QLabel* infoLabel = new QLabel(itemLabel, q);
|
valueWidget->setText(value.toString());
|
||||||
QLabel* infoValue = new QLabel(itemValue, q);
|
setCustomValueWidget(rowIndex, 0);
|
||||||
connect(infoValue, SIGNAL(linkActivated(QString)),
|
|
||||||
q, SLOT(slotLinkActivated(QString)));
|
|
||||||
addRow(infoLabel, infoValue);
|
|
||||||
}
|
|
||||||
++rowIndex;
|
|
||||||
}
|
}
|
||||||
|
++rowIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove rows that are not needed anymore
|
// remove rows that are not needed anymore
|
||||||
for (int i = m_rows.count() - 1; i >= rowIndex; --i) {
|
for (int i = m_rows.count() - 1; i >= rowIndex; --i) {
|
||||||
delete m_rows[i].label;
|
delete m_rows[i].label;
|
||||||
delete m_rows[i].infoWidget;
|
delete m_rows[i].defaultValueWidget;
|
||||||
m_rows.pop_back();
|
m_rows.pop_back();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -502,8 +513,6 @@ void KMetaDataWidget::Private::startChangeDataJob(KJob* job)
|
||||||
|
|
||||||
QList<KUrl> KMetaDataWidget::Private::sortedKeys(const QHash<KUrl, Nepomuk::Variant>& data) const
|
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
|
// Create a map, where the translated label prefixed with the
|
||||||
// sort priority acts as key. The data of each entry is the URI
|
// 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
|
// 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();
|
const KUrl uri = hashIt.key();
|
||||||
|
|
||||||
QString key = q->model()->group(uri);
|
QString key = q->model()->group(uri);
|
||||||
key += nfo.translation(uri);
|
key += q->label(uri);
|
||||||
|
|
||||||
map.insert(key, uri);
|
map.insert(key, uri);
|
||||||
++hashIt;
|
++hashIt;
|
||||||
|
@ -670,10 +679,15 @@ QSize KMetaDataWidget::sizeHint() const
|
||||||
d->m_gridLayout->spacing() * (d->m_rows.count() - 1);
|
d->m_gridLayout->spacing() * (d->m_rows.count() - 1);
|
||||||
|
|
||||||
foreach (const Private::Row& row, d->m_rows) {
|
foreach (const Private::Row& row, d->m_rows) {
|
||||||
if (row.infoWidget != 0) {
|
QWidget* valueWidget = row.defaultValueWidget;
|
||||||
int rowHeight = row.infoWidget->heightForWidth(fixedWidth / 2);
|
if (valueWidget != 0) {
|
||||||
|
if (row.customValueWidget != 0) {
|
||||||
|
valueWidget = row.customValueWidget;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rowHeight = valueWidget->heightForWidth(fixedWidth / 2);
|
||||||
if (rowHeight <= 0) {
|
if (rowHeight <= 0) {
|
||||||
rowHeight = row.infoWidget->sizeHint().height();
|
rowHeight = valueWidget->sizeHint().height();
|
||||||
}
|
}
|
||||||
height += rowHeight;
|
height += rowHeight;
|
||||||
}
|
}
|
||||||
|
@ -682,6 +696,71 @@ QSize KMetaDataWidget::sizeHint() const
|
||||||
return QSize(fixedWidth, height);
|
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)
|
bool KMetaDataWidget::event(QEvent* event)
|
||||||
{
|
{
|
||||||
if (event->type() == QEvent::Polish) {
|
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", "Owner"), this), d->m_ownerInfo);
|
||||||
d->addRow(new QLabel(i18nc("@label", "Permissions"), this), d->m_permissionsInfo);
|
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
|
// 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
|
// all files. Dynamic meta data will be appended after those rows (see
|
||||||
// slotLoadingFinished()).
|
// slotLoadingFinished()).
|
||||||
|
|
|
@ -25,6 +25,12 @@
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
|
#include <config-nepomuk.h>
|
||||||
|
#ifdef HAVE_NEPOMUK
|
||||||
|
#define DISABLE_NEPOMUK_LEGACY
|
||||||
|
#include <nepomuk/variant.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
class KMetaDataModel;
|
class KMetaDataModel;
|
||||||
class KUrl;
|
class KUrl;
|
||||||
|
|
||||||
|
@ -41,6 +47,16 @@ class KUrl;
|
||||||
* To show more than basic meta data, the meta data widget
|
* To show more than basic meta data, the meta data widget
|
||||||
* must be provided with a meta data model
|
* must be provided with a meta data model
|
||||||
* (see KMetaDataWidget::setModel()).
|
* (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
|
class KMetaDataWidget : public QWidget
|
||||||
{
|
{
|
||||||
|
@ -138,6 +154,33 @@ Q_SIGNALS:
|
||||||
void urlActivated(const KUrl& url);
|
void urlActivated(const KUrl& url);
|
||||||
|
|
||||||
protected:
|
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);
|
virtual bool event(QEvent* event);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
Loading…
Reference in a new issue