kdelibs/kio/kfile/kfilemetadatawidget.cpp

349 lines
12 KiB
C++
Raw Normal View History

2014-11-13 01:04:59 +02:00
/*****************************************************************************
* Copyright (C) 2008-2010 by Sebastian Trueg <trueg@kde.org> *
* Copyright (C) 2009-2010 by Peter Penz <peter.penz@gmx.at> *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public License *
* along with this library; see the file COPYING.LIB. If not, write to *
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *
* Boston, MA 02110-1301, USA. *
*****************************************************************************/
#include "kfilemetadatawidget.h"
#include <kconfig.h>
#include <kconfiggroup.h>
#include <kfileitem.h>
#include <klocale.h>
#include "kfilemetadataprovider_p.h"
2014-11-13 01:04:59 +02:00
#include <QGridLayout>
#include <QLabel>
#include <QList>
#include <QSet>
#include <QString>
#include <QTimer>
#include <QSpacerItem>
2014-11-13 01:04:59 +02:00
#include <config-kio.h>
class KFileMetaDataWidget::Private
{
public:
struct Row
{
QLabel* label;
QWidget* value;
};
Private(KFileMetaDataWidget* parent);
~Private();
/**
* Initializes the configuration file "kmetainformationrc"
* with proper default settings for the first start in
* an uninitialized environment.
*/
void initMetaInfoSettings();
/**
* Parses the configuration file "kmetainformationrc" and
* updates the visibility of all rows that got their data
* from KFileItem.
*/
void updateFileItemRowsVisibility();
void deleteRows();
void slotLoadingFinished();
void slotLinkActivated(const QString& link);
void slotDataChangeStarted();
void slotDataChangeFinished();
QList<KUrl> sortedKeys(const QHash<KUrl, QVariant>& data) const;
2014-11-13 01:04:59 +02:00
QList<Row> m_rows;
KFileMetaDataProvider* m_provider;
2014-11-13 01:04:59 +02:00
QGridLayout* m_gridLayout;
private:
KFileMetaDataWidget* const q;
};
KFileMetaDataWidget::Private::Private(KFileMetaDataWidget* parent) :
m_rows(),
m_provider(0),
2014-11-13 01:04:59 +02:00
m_gridLayout(0),
q(parent)
{
initMetaInfoSettings();
// TODO: If KFileMetaDataProvider might get a public class in future KDE releases,
// the following code should be moved into KFileMetaDataWidget::setModel():
m_provider = new KFileMetaDataProvider(q);
connect(m_provider, SIGNAL(loadingFinished()), q, SLOT(slotLoadingFinished()));
connect(m_provider, SIGNAL(urlActivated(KUrl)), q, SIGNAL(urlActivated(KUrl)));
2014-11-13 01:04:59 +02:00
}
KFileMetaDataWidget::Private::~Private()
{
}
void KFileMetaDataWidget::Private::initMetaInfoSettings()
{
2015-07-27 02:02:50 +03:00
const int currentVersion = 4; // increase version, if the blacklist of disabled
2014-11-13 01:04:59 +02:00
// properties should be updated
KConfig config("kmetainformationrc", KConfig::NoGlobals);
if (config.group("Misc").readEntry("version", 0) < currentVersion) {
// The resource file is read the first time. Assure
// that some meta information is enabled per default.
2014-11-13 01:04:59 +02:00
// clear old info
config.deleteGroup("Show");
KConfigGroup settings = config.group("Show");
2015-07-27 02:02:50 +03:00
static const char* enabledProperties[] = {
2014-11-13 01:04:59 +02:00
"http://www.semanticdesktop.org/ontologies/2007/01/19/nie#comment",
"http://www.semanticdesktop.org/ontologies/2007/01/19/nie#contentSize",
"http://www.semanticdesktop.org/ontologies/2007/01/19/nie#depends",
"http://www.semanticdesktop.org/ontologies/2007/01/19/nie#lastModified",
"http://www.semanticdesktop.org/ontologies/2007/01/19/nie#mimeType",
"http://www.semanticdesktop.org/ontologies/2007/01/19/nie#plainTextContent",
"http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#averageBitrate",
"http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#channels",
"http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#apertureValue",
"http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#exposureBiasValue",
"http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#exposureTime",
"http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#flash",
"http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#focalLength",
"http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#focalLengthIn35mmFilm",
"http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#isoSpeedRatings",
"http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#make",
"http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#meteringMode",
"http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#model",
"http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#orientation",
"http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#whiteBalance",
"http://www.semanticdesktop.org/ontologies/2007/08/15/nao#description",
"http://www.semanticdesktop.org/ontologies/2007/08/15/nao#hasTag",
"http://www.semanticdesktop.org/ontologies/2007/08/15/nao#lastModified",
"http://www.semanticdesktop.org/ontologies/2007/08/15/nao#numericRating",
"kfileitem#owner",
"kfileitem#permissions",
0 // mandatory last entry
};
2015-07-27 02:02:50 +03:00
static const char* disabledProperties[] = {
"http://www.semanticdesktop.org/ontologies/2007/01/19/nie#url",
"http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#fileName",
"http://www.semanticdesktop.org/ontologies/2007/01/19/nie#isPartOf",
"http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
0 // mandatory last entry
};
for (int i = 0; enabledProperties[i] != 0; ++i) {
settings.writeEntry(enabledProperties[i], true);
2014-11-13 01:04:59 +02:00
}
2015-07-27 02:02:50 +03:00
for (int i = 0; disabledProperties[i] != 0; ++i) {
settings.writeEntry(disabledProperties[i], false);
}
2014-11-13 01:04:59 +02:00
// mark the group as initialized
config.group("Misc").writeEntry("version", currentVersion);
}
}
void KFileMetaDataWidget::Private::deleteRows()
{
foreach (const Row& row, m_rows) {
delete row.label;
delete row.value;
}
m_rows.clear();
}
void KFileMetaDataWidget::Private::slotLoadingFinished()
{
deleteRows();
2014-11-13 01:04:59 +02:00
2015-05-04 11:02:47 +00:00
if (m_gridLayout == 0) {
m_gridLayout = new QGridLayout(q);
m_gridLayout->setMargin(0);
m_gridLayout->setSpacing(q->fontMetrics().height() / 4);
}
QHash<KUrl, QVariant> data = m_provider->data();
// Remove all items, that are marked as hidden in kmetainformationrc
KConfig config("kmetainformationrc", KConfig::NoGlobals);
KConfigGroup settings = config.group("Show");
QHash<KUrl, QVariant>::iterator it = data.begin();
while (it != data.end()) {
const QString uriString = it.key().url();
if (!settings.readEntry(uriString, true)) {
it = data.erase(it);
} else {
++it;
}
}
// Iterate through all remaining items embed the label
// and the value as new row in the widget
int rowIndex = 0;
const QList<KUrl> keys = sortedKeys(data);
foreach (const KUrl& key, keys) {
const QVariant value = data[key];
QString itemLabel = m_provider->label(key);
itemLabel.append(QLatin1Char(':'));
// Create label
QLabel* label = new QLabel(itemLabel, q);
label->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
label->setForegroundRole(q->foregroundRole());
label->setFont(q->font());
label->setWordWrap(true);
label->setAlignment(Qt::AlignTop | Qt::AlignRight);
// Create value-widget
QWidget* valueWidget = m_provider->createValueWidget(key, value, q);
// Add the label and value-widget to grid layout
m_gridLayout->addWidget(label, rowIndex, 0, Qt::AlignRight);
const int spacerWidth = QFontMetrics(q->font()).size(Qt::TextSingleLine, " ").width();
m_gridLayout->addItem(new QSpacerItem(spacerWidth, 1), rowIndex, 1);
m_gridLayout->addWidget(valueWidget, rowIndex, 2, Qt::AlignLeft);
// Remember the label and value-widget as row
Row row;
row.label = label;
row.value = valueWidget;
m_rows.append(row);
++rowIndex;
}
2014-11-13 01:04:59 +02:00
q->updateGeometry();
emit q->metaDataRequestFinished(m_provider->items());
2014-11-13 01:04:59 +02:00
}
void KFileMetaDataWidget::Private::slotLinkActivated(const QString& link)
{
const KUrl url(link);
if (url.isValid()) {
emit q->urlActivated(url);
}
}
void KFileMetaDataWidget::Private::slotDataChangeStarted()
{
q->setEnabled(false);
}
void KFileMetaDataWidget::Private::slotDataChangeFinished()
{
q->setEnabled(true);
}
QList<KUrl> KFileMetaDataWidget::Private::sortedKeys(const QHash<KUrl, QVariant>& data) const
{
// 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
// and sub sorted by the translated labels.
QMap<QString, KUrl> map;
QHash<KUrl, QVariant>::const_iterator hashIt = data.constBegin();
while (hashIt != data.constEnd()) {
const KUrl uri = hashIt.key();
QString key = m_provider->group(uri);
key += m_provider->label(uri);
map.insert(key, uri);
++hashIt;
}
// Apply the URIs from the map to the list that will get returned.
// The list will then be alphabetically ordered by the translated labels of the URIs.
QList<KUrl> list;
QMap<QString, KUrl>::const_iterator mapIt = map.constBegin();
while (mapIt != map.constEnd()) {
list.append(mapIt.value());
++mapIt;
}
return list;
}
2014-11-13 01:04:59 +02:00
KFileMetaDataWidget::KFileMetaDataWidget(QWidget* parent) :
QWidget(parent),
d(new Private(this))
{
}
KFileMetaDataWidget::~KFileMetaDataWidget()
{
delete d;
}
void KFileMetaDataWidget::setItems(const KFileItemList& items)
{
d->m_provider->setItems(items);
2014-11-13 01:04:59 +02:00
}
KFileItemList KFileMetaDataWidget::items() const
{
return d->m_provider->items();
2014-11-13 01:04:59 +02:00
}
QSize KFileMetaDataWidget::sizeHint() const
{
if (d->m_gridLayout == 0) {
return QWidget::sizeHint();
}
// Calculate the required width for the labels and values
int leftWidthMax = 0;
int rightWidthMax = 0;
foreach (const Private::Row& row, d->m_rows) {
const int rightWidth = row.value->sizeHint().width();
2014-11-13 01:04:59 +02:00
if (rightWidth > rightWidthMax) {
rightWidthMax = rightWidth;
}
const int leftWidth = row.label->sizeHint().width();
if (leftWidth > leftWidthMax) {
leftWidthMax = leftWidth;
}
}
// Based on the available width calculate the required height
int height = d->m_gridLayout->margin() * 2 + d->m_gridLayout->spacing() * (d->m_rows.count() - 1);
foreach (const Private::Row& row, d->m_rows) {
const int rowHeight = qMax(row.label->heightForWidth(leftWidthMax),
row.value->heightForWidth(rightWidthMax));
2014-11-13 01:04:59 +02:00
height += rowHeight;
}
const int width = d->m_gridLayout->margin() * 2 + leftWidthMax +
d->m_gridLayout->spacing() + rightWidthMax;
return QSize(width, height);
}
bool KFileMetaDataWidget::event(QEvent* event)
{
return QWidget::event(event);
}
#include "moc_kfilemetadatawidget.cpp"