Backport from Qt6.6.2[1] per Plasma 6 recommendation[2] for QTBUG-116905[3].

Tests changes were dropped due to not applying cleanly, but tests still
build and pass either way (may not get properly tested but that's of
little concern here).

[1] https://codereview.qt-project.org/c/qt/qtbase/+/523541
[2] https://community.kde.org/Plasma/Plasma_6.0_Release_notes#Required_Qt_Version
[3] https://bugreports.qt.io/browse/QTBUG-116905

From 705118a554083161b6fe54aaf37a04ddca844f48 Mon Sep 17 00:00:00 2001
From: David Faure <david.faure@kdab.com>
Date: Thu, 07 Dec 2023 11:38:38 +0100
Subject: [PATCH] QMimeDatabase: collect glob patterns from all locations

A QMimeTypePrivate used to belong to a single provider, which would
provide the complete data for it.
But since the redesign in commit 7a5644d6481a3c1a741677, each provider
represents is a single mime directory, and the merging happens at the
QMimeDatabase level. So we need a QMimeType[Private] to be just a name
(a "request" for information about this mimetype) and the information
for that mimetype is retrieved on demand by querying the providers
and either stopping at the first one (e.g. for icons) or merging
the data from all of them (e.g. for glob patterns).

The XML provider was using QMimeTypePrivate as data storage,
give it its own struct QMimeTypeXMLData for that purpose instead.

Task-number: QTBUG-116905
Change-Id: Ia0e0d94aa899720dc0b908f40c25317473005af4
(cherry picked from commit 4e9944e6c8a456353d243ab268cb0f01ff006faa)
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
--- a/src/corelib/mimetypes/qmimedatabase.cpp
+++ b/src/corelib/mimetypes/qmimedatabase.cpp
@@ -191,7 +191,6 @@
     const QString mimeName = resolveAlias(nameOrAlias);
     for (const auto &provider : providers()) {
-        QMimeType mime = provider->mimeTypeForName(mimeName);
-        if (mime.isValid())
-            return mime;
+        if (provider->knowsMimeType(mimeName))
+            return QMimeType(QMimeTypePrivate(mimeName));
     }
     return {};
@@ -218,52 +217,52 @@
 }
 
