diff --git a/src/filemetadataprovider.h b/src/filemetadataprovider.h --- a/src/filemetadataprovider.h +++ b/src/filemetadataprovider.h @@ -116,18 +116,37 @@ void slotLoadingFinished(KJob* job); void slotFileFetchFinished(KJob* job); + +private: void insertBasicData(); void insertEditableData(); + + void setFileItem(); + void setFilesItems(); + + /** + * Insert intersection of common data of \p files + */ + void insertCommonData(const QList& files); -private: + /** + * Insert basic data of a single file + */ + void insertSingleFileBasicData(); + + /** + * Insert basic data of a list of files + */ + void insertFilesListBasicData(); + /** * Checks for the existance of \p uri in \p allProperties, and accordingly * inserts the total integer value of that property in m_data. On completion * it removes \p uri from \p allProperties */ void totalPropertyAndInsert(const QString& prop, const QList& resources, QSet& allProperties); - + /* * @return The number of subdirectories for the directory \a path. */ diff --git a/src/filemetadataprovider.cpp b/src/filemetadataprovider.cpp --- a/src/filemetadataprovider.cpp +++ b/src/filemetadataprovider.cpp @@ -31,26 +31,28 @@ // Required includes for subDirectoriesCount(): #ifdef Q_OS_WIN - #include + #include #else #include - #include + #include #endif using namespace Baloo; namespace { QVariant intersect(const QVariant& v1, const QVariant& v2) { - if( !v1.isValid() || !v2.isValid() ) + if (!v1.isValid() || !v2.isValid()) { return QVariant(); + } // List and String if (v1.type() == QVariant::StringList && v2.type() == QVariant::String) { QStringList list = v1.toStringList(); QString str = v2.toString(); - if (!list.contains(str)) + if (!list.contains(str)) { list << str; + } return QVariant(list); } @@ -60,8 +62,9 @@ QStringList list = v2.toStringList(); QString str = v1.toString(); - if (!list.contains(str)) + if (!list.contains(str)) { list << str; + } return QVariant(list); } @@ -74,8 +77,9 @@ return QVariant(s1.intersect(s2).toList()); } - if (v1 == v2) + if (v1 == v2) { return v1; + } return QVariant(); } @@ -98,85 +102,46 @@ return v; } + + } void FileMetaDataProvider::totalPropertyAndInsert(const QString& prop, const QList& resources, QSet& allProperties) { - if( allProperties.contains( prop ) ) { + if (allProperties.contains(prop)) { int total = 0; foreach (const QVariantMap& map, resources) { - QVariantMap::const_iterator it = map.constFind( prop ); - if( it == map.constEnd() ) { + QVariantMap::const_iterator it = map.constFind(prop); + if (it == map.constEnd()) { total = 0; break; - } - else { + } else { total += it.value().toInt(); } } - if( total ) - m_data.insert( prop, QVariant(total) ); - allProperties.remove( prop ); + if (total) { + m_data.insert (prop, QVariant(total)); + } + allProperties.remove(prop); } } void FileMetaDataProvider::slotFileFetchFinished(KJob* job) { FileFetchJob* fetchJob = static_cast(job); QList files = fetchJob->data(); - if (files.size() == 1) { + if (files.size() > 1) { + insertCommonData(files); + } else { m_data = files.first(); - insertBasicData(); - } - else { - // - // Only report the stuff that is common to all the files - // - QSet allProperties; - QList propertyList; - foreach (const QVariantMap& fileData, files) { - propertyList << fileData; - allProperties.unite(fileData.uniqueKeys().toSet()); - } - - // Special handling for certain properties - totalPropertyAndInsert("duration", propertyList, allProperties); - totalPropertyAndInsert("characterCount", propertyList, allProperties); - totalPropertyAndInsert("wordCount", propertyList, allProperties); - totalPropertyAndInsert("lineCount", propertyList, allProperties); - - foreach (const QString& propUri, allProperties) { - foreach (const QVariantMap& map, propertyList) { - QVariantMap::const_iterator it = map.find( propUri ); - if( it == map.constEnd() ) { - m_data.remove( propUri ); - break; - } - else { - QVariantMap::iterator dit = m_data.find( it.key() ); - if( dit == m_data.end() ) { - m_data.insert( propUri, it.value() ); - } - else { - QVariant finalValue = intersect( it.value(), dit.value() ); - if( finalValue.isValid() ) - m_data[propUri] = finalValue; - else { - m_data.remove( propUri ); - break; - } - } - } - } - } + insertSingleFileBasicData(); } insertEditableData(); - emit loadingFinished(); } @@ -188,74 +153,134 @@ emit loadingFinished(); } -void FileMetaDataProvider::insertBasicData() +void FileMetaDataProvider::insertSingleFileBasicData() { - KFormat format; + // TODO: Handle case if remote URLs are used properly. isDir() does + // not work, the modification date needs also to be adjusted... + Q_ASSERT(m_fileItems.count() <= 1); if (m_fileItems.count() == 1) { - // TODO: Handle case if remote URLs are used properly. isDir() does - // not work, the modification date needs also to be adjusted... - const KFileItem& item = m_fileItems.first(); - - if (item.isDir()) { - const int count = subDirectoriesCount(item.url().path()); - if (count == -1) { - m_data.insert("kfileitem#size", i18nc("unknown file size", "Unknown")); - } else { - const QString itemCountString = i18ncp("@item:intable", "%1 item", "%1 items", count); - m_data.insert("kfileitem#size", itemCountString); - } - } else { - m_data.insert("kfileitem#size", format.formatByteSize(item.size())); - } + KFormat format; + const KFileItem& item = m_fileItems.first(); + + if (item.isDir()) { + const int count = subDirectoriesCount(item.url().path()); + if (count == -1) { + m_data.insert("kfileitem#size", i18nc("unknown file size", "Unknown")); + } else { + const QString itemCountString = i18ncp("@item:intable", "%1 item", "%1 items", count); + m_data.insert("kfileitem#size", itemCountString); + } + } else { + m_data.insert("kfileitem#size", format.formatByteSize(item.size())); + } + + m_data.insert("kfileitem#type", item.mimeComment()); + m_data.insert("kfileitem#modified", + format.formatRelativeDateTime(item.time(KFileItem::ModificationTime), QLocale::LongFormat)); + m_data.insert("kfileitem#owner", item.user()); + m_data.insert("kfileitem#permissions", item.permissionsString()); + } + +} - m_data.insert("kfileitem#type", item.mimeComment()); - m_data.insert("kfileitem#modified", format.formatRelativeDateTime(item.time(KFileItem::ModificationTime), QLocale::LongFormat) ); - m_data.insert("kfileitem#owner", item.user()); - m_data.insert("kfileitem#permissions", item.permissionsString()); +void FileMetaDataProvider::insertFilesListBasicData() +{ + + KFormat format; + // If all directories + Q_ASSERT(m_fileItems.count() > 1); + bool allDirectories = true; + for (const KFileItem& item : m_fileItems) { + allDirectories &= item.isDir(); } - else if (m_fileItems.count() > 1) { - // If all directories - bool allDirectories = true; + + if (allDirectories) { + int count = 0; for (const KFileItem& item : m_fileItems) { - allDirectories &= item.isDir(); + count += subDirectoriesCount(item.url().path()); } - if (allDirectories) { - int count = 0; - for (const KFileItem& item : m_fileItems) { - count += subDirectoriesCount(item.url().path()); - } - - if (count) { - const QString itemCountString = i18ncp("@item:intable", "%1 item", "%1 items", count); - m_data.insert("kfileitem#totalSize", itemCountString); - } + if (count) { + const QString itemCountString = i18ncp("@item:intable", "%1 item", "%1 items", count); + m_data.insert("kfileitem#totalSize", itemCountString); } - else { - // Calculate the size of all items - quint64 totalSize = 0; - for (const KFileItem& item : m_fileItems) { - if (!item.isDir() && !item.isLink()) { - totalSize += item.size(); - } + } else { + // Calculate the size of all items + quint64 totalSize = 0; + for (const KFileItem& item : m_fileItems) { + if (!item.isDir() && !item.isLink()) { + totalSize += item.size(); } - m_data.insert("kfileitem#totalSize", format.formatByteSize(totalSize)); } + m_data.insert("kfileitem#totalSize", format.formatByteSize(totalSize)); + } +} + +void FileMetaDataProvider::insertBasicData() +{ + if (m_fileItems.count() > 1) { + insertFilesListBasicData(); + } else { + insertSingleFileBasicData(); } } void FileMetaDataProvider::insertEditableData() { if (!m_readOnly) { - if (!m_data.contains("tags")) + if (!m_data.contains("tags")) { m_data.insert("tags", QVariant()); - if (!m_data.contains("rating")) + } + if (!m_data.contains("rating")) { m_data.insert("rating", 0); - if (!m_data.contains("userComment") ) + } + if (!m_data.contains("userComment")) { m_data.insert("userComment", QVariant()); + } } } +void FileMetaDataProvider::insertCommonData(const QList& files) +{ + // + // Only report the stuff that is common to all the files + // + QSet allProperties; + QList propertyList; + foreach (const QVariantMap& fileData, files) { + propertyList << fileData; + allProperties.unite(fileData.uniqueKeys().toSet()); + } + + // Special handling for certain properties + totalPropertyAndInsert("duration", propertyList, allProperties); + totalPropertyAndInsert("characterCount", propertyList, allProperties); + totalPropertyAndInsert("wordCount", propertyList, allProperties); + totalPropertyAndInsert("lineCount", propertyList, allProperties); + + foreach (const QString& propUri, allProperties) { + foreach (const QVariantMap& map, propertyList) { + QVariantMap::const_iterator it = map.find(propUri); + if (it == map.constEnd()) { + m_data.remove(propUri); + break; + } + + QVariantMap::iterator dit = m_data.find(it.key()); + if (dit == m_data.end()) { + m_data.insert(propUri, it.value()); + } else { + QVariant finalValue = intersect(it.value(), dit.value()); + if (finalValue.isValid()) { + m_data[propUri] = finalValue; + } else { + m_data.remove(propUri); + break; + } + } + } + } +} FileMetaDataProvider::FileMetaDataProvider(QObject* parent) : QObject(parent) @@ -268,76 +293,79 @@ { } -void FileMetaDataProvider::setItems(const KFileItemList& items) +void FileMetaDataProvider::setFileItem() { - m_fileItems = items; - m_data.clear(); - m_realTimeIndexing = false; - - if (items.isEmpty()) { - emit loadingFinished(); - return; - } - // There are 4 code paths - // Single File - // * Not Indexed // * Indexed // - if (items.size() == 1) { - const QUrl url = items.first().targetUrl(); - if (!url.isLocalFile()) { - insertBasicData(); - emit loadingFinished(); - return; - } + const QUrl url = m_fileItems.first().targetUrl(); + if (!url.isLocalFile()) { + insertBasicData(); + emit loadingFinished(); + return; + } - // Not Indexed - const QString filePath = url.toLocalFile(); - if (!m_config.fileIndexingEnabled() || !m_config.shouldBeIndexed(filePath)) { - m_realTimeIndexing = true; + // Not Indexed + const QString filePath = url.toLocalFile(); + if (!m_config.fileIndexingEnabled() || !m_config.shouldBeIndexed(filePath)) { + m_realTimeIndexing = true; - IndexedDataRetriever *ret = new IndexedDataRetriever(filePath, this); - connect(ret, SIGNAL(finished(KJob*)), this, SLOT(slotLoadingFinished(KJob*))); - ret->start(); + IndexedDataRetriever *ret = new IndexedDataRetriever(filePath, this); + connect(ret, SIGNAL(finished(KJob*)), this, SLOT(slotLoadingFinished(KJob*))); + ret->start(); - insertBasicData(); - insertEditableData(); - emit loadingFinished(); - } - else { - FileFetchJob* job = new FileFetchJob(QStringList() << filePath, this); - connect(job, SIGNAL(finished(KJob*)), this, SLOT(slotFileFetchFinished(KJob*))); - job->start(); - } + insertBasicData(); + insertEditableData(); + emit loadingFinished(); + + } else { + FileFetchJob* job = new FileFetchJob(QStringList() << filePath, this); + connect(job, SIGNAL(finished(KJob*)), this, SLOT(slotFileFetchFinished(KJob*))); + job->start(); } +} + +void FileMetaDataProvider::setFilesItems() +{ // // Multiple Files - // * Not Indexed // * Indexed - // If Multiple Files are not indexed, we do not extract data from the files as it would - // be too expensive. - // - else { - QStringList urls; - Q_FOREACH (const KFileItem& item, items) { - const QUrl url = item.targetUrl(); - if (url.isLocalFile()) - urls << url.toLocalFile(); - } - if (urls.isEmpty()) { - insertBasicData(); - emit loadingFinished(); - return; + QStringList urls; + Q_FOREACH (const KFileItem& item, m_fileItems) { + const QUrl url = item.targetUrl(); + // If Multiple Files are not indexed, we do not extract data from the files as it would + // be too expensive. + if (url.isLocalFile()) { + urls << url.toLocalFile(); } + } + if (!urls.isEmpty()) { FileFetchJob* job = new FileFetchJob(urls, this); connect(job, SIGNAL(finished(KJob*)), this, SLOT(slotFileFetchFinished(KJob*))); job->start(); + } - insertBasicData(); + insertBasicData(); + emit loadingFinished(); +} + +void FileMetaDataProvider::setItems(const KFileItemList& items) +{ + m_fileItems = items; + m_data.clear(); + m_realTimeIndexing = false; + + if (items.isEmpty()) { emit loadingFinished(); + } else if (items.size() == 1) { + setFileItem(); + } else { + setFilesItems(); } } @@ -386,7 +414,7 @@ QString FileMetaDataProvider::group(const QString& label) const { static QHash uriGrouper; - if( uriGrouper.isEmpty() ) { + if (uriGrouper.isEmpty()) { // KFileItem Data uriGrouper.insert(QLatin1String("kfileitem#type"), QLatin1String("0FileItemA")); uriGrouper.insert(QLatin1String("kfileitem#size"), QLatin1String("0FileItemB")); @@ -405,24 +433,25 @@ uriGrouper.insert(QLatin1String("height"), QLatin1String("2SizeB")); // Music Data - uriGrouper.insert( "title", QLatin1String("3MusicA") ); - uriGrouper.insert( "artist", QLatin1String("3MusicB") ); - uriGrouper.insert( "album", QLatin1String("3MusicC") ); - uriGrouper.insert( "genre", QLatin1String("3MusicD") ); - uriGrouper.insert( "trackNumber", QLatin1String("3MusicE") ); + uriGrouper.insert("title", QLatin1String("3MusicA")); + uriGrouper.insert("artist", QLatin1String("3MusicB")); + uriGrouper.insert("album", QLatin1String("3MusicC")); + uriGrouper.insert("genre", QLatin1String("3MusicD")); + uriGrouper.insert("trackNumber", QLatin1String("3MusicE")); // Audio Data - uriGrouper.insert( "duration", QLatin1String("4AudioA") ); - uriGrouper.insert( "sampleRate", QLatin1String("4AudioB") ); - uriGrouper.insert( "sampleCount", QLatin1String("4AudioC") ); + uriGrouper.insert("duration", QLatin1String("4AudioA")); + uriGrouper.insert("sampleRate", QLatin1String("4AudioB")); + uriGrouper.insert("sampleCount", QLatin1String("4AudioC")); // Miscellaneous Data - uriGrouper.insert( "originUrl", QLatin1String("5MiscA") ); + uriGrouper.insert("originUrl", QLatin1String("5MiscA")); } const QString val = uriGrouper.value(label); - if (val.isEmpty()) + if (val.isEmpty()) { return "lastGroup"; + } return val; }