]>
cloud.milkyroute.net Git - dolphin.git/blob - src/panels/information/metadatawidget.cpp
1 /***************************************************************************
2 * Copyright (C) 2008 by Sebastian Trueg <trueg@kde.org> *
3 * Copyright (C) 2009 by Peter Penz <peter.penz@gmx.at> *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
19 ***************************************************************************/
21 #include "metadatawidget.h"
23 #include <kfileitem.h>
24 #include <kglobalsettings.h>
27 #include <QFontMetrics>
28 #include <QGridLayout>
33 #include <config-nepomuk.h>
35 #define DISABLE_NEPOMUK_LEGACY
37 #include "commentwidget_p.h"
38 #include "nepomukmassupdatejob_p.h"
39 #include "taggingwidget_p.h"
42 #include <kconfiggroup.h>
44 #include <Nepomuk/KRatingWidget>
45 #include <Nepomuk/Resource>
46 #include <Nepomuk/Tag>
47 #include <Nepomuk/Types/Property>
48 #include <Nepomuk/Variant>
50 #include <Soprano/Vocabulary/Xesam>
52 #include <QSpacerItem>
56 class MetaDataWidget::Private
65 Private(MetaDataWidget
* parent
);
68 void addRow(QLabel
* label
, QWidget
* infoWidget
);
69 void removeMetaInfoRows();
70 void setRowVisible(QWidget
* infoWidget
, bool visible
);
72 void slotLoadingFinished();
76 QGridLayout
* m_gridLayout
;
81 QLabel
* m_modifiedInfo
;
83 QLabel
* m_permissionsInfo
;
86 KRatingWidget
* m_ratingWidget
;
87 TaggingWidget
* m_taggingWidget
;
88 CommentWidget
* m_commentWidget
;
90 // shared data between the GUI-thread and
91 // the loader-thread (see LoadFilesThread):
97 QList
<Nepomuk::Tag
> tags
;
98 QList
<QString
> metaInfoLabels
;
99 QList
<QString
> metaInfoValues
;
103 * Loads the meta data of files and writes
104 * the result into a shared data pool that
105 * can be used by the widgets in the GUI thread.
107 class LoadFilesThread
: public QThread
110 LoadFilesThread(SharedData
* m_sharedData
, QMutex
* m_mutex
);
111 virtual ~LoadFilesThread();
112 void loadFiles(const KUrl::List
& urls
);
117 * Assures that the settings for the meta information
118 * are initialized with proper default values.
120 void initMetaInfoSettings(KConfigGroup
& group
);
123 * Temporary helper method for KDE 4.3 as we currently don't get
124 * translated labels for Nepmok literals: Replaces camelcase labels
125 * like "fileLocation" by "File Location:".
127 QString
tunedLabel(const QString
& label
) const;
130 SharedData
* m_m_sharedData
;
136 LoadFilesThread
* m_loadFilesThread
;
140 MetaDataWidget
* const q
;
143 MetaDataWidget::Private::Private(MetaDataWidget
* parent
) :
151 m_permissionsInfo(0),
156 m_loadFilesThread(0),
160 m_gridLayout
= new QGridLayout(parent
);
161 m_gridLayout
->setMargin(0);
163 m_typeInfo
= new QLabel(parent
);
164 m_sizeLabel
= new QLabel(parent
);
165 m_sizeInfo
= new QLabel(parent
);
166 m_modifiedInfo
= new QLabel(parent
);
167 m_ownerInfo
= new QLabel(parent
);
168 m_permissionsInfo
= new QLabel(parent
);
170 const QFontMetrics
fontMetrics(KGlobalSettings::smallestReadableFont());
171 m_ratingWidget
= new KRatingWidget(parent
);
172 m_ratingWidget
->setFixedHeight(fontMetrics
.height());
174 m_taggingWidget
= new TaggingWidget(parent
);
176 m_commentWidget
= new CommentWidget(parent
);
179 addRow(new QLabel(i18nc("@label", "Type:"), parent
), m_typeInfo
);
180 addRow(m_sizeLabel
, m_sizeInfo
);
181 addRow(new QLabel(i18nc("@label", "Modified:"), parent
), m_modifiedInfo
);
182 addRow(new QLabel(i18nc("@label", "Owner:"), parent
), m_ownerInfo
);
183 addRow(new QLabel(i18nc("@label", "Permissions:"), parent
), m_permissionsInfo
);
185 addRow(new QLabel(i18nc("@label", "Rating:"), parent
), m_ratingWidget
);
186 addRow(new QLabel(i18nc("@label", "Tags:"), parent
), m_taggingWidget
);
187 addRow(new QLabel(i18nc("@label", "Comment:"), parent
), m_commentWidget
);
189 m_sharedData
.rating
= 0;
190 m_loadFilesThread
= new LoadFilesThread(&m_sharedData
, &m_mutex
);
191 connect(m_loadFilesThread
, SIGNAL(finished()), q
, SLOT(slotLoadingFinished()));
195 MetaDataWidget::Private::~Private()
198 delete m_loadFilesThread
;
202 void MetaDataWidget::Private::addRow(QLabel
* label
, QWidget
* infoWidget
)
206 row
.infoWidget
= infoWidget
;
209 const QFont smallFont
= KGlobalSettings::smallestReadableFont();
210 // use a brighter color for the label and a small font size
211 QPalette palette
= label
->palette();
212 QColor textColor
= palette
.color(QPalette::Text
);
213 textColor
.setAlpha(128);
214 palette
.setColor(QPalette::WindowText
, textColor
);
215 label
->setPalette(palette
);
216 label
->setFont(smallFont
);
217 label
->setWordWrap(true);
218 label
->setAlignment(Qt::AlignTop
| Qt::AlignRight
);
220 QLabel
* infoLabel
= qobject_cast
<QLabel
*>(infoWidget
);
221 if (infoLabel
!= 0) {
222 infoLabel
->setFont(smallFont
);
223 infoLabel
->setWordWrap(true);
224 infoLabel
->setAlignment(Qt::AlignTop
| Qt::AlignLeft
);
227 // add the row to grid layout
228 const int rowIndex
= m_rows
.count();
229 m_gridLayout
->addWidget(label
, rowIndex
, 0, Qt::AlignRight
);
230 const int spacerWidth
= QFontMetrics(smallFont
).size(Qt::TextSingleLine
, " ").width();
231 m_gridLayout
->addItem(new QSpacerItem(spacerWidth
, 1), rowIndex
, 1);
232 m_gridLayout
->addWidget(infoWidget
, rowIndex
, 2, Qt::AlignLeft
);
235 void MetaDataWidget::Private::setRowVisible(QWidget
* infoWidget
, bool visible
)
237 foreach (const Row
& row
, m_rows
) {
238 if (row
.infoWidget
== infoWidget
) {
239 row
.label
->setVisible(visible
);
240 row
.infoWidget
->setVisible(visible
);
246 void MetaDataWidget::Private::slotLoadingFinished()
249 QMutexLocker
locker(&m_mutex
);
250 m_ratingWidget
->setRating(m_sharedData
.rating
);
251 m_commentWidget
->setText(m_sharedData
.comment
);
252 m_taggingWidget
->setTags(m_sharedData
.tags
);
254 // Show the remaining meta information as text. The number
255 // of required rows may very. Existing rows are reused to
256 // prevent flickering.
257 int index
= 8; // TODO: don't hardcode this value here
258 const int rowCount
= m_rows
.count();
259 Q_ASSERT(rowCount
>= index
);
261 Q_ASSERT(m_sharedData
.metaInfoLabels
.count() == m_sharedData
.metaInfoValues
.count());
262 const int metaInfoCount
= m_sharedData
.metaInfoLabels
.count();
263 for (int i
= 0; i
< metaInfoCount
; ++i
) {
264 if (index
< rowCount
) {
265 // adjust texts of the current row
266 m_rows
[index
].label
->setText(m_sharedData
.metaInfoLabels
[i
]);
267 QLabel
* infoValueLabel
= qobject_cast
<QLabel
*>(m_rows
[index
].infoWidget
);
268 Q_ASSERT(infoValueLabel
!= 0);
269 infoValueLabel
->setText(m_sharedData
.metaInfoValues
[i
]);
272 QLabel
* infoLabel
= new QLabel(m_sharedData
.metaInfoLabels
[i
], q
);
273 QLabel
* infoValue
= new QLabel(m_sharedData
.metaInfoValues
[i
], q
);
274 addRow(infoLabel
, infoValue
);
278 if (metaInfoCount
> 0) {
282 // remove rows that are not needed anymore
283 for (int i
= rowCount
- 1; i
> index
; --i
) {
284 delete m_rows
[i
].label
;
285 delete m_rows
[i
].infoWidget
;
292 MetaDataWidget::Private::LoadFilesThread::LoadFilesThread(
293 MetaDataWidget::Private::SharedData
* m_sharedData
,
295 m_m_sharedData(m_sharedData
),
302 MetaDataWidget::Private::LoadFilesThread::~LoadFilesThread()
304 // This thread may very well be deleted during execution. We need
305 // to protect it from crashes here.
310 void MetaDataWidget::Private::LoadFilesThread::loadFiles(const KUrl::List
& urls
)
312 QMutexLocker
locker(m_m_mutex
);
318 void MetaDataWidget::Private::LoadFilesThread::run()
320 QMutexLocker
locker(m_m_mutex
);
321 const KUrl::List urls
= m_urls
;
324 KConfig
config("kmetainformationrc", KConfig::NoGlobals
);
325 KConfigGroup settings
= config
.group("Show");
326 initMetaInfoSettings(settings
);
329 unsigned int rating
= 0;
331 QList
<Nepomuk::Tag
> tags
;
332 QList
<QString
> metaInfoLabels
;
333 QList
<QString
> metaInfoValues
;
334 foreach (const KUrl
& url
, urls
) {
339 Nepomuk::Resource
file(url
, Soprano::Vocabulary::Xesam::File());
341 if (!first
&& (rating
!= file
.rating())) {
342 rating
= 0; // reset rating
344 rating
= file
.rating();
347 if (!first
&& (comment
!= file
.description())) {
348 comment
.clear(); // reset comment
350 comment
= file
.description();
353 if (!first
&& (tags
!= file
.tags())) {
354 tags
.clear(); // reset tags
359 if (first
&& (urls
.count() == 1)) {
360 // TODO: show shared meta informations instead
361 // of not showing anything on multiple selections
362 QHash
<QUrl
, Nepomuk::Variant
> properties
= file
.properties();
363 QHash
<QUrl
, Nepomuk::Variant
>::const_iterator it
= properties
.constBegin();
364 while (it
!= properties
.constEnd()) {
365 Nepomuk::Types::Property
prop(it
.key());
366 if (true /*settings.readEntry(prop.name(), true)*/) {
367 // TODO #1: use Nepomuk::formatValue(res, prop) if available
368 // instead of it.value().toString()
369 // TODO #2: using tunedLabel() is a workaround for KDE 4.3 until
370 // we get translated labels
371 metaInfoLabels
.append(tunedLabel(prop
.label()));
372 metaInfoValues
.append(it
.value().toString());
382 m_m_sharedData
->rating
= rating
;
383 m_m_sharedData
->comment
= comment
;
384 m_m_sharedData
->tags
= tags
;
385 m_m_sharedData
->metaInfoLabels
= metaInfoLabels
;
386 m_m_sharedData
->metaInfoValues
= metaInfoValues
;
389 void MetaDataWidget::Private::LoadFilesThread::initMetaInfoSettings(KConfigGroup
& group
)
391 if (!group
.readEntry("initialized", false)) {
392 // The resource file is read the first time. Assure
393 // that some meta information is disabled per default.
395 static const char* disabledProperties
[] = {
396 "asText", "contentSize", "depth", "fileExtension",
397 "fileName", "fileSize", "isPartOf", "mimetype", "name",
398 "parentUrl", "plainTextContent", "sourceModified",
400 0 // mandatory last entry
404 while (disabledProperties
[i
] != 0) {
405 group
.writeEntry(disabledProperties
[i
], false);
409 // mark the group as initialized
410 group
.writeEntry("initialized", true);
414 QString
MetaDataWidget::Private::LoadFilesThread::tunedLabel(const QString
& label
) const
417 const int labelLength
= label
.length();
418 if (labelLength
> 0) {
419 tunedLabel
.reserve(labelLength
);
420 tunedLabel
= label
[0].toUpper();
421 for (int i
= 1; i
< labelLength
; ++i
) {
422 if (label
[i
].isUpper() && !label
[i
- 1].isSpace() && !label
[i
- 1].isUpper()) {
424 tunedLabel
+= label
[i
].toLower();
426 tunedLabel
+= label
[i
];
430 return tunedLabel
+ ':';
435 MetaDataWidget::MetaDataWidget(QWidget
* parent
) :
441 MetaDataWidget::~MetaDataWidget()
446 void MetaDataWidget::setItem(const KFileItem
& item
)
448 // update values for "type", "size", "modified",
449 // "owner" and "permissions" synchronously
450 d
->m_sizeLabel
->setText(i18nc("@label", "Size:"));
452 d
->m_typeInfo
->setText(i18nc("@label", "Folder"));
453 d
->setRowVisible(d
->m_sizeInfo
, false);
455 d
->m_typeInfo
->setText(item
.mimeComment());
456 d
->m_sizeInfo
->setText(KIO::convertSize(item
.size()));
457 d
->setRowVisible(d
->m_sizeInfo
, true);
459 d
->m_modifiedInfo
->setText(item
.timeString());
460 d
->m_ownerInfo
->setText(item
.user());
461 d
->m_permissionsInfo
->setText(item
.permissionsString());
463 setItems(KFileItemList() << item
);
466 void MetaDataWidget::setItems(const KFileItemList
& items
)
468 if (items
.count() > 1) {
469 // calculate the size of all items and show this
470 // information to the user
471 d
->m_sizeLabel
->setText(i18nc("@label", "Total Size:"));
472 d
->setRowVisible(d
->m_sizeInfo
, true);
474 quint64 totalSize
= 0;
475 foreach (const KFileItem
& item
, items
) {
476 if (!item
.isDir() && !item
.isLink()) {
477 totalSize
+= item
.size();
480 d
->m_sizeInfo
->setText(KIO::convertSize(totalSize
));
485 foreach (const KFileItem
& item
, items
) {
486 const KUrl url
= item
.nepomukUri();
491 d
->m_loadFilesThread
->loadFiles(urls
);
495 #include "metadatawidget.moc"