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