-void QMimeDatabasePrivate::loadMimeTypePrivate(QMimeTypePrivate &mimePrivate)
+QMimeTypePrivate::LocaleHash QMimeDatabasePrivate::localeComments(const QString &name)
 {
     QMutexLocker locker(&mutex);
-    if (mimePrivate.name.isEmpty())
-        return; // invalid mimetype
-    if (!mimePrivate.loaded) { // XML provider sets loaded=true, binary provider does this on demand
-        Q_ASSERT(mimePrivate.fromCache);
-        bool found = false;
-        for (const auto &provider : providers()) {
-            if (provider->loadMimeTypePrivate(mimePrivate)) {
-                found = true;
-                break;
-            }
-        }
-        if (!found) {
-            const QString file = mimePrivate.name + ".xml"_L1;
-            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..."
-                       << locateMimeDirectories();
-        }
-        mimePrivate.loaded = true;
+    for (const auto &provider : providers()) {
+        auto comments = provider->localeComments(name);
+        if (!comments.isEmpty())
+            return comments; // maybe we want to merge in comments from more global providers, in
+                             // case of more translations?
     }
+    return {};
 }
 
-void QMimeDatabasePrivate::loadGenericIcon(QMimeTypePrivate &mimePrivate)
+QStringList QMimeDatabasePrivate::globPatterns(const QString &name)
 {
     QMutexLocker locker(&mutex);
-    if (mimePrivate.fromCache) {
-        mimePrivate.genericIconName.clear();
-        for (const auto &provider : providers()) {
-            provider->loadGenericIcon(mimePrivate);
-            if (!mimePrivate.genericIconName.isEmpty())
-                break;
-        }
+    QStringList patterns;
+    const auto &providerList = providers();
+    // reverse iteration because we start from most global, add up, clear if delete-all, and add up
+    // again.
+    for (auto rit = providerList.rbegin(); rit != providerList.rend(); ++rit) {
+        auto *provider = rit->get();
+        if (provider->hasGlobDeleteAll(name))
+            patterns.clear();
+        patterns += provider->globPatterns(name);
     }
+    return patterns;
 }
 
-void QMimeDatabasePrivate::loadIcon(QMimeTypePrivate &mimePrivate)
+QString QMimeDatabasePrivate::genericIcon(const QString &name)
 {
     QMutexLocker locker(&mutex);
-    if (mimePrivate.fromCache) {
-        mimePrivate.iconName.clear();
-        for (const auto &provider : providers()) {
-            provider->loadIcon(mimePrivate);
-            if (!mimePrivate.iconName.isEmpty())
-                break;
-        }
+    for (const auto &provider : providers()) {
+        QString genericIconName = provider->genericIcon(name);
+        if (!genericIconName.isEmpty())
+            return genericIconName;
     }
+    return {};
+}
+
+QString QMimeDatabasePrivate::icon(const QString &name)
+{
+    QMutexLocker locker(&mutex);
+    for (const auto &provider : providers()) {
+        QString iconName = provider->icon(name);
+        if (!iconName.isEmpty())
+            return iconName;
+    }
+    return {};
 }
 
@@ -346,10 +345,10 @@
 
     *accuracyPtr = 0;
-    QMimeType candidate;
+    QString candidate;
     for (const auto &provider : providers())
-        provider->findByMagic(data, accuracyPtr, candidate);
+        provider->findByMagic(data, accuracyPtr, &candidate);
 
-    if (candidate.isValid())
-        return candidate;
+    if (!candidate.isEmpty())
+        return QMimeType(QMimeTypePrivate(candidate));
 
     if (isTextFile(data)) {
--- a/src/corelib/mimetypes/qmimedatabase_p.h
+++ b/src/corelib/mimetypes/qmimedatabase_p.h
@@ -67,7 +67,8 @@
 
     // API for QMimeType. Takes care of locking the mutex.
-    void loadMimeTypePrivate(QMimeTypePrivate &mimePrivate);
-    void loadGenericIcon(QMimeTypePrivate &mimePrivate);
-    void loadIcon(QMimeTypePrivate &mimePrivate);
+    QMimeTypePrivate::LocaleHash localeComments(const QString &name);
+    QStringList globPatterns(const QString &name);
+    QString genericIcon(const QString &name);
+    QString icon(const QString &name);
     QStringList mimeParents(const QString &mimeName);
     QStringList listAliases(const QString &mimeName);
@@ -82,5 +83,5 @@
 
     const QString m_defaultMimeType;
-    mutable Providers m_providers;
+    mutable Providers m_providers; // most local first, most global last
     QElapsedTimer m_lastCheck;
 
--- a/src/corelib/mimetypes/qmimeprovider.cpp
+++ b/src/corelib/mimetypes/qmimeprovider.cpp
@@ -187,23 +187,9 @@
 }
 
-static QMimeType mimeTypeForNameUnchecked(const QString &name)
-{
-    QMimeTypePrivate data;
-    data.name = name;
-    data.fromCache = true;
-    // The rest is retrieved on demand.
-    // comment and globPatterns: in loadMimeTypePrivate
-    // iconName: in loadIcon
-    // genericIconName: in loadGenericIcon
-    return QMimeType(data);
-}
-
-QMimeType QMimeBinaryProvider::mimeTypeForName(const QString &name)
+bool QMimeBinaryProvider::knowsMimeType(const QString &name)
 {
     if (!m_mimetypeListLoaded)
         loadMimeTypeList();
-    if (!m_mimetypeNames.contains(name))
-        return QMimeType(); // unknown mimetype
-    return mimeTypeForNameUnchecked(name);
+    return m_mimetypeNames.contains(name);
 }
 
@@ -355,5 +341,5 @@
 }
 
-void QMimeBinaryProvider::findByMagic(const QByteArray &data, int *accuracyPtr, QMimeType &candidate)
+void QMimeBinaryProvider::findByMagic(const QByteArray &data, int *accuracyPtr, QString *candidate)
 {
     const int magicListOffset = m_cacheFile->getUint32(PosMagicListOffset);
@@ -372,5 +358,5 @@
             // Return the first match. We have no rules for conflicting magic data...
             // (mime.cache itself is sorted, but what about local overrides with a lower prio?)
-            candidate = mimeTypeForNameUnchecked(QLatin1StringView(mimeType));
+            *candidate = QString::fromLatin1(mimeType);
             return;
         }
@@ -480,33 +466,61 @@
         result.reserve(m_mimetypeNames.size());
         for (const QString &name : std::as_const(m_mimetypeNames))
-            result.append(mimeTypeForNameUnchecked(name));
+            result.append(QMimeType(QMimeTypePrivate(name)));
     } else {
         for (const QString &name : std::as_const(m_mimetypeNames))
             if (std::find_if(result.constBegin(), result.constEnd(), [name](const QMimeType &mime) -> bool { return mime.name() == name; })
                     == result.constEnd())
-                result.append(mimeTypeForNameUnchecked(name));
+                result.append(QMimeType(QMimeTypePrivate(name)));
     }
 }
 
