diff options
author | Alexander Volkov <avolkov@astralinux.ru> | 2021-05-06 20:13:35 +0300 |
---|---|---|
committer | Alexander Volkov <avolkov@astralinux.ru> | 2021-06-17 17:36:29 +0300 |
commit | d8dbc2b95aa89a9f2c8515bd12d2729a018dded4 (patch) | |
tree | 9decd7b10b2810fbfc4a7b40d7e49ee6337b6e1e /src/corelib/mimetypes | |
parent | ada29a19cd4b995dfd3e3059ccdf360ba13de08c (diff) |
QMimeBinaryProvider: cache comments and globPatterns
Avoid multiple re-reads of xml files, for example in dolphin,
which displays MIME type comments as file types.
Change-Id: Ia124930e2a1fdc99d8a4d160f2288a00f55e0e8e
Reviewed-by: David Faure <david.faure@kdab.com>
Diffstat (limited to 'src/corelib/mimetypes')
-rw-r--r-- | src/corelib/mimetypes/qmimedatabase.cpp | 15 | ||||
-rw-r--r-- | src/corelib/mimetypes/qmimeprovider.cpp | 92 | ||||
-rw-r--r-- | src/corelib/mimetypes/qmimeprovider_p.h | 9 |
3 files changed, 62 insertions, 54 deletions
diff --git a/src/corelib/mimetypes/qmimedatabase.cpp b/src/corelib/mimetypes/qmimedatabase.cpp index 2bbe6c3ad7..0be220e124 100644 --- a/src/corelib/mimetypes/qmimedatabase.cpp +++ b/src/corelib/mimetypes/qmimedatabase.cpp @@ -228,7 +228,20 @@ void QMimeDatabasePrivate::loadMimeTypePrivate(QMimeTypePrivate &mimePrivate) return; // invalid mimetype if (!mimePrivate.loaded) { // XML provider sets loaded=true, binary provider does this on demand Q_ASSERT(mimePrivate.fromCache); - QMimeBinaryProvider::loadMimeTypePrivate(mimePrivate); + bool found = false; + for (const auto &provider : providers()) { + if (provider->loadMimeTypePrivate(mimePrivate)) { + found = true; + break; + } + } + if (!found) { + const QString file = mimePrivate.name + QLatin1String(".xml"); + qWarning() << "No file found for" << file << ", even though update-mime-info said it would exist.\n" + "Either it was just removed, or the directory doesn't have executable permission..." + << QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("mime"), QStandardPaths::LocateDirectory); + } + mimePrivate.loaded = true; } } diff --git a/src/corelib/mimetypes/qmimeprovider.cpp b/src/corelib/mimetypes/qmimeprovider.cpp index 11643b8a1e..92be90658e 100644 --- a/src/corelib/mimetypes/qmimeprovider.cpp +++ b/src/corelib/mimetypes/qmimeprovider.cpp @@ -203,11 +203,14 @@ void QMimeBinaryProvider::ensureLoaded() const QString cacheFileName = m_directory + QLatin1String("/mime.cache"); m_cacheFile = new CacheFile(cacheFileName); m_mimetypeListLoaded = false; + m_mimetypeExtra.clear(); } else { - if (checkCacheChanged()) + if (checkCacheChanged()) { m_mimetypeListLoaded = false; - else + m_mimetypeExtra.clear(); + } else { return; // nothing to do + } } if (!m_cacheFile->isValid()) { // verify existence and version delete m_cacheFile; @@ -489,47 +492,44 @@ void QMimeBinaryProvider::addAllMimeTypes(QList<QMimeType> &result) } } -void QMimeBinaryProvider::loadMimeTypePrivate(QMimeTypePrivate &data) +bool QMimeBinaryProvider::loadMimeTypePrivate(QMimeTypePrivate &data) { #ifdef QT_NO_XMLSTREAMREADER Q_UNUSED(data); qWarning("Cannot load mime type since QXmlStreamReader is not available."); - return; + return false; #else if (data.loaded) - return; - data.loaded = true; - // load comment and globPatterns - - const QString file = data.name + QLatin1String(".xml"); - // shared-mime-info since 1.3 lowercases the xml files - QStringList mimeFiles = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("mime/") + file.toLower()); - if (mimeFiles.isEmpty()) - mimeFiles = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("mime/") + file); // pre-1.3 - if (mimeFiles.isEmpty()) { - qWarning() << "No file found for" << file << ", even though update-mime-info said it would exist.\n" - "Either it was just removed, or the directory doesn't have executable permission..." - << QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("mime"), QStandardPaths::LocateDirectory); - return; - } + return true; + + auto it = m_mimetypeExtra.constFind(data.name); + if (it == m_mimetypeExtra.constEnd()) { + // load comment and globPatterns - QString mainPattern; + // shared-mime-info since 1.3 lowercases the xml files + QString mimeFile = m_directory + QLatin1Char('/') + data.name.toLower() + QLatin1String(".xml"); + if (!QFile::exists(mimeFile)) + mimeFile = m_directory + QLatin1Char('/') + data.name + QLatin1String(".xml"); // pre-1.3 - for (QStringList::const_reverse_iterator it = mimeFiles.crbegin(), end = mimeFiles.crend(); it != end; ++it) { // global first, then local. - QFile qfile(*it); + QFile qfile(mimeFile); if (!qfile.open(QFile::ReadOnly)) - continue; + return false; + + auto insertIt = m_mimetypeExtra.insert(data.name, MimeTypeExtra{}); + it = insertIt; + MimeTypeExtra &extra = insertIt.value(); + QString mainPattern; QXmlStreamReader xml(&qfile); if (xml.readNextStartElement()) { if (xml.name() != QLatin1String("mime-type")) { - continue; + return false; } const auto name = xml.attributes().value(QLatin1String("type")); if (name.isEmpty()) - continue; + return false; if (name.compare(data.name, Qt::CaseInsensitive)) - qWarning() << "Got name" << name << "in file" << file << "expected" << data.name; + qWarning() << "Got name" << name << "in file" << mimeFile << "expected" << data.name; while (xml.readNextStartElement()) { const auto tag = xml.name(); @@ -539,49 +539,37 @@ void QMimeBinaryProvider::loadMimeTypePrivate(QMimeTypePrivate &data) if (lang.isEmpty()) { lang = QLatin1String("default"); // no locale attribute provided, treat it as default. } - data.localeComments.insert(lang, text); + extra.localeComments.insert(lang, text); continue; // we called readElementText, so we're at the EndElement already. - } else if (tag == QLatin1String("icon")) { // as written out by shared-mime-info >= 0.40 - data.iconName = xml.attributes().value(QLatin1String("name")).toString(); } else if (tag == QLatin1String("glob-deleteall")) { // as written out by shared-mime-info >= 0.70 - data.globPatterns.clear(); + extra.globPatterns.clear(); mainPattern.clear(); } else if (tag == QLatin1String("glob")) { // as written out by shared-mime-info >= 0.70 const QString pattern = xml.attributes().value(QLatin1String("pattern")).toString(); if (mainPattern.isEmpty() && pattern.startsWith(QLatin1Char('*'))) { mainPattern = pattern; } - if (!data.globPatterns.contains(pattern)) - data.globPatterns.append(pattern); + if (!extra.globPatterns.contains(pattern)) + extra.globPatterns.append(pattern); } xml.skipCurrentElement(); } Q_ASSERT(xml.name() == QLatin1String("mime-type")); } - } - // Let's assume that shared-mime-info is at least version 0.70 - // Otherwise we would need 1) a version check, and 2) code for parsing patterns from the globs file. -#if 1 - if (!mainPattern.isEmpty() && (data.globPatterns.isEmpty() || data.globPatterns.constFirst() != mainPattern)) { - // ensure it's first in the list of patterns - data.globPatterns.removeAll(mainPattern); - data.globPatterns.prepend(mainPattern); - } -#else - const bool globsInXml = sharedMimeInfoVersion() >= QT_VERSION_CHECK(0, 70, 0); - if (globsInXml) { - if (!mainPattern.isEmpty() && data.globPatterns.constFirst() != mainPattern) { + // Let's assume that shared-mime-info is at least version 0.70 + // Otherwise we would need 1) a version check, and 2) code for parsing patterns from the globs file. + if (!mainPattern.isEmpty() && + (extra.globPatterns.isEmpty() || extra.globPatterns.constFirst() != mainPattern)) { // ensure it's first in the list of patterns - data.globPatterns.removeAll(mainPattern); - data.globPatterns.prepend(mainPattern); + extra.globPatterns.removeAll(mainPattern); + extra.globPatterns.prepend(mainPattern); } - } else { - // Fallback: get the patterns from the globs file - // TODO: This would be the only way to support shared-mime-info < 0.70 - // But is this really worth the effort? } -#endif + const MimeTypeExtra &e = it.value(); + data.localeComments = e.localeComments; + data.globPatterns = e.globPatterns; + return true; #endif //QT_NO_XMLSTREAMREADER } diff --git a/src/corelib/mimetypes/qmimeprovider_p.h b/src/corelib/mimetypes/qmimeprovider_p.h index f9c8ef384c..affc554698 100644 --- a/src/corelib/mimetypes/qmimeprovider_p.h +++ b/src/corelib/mimetypes/qmimeprovider_p.h @@ -79,6 +79,7 @@ public: virtual void addAliases(const QString &name, QStringList &result) = 0; virtual void findByMagic(const QByteArray &data, int *accuracyPtr, QMimeType &candidate) = 0; virtual void addAllMimeTypes(QList<QMimeType> &result) = 0; + virtual bool loadMimeTypePrivate(QMimeTypePrivate &) { return false; } virtual void loadIcon(QMimeTypePrivate &) {} virtual void loadGenericIcon(QMimeTypePrivate &) {} virtual void ensureLoaded() {} @@ -107,7 +108,7 @@ public: void addAliases(const QString &name, QStringList &result) override; void findByMagic(const QByteArray &data, int *accuracyPtr, QMimeType &candidate) override; void addAllMimeTypes(QList<QMimeType> &result) override; - static void loadMimeTypePrivate(QMimeTypePrivate &); + bool loadMimeTypePrivate(QMimeTypePrivate &) override; void loadIcon(QMimeTypePrivate &) override; void loadGenericIcon(QMimeTypePrivate &) override; void ensureLoaded() override; @@ -126,6 +127,12 @@ private: QStringList m_cacheFileNames; QSet<QString> m_mimetypeNames; bool m_mimetypeListLoaded; + struct MimeTypeExtra + { + QHash<QString, QString> localeComments; + QStringList globPatterns; + }; + QMap<QString, MimeTypeExtra> m_mimetypeExtra; }; /* |