1 /*****************************************************************************
2 * Copyright (C) 2008 by Sebastian Trueg <trueg@kde.org> *
3 * Copyright (C) 2009 by Peter Penz <peter.penz@gmx.at> *
5 * This library is free software; you can redistribute it and/or *
6 * modify it under the terms of the GNU Library General Public *
7 * License version 2 as published by the Free Software Foundation. *
9 * This library is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
12 * Library General Public License for more details. *
14 * You should have received a copy of the GNU Library General Public License *
15 * along with this library; see the file COPYING.LIB. If not, write to *
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *
17 * Boston, MA 02110-1301, USA. *
18 *****************************************************************************/
20 #include "kmetadatawidget.h"
23 #include <kconfiggroup.h>
24 #include <kfileitem.h>
25 #include <kglobalsettings.h>
29 #include <QFontMetrics>
30 #include <QGridLayout>
35 #include <config-nepomuk.h>
37 #define DISABLE_NEPOMUK_LEGACY
39 #include "kcommentwidget_p.h"
40 #include "kloadmetadatathread_p.h"
41 #include "ktaggingwidget_p.h"
43 #include <nepomuk/kratingwidget.h>
44 #include <nepomuk/resource.h>
45 #include <nepomuk/resourcemanager.h>
46 #include <nepomuk/property.h>
47 #include <nepomuk/tag.h>
48 #include <nepomuk/variant.h>
49 #include "nepomukmassupdatejob_p.h"
52 #include <QSpacerItem>
61 class KMetaDataWidget::Private
70 Private(KMetaDataWidget
* parent
);
73 void addRow(QLabel
* label
, QWidget
* infoWidget
);
74 void removeMetaInfoRows();
75 void setRowVisible(QWidget
* infoWidget
, bool visible
);
78 * Initializes the configuration file "kmetainformationrc"
79 * with proper default settings for the first start in
80 * an uninitialized environment.
82 void initMetaInfoSettings();
85 * Parses the configuration file "kmetainformationrc" and
86 * updates the visibility of all rows.
88 void updateRowsVisibility();
90 void slotLoadingFinished();
92 void slotRatingChanged(unsigned int rating
);
93 void slotTagsChanged(const QList
<Nepomuk::Tag
>& tags
);
94 void slotCommentChanged(const QString
& comment
);
96 void slotMetaDataUpdateDone();
99 * Disables the metadata widget and starts the job that
100 * changes the meta data asynchronously. After the job
101 * has been finished, the metadata widget gets enabled again.
103 void startChangeDataJob(KJob
* job
);
105 bool m_isSizeVisible
;
106 MetaDataTypes m_visibleDataTypes
;
107 QList
<KFileItem
> m_fileItems
;
110 QGridLayout
* m_gridLayout
;
115 QLabel
* m_modifiedInfo
;
117 QLabel
* m_permissionsInfo
;
120 KRatingWidget
* m_ratingWidget
;
121 KTaggingWidget
* m_taggingWidget
;
122 KCommentWidget
* m_commentWidget
;
124 QMap
<KUrl
, Nepomuk::Resource
> m_files
;
126 KLoadMetaDataThread
* m_loadMetaDataThread
;
130 KMetaDataWidget
* const q
;
133 KMetaDataWidget::Private::Private(KMetaDataWidget
* parent
) :
134 m_isSizeVisible(true),
135 m_visibleDataTypes(TypeData
| SizeData
| ModifiedData
| OwnerData
|
136 PermissionsData
| RatingData
| TagsData
| CommentData
),
145 m_permissionsInfo(0),
151 m_loadMetaDataThread(0),
155 const QFontMetrics
fontMetrics(KGlobalSettings::smallestReadableFont());
157 m_gridLayout
= new QGridLayout(parent
);
158 m_gridLayout
->setMargin(0);
159 m_gridLayout
->setSpacing(fontMetrics
.height() / 4);
161 m_typeInfo
= new QLabel(parent
);
162 m_sizeLabel
= new QLabel(parent
);
163 m_sizeInfo
= new QLabel(parent
);
164 m_modifiedInfo
= new QLabel(parent
);
165 m_ownerInfo
= new QLabel(parent
);
166 m_permissionsInfo
= new QLabel(parent
);
168 addRow(new QLabel(i18nc("@label", "Type:"), parent
), m_typeInfo
);
169 addRow(m_sizeLabel
, m_sizeInfo
);
170 addRow(new QLabel(i18nc("@label", "Modified:"), parent
), m_modifiedInfo
);
171 addRow(new QLabel(i18nc("@label", "Owner:"), parent
), m_ownerInfo
);
172 addRow(new QLabel(i18nc("@label", "Permissions:"), parent
), m_permissionsInfo
);
175 if (Nepomuk::ResourceManager::instance()->init() == 0) {
176 m_ratingWidget
= new KRatingWidget(parent
);
177 m_ratingWidget
->setFixedHeight(fontMetrics
.height());
178 connect(m_ratingWidget
, SIGNAL(ratingChanged(unsigned int)),
179 q
, SLOT(slotRatingChanged(unsigned int)));
181 m_taggingWidget
= new KTaggingWidget(parent
);
182 connect(m_taggingWidget
, SIGNAL(tagsChanged(const QList
<Nepomuk::Tag
>&)),
183 q
, SLOT(slotTagsChanged(const QList
<Nepomuk::Tag
>&)));
185 m_commentWidget
= new KCommentWidget(parent
);
186 connect(m_commentWidget
, SIGNAL(commentChanged(const QString
&)),
187 q
, SLOT(slotCommentChanged(const QString
&)));
189 addRow(new QLabel(i18nc("@label", "Rating:"), parent
), m_ratingWidget
);
190 addRow(new QLabel(i18nc("@label", "Tags:"), parent
), m_taggingWidget
);
191 addRow(new QLabel(i18nc("@label", "Comment:"), parent
), m_commentWidget
);
195 initMetaInfoSettings();
196 updateRowsVisibility();
199 KMetaDataWidget::Private::~Private()
202 if (m_loadMetaDataThread
!= 0) {
203 disconnect(m_loadMetaDataThread
, SIGNAL(finished()), q
, SLOT(slotLoadingFinished()));
204 m_loadMetaDataThread
->cancelAndDelete();
205 m_loadMetaDataThread
= 0;
210 void KMetaDataWidget::Private::addRow(QLabel
* label
, QWidget
* infoWidget
)
214 row
.infoWidget
= infoWidget
;
217 const QFont smallFont
= KGlobalSettings::smallestReadableFont();
218 // use a brighter color for the label and a small font size
219 QPalette palette
= label
->palette();
220 QColor textColor
= palette
.color(QPalette::Text
);
221 textColor
.setAlpha(128);
222 palette
.setColor(QPalette::WindowText
, textColor
);
223 label
->setPalette(palette
);
224 label
->setFont(smallFont
);
225 label
->setWordWrap(true);
226 label
->setAlignment(Qt::AlignTop
| Qt::AlignRight
);
228 QLabel
* infoLabel
= qobject_cast
<QLabel
*>(infoWidget
);
229 if (infoLabel
!= 0) {
230 infoLabel
->setFont(smallFont
);
231 infoLabel
->setWordWrap(true);
232 infoLabel
->setAlignment(Qt::AlignTop
| Qt::AlignLeft
);
235 // add the row to grid layout
236 const int rowIndex
= m_rows
.count();
237 m_gridLayout
->addWidget(label
, rowIndex
, 0, Qt::AlignRight
);
238 const int spacerWidth
= QFontMetrics(smallFont
).size(Qt::TextSingleLine
, " ").width();
239 m_gridLayout
->addItem(new QSpacerItem(spacerWidth
, 1), rowIndex
, 1);
240 m_gridLayout
->addWidget(infoWidget
, rowIndex
, 2, Qt::AlignLeft
);
243 void KMetaDataWidget::Private::setRowVisible(QWidget
* infoWidget
, bool visible
)
245 foreach (const Row
& row
, m_rows
) {
246 if (row
.infoWidget
== infoWidget
) {
247 row
.label
->setVisible(visible
);
248 row
.infoWidget
->setVisible(visible
);
255 void KMetaDataWidget::Private::initMetaInfoSettings()
257 KConfig
config("kmetainformationrc", KConfig::NoGlobals
);
258 KConfigGroup settings
= config
.group("Show");
259 if (!settings
.readEntry("initialized", false)) {
260 // The resource file is read the first time. Assure
261 // that some meta information is disabled per default.
263 static const char* disabledProperties
[] = {
264 "asText", "contentSize", "created", "depth", "description", "fileExtension",
265 "fileName", "fileSize", "hasTag", "isPartOf", "lastModified", "mimeType", "name",
266 "numericRating", "parentUrl", "permissions", "plainTextContent", "owner",
267 "sourceModified", "url",
268 0 // mandatory last entry
272 while (disabledProperties
[i
] != 0) {
273 settings
.writeEntry(disabledProperties
[i
], false);
277 // mark the group as initialized
278 settings
.writeEntry("initialized", true);
282 void KMetaDataWidget::Private::updateRowsVisibility()
284 KConfig
config("kmetainformationrc", KConfig::NoGlobals
);
285 KConfigGroup settings
= config
.group("Show");
287 setRowVisible(m_typeInfo
,
288 (m_visibleDataTypes
& KMetaDataWidget::TypeData
) &&
289 settings
.readEntry("type", true));
291 // Cache in m_isSizeVisible whether the size should be shown. This
292 // is necessary as the size is temporary hidden when the target
293 // file item is a directory.
294 m_isSizeVisible
= (m_visibleDataTypes
& KMetaDataWidget::SizeData
) &&
295 settings
.readEntry("size", true);
296 setRowVisible(m_sizeInfo
, m_isSizeVisible
);
298 setRowVisible(m_modifiedInfo
,
299 (m_visibleDataTypes
& KMetaDataWidget::ModifiedData
) &&
300 settings
.readEntry("modified", true));
302 setRowVisible(m_ownerInfo
,
303 (m_visibleDataTypes
& KMetaDataWidget::OwnerData
) &&
304 settings
.readEntry("owner", true));
306 setRowVisible(m_permissionsInfo
,
307 (m_visibleDataTypes
& KMetaDataWidget::PermissionsData
) &&
308 settings
.readEntry("permissions", true));
311 if (Nepomuk::ResourceManager::instance()->init() == 0) {
312 setRowVisible(m_ratingWidget
,
313 (m_visibleDataTypes
& KMetaDataWidget::RatingData
) &&
314 settings
.readEntry("rating", true));
316 setRowVisible(m_taggingWidget
,
317 (m_visibleDataTypes
& KMetaDataWidget::TagsData
) &&
318 settings
.readEntry("tags", true));
320 setRowVisible(m_commentWidget
,
321 (m_visibleDataTypes
& KMetaDataWidget::CommentData
) &&
322 settings
.readEntry("comment", true));
327 void KMetaDataWidget::Private::slotLoadingFinished()
330 Q_ASSERT(m_loadMetaDataThread
!= 0);
331 m_ratingWidget
->setRating(m_loadMetaDataThread
->rating());
332 m_commentWidget
->setText(m_loadMetaDataThread
->comment());
333 m_taggingWidget
->setTags(m_loadMetaDataThread
->tags());
335 // Show the remaining meta information as text. The number
336 // of required rows may very. Existing rows are reused to
337 // prevent flickering.
338 int index
= 8; // TODO: don't hardcode this value here
339 const int rowCount
= m_rows
.count();
340 Q_ASSERT(rowCount
>= index
);
342 Q_ASSERT(m_loadMetaDataThread
->metaInfoLabels().count() == m_loadMetaDataThread
->metaInfoValues().count());
343 const int metaInfoCount
= m_loadMetaDataThread
->metaInfoLabels().count();
344 for (int i
= 0; i
< metaInfoCount
; ++i
) {
345 const QList
<QString
> metaInfoLabels
= m_loadMetaDataThread
->metaInfoLabels();
346 const QList
<QString
> metaInfoValues
= m_loadMetaDataThread
->metaInfoValues();
347 if (index
< rowCount
) {
348 // adjust texts of the current row
349 m_rows
[index
].label
->setText(metaInfoLabels
[i
]);
350 QLabel
* infoValueLabel
= qobject_cast
<QLabel
*>(m_rows
[index
].infoWidget
);
351 Q_ASSERT(infoValueLabel
!= 0);
352 infoValueLabel
->setText(metaInfoValues
[i
]);
355 QLabel
* infoLabel
= new QLabel(metaInfoLabels
[i
], q
);
356 QLabel
* infoValue
= new QLabel(metaInfoValues
[i
], q
);
357 addRow(infoLabel
, infoValue
);
361 if (metaInfoCount
> 0) {
365 // remove rows that are not needed anymore
366 for (int i
= rowCount
- 1; i
> index
; --i
) {
367 delete m_rows
[i
].label
;
368 delete m_rows
[i
].infoWidget
;
372 m_files
= m_loadMetaDataThread
->files();
374 delete m_loadMetaDataThread
;
375 m_loadMetaDataThread
= 0;
381 void KMetaDataWidget::Private::slotRatingChanged(unsigned int rating
)
384 Nepomuk::MassUpdateJob
* job
=
385 Nepomuk::MassUpdateJob::rateResources(m_files
.values(), rating
);
386 startChangeDataJob(job
);
392 void KMetaDataWidget::Private::slotTagsChanged(const QList
<Nepomuk::Tag
>& tags
)
395 m_taggingWidget
->setTags(tags
);
397 Nepomuk::MassUpdateJob
* job
=
398 Nepomuk::MassUpdateJob::tagResources(m_files
.values(), tags
);
399 startChangeDataJob(job
);
405 void KMetaDataWidget::Private::slotCommentChanged(const QString
& comment
)
408 Nepomuk::MassUpdateJob
* job
=
409 Nepomuk::MassUpdateJob::commentResources(m_files
.values(), comment
);
410 startChangeDataJob(job
);
416 void KMetaDataWidget::Private::slotMetaDataUpdateDone()
424 void KMetaDataWidget::Private::startChangeDataJob(KJob
* job
)
426 connect(job
, SIGNAL(result(KJob
*)),
427 q
, SLOT(slotMetaDataUpdateDone()));
428 q
->setEnabled(false); // no updates during execution
433 KMetaDataWidget::KMetaDataWidget(QWidget
* parent
) :
439 KMetaDataWidget::~KMetaDataWidget()
444 void KMetaDataWidget::setItem(const KFileItem
& item
)
446 // update values for "type", "size", "modified",
447 // "owner" and "permissions" synchronously
448 d
->m_sizeLabel
->setText(i18nc("@label", "Size:"));
450 d
->m_typeInfo
->setText(i18nc("@label", "Folder"));
451 d
->setRowVisible(d
->m_sizeInfo
, false);
453 d
->m_typeInfo
->setText(item
.mimeComment());
454 d
->m_sizeInfo
->setText(KIO::convertSize(item
.size()));
455 d
->setRowVisible(d
->m_sizeInfo
, d
->m_isSizeVisible
);
457 d
->m_modifiedInfo
->setText(KGlobal::locale()->formatDateTime(item
.time(KFileItem::ModificationTime
), KLocale::FancyLongDate
));
458 d
->m_ownerInfo
->setText(item
.user());
459 d
->m_permissionsInfo
->setText(item
.permissionsString());
461 setItems(KFileItemList() << item
);
464 void KMetaDataWidget::setItems(const KFileItemList
& items
)
466 d
->m_fileItems
= 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
, d
->m_isSizeVisible
);
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
));
484 if (Nepomuk::ResourceManager::instance()->init() == 0) {
486 foreach (const KFileItem
& item
, items
) {
487 const KUrl url
= item
.nepomukUri();
493 if (d
->m_loadMetaDataThread
!= 0) {
494 disconnect(d
->m_loadMetaDataThread
, SIGNAL(finished()), this, SLOT(slotLoadingFinished()));
495 d
->m_loadMetaDataThread
->cancelAndDelete();
498 d
->m_loadMetaDataThread
= new KLoadMetaDataThread();
499 connect(d
->m_loadMetaDataThread
, SIGNAL(finished()), this, SLOT(slotLoadingFinished()));
500 d
->m_loadMetaDataThread
->load(urls
);
505 void KMetaDataWidget::setItem(const KUrl
& url
)
507 KFileItem
item(KFileItem::Unknown
, KFileItem::Unknown
, url
);
512 void KMetaDataWidget::setItems(const QList
<KUrl
>& urls
)
515 foreach (const KUrl
& url
, urls
) {
516 KFileItem
item(KFileItem::Unknown
, KFileItem::Unknown
, url
);
523 KFileItemList
KMetaDataWidget::items() const
525 return d
->m_fileItems
;
528 void KMetaDataWidget::setVisibleDataTypes(MetaDataTypes data
)
530 d
->m_visibleDataTypes
= data
;
531 d
->updateRowsVisibility();
534 KMetaDataWidget::MetaDataTypes
KMetaDataWidget::visibleDataTypes() const
536 return d
->m_visibleDataTypes
;
539 QSize
KMetaDataWidget::sizeHint() const
541 const int fixedWidth
= 200;
543 int height
= d
->m_gridLayout
->margin() * 2 +
544 d
->m_gridLayout
->spacing() * (d
->m_rows
.count() - 1);
546 foreach (const Private::Row
& row
, d
->m_rows
) {
547 if (row
.infoWidget
!= 0) {
548 int rowHeight
= row
.infoWidget
->heightForWidth(fixedWidth
/ 2);
549 if (rowHeight
<= 0) {
550 rowHeight
= row
.infoWidget
->sizeHint().height();
556 return QSize(fixedWidth
, height
);
559 #include "kmetadatawidget.moc"