-bool QMimeBinaryProvider::loadMimeTypePrivate(QMimeTypePrivate &data)
+QMimeTypePrivate::LocaleHash QMimeBinaryProvider::localeComments(const QString &name)
 {
-#if QT_CONFIG(xmlstreamreader)
-    if (data.loaded)
-        return true;
+    MimeTypeExtraMap::const_iterator it = loadMimeTypeExtra(name);
+    if (it != m_mimetypeExtra.constEnd()) {
+        const MimeTypeExtra &e = it.value();
+        return e.localeComments;
+    }
+    return {};
+}
+
+bool QMimeBinaryProvider::hasGlobDeleteAll(const QString &name)
+{
+    MimeTypeExtraMap::const_iterator it = loadMimeTypeExtra(name);
+    if (it != m_mimetypeExtra.constEnd()) {
+        const MimeTypeExtra &e = it.value();
+        return e.hasGlobDeleteAll;
+    }
+    return {};
+}
 
-    auto it = m_mimetypeExtra.constFind(data.name);
+QStringList QMimeBinaryProvider::globPatterns(const QString &name)
+{
+    MimeTypeExtraMap::const_iterator it = loadMimeTypeExtra(name);
+    if (it != m_mimetypeExtra.constEnd()) {
+        const MimeTypeExtra &e = it.value();
+        return e.globPatterns;
+    }
+    return {};
+}
+
+QMimeBinaryProvider::MimeTypeExtraMap::const_iterator
+QMimeBinaryProvider::loadMimeTypeExtra(const QString &mimeName)
+{
+#if QT_CONFIG(xmlstreamreader)
+    auto it = m_mimetypeExtra.constFind(mimeName);
     if (it == m_mimetypeExtra.constEnd()) {
         // load comment and globPatterns
 
         // shared-mime-info since 1.3 lowercases the xml files
-        QString mimeFile = m_directory + u'/' + data.name.toLower() + ".xml"_L1;
+        QString mimeFile = m_directory + u'/' + mimeName.toLower() + ".xml"_L1;
         if (!QFile::exists(mimeFile))
-            mimeFile = m_directory + u'/' + data.name + ".xml"_L1; // pre-1.3
+            mimeFile = m_directory + u'/' + mimeName + ".xml"_L1; // pre-1.3
 
         QFile qfile(mimeFile);
         if (!qfile.open(QFile::ReadOnly))
-            return false;
+            return m_mimetypeExtra.constEnd();
 
-        auto insertIt = m_mimetypeExtra.insert(data.name, MimeTypeExtra{});
+        auto insertIt = m_mimetypeExtra.insert(mimeName, MimeTypeExtra{});
         it = insertIt;
         MimeTypeExtra &extra = insertIt.value();
@@ -516,11 +530,11 @@
         if (xml.readNextStartElement()) {
             if (xml.name() != "mime-type"_L1) {
-                return false;
+                return m_mimetypeExtra.constEnd();
             }
             const auto name = xml.attributes().value("type"_L1);
             if (name.isEmpty())
-                return false;
-            if (name.compare(data.name, Qt::CaseInsensitive))
-                qWarning() << "Got name" << name << "in file" << mimeFile << "expected" << data.name;
+                return m_mimetypeExtra.constEnd();
+            if (name.compare(mimeName, Qt::CaseInsensitive))
+                qWarning() << "Got name" << name << "in file" << mimeFile << "expected" << mimeName;
 
             while (xml.readNextStartElement()) {
@@ -535,6 +549,5 @@
                     continue; // we called readElementText, so we're at the EndElement already.
                 } else if (tag == "glob-deleteall"_L1) { // as written out by shared-mime-info >= 0.70
-                    extra.globPatterns.clear();
-                    mainPattern.clear();
+                    extra.hasGlobDeleteAll = true;
                 } else if (tag == "glob"_L1) { // as written out by shared-mime-info >= 0.70
                     const QString pattern = xml.attributes().value("pattern"_L1).toString();
@@ -558,12 +571,9 @@
         }
     }
-    const MimeTypeExtra &e = it.value();
-    data.localeComments = e.localeComments;
-    data.globPatterns = e.globPatterns;
-    return true;
+    return it;
 #else
-    Q_UNUSED(data);
+    Q_UNUSED(mimeName);
     qWarning("Cannot load mime type since QXmlStreamReader is not available.");
-    return false;
+    return m_mimetypeExtra.constEnd();
 #endif // feature xmlstreamreader
 }
@@ -595,20 +605,14 @@
 }
 
-void QMimeBinaryProvider::loadIcon(QMimeTypePrivate &data)
+QString QMimeBinaryProvider::icon(const QString &name)
 {
-    const QByteArray inputMime = data.name.toLatin1();
-    const QLatin1StringView icon = iconForMime(m_cacheFile.get(), PosIconsListOffset, inputMime);
-    if (!icon.isEmpty()) {
-        data.iconName = icon;
-    }
+    const QByteArray inputMime = name.toLatin1();
+    return iconForMime(m_cacheFile.get(), PosIconsListOffset, inputMime);
 }
 
-void QMimeBinaryProvider::loadGenericIcon(QMimeTypePrivate &data)
+QString QMimeBinaryProvider::genericIcon(const QString &name)
 {
-    const QByteArray inputMime = data.name.toLatin1();
-    const QLatin1StringView icon = iconForMime(m_cacheFile.get(), PosGenericIconsListOffset, inputMime);
-    if (!icon.isEmpty()) {
-        data.genericIconName = icon;
-    }
+    const QByteArray inputMime = name.toLatin1();
+    return iconForMime(m_cacheFile.get(), PosGenericIconsListOffset, inputMime);
 }
 
@@ -695,7 +699,7 @@
 }
 
-QMimeType QMimeXMLProvider::mimeTypeForName(const QString &name)
+bool QMimeXMLProvider::knowsMimeType(const QString &name)
 {
-    return m_nameMimeTypeMap.value(name);
+    return m_nameMimeTypeMap.contains(name);
 }
 
@@ -705,8 +709,6 @@
 }
 
-void QMimeXMLProvider::findByMagic(const QByteArray &data, int *accuracyPtr, QMimeType &candidate)
+void QMimeXMLProvider::findByMagic(const QByteArray &data, int *accuracyPtr, QString *candidate)
 {
-    QString candidateName;
-    bool foundOne = false;
     for (const QMimeMagicRuleMatcher &matcher : std::as_const(m_magicMatchers)) {
         if (matcher.matches(data)) {
@@ -714,11 +716,8 @@
             if (priority > *accuracyPtr) {
                 *accuracyPtr = priority;
-                candidateName = matcher.mimetype();
-                foundOne = true;
+                *candidate = matcher.mimetype();
             }
         }
     }
-    if (foundOne)
-        candidate = mimeTypeForName(candidateName);
 }
 
@@ -750,4 +749,29 @@
 }
 
+QMimeTypePrivate::LocaleHash QMimeXMLProvider::localeComments(const QString &name)
+{
+    return m_nameMimeTypeMap.value(name).localeComments;
+}
+
+bool QMimeXMLProvider::hasGlobDeleteAll(const QString &name)
+{
+    return m_nameMimeTypeMap.value(name).hasGlobDeleteAll;
+}
+
+QStringList QMimeXMLProvider::globPatterns(const QString &name)
+{
+    return m_nameMimeTypeMap.value(name).globPatterns;
+}
+
+QString QMimeXMLProvider::icon(const QString &name)
+{
+    return m_nameMimeTypeMap.value(name).iconName;
+}
+
+QString QMimeXMLProvider::genericIcon(const QString &name)
+{
+    return m_nameMimeTypeMap.value(name).genericIconName;
+}
+
 void QMimeXMLProvider::load(const QString &fileName)
 {
@@ -791,12 +815,9 @@
 }
 
-void QMimeXMLProvider::addMimeType(const QMimeType &mt)
+void QMimeXMLProvider::addMimeType(const QMimeTypeXMLData &mt)
 {
-    Q_ASSERT(!mt.d.data()->fromCache);
-
-    QString name = mt.name();
-    if (mt.d->hasGlobDeleteAll)
-        appendIfNew(m_mimeTypesWithDeletedGlobs, name);
-    m_nameMimeTypeMap.insert(mt.name(), mt);
+    if (mt.hasGlobDeleteAll)
+        appendIfNew(m_mimeTypesWithDeletedGlobs, mt.name);
+    m_nameMimeTypeMap.insert(mt.name, mt);
 }
 
@@ -814,5 +835,5 @@
         auto it = m_nameMimeTypeMap.find(mt);
         if (it != m_nameMimeTypeMap.end())
-            it->d->globPatterns.clear();
+            it->globPatterns.clear();
         m_mimeTypeGlobs.removeMimeType(mt);
     }
@@ -854,5 +875,8 @@
 {
     if (result.isEmpty()) { // fast path
-        result = m_nameMimeTypeMap.values();
+        for (auto it = m_nameMimeTypeMap.constBegin(), end = m_nameMimeTypeMap.constEnd();
+             it != end; ++it) {
+            result.append(QMimeType(QMimeTypePrivate(it.value().name)));
+        }
     } else {
         for (auto it = m_nameMimeTypeMap.constBegin(), end = m_nameMimeTypeMap.constEnd() ; it != end ; ++it) {
@@ -860,5 +884,5 @@
             if (std::find_if(result.constBegin(), result.constEnd(), [newMime](const QMimeType &mime) -> bool { return mime.name() == newMime; })
                     == result.constEnd())
-                result.append(it.value());
+                result.append(QMimeType(QMimeTypePrivate(it.value().name)));
         }
     }
--- a/src/corelib/mimetypes/qmimeprovider_p.h
+++ b/src/corelib/mimetypes/qmimeprovider_p.h
@@ -29,4 +29,5 @@
 
 class QMimeMagicRuleMatcher;
+class QMimeTypeXMLData;
 
 class QMimeProviderBase
@@ -40,16 +41,18 @@
     virtual bool isValid() = 0;
     virtual bool isInternalDatabase() const = 0;
-    virtual QMimeType mimeTypeForName(const QString &name) = 0;
+    virtual bool knowsMimeType(const QString &name) = 0;
     virtual void addFileNameMatches(const QString &fileName, QMimeGlobMatchResult &result) = 0;
     virtual void addParents(const QString &mime, QStringList &result) = 0;
     virtual QString resolveAlias(const QString &name) = 0;
     virtual void addAliases(const QString &name, QStringList &result) = 0;
-    virtual void findByMagic(const QByteArray &data, int *accuracyPtr, QMimeType &candidate) = 0;
+    virtual void findByMagic(const QByteArray &data, int *accuracyPtr, QString *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() {}
-    virtual void excludeMimeTypeGlobs(const QStringList &) {}
+    virtual QMimeTypePrivate::LocaleHash localeComments(const QString &name) = 0;
+    virtual bool hasGlobDeleteAll(const QString &name) = 0;
+    virtual QStringList globPatterns(const QString &name) = 0;
+    virtual QString icon(const QString &name) = 0;
+    virtual QString genericIcon(const QString &name) = 0;
+    virtual void ensureLoaded() { }
+    virtual void excludeMimeTypeGlobs(const QStringList &) { }
 
     QString directory() const { return m_directory; }
@@ -61,7 +64,7 @@
         MimeTypes with "glob-deleteall" tags are handled differently by each provider
         sub-class:
-        - QMimeBinaryProvider parses glob-deleteall tags lazily, i.e. only when loadMimeTypePrivate()
+        - QMimeBinaryProvider parses glob-deleteall tags lazily, i.e. only when hasGlobDeleteAll()
           is called, and clears the glob patterns associated with mimetypes that have this tag
-        - QMimeXMLProvider parses glob-deleteall from the the start, i.e. when a XML file is
+        - QMimeXMLProvider parses glob-deleteall from the start, i.e. when a XML file is
           parsed with QMimeTypeParser
 
@@ -96,14 +99,16 @@
     bool isValid() override;
     bool isInternalDatabase() const override;
-    QMimeType mimeTypeForName(const QString &name) override;
+    bool knowsMimeType(const QString &name) override;
     void addFileNameMatches(const QString &fileName, QMimeGlobMatchResult &result) override;
     void addParents(const QString &mime, QStringList &result) override;
     QString resolveAlias(const QString &name) override;
     void addAliases(const QString &name, QStringList &result) override;
-    void findByMagic(const QByteArray &data, int *accuracyPtr, QMimeType &candidate) override;
+    void findByMagic(const QByteArray &data, int *accuracyPtr, QString *candidate) override;
     void addAllMimeTypes(QList<QMimeType> &result) override;
-    bool loadMimeTypePrivate(QMimeTypePrivate &) override;
-    void loadIcon(QMimeTypePrivate &) override;
-    void loadGenericIcon(QMimeTypePrivate &) override;
+    QMimeTypePrivate::LocaleHash localeComments(const QString &name) override;
+    bool hasGlobDeleteAll(const QString &name) override;
+    QStringList globPatterns(const QString &name) override;
+    QString icon(const QString &name) override;
+    QString genericIcon(const QString &name) override;
     void ensureLoaded() override;
     void excludeMimeTypeGlobs(const QStringList &toExclude) override;
@@ -117,6 +122,7 @@
                          int firstOffset, const QString &fileName, qsizetype charPos,
                          bool caseSensitiveCheck);
-    bool matchMagicRule(CacheFile *cacheFile, int numMatchlets, int firstOffset, const QByteArray &data);
     bool isMimeTypeGlobsExcluded(const char *name);
+    bool matchMagicRule(CacheFile *cacheFile, int numMatchlets, int firstOffset,
+                        const QByteArray &data);
     QLatin1StringView iconForMime(CacheFile *cacheFile, int posListOffset, const QByteArray &inputMime);
     void loadMimeTypeList();
@@ -129,9 +135,12 @@
     struct MimeTypeExtra
     {
-        // Both retrieved on demand in loadMimeTypePrivate
         QHash<QString, QString> localeComments;
         QStringList globPatterns;
+        bool hasGlobDeleteAll = false;
     };
-    QMap<QString, MimeTypeExtra> m_mimetypeExtra;
+    using MimeTypeExtraMap = QMap<QString, MimeTypeExtra>;
+    MimeTypeExtraMap m_mimetypeExtra;
+
+    MimeTypeExtraMap::const_iterator loadMimeTypeExtra(const QString &mimeName);
 };
 
@@ -154,17 +163,22 @@
     bool isValid() override;
     bool isInternalDatabase() const override;
-    QMimeType mimeTypeForName(const QString &name) override;
+    bool knowsMimeType(const QString &name) override;
     void addFileNameMatches(const QString &fileName, QMimeGlobMatchResult &result) override;
     void addParents(const QString &mime, QStringList &result) override;
     QString resolveAlias(const QString &name) override;
     void addAliases(const QString &name, QStringList &result) override;
-    void findByMagic(const QByteArray &data, int *accuracyPtr, QMimeType &candidate) override;
+    void findByMagic(const QByteArray &data, int *accuracyPtr, QString *candidate) override;
     void addAllMimeTypes(QList<QMimeType> &result) override;
     void ensureLoaded() override;
+    QMimeTypePrivate::LocaleHash localeComments(const QString &name) override;
+    bool hasGlobDeleteAll(const QString &name) override;
+    QStringList globPatterns(const QString &name) override;
+    QString icon(const QString &name) override;
+    QString genericIcon(const QString &name) override;
 
     bool load(const QString &fileName, QString *errorMessage);
 
     // Called by the mimetype xml parser
-    void addMimeType(const QMimeType &mt);
+    void addMimeType(const QMimeTypeXMLData &mt);
     void excludeMimeTypeGlobs(const QStringList &toExclude) override;
     void addGlobPattern(const QMimeGlobPattern &glob);
@@ -177,5 +191,5 @@
     void load(const char *data, qsizetype len);
 
-    typedef QHash<QString, QMimeType> NameMimeTypeMap;
+    typedef QHash<QString, QMimeTypeXMLData> NameMimeTypeMap;
     NameMimeTypeMap m_nameMimeTypeMap;
 
--- a/src/corelib/mimetypes/qmimetype.cpp
+++ b/src/corelib/mimetypes/qmimetype.cpp
@@ -7,7 +7,4 @@
 #include "qmimetype_p.h"
 #include "qmimedatabase_p.h"
-#include "qmimeprovider_p.h"
-
-#include "qmimeglobpattern_p.h"
 
 #include <QtCore/QDebug>
@@ -21,31 +18,4 @@
 using namespace Qt::StringLiterals;
 
-QMimeTypePrivate::QMimeTypePrivate()
-    : loaded(false), fromCache(false)
-{}
-
-QMimeTypePrivate::QMimeTypePrivate(const QMimeType &other)
-      : loaded(other.d->loaded),
-        name(other.d->name),
-        localeComments(other.d->localeComments),
-        genericIconName(other.d->genericIconName),
-        iconName(other.d->iconName),
-        globPatterns(other.d->globPatterns)
-{}
-
-void QMimeTypePrivate::clear()
-{
-    name.clear();
-    localeComments.clear();
-    genericIconName.clear();
-    iconName.clear();
-    globPatterns.clear();
-}
-
-void QMimeTypePrivate::addGlobPattern(const QString &pattern)
-{
-    globPatterns.append(pattern);
-}
-
 /*!
     \class QMimeType
@@ -220,5 +190,5 @@
 QString QMimeType::comment() const
 {
-    QMimeDatabasePrivate::instance()->loadMimeTypePrivate(const_cast<QMimeTypePrivate&>(*d));
+    const auto localeComments = QMimeDatabasePrivate::instance()->localeComments(d->name);
 
     QStringList languageList = QLocale().uiLanguages();
@@ -245,5 +215,5 @@
         const QString lang
             = language == "C"_L1 ? u"en_US"_s : QString(language).replace(u'-', u'_');
-        QString comm = d->localeComments.value(lang);
+        QString comm = localeComments.value(lang);
         if (!comm.isEmpty())
             return comm;
@@ -251,5 +221,5 @@
         // If "de_CH" is missing, check for "de" (and similar):
         if (cut != -1) {
-            comm = d->localeComments.value(lang.left(cut));
+            comm = localeComments.value(lang.left(cut));
             if (!comm.isEmpty())
                 return comm;
@@ -277,6 +247,6 @@
 QString QMimeType::genericIconName() const
 {
-    QMimeDatabasePrivate::instance()->loadGenericIcon(const_cast<QMimeTypePrivate&>(*d));
-    if (d->genericIconName.isEmpty()) {
+    QString genericIconName = QMimeDatabasePrivate::instance()->genericIcon(d->name);
+    if (genericIconName.isEmpty()) {
         // From the spec:
         // If the generic icon name is empty (not specified by the mimetype definition)
@@ -291,5 +261,5 @@
         return groupRef + "-x-generic"_L1;
     }
-    return d->genericIconName;
+    return genericIconName;
 }
 
@@ -313,9 +283,9 @@
 QString QMimeType::iconName() const
 {
-    QMimeDatabasePrivate::instance()->loadIcon(const_cast<QMimeTypePrivate&>(*d));
-    if (d->iconName.isEmpty()) {
+    QString iconName = QMimeDatabasePrivate::instance()->icon(d->name);
+    if (iconName.isEmpty()) {
         return make_default_icon_name_from_mimetype_name(name());
     }
-    return d->iconName;
+    return iconName;
 }
 
@@ -329,6 +299,5 @@
 QStringList QMimeType::globPatterns() const
 {
-    QMimeDatabasePrivate::instance()->loadMimeTypePrivate(const_cast<QMimeTypePrivate&>(*d));
-    return d->globPatterns;
+    return QMimeDatabasePrivate::instance()->globPatterns(d->name);
 }
 
@@ -424,8 +393,9 @@
 QStringList QMimeType::suffixes() const
 {
-    QMimeDatabasePrivate::instance()->loadMimeTypePrivate(const_cast<QMimeTypePrivate&>(*d));
+    const QStringList patterns = globPatterns();
 
     QStringList result;
-    for (const QString &pattern : std::as_const(d->globPatterns)) {
+    result.reserve(patterns.size());
+    for (const QString &pattern : patterns) {
         // Not a simple suffix if it looks like: README or *. or *.* or *.JP*G or *.JP?
         if (pattern.startsWith("*."_L1) &&
@@ -467,13 +437,13 @@
 QString QMimeType::filterString() const
 {
-    QMimeDatabasePrivate::instance()->loadMimeTypePrivate(const_cast<QMimeTypePrivate&>(*d));
+    const QStringList patterns = globPatterns();
     QString filter;
 
-    if (!d->globPatterns.empty()) {
+    if (!patterns.empty()) {
         filter += comment() + " ("_L1;
-        for (int i = 0; i < d->globPatterns.size(); ++i) {
+        for (int i = 0; i < patterns.size(); ++i) {
             if (i != 0)
                 filter += u' ';
-            filter += d->globPatterns.at(i);
+            filter += patterns.at(i);
         }
         filter +=  u')';
--- a/src/corelib/mimetypes/qmimetype_p.h
+++ b/src/corelib/mimetypes/qmimetype_p.h
@@ -17,5 +17,5 @@
 
 #include <QtCore/private/qglobal_p.h>
-#include "qmimetype.h"
+#include <QtCore/qshareddata.h>
 
 QT_REQUIRE_CONFIG(mimetype);
@@ -24,4 +24,5 @@
 #include <QtCore/qstringlist.h>
 
+class QMimeBinaryProvider;
 QT_BEGIN_NAMESPACE
 
@@ -31,41 +32,11 @@
     typedef QHash<QString, QString> LocaleHash;
 
-    QMimeTypePrivate();
-    explicit QMimeTypePrivate(const QMimeType &other);
+    QMimeTypePrivate() { }
+    explicit QMimeTypePrivate(const QString &name) : name(name) { }
 
-    void clear();
-
-    void addGlobPattern(const QString &pattern);
-
-    bool loaded; // QSharedData leaves a 4 byte gap, so don't put 8 byte members first
-    bool fromCache; // true if this comes from the binary provider
-    bool hasGlobDeleteAll = false; // true if the mimetype has a glob-deleteall tag
     QString name;
-    LocaleHash localeComments;
-    QString genericIconName;
-    QString iconName;
-    QStringList globPatterns;
 };
 
 QT_END_NAMESPACE
 
-#define QMIMETYPE_BUILDER_FROM_RVALUE_REFS \
-    QT_BEGIN_NAMESPACE \
-    static QMimeType buildQMimeType ( \
-                         QString &&name, \
-                         QString &&genericIconName, \
-                         QString &&iconName, \
-                         QStringList &&globPatterns \
-                     ) \
-    { \
-        QMimeTypePrivate qMimeTypeData; \
-        qMimeTypeData.loaded = true; \
-        qMimeTypeData.name = std::move(name); \
-        qMimeTypeData.genericIconName = std::move(genericIconName); \
-        qMimeTypeData.iconName = std::move(iconName); \
-        qMimeTypeData.globPatterns = std::move(globPatterns); \
-        return QMimeType(qMimeTypeData); \
-    } \
-    QT_END_NAMESPACE
-
-#endif   // QMIMETYPE_P_H
+#endif // QMIMETYPE_P_H
--- a/src/corelib/mimetypes/qmimetypeparser.cpp
+++ b/src/corelib/mimetypes/qmimetypeparser.cpp
@@ -166,6 +166,5 @@
 {
 #if QT_CONFIG(xmlstreamreader)
-    QMimeTypePrivate data;
-    data.loaded = true;
+    QMimeTypeXMLData data;
     int priority = 50;
     QStack<QMimeMagicRule *> currentRules; // stack for the nesting of rules
@@ -274,5 +273,5 @@
             const auto elementName = reader.name();
             if (elementName == QLatin1StringView(mimeTypeTagC)) {
-                if (!process(QMimeType(data), errorMessage))
+                if (!process(data, errorMessage))
                     return false;
                 data.clear();
@@ -315,3 +314,18 @@
 }
 
+void QMimeTypeXMLData::clear()
+{
+    hasGlobDeleteAll = false;
+    name.clear();
+    localeComments.clear();
+    genericIconName.clear();
+    iconName.clear();
+    globPatterns.clear();
+}
+
+void QMimeTypeXMLData::addGlobPattern(const QString &pattern)
+{
+    globPatterns.append(pattern);
+}
+
 QT_END_NAMESPACE
--- a/src/corelib/mimetypes/qmimetypeparser_p.h
+++ b/src/corelib/mimetypes/qmimetypeparser_p.h
@@ -17,5 +17,5 @@
 //
 
-#include "qmimedatabase_p.h"
+#include <QtCore/qtconfigmacros.h>
 
 QT_REQUIRE_CONFIG(mimetype);
@@ -25,4 +25,19 @@
 QT_BEGIN_NAMESPACE
 
+class QMimeTypeXMLData
+{
+public:
+    void clear();
+
+    void addGlobPattern(const QString &pattern);
+
+    bool hasGlobDeleteAll = false; // true if the mimetype has a glob-deleteall tag
+    QString name;
+    QMimeTypePrivate::LocaleHash localeComments;
+    QString genericIconName; // TODO move to a struct that's specific to the XML provider
+    QString iconName; // TODO move to a struct that's specific to the XML provider
+    QStringList globPatterns;
+};
+
 class QIODevice;
 
@@ -40,5 +55,5 @@
 
 protected:
-    virtual bool process(const QMimeType &t, QString *errorMessage) = 0;
+    virtual bool process(const QMimeTypeXMLData &t, QString *errorMessage) = 0;
     virtual bool process(const QMimeGlobPattern &t, QString *errorMessage) = 0;
     virtual void processParent(const QString &child, const QString &parent) = 0;
@@ -74,5 +89,5 @@
 
 protected:
-    inline bool process(const QMimeType &t, QString *) override
+    inline bool process(const QMimeTypeXMLData &t, QString *) override
     { m_provider.addMimeType(t); return true; }
 
