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>
|
2015-05-03 16:49:26 +00:00
|
|
|
#include "kfilemetadataprovider_p.h"
|
2014-11-13 01:04:59 +02:00
|
|
|
|
|
|
|
#include <QGridLayout>
|
|
|
|
#include <QLabel>
|
|
|
|
#include <QList>
|
|
|
|
#include <QSet>
|
|
|
|
#include <QString>
|
|
|
|
#include <QTimer>
|
2015-05-03 16:49:26 +00:00
|
|
|
#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();
|
|
|
|
|
2015-05-03 16:49:26 +00:00
|
|
|
QList<KUrl> sortedKeys(const QHash<KUrl, QVariant>& data) const;
|
2014-11-13 01:04:59 +02:00
|
|
|
|
|
|
|
QList<Row> m_rows;
|
2015-05-03 16:49:26 +00:00
|
|
|
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(),
|
2015-05-03 16:49:26 +00:00
|
|
|
m_provider(0),
|
2014-11-13 01:04:59 +02:00
|
|
|
m_gridLayout(0),
|
|
|
|
q(parent)
|
|
|
|
{
|
|
|
|
initMetaInfoSettings();
|
|
|
|
|
2015-05-03 16:49:26 +00:00
|
|
|
// 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()
|
|
|
|
{
|
|
|
|
const int currentVersion = 3; // increase version, if the blacklist of disabled
|
|
|
|
// 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 disabled per default.
|
|
|
|
|
|
|
|
// clear old info
|
|
|
|
config.deleteGroup("Show");
|
|
|
|
KConfigGroup settings = config.group("Show");
|
|
|
|
|
|
|
|
static const char* const disabledProperties[] = {
|
|
|
|
"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#isPartOf",
|
|
|
|
"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/01/19/nie#url",
|
|
|
|
"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/03/22/nfo#fileName",
|
|
|
|
"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",
|
|
|
|
"http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
|
|
|
|
"kfileitem#owner",
|
|
|
|
"kfileitem#permissions",
|
|
|
|
0 // mandatory last entry
|
|
|
|
};
|
|
|
|
|
|
|
|
for (int i = 0; disabledProperties[i] != 0; ++i) {
|
|
|
|
settings.writeEntry(disabledProperties[i], false);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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()
|
|
|
|
{
|
2015-05-03 16:49:26 +00:00
|
|
|
deleteRows();
|
2014-11-13 01:04:59 +02:00
|
|
|
|
|
|
|
q->updateGeometry();
|
2015-05-03 16:49:26 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2015-05-03 16:49:26 +00:00
|
|
|
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)
|
|
|
|
{
|
2015-05-03 16:49:26 +00:00
|
|
|
d->m_provider->setItems(items);
|
2014-11-13 01:04:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
KFileItemList KFileMetaDataWidget::items() const
|
|
|
|
{
|
2015-05-03 16:49:26 +00:00
|
|
|
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;
|
|
|
|
int rightWidthAverage = 0;
|
|
|
|
foreach (const Private::Row& row, d->m_rows) {
|
|
|
|
const QWidget* valueWidget = row.value;
|
|
|
|
const int rightWidth = valueWidget->sizeHint().width();
|
|
|
|
rightWidthAverage += rightWidth;
|
|
|
|
if (rightWidth > rightWidthMax) {
|
|
|
|
rightWidthMax = rightWidth;
|
|
|
|
}
|
|
|
|
|
|
|
|
const int leftWidth = row.label->sizeHint().width();
|
|
|
|
if (leftWidth > leftWidthMax) {
|
|
|
|
leftWidthMax = leftWidth;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Some value widgets might return a very huge width for the size hint.
|
|
|
|
// Limit the maximum width to the double width of the overall average
|
|
|
|
// to assure a less messed layout.
|
|
|
|
if (d->m_rows.count() > 1) {
|
|
|
|
rightWidthAverage /= d->m_rows.count();
|
|
|
|
if (rightWidthMax > rightWidthAverage * 2) {
|
|
|
|
rightWidthMax = rightWidthAverage * 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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 QWidget* valueWidget = row.value;
|
|
|
|
const int rowHeight = qMax(row.label->heightForWidth(leftWidthMax),
|
|
|
|
valueWidget->heightForWidth(rightWidthMax));
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2015-02-27 07:40:26 +00:00
|
|
|
#include "moc_kfilemetadatawidget.cpp"
|