diff --git a/src/filefetchjob.cpp b/src/filefetchjob.cpp index 143b4fe..2c9c913 100644 --- a/src/filefetchjob.cpp +++ b/src/filefetchjob.cpp @@ -1,79 +1,101 @@ /* * * Copyright (C) 2014 Vishesh Handa * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ #include "filefetchjob.h" #include "filemetadatautil_p.h" +#include "widgetsdebug.h" #include #include #include #include using namespace Baloo; -FileFetchJob::FileFetchJob(const QStringList& urls, bool canEditAll, QObject* parent) +FileFetchJob::FileFetchJob(const QStringList& urls, bool canEditAll, + FileFetchJob::UseRealtimeIndexing useRealtime, QObject* parent) : KJob(parent) , m_urls(urls) , m_canEditAll(canEditAll) + , m_useRealtime(useRealtime) { } void FileFetchJob::start() { QTimer::singleShot(0, this, SLOT(doStart())); } void FileFetchJob::doStart() { for (const QString& filePath : m_urls) { - Baloo::File file(filePath); - file.load(); - QVariantMap prop = Baloo::Private::toNamedVariantMap(file.properties()); + bool extractorRunning = false; + KFileMetaData::PropertyMap fileProperties; + + // UseRealtimeIndexing::Fallback: try DB first, then filesystem + // UseRealtimeIndexing::Disabled: DB contents only + // UseRealtimeIndexing::Only: DB disabled, use filesystem + if (m_useRealtime != UseRealtimeIndexing::Only) { + Baloo::File file(filePath); + file.load(); + fileProperties = file.properties(); + qCDebug(WIDGETS) << filePath << "DB properties:" << fileProperties; + } + if (fileProperties.empty() && m_useRealtime != UseRealtimeIndexing::Disabled) { + extractorRunning = true; + m_extractor.process(filePath); + } + + QVariantMap prop; KFileMetaData::UserMetaData umd(filePath); if (umd.isSupported()) { - // FIXME - check writable - - QVariantMap attributes = Baloo::Private::convertUserMetaData(umd); - prop.unite(attributes); + prop = Baloo::Private::convertUserMetaData(umd); } else { m_canEditAll = false; } if (m_canEditAll) { m_canEditAll = QFileInfo(filePath).isWritable(); } + if (extractorRunning) { + m_extractor.waitFinished(); + fileProperties = m_extractor.properties(); + qCDebug(WIDGETS) << filePath << " properties:" << fileProperties; + } + prop.unite(Baloo::Private::toNamedVariantMap(fileProperties)); + m_data << prop; } emitResult(); } QList Baloo::FileFetchJob::data() const { return m_data; } bool FileFetchJob::canEditAll() const { return m_canEditAll; } diff --git a/src/filefetchjob.h b/src/filefetchjob.h index c86efef..0baace5 100644 --- a/src/filefetchjob.h +++ b/src/filefetchjob.h @@ -1,50 +1,59 @@ /* * * Copyright (C) 2014 Vishesh Handa * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef BALOO_FILEFETCHJOB_H #define BALOO_FILEFETCHJOB_H #include #include +#include "ondemandextractor.h" namespace Baloo { class FileFetchJob : public KJob { Q_OBJECT public: - explicit FileFetchJob(const QStringList& urls, bool canEditAll, QObject* parent = nullptr); + enum class UseRealtimeIndexing : char { + Disabled = 0, + Only, + Fallback + }; + explicit FileFetchJob(const QStringList& urls, bool canEditAll, + UseRealtimeIndexing useRealtime, QObject* parent = nullptr); QList data() const; bool canEditAll() const; void start() override; private Q_SLOTS: void doStart(); private: QStringList m_urls; QList m_data; bool m_canEditAll; + UseRealtimeIndexing m_useRealtime; + Private::OnDemandExtractor m_extractor; }; } #endif // BALOO_FILEFETCHJOB_H diff --git a/src/filemetadataprovider.cpp b/src/filemetadataprovider.cpp index 5b7aa81..b24f737 100644 --- a/src/filemetadataprovider.cpp +++ b/src/filemetadataprovider.cpp @@ -1,567 +1,570 @@ /***************************************************************************** * Copyright (C) 2010 by Peter Penz * * Copyright (C) 2012 by Vishesh Handa * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Library General Public * * License as published by the Free Software Foundation; either * * version 2 of the License, or (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public License * * along with this library; see the file COPYING.LIB. If not, write to * * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * *****************************************************************************/ #include "filemetadataprovider.h" #include "indexeddataretriever.h" #include "filefetchjob.h" #include #include #include #include #include // Required includes for subDirectoriesCount(): #ifdef Q_OS_WIN #include #else #include #include #endif using namespace Baloo; namespace { QVariant intersect(const QVariant& v1, const QVariant& v2) { 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)) { list << str; } return QVariant(list); } // String and List if (v1.type() == QVariant::String && v2.type() == QVariant::StringList) { QStringList list = v2.toStringList(); QString str = v1.toString(); if (!list.contains(str)) { list << str; } return QVariant(list); } // List and List if (v1.type() == QVariant::StringList && v2.type() == QVariant::StringList) { QSet s1 = v1.toStringList().toSet(); QSet s2 = v2.toStringList().toSet(); return QVariant(s1.intersect(s2).toList()); } if (v1 == v2) { return v1; } return QVariant(); } /** * The standard QMap::unite will contain the key multiple times if both \p v1 and \p v2 * contain the same key. * * This will only take the key from \p v2 into account */ QVariantMap unite(const QVariantMap& v1, const QVariantMap& v2) { QVariantMap v(v1); QMapIterator it(v2); while (it.hasNext()) { it.next(); v[it.key()] = it.value(); } return v; } } // anonymous namespace void FileMetaDataProvider::totalPropertyAndInsert(const QString& prop, const QList& resources, QSet& allProperties) { if (allProperties.contains(prop)) { int total = 0; for (const QVariantMap& map : resources) { QVariantMap::const_iterator it = map.constFind(prop); if (it == map.constEnd()) { total = 0; break; } else { total += it.value().toInt(); } } 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(); Q_ASSERT(!files.isEmpty()); if (files.size() > 1) { insertCommonData(files); } else { m_data = unite(m_data, files.first()); } m_readOnly = !fetchJob->canEditAll(); insertEditableData(); emit loadingFinished(); } void FileMetaDataProvider::slotLoadingFinished(KJob* job) { IndexedDataRetriever* ret = dynamic_cast(job); m_data = unite(m_data, ret->data()); m_readOnly = !ret->canEdit(); insertEditableData(); emit loadingFinished(); } void FileMetaDataProvider::insertSingleFileBasicData() { // 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) { const KFileItem& item = m_fileItems.first(); if (item.isDir()) { bool isSizeUnknown = !item.isLocalFile(); if (!isSizeUnknown) { const QPair counts = subDirectoriesCount(item.url().path()); const int count = counts.first; isSizeUnknown = count == -1; if (!isSizeUnknown) { QString itemCountString = i18ncp("@item:intable", "%1 item", "%1 items", count); m_data.insert(QStringLiteral("kfileitem#size"), itemCountString); const int hiddenCount = counts.second; if (hiddenCount > 0) { // add hidden items count QString hiddenCountString = i18ncp("@item:intable", "%1 item", "%1 items", hiddenCount); m_data.insert(QStringLiteral("kfileitem#hiddenItems"), hiddenCountString); } } } else if (item.entry().contains(KIO::UDSEntry::UDS_SIZE)) { isSizeUnknown = false; KFormat format; m_data.insert(QStringLiteral("kfileitem#size"), format.formatByteSize(item.size())); } if (isSizeUnknown) { m_data.insert(QStringLiteral("kfileitem#size"), i18nc("unknown file size", "Unknown")); } } else { KFormat format; m_data.insert(QStringLiteral("kfileitem#size"), format.formatByteSize(item.size())); } m_data.insert(QStringLiteral("kfileitem#type"), item.mimeComment()); m_data.insert(QStringLiteral("kfileitem#modified"), item.time(KFileItem::ModificationTime)); QDateTime creationTime = item.time(KFileItem::CreationTime); if (creationTime.isValid()) { m_data.insert(QStringLiteral("kfileitem#created"), creationTime); } m_data.insert(QStringLiteral("kfileitem#accessed"), item.time(KFileItem::AccessTime)); m_data.insert(QStringLiteral("kfileitem#owner"), item.user()); m_data.insert(QStringLiteral("kfileitem#group"), item.group()); m_data.insert(QStringLiteral("kfileitem#permissions"), item.permissionsString()); } } void FileMetaDataProvider::insertFilesListBasicData() { // If all directories Q_ASSERT(m_fileItems.count() > 1); bool allDirectories = true; for (const KFileItem& item : qAsConst(m_fileItems)) { allDirectories &= item.isDir(); if (!allDirectories) { break; } } if (allDirectories) { int count = 0; int hiddenCount = 0; bool isSizeKnown = true; for (const KFileItem& item : qAsConst(m_fileItems)) { isSizeKnown = item.isLocalFile(); if (!isSizeKnown) { return; } const QPair counts = subDirectoriesCount(item.url().path()); const int subcount = counts.first; isSizeKnown = subcount != -1; if (!isSizeKnown) { return; } count += subcount; hiddenCount += counts.second; } QString itemCountString = i18ncp("@item:intable", "%1 item", "%1 items", count); if (hiddenCount > 0) { // add hidden items count QString hiddenCountString = i18ncp("@item:intable", "%1 item", "%1 items", hiddenCount); m_data.insert(QStringLiteral("kfileitem#hiddenItems"), hiddenCountString); } m_data.insert(QStringLiteral("kfileitem#totalSize"), itemCountString); } else { // Calculate the size of all items quint64 totalSize = 0; for (const KFileItem& item : qAsConst(m_fileItems)) { if (!item.isDir() && !item.isLink()) { totalSize += item.size(); } } KFormat format; m_data.insert(QStringLiteral("kfileitem#totalSize"), format.formatByteSize(totalSize)); } } void FileMetaDataProvider::insertEditableData() { if (!m_readOnly) { if (!m_data.contains(QStringLiteral("tags"))) { m_data.insert(QStringLiteral("tags"), QVariant()); } if (!m_data.contains(QStringLiteral("rating"))) { m_data.insert(QStringLiteral("rating"), 0); } if (!m_data.contains(QStringLiteral("userComment"))) { m_data.insert(QStringLiteral("userComment"), QVariant()); } } } void FileMetaDataProvider::insertCommonData(const QList& files) { // // Only report the stuff that is common to all the files // QSet allProperties; QList propertyList; for (const QVariantMap& fileData : files) { propertyList << fileData; allProperties.unite(fileData.uniqueKeys().toSet()); } // Special handling for certain properties totalPropertyAndInsert(QStringLiteral("duration"), propertyList, allProperties); totalPropertyAndInsert(QStringLiteral("characterCount"), propertyList, allProperties); totalPropertyAndInsert(QStringLiteral("wordCount"), propertyList, allProperties); totalPropertyAndInsert(QStringLiteral("lineCount"), propertyList, allProperties); for (const QString& propUri : qAsConst(allProperties)) { for (const QVariantMap& map : qAsConst(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) , m_readOnly(false) , m_realTimeIndexing(false) { } FileMetaDataProvider::~FileMetaDataProvider() { } void FileMetaDataProvider::setFileItem() { // There are 3 code paths - // Remote file // Single local file - // * Not Indexed // * Indexed // insertSingleFileBasicData(); const QUrl url = m_fileItems.first().targetUrl(); if (!url.isLocalFile()) { // FIXME - are extended attributes supported for remote files? m_readOnly = true; emit loadingFinished(); return; } - // Not indexed or only basic file indexing (no content) const QString filePath = url.toLocalFile(); + FileFetchJob* job; + + // Not indexed or only basic file indexing (no content) if (!m_config.fileIndexingEnabled() || !m_config.shouldBeIndexed(filePath) || m_config.onlyBasicIndexing()) { m_realTimeIndexing = true; - IndexedDataRetriever *ret = new IndexedDataRetriever(filePath, this); - connect(ret, &IndexedDataRetriever::finished, this, &FileMetaDataProvider::slotLoadingFinished); - ret->start(); + job = new FileFetchJob(QStringList{filePath}, true, + FileFetchJob::UseRealtimeIndexing::Only, this); // Fully indexed by Baloo } else { - FileFetchJob* job = new FileFetchJob(QStringList{filePath}, true, this); - connect(job, &FileFetchJob::finished, this, &FileMetaDataProvider::slotFileFetchFinished); - job->start(); + job = new FileFetchJob(QStringList{filePath}, true, + FileFetchJob::UseRealtimeIndexing::Fallback, this); } + connect(job, &FileFetchJob::finished, this, &FileMetaDataProvider::slotFileFetchFinished); + job->start(); } void FileMetaDataProvider::setFileItems() { // Multiple Files - // * Not Indexed // * Indexed QStringList urls; urls.reserve(m_fileItems.size()); // Only extract data from indexed files, // it would be too expensive otherwise. for (const KFileItem& item : qAsConst(m_fileItems)) { const QUrl url = item.targetUrl(); if (url.isLocalFile()) { urls << url.toLocalFile(); } } insertFilesListBasicData(); if (!urls.isEmpty()) { // Editing only if all URLs are local bool canEdit = (urls.size() == m_fileItems.size()); - FileFetchJob* job = new FileFetchJob(urls, canEdit, this); + FileFetchJob* job = new FileFetchJob(urls, canEdit, + FileFetchJob::UseRealtimeIndexing::Disabled, this); connect(job, &FileFetchJob::finished, this, &FileMetaDataProvider::slotFileFetchFinished); job->start(); } else { // FIXME - are extended attributes supported for remote files? m_readOnly = true; 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 { setFileItems(); } } QString FileMetaDataProvider::label(const QString& metaDataLabel) const { static QHash hash = { { QStringLiteral("kfileitem#comment"), i18nc("@label", "Comment") }, { QStringLiteral("kfileitem#created"), i18nc("@label", "Created") }, { QStringLiteral("kfileitem#accessed"), i18nc("@label", "Accessed") }, { QStringLiteral("kfileitem#modified"), i18nc("@label", "Modified") }, { QStringLiteral("kfileitem#owner"), i18nc("@label", "Owner") }, { QStringLiteral("kfileitem#group"), i18nc("@label", "Group") }, { QStringLiteral("kfileitem#permissions"), i18nc("@label", "Permissions") }, { QStringLiteral("kfileitem#rating"), i18nc("@label", "Rating") }, { QStringLiteral("kfileitem#size"), i18nc("@label", "Size") }, { QStringLiteral("kfileitem#tags"), i18nc("@label", "Tags") }, { QStringLiteral("kfileitem#totalSize"), i18nc("@label", "Total Size") }, { QStringLiteral("kfileitem#hiddenItems"), i18nc("@label", "Hidden items") }, { QStringLiteral("kfileitem#type"), i18nc("@label", "Type") }, { QStringLiteral("tags"), i18nc("@label", "Tags") }, { QStringLiteral("rating"), i18nc("@label", "Rating") }, { QStringLiteral("userComment"), i18nc("@label", "Comment") }, { QStringLiteral("originUrl"), i18nc("@label", "Downloaded From") }, }; QString value = hash.value(metaDataLabel); if (value.isEmpty()) { value = KFileMetaData::PropertyInfo::fromName(metaDataLabel).displayName(); } return value; } QString FileMetaDataProvider::group(const QString& label) const { static QHash uriGrouper = { // KFileItem Data { QStringLiteral("kfileitem#type"), QStringLiteral("0FileItemA") }, { QStringLiteral("kfileitem#size"), QStringLiteral("0FileItemB") }, { QStringLiteral("kfileitem#totalSize"), QStringLiteral("0FileItemB") }, { QStringLiteral("kfileitem#hiddenItems"), QStringLiteral("0FileItemC") }, { QStringLiteral("kfileitem#modified"), QStringLiteral("0FileItemD") }, { QStringLiteral("kfileitem#accessed"), QStringLiteral("0FileItemE") }, { QStringLiteral("kfileitem#created"), QStringLiteral("0FileItemF") }, { QStringLiteral("kfileitem#owner"), QStringLiteral("0FileItemG") }, { QStringLiteral("kfileitem#group"), QStringLiteral("0FileItemH") }, { QStringLiteral("kfileitem#permissions"), QStringLiteral("0FileItemI") }, // Editable Data { QStringLiteral("tags"), QStringLiteral("1EditableDataA") }, { QStringLiteral("rating"), QStringLiteral("1EditableDataB") }, { QStringLiteral("userComment"), QStringLiteral("1EditableDataC") }, // Image Data { QStringLiteral("width"), QStringLiteral("2ImageA") }, { QStringLiteral("height"), QStringLiteral("2ImageB") }, { QStringLiteral("photoFNumber"), QStringLiteral("2ImageC") }, { QStringLiteral("photoExposureTime"), QStringLiteral("2ImageD") }, { QStringLiteral("photoExposureBiasValue"), QStringLiteral("2ImageE") }, { QStringLiteral("photoISOSpeedRatings"), QStringLiteral("2ImageF") }, { QStringLiteral("photoFocalLength"), QStringLiteral("2ImageG") }, { QStringLiteral("photoFocalLengthIn35mmFilm"), QStringLiteral("2ImageH") }, { QStringLiteral("photoFlash"), QStringLiteral("2ImageI") }, { QStringLiteral("imageOrientation"), QStringLiteral("2ImageJ") }, { QStringLiteral("photoGpsLatitude"), QStringLiteral("2ImageK") }, { QStringLiteral("photoGpsLongitude"), QStringLiteral("2ImageL") }, { QStringLiteral("photoGpsAltitude"), QStringLiteral("2ImageM") }, { QStringLiteral("manufacturer"), QStringLiteral("2ImageN") }, { QStringLiteral("model"), QStringLiteral("2ImageO") }, // Media Data { QStringLiteral("title"), QStringLiteral("3MediaA") }, { QStringLiteral("artist"), QStringLiteral("3MediaB") }, { QStringLiteral("album"), QStringLiteral("3MediaC") }, { QStringLiteral("albumArtist"), QStringLiteral("3MediaD") }, { QStringLiteral("genre"), QStringLiteral("3MediaE") }, { QStringLiteral("trackNumber"), QStringLiteral("3MediaF") }, { QStringLiteral("discNumber"), QStringLiteral("3MediaG") }, { QStringLiteral("releaseYear"), QStringLiteral("3MediaH") }, { QStringLiteral("duration"), QStringLiteral("3MediaI") }, { QStringLiteral("sampleRate"), QStringLiteral("3MediaJ") }, { QStringLiteral("bitRate"), QStringLiteral("3MediaK") }, // Miscellaneous Data { QStringLiteral("originUrl"), QStringLiteral("4MiscA") }, }; const QString val = uriGrouper.value(label); if (val.isEmpty()) { return QStringLiteral("lastGroup"); } return val; } KFileItemList FileMetaDataProvider::items() const { return m_fileItems; } void FileMetaDataProvider::setReadOnly(bool readOnly) { m_readOnly = readOnly; } bool FileMetaDataProvider::isReadOnly() const { return m_readOnly; } QVariantMap FileMetaDataProvider::data() const { return m_data; } QPair FileMetaDataProvider::subDirectoriesCount(const QString& path) { #ifdef Q_OS_WIN QDir dir(path); int count = dir.entryList(QDir::AllEntries|QDir::NoDotAndDotDot|QDir::System).count(); int hiddenCount = dir.entryList(QDir::AllEntries|QDir::NoDotAndDotDot|QDir::System|QDir::Hidden).count(); return QPair (count, hiddenCount); #else // Taken from kdelibs/kio/kio/kdirmodel.cpp // Copyright (C) 2006 David Faure int count = -1; int hiddenCount = -1; DIR* dir = ::opendir(QFile::encodeName(path).constData()); if (dir) { count = 0; hiddenCount = 0; struct dirent *dirEntry = nullptr; while ((dirEntry = ::readdir(dir))) { // krazy:exclude=syscalls if (dirEntry->d_name[0] == '.') { if (dirEntry->d_name[1] == '\0') { // Skip "." continue; } if (dirEntry->d_name[1] == '.' && dirEntry->d_name[2] == '\0') { // Skip ".." continue; } // hidden files hiddenCount++; } else { ++count; } } ::closedir(dir); } return QPair(count, hiddenCount); #endif } bool FileMetaDataProvider::realTimeIndexing() { return m_realTimeIndexing; } diff --git a/src/ondemandextractor.cpp b/src/ondemandextractor.cpp index a789040..8da20c8 100644 --- a/src/ondemandextractor.cpp +++ b/src/ondemandextractor.cpp @@ -1,71 +1,76 @@ /* * * Copyright (C) 2019 Stefan Brüns * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ #include "ondemandextractor.h" #include "widgetsdebug.h" #include "extractorutil_p.h" #include #include namespace Baloo { namespace Private { OnDemandExtractor::OnDemandExtractor(QObject* parent) : QObject(parent) { } OnDemandExtractor::~OnDemandExtractor() { } void OnDemandExtractor::process(const QString& filePath) { const QString exe = QStandardPaths::findExecutable(QLatin1String("baloo_filemetadata_temp_extractor")); m_process.setReadChannel(QProcess::StandardOutput); connect(&m_process, QOverload::of(&QProcess::finished), this, &OnDemandExtractor::slotIndexedFile); m_process.start(exe, QStringList{ filePath }); } void OnDemandExtractor::slotIndexedFile(int, QProcess::ExitStatus exitStatus) { if (exitStatus == QProcess::CrashExit) { qCWarning(WIDGETS) << "Extractor crashed when processing" << m_process.arguments(); emit fileFinished(exitStatus); return; } QByteArray data = m_process.readAllStandardOutput(); QDataStream in(&data, QIODevice::ReadOnly); m_properties.clear(); in >> m_properties; emit fileFinished(QProcess::NormalExit); } +bool OnDemandExtractor::waitFinished() +{ + return m_process.waitForFinished(); +} + KFileMetaData::PropertyMap OnDemandExtractor::properties() const { return m_properties; } } // namespace Private } // namespace Baloo diff --git a/src/ondemandextractor.h b/src/ondemandextractor.h index b78cc03..5117fba 100644 --- a/src/ondemandextractor.h +++ b/src/ondemandextractor.h @@ -1,56 +1,57 @@ /* * * Copyright (C) 2019 Stefan Brüns * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef ONDEMANDEXTRACTOR_H #define ONDEMANDEXTRACTOR_H #include #include namespace Baloo { namespace Private { class OnDemandExtractor : public QObject { Q_OBJECT public: explicit OnDemandExtractor(QObject* parent = nullptr); ~OnDemandExtractor(); void process(const QString& filePath); + bool waitFinished(); KFileMetaData::PropertyMap properties() const; Q_SIGNALS: void fileFinished(QProcess::ExitStatus exitStatus); private Q_SLOTS: void slotIndexedFile(int exitCode, QProcess::ExitStatus exitStatus); private: QProcess m_process; KFileMetaData::PropertyMap m_properties; }; } // namespace Private } // namespace Baloo #endif // ONDEMANDEXTRACTOR_H