KIO
kfilemetadatawidget.cpp
Go to the documentation of this file.
00001 /***************************************************************************** 00002 * Copyright (C) 2008-2010 by Sebastian Trueg <trueg@kde.org> * 00003 * Copyright (C) 2009-2010 by Peter Penz <peter.penz@gmx.at> * 00004 * * 00005 * This library is free software; you can redistribute it and/or * 00006 * modify it under the terms of the GNU Library General Public * 00007 * License as published by the Free Software Foundation; either * 00008 * version 2 of the License, or (at your option) any later version. * 00009 * * 00010 * This library is distributed in the hope that it will be useful, * 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 00013 * Library General Public License for more details. * 00014 * * 00015 * You should have received a copy of the GNU Library General Public License * 00016 * along with this library; see the file COPYING.LIB. If not, write to * 00017 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * 00018 * Boston, MA 02110-1301, USA. * 00019 *****************************************************************************/ 00020 00021 #include "kfilemetadatawidget.h" 00022 00023 #include <kconfig.h> 00024 #include <kconfiggroup.h> 00025 #include <kfileitem.h> 00026 #include <kglobal.h> 00027 #include <klocale.h> 00028 #include "kfilemetadataprovider_p.h" 00029 00030 #include <QGridLayout> 00031 #include <QLabel> 00032 #include <QList> 00033 #include <QSet> 00034 #include <QString> 00035 #include <QTimer> 00036 00037 #include <config-kio.h> 00038 #ifndef KIO_NO_NEPOMUK 00039 #define DISABLE_NEPOMUK_LEGACY 00040 00041 #include <property.h> 00042 #include <tag.h> 00043 00044 #include <QMutex> 00045 #include <QSpacerItem> 00046 #include <QThread> 00047 #endif 00048 00049 class KFileMetaDataWidget::Private 00050 { 00051 public: 00052 struct Row 00053 { 00054 QLabel* label; 00055 QWidget* value; 00056 }; 00057 00058 Private(KFileMetaDataWidget* parent); 00059 ~Private(); 00060 00066 void initMetaInfoSettings(); 00067 00073 void updateFileItemRowsVisibility(); 00074 00075 void deleteRows(); 00076 00077 void slotLoadingFinished(); 00078 void slotLinkActivated(const QString& link); 00079 void slotDataChangeStarted(); 00080 void slotDataChangeFinished(); 00081 00082 #ifndef KIO_NO_NEPOMUK 00083 QList<KUrl> sortedKeys(const QHash<KUrl, Nepomuk::Variant>& data) const; 00084 00089 bool hasNepomukUris() const; 00090 #endif 00091 00092 QList<Row> m_rows; 00093 KFileMetaDataProvider* m_provider; 00094 QGridLayout* m_gridLayout; 00095 00096 private: 00097 KFileMetaDataWidget* const q; 00098 }; 00099 00100 KFileMetaDataWidget::Private::Private(KFileMetaDataWidget* parent) : 00101 m_rows(), 00102 m_provider(0), 00103 m_gridLayout(0), 00104 q(parent) 00105 { 00106 initMetaInfoSettings(); 00107 00108 // TODO: If KFileMetaDataProvider might get a public class in future KDE releases, 00109 // the following code should be moved into KFileMetaDataWidget::setModel(): 00110 m_provider = new KFileMetaDataProvider(q); 00111 connect(m_provider, SIGNAL(loadingFinished()), q, SLOT(slotLoadingFinished())); 00112 connect(m_provider, SIGNAL(urlActivated(KUrl)), q, SIGNAL(urlActivated(KUrl))); 00113 } 00114 00115 KFileMetaDataWidget::Private::~Private() 00116 { 00117 } 00118 00119 void KFileMetaDataWidget::Private::initMetaInfoSettings() 00120 { 00121 const int currentVersion = 3; // increase version, if the blacklist of disabled 00122 // properties should be updated 00123 00124 KConfig config("kmetainformationrc", KConfig::NoGlobals); 00125 if (config.group("Misc").readEntry("version", 0) < currentVersion) { 00126 // The resource file is read the first time. Assure 00127 // that some meta information is disabled per default. 00128 00129 // clear old info 00130 config.deleteGroup("Show"); 00131 KConfigGroup settings = config.group("Show"); 00132 00133 static const char* const disabledProperties[] = { 00134 "http://www.semanticdesktop.org/ontologies/2007/01/19/nie#comment", 00135 "http://www.semanticdesktop.org/ontologies/2007/01/19/nie#contentSize", 00136 "http://www.semanticdesktop.org/ontologies/2007/01/19/nie#depends", 00137 "http://www.semanticdesktop.org/ontologies/2007/01/19/nie#isPartOf", 00138 "http://www.semanticdesktop.org/ontologies/2007/01/19/nie#lastModified", 00139 "http://www.semanticdesktop.org/ontologies/2007/01/19/nie#mimeType", 00140 "http://www.semanticdesktop.org/ontologies/2007/01/19/nie#plainTextContent", 00141 "http://www.semanticdesktop.org/ontologies/2007/01/19/nie#url", 00142 "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#averageBitrate", 00143 "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#channels", 00144 "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#fileName", 00145 "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#apertureValue", 00146 "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#exposureBiasValue", 00147 "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#exposureTime", 00148 "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#flash", 00149 "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#focalLength", 00150 "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#focalLengthIn35mmFilm", 00151 "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#isoSpeedRatings", 00152 "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#make", 00153 "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#meteringMode", 00154 "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#model", 00155 "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#orientation", 00156 "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#whiteBalance", 00157 "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#description", 00158 "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#hasTag", 00159 "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#lastModified", 00160 "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#numericRating", 00161 "http://www.w3.org/1999/02/22-rdf-syntax-ns#type", 00162 "kfileitem#owner", 00163 "kfileitem#permissions", 00164 0 // mandatory last entry 00165 }; 00166 00167 for (int i = 0; disabledProperties[i] != 0; ++i) { 00168 settings.writeEntry(disabledProperties[i], false); 00169 } 00170 00171 // mark the group as initialized 00172 config.group("Misc").writeEntry("version", currentVersion); 00173 } 00174 } 00175 00176 void KFileMetaDataWidget::Private::deleteRows() 00177 { 00178 foreach (const Row& row, m_rows) { 00179 delete row.label; 00180 delete row.value; 00181 } 00182 m_rows.clear(); 00183 } 00184 00185 void KFileMetaDataWidget::Private::slotLoadingFinished() 00186 { 00187 #ifndef KIO_NO_NEPOMUK 00188 deleteRows(); 00189 00190 if (!hasNepomukUris()) { 00191 q->updateGeometry(); 00192 emit q->metaDataRequestFinished(m_provider->items()); 00193 return; 00194 } 00195 00196 if (m_gridLayout == 0) { 00197 m_gridLayout = new QGridLayout(q); 00198 m_gridLayout->setMargin(0); 00199 m_gridLayout->setSpacing(q->fontMetrics().height() / 4); 00200 } 00201 00202 QHash<KUrl, Nepomuk::Variant> data = m_provider->data(); 00203 00204 // Remove all items, that are marked as hidden in kmetainformationrc 00205 KConfig config("kmetainformationrc", KConfig::NoGlobals); 00206 KConfigGroup settings = config.group("Show"); 00207 QHash<KUrl, Nepomuk::Variant>::iterator it = data.begin(); 00208 while (it != data.end()) { 00209 const QString uriString = it.key().url(); 00210 if (!settings.readEntry(uriString, true) || 00211 !Nepomuk::Types::Property(it.key()).userVisible()) { 00212 it = data.erase(it); 00213 } else { 00214 ++it; 00215 } 00216 } 00217 00218 // Iterate through all remaining items embed the label 00219 // and the value as new row in the widget 00220 int rowIndex = 0; 00221 const QList<KUrl> keys = sortedKeys(data); 00222 foreach (const KUrl& key, keys) { 00223 const Nepomuk::Variant value = data[key]; 00224 QString itemLabel = m_provider->label(key); 00225 itemLabel.append(QLatin1Char(':')); 00226 00227 // Create label 00228 QLabel* label = new QLabel(itemLabel, q); 00229 label->setForegroundRole(q->foregroundRole()); 00230 label->setFont(q->font()); 00231 label->setWordWrap(true); 00232 label->setAlignment(Qt::AlignTop | Qt::AlignRight); 00233 00234 // Create value-widget 00235 QWidget* valueWidget = m_provider->createValueWidget(key, value, q); 00236 00237 // Add the label and value-widget to grid layout 00238 m_gridLayout->addWidget(label, rowIndex, 0, Qt::AlignRight); 00239 const int spacerWidth = QFontMetrics(q->font()).size(Qt::TextSingleLine, " ").width(); 00240 m_gridLayout->addItem(new QSpacerItem(spacerWidth, 1), rowIndex, 1); 00241 m_gridLayout->addWidget(valueWidget, rowIndex, 2, Qt::AlignLeft); 00242 00243 // Remember the label and value-widget as row 00244 Row row; 00245 row.label = label; 00246 row.value = valueWidget; 00247 m_rows.append(row); 00248 00249 ++rowIndex; 00250 } 00251 #endif 00252 00253 q->updateGeometry(); 00254 emit q->metaDataRequestFinished(m_provider->items()); 00255 } 00256 00257 void KFileMetaDataWidget::Private::slotLinkActivated(const QString& link) 00258 { 00259 const KUrl url(link); 00260 if (url.isValid()) { 00261 emit q->urlActivated(url); 00262 } 00263 } 00264 00265 void KFileMetaDataWidget::Private::slotDataChangeStarted() 00266 { 00267 q->setEnabled(false); 00268 } 00269 00270 void KFileMetaDataWidget::Private::slotDataChangeFinished() 00271 { 00272 q->setEnabled(true); 00273 } 00274 00275 #ifndef KIO_NO_NEPOMUK 00276 QList<KUrl> KFileMetaDataWidget::Private::sortedKeys(const QHash<KUrl, Nepomuk::Variant>& data) const 00277 { 00278 // Create a map, where the translated label prefixed with the 00279 // sort priority acts as key. The data of each entry is the URI 00280 // of the data. By this the all URIs are sorted by the sort priority 00281 // and sub sorted by the translated labels. 00282 QMap<QString, KUrl> map; 00283 QHash<KUrl, Nepomuk::Variant>::const_iterator hashIt = data.constBegin(); 00284 while (hashIt != data.constEnd()) { 00285 const KUrl uri = hashIt.key(); 00286 00287 QString key = m_provider->group(uri); 00288 key += m_provider->label(uri); 00289 00290 map.insert(key, uri); 00291 ++hashIt; 00292 } 00293 00294 // Apply the URIs from the map to the list that will get returned. 00295 // The list will then be alphabetically ordered by the translated labels of the URIs. 00296 QList<KUrl> list; 00297 QMap<QString, KUrl>::const_iterator mapIt = map.constBegin(); 00298 while (mapIt != map.constEnd()) { 00299 list.append(mapIt.value()); 00300 ++mapIt; 00301 } 00302 00303 return list; 00304 } 00305 00306 bool KFileMetaDataWidget::Private::hasNepomukUris() const 00307 { 00308 foreach (const KFileItem& fileItem, m_provider->items()) { 00309 if (fileItem.nepomukUri().isValid()) { 00310 return true; 00311 } 00312 } 00313 return false; 00314 } 00315 #endif 00316 00317 KFileMetaDataWidget::KFileMetaDataWidget(QWidget* parent) : 00318 QWidget(parent), 00319 d(new Private(this)) 00320 { 00321 } 00322 00323 KFileMetaDataWidget::~KFileMetaDataWidget() 00324 { 00325 delete d; 00326 } 00327 00328 void KFileMetaDataWidget::setItems(const KFileItemList& items) 00329 { 00330 d->m_provider->setItems(items); 00331 } 00332 00333 KFileItemList KFileMetaDataWidget::items() const 00334 { 00335 return d->m_provider->items(); 00336 } 00337 00338 void KFileMetaDataWidget::setReadOnly(bool readOnly) 00339 { 00340 d->m_provider->setReadOnly(readOnly); 00341 } 00342 00343 bool KFileMetaDataWidget::isReadOnly() const 00344 { 00345 return d->m_provider->isReadOnly(); 00346 } 00347 00348 QSize KFileMetaDataWidget::sizeHint() const 00349 { 00350 if (d->m_gridLayout == 0) { 00351 return QWidget::sizeHint(); 00352 } 00353 00354 // Calculate the required width for the labels and values 00355 int leftWidthMax = 0; 00356 int rightWidthMax = 0; 00357 int rightWidthAverage = 0; 00358 foreach (const Private::Row& row, d->m_rows) { 00359 const QWidget* valueWidget = row.value; 00360 const int rightWidth = valueWidget->sizeHint().width(); 00361 rightWidthAverage += rightWidth; 00362 if (rightWidth > rightWidthMax) { 00363 rightWidthMax = rightWidth; 00364 } 00365 00366 const int leftWidth = row.label->sizeHint().width(); 00367 if (leftWidth > leftWidthMax) { 00368 leftWidthMax = leftWidth; 00369 } 00370 } 00371 00372 // Some value widgets might return a very huge width for the size hint. 00373 // Limit the maximum width to the double width of the overall average 00374 // to assure a less messed layout. 00375 if (d->m_rows.count() > 1) { 00376 rightWidthAverage /= d->m_rows.count(); 00377 if (rightWidthMax > rightWidthAverage * 2) { 00378 rightWidthMax = rightWidthAverage * 2; 00379 } 00380 } 00381 00382 // Based on the available width calculate the required height 00383 int height = d->m_gridLayout->margin() * 2 + d->m_gridLayout->spacing() * (d->m_rows.count() - 1); 00384 foreach (const Private::Row& row, d->m_rows) { 00385 const QWidget* valueWidget = row.value; 00386 const int rowHeight = qMax(row.label->heightForWidth(leftWidthMax), 00387 valueWidget->heightForWidth(rightWidthMax)); 00388 height += rowHeight; 00389 } 00390 00391 const int width = d->m_gridLayout->margin() * 2 + leftWidthMax + 00392 d->m_gridLayout->spacing() + rightWidthMax; 00393 00394 return QSize(width, height); 00395 } 00396 00397 bool KFileMetaDataWidget::event(QEvent* event) 00398 { 00399 return QWidget::event(event); 00400 } 00401 00402 #include "kfilemetadatawidget.moc"
KDE 4.6 API Reference