forked from qt-creator/qt-creator
Update mime database from Qt
qtbase/4e9944e6c8a456353d243ab268cb0f01ff006faa QMimeDatabase: collect glob patterns from all locations The original patch needs some adaptions for Qt Creator's custom setPreferredSuffix and setGlobPatternsForMimeType Change-Id: I9a7a2cbe79bd732a63f3a88fc81ff4d0b18c75c8 Reviewed-by: Jarek Kobus <jaroslaw.kobus@qt.io>
This commit is contained in:
@@ -77,10 +77,12 @@ bool MimeDatabasePrivate::shouldCheck()
|
|||||||
return m_forceLoad;
|
return m_forceLoad;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
static QStringList locateMimeDirectories()
|
static QStringList locateMimeDirectories()
|
||||||
{
|
{
|
||||||
return QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("mime"), QStandardPaths::LocateDirectory);
|
return QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("mime"), QStandardPaths::LocateDirectory);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(Q_OS_UNIX) && !defined(Q_OS_NACL) && !defined(Q_OS_INTEGRITY)
|
#if defined(Q_OS_UNIX) && !defined(Q_OS_NACL) && !defined(Q_OS_INTEGRITY)
|
||||||
# define QT_USE_MMAP
|
# define QT_USE_MMAP
|
||||||
@@ -246,9 +248,8 @@ MimeType MimeDatabasePrivate::mimeTypeForName(const QString &nameOrAlias)
|
|||||||
{
|
{
|
||||||
const QString mimeName = resolveAlias(nameOrAlias);
|
const QString mimeName = resolveAlias(nameOrAlias);
|
||||||
for (const auto &provider : providers()) {
|
for (const auto &provider : providers()) {
|
||||||
MimeType mime = provider->mimeTypeForName(mimeName);
|
if (provider->knowsMimeType(mimeName))
|
||||||
if (mime.isValid())
|
return MimeType(MimeTypePrivate(mimeName));
|
||||||
return mime;
|
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@@ -273,54 +274,70 @@ MimeGlobMatchResult MimeDatabasePrivate::findByFileName(const QString &fileName)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MimeDatabasePrivate::loadMimeTypePrivate(MimeTypePrivate &mimePrivate)
|
MimeTypePrivate::LocaleHash MimeDatabasePrivate::localeComments(const QString &name)
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&mutex);
|
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()) {
|
for (const auto &provider : providers()) {
|
||||||
if (provider->loadMimeTypePrivate(mimePrivate)) {
|
auto comments = provider->localeComments(name);
|
||||||
found = true;
|
if (!comments.isEmpty())
|
||||||
break;
|
return comments; // maybe we want to merge in comments from more global providers, in
|
||||||
}
|
// case of more translations?
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void MimeDatabasePrivate::loadGenericIcon(MimeTypePrivate &mimePrivate)
|
QStringList MimeDatabasePrivate::globPatterns(const QString &name)
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&mutex);
|
QMutexLocker locker(&mutex);
|
||||||
if (mimePrivate.fromCache) {
|
QStringList patterns;
|
||||||
mimePrivate.genericIconName.clear();
|
const auto &providerList = providers();
|
||||||
for (const auto &provider : providers()) {
|
// reverse iteration because we start from most global, add up, clear if delete-all, and add up
|
||||||
provider->loadGenericIcon(mimePrivate);
|
// again.
|
||||||
if (!mimePrivate.genericIconName.isEmpty())
|
for (auto rit = providerList.rbegin(); rit != providerList.rend(); ++rit) {
|
||||||
break;
|
auto *provider = rit->get();
|
||||||
|
if (provider->hasGlobDeleteAll(name))
|
||||||
|
patterns.clear();
|
||||||
|
// handle MIME type overriding from Qt Creator
|
||||||
|
if (!provider->m_overriddenMimeTypes.contains(name))
|
||||||
|
patterns += provider->globPatterns(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// added for Qt Creator, overriding preferred suffix (first pattern in the list)
|
||||||
|
const QString preferredSuffix = m_preferredSuffix.value(name);
|
||||||
|
if (!preferredSuffix.isEmpty()) {
|
||||||
|
auto it = std::find_if(patterns.begin(),
|
||||||
|
patterns.end(),
|
||||||
|
[preferredSuffix](const QString &pattern) {
|
||||||
|
return MimeType::suffixFromPattern(pattern) == preferredSuffix;
|
||||||
|
});
|
||||||
|
if (it != patterns.end())
|
||||||
|
patterns.erase(it);
|
||||||
|
patterns.prepend(QLatin1String("*.") + preferredSuffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return patterns;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MimeDatabasePrivate::loadIcon(MimeTypePrivate &mimePrivate)
|
QString MimeDatabasePrivate::genericIcon(const QString &name)
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&mutex);
|
QMutexLocker locker(&mutex);
|
||||||
if (mimePrivate.fromCache) {
|
|
||||||
mimePrivate.iconName.clear();
|
|
||||||
for (const auto &provider : providers()) {
|
for (const auto &provider : providers()) {
|
||||||
provider->loadIcon(mimePrivate);
|
QString genericIconName = provider->genericIcon(name);
|
||||||
if (!mimePrivate.iconName.isEmpty())
|
if (!genericIconName.isEmpty())
|
||||||
break;
|
return genericIconName;
|
||||||
}
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
QString MimeDatabasePrivate::icon(const QString &name)
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&mutex);
|
||||||
|
for (const auto &provider : providers()) {
|
||||||
|
QString iconName = provider->icon(name);
|
||||||
|
if (!iconName.isEmpty())
|
||||||
|
return iconName;
|
||||||
}
|
}
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
QString MimeDatabasePrivate::fallbackParent(const QString &mimeTypeName) const
|
QString MimeDatabasePrivate::fallbackParent(const QString &mimeTypeName) const
|
||||||
@@ -411,12 +428,12 @@ MimeType MimeDatabasePrivate::findByData(const QByteArray &data, int *accuracyPt
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
*accuracyPtr = 0;
|
*accuracyPtr = 0;
|
||||||
MimeType candidate;
|
QString candidate;
|
||||||
for (const auto &provider : providers())
|
for (const auto &provider : providers())
|
||||||
provider->findByMagic(data, accuracyPtr, candidate);
|
provider->findByMagic(data, accuracyPtr, &candidate);
|
||||||
|
|
||||||
if (candidate.isValid())
|
if (!candidate.isEmpty())
|
||||||
return candidate;
|
return MimeType(MimeTypePrivate(candidate));
|
||||||
|
|
||||||
if (isTextFile(data)) {
|
if (isTextFile(data)) {
|
||||||
*accuracyPtr = 5;
|
*accuracyPtr = 5;
|
||||||
@@ -937,6 +954,12 @@ void MimeDatabasePrivate::setGlobPatternsForMimeType(const MimeType &mimeType,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MimeDatabasePrivate::setPreferredSuffix(const QString &mimeName, const QString &suffix)
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&mutex);
|
||||||
|
m_preferredSuffix.insert(mimeName, suffix);
|
||||||
|
}
|
||||||
|
|
||||||
void MimeDatabasePrivate::checkInitPhase(const QString &info)
|
void MimeDatabasePrivate::checkInitPhase(const QString &info)
|
||||||
{
|
{
|
||||||
QReadLocker locker(&m_initMutex);
|
QReadLocker locker(&m_initMutex);
|
||||||
|
@@ -70,9 +70,10 @@ public:
|
|||||||
MimeGlobMatchResult findByFileName(const QString &fileName);
|
MimeGlobMatchResult findByFileName(const QString &fileName);
|
||||||
|
|
||||||
// API for MimeType. Takes care of locking the mutex.
|
// API for MimeType. Takes care of locking the mutex.
|
||||||
void loadMimeTypePrivate(MimeTypePrivate &mimePrivate);
|
MimeTypePrivate::LocaleHash localeComments(const QString &name);
|
||||||
void loadGenericIcon(MimeTypePrivate &mimePrivate);
|
QStringList globPatterns(const QString &name);
|
||||||
void loadIcon(MimeTypePrivate &mimePrivate);
|
QString genericIcon(const QString &name);
|
||||||
|
QString icon(const QString &name);
|
||||||
QStringList mimeParents(const QString &mimeName);
|
QStringList mimeParents(const QString &mimeName);
|
||||||
QStringList listAliases(const QString &mimeName);
|
QStringList listAliases(const QString &mimeName);
|
||||||
bool mimeInherits(const QString &mime, const QString &parent);
|
bool mimeInherits(const QString &mime, const QString &parent);
|
||||||
@@ -83,6 +84,7 @@ public:
|
|||||||
void setMagicRulesForMimeType(const MimeType &mimeType,
|
void setMagicRulesForMimeType(const MimeType &mimeType,
|
||||||
const QMap<int, QList<MimeMagicRule>> &rules);
|
const QMap<int, QList<MimeMagicRule>> &rules);
|
||||||
void setGlobPatternsForMimeType(const MimeType &mimeType, const QStringList &patterns);
|
void setGlobPatternsForMimeType(const MimeType &mimeType, const QStringList &patterns);
|
||||||
|
void setPreferredSuffix(const QString &mimeName, const QString &suffix);
|
||||||
void checkInitPhase(const QString &info);
|
void checkInitPhase(const QString &info);
|
||||||
void addInitializer(const std::function<void()> &init);
|
void addInitializer(const std::function<void()> &init);
|
||||||
|
|
||||||
@@ -94,7 +96,7 @@ private:
|
|||||||
QString fallbackParent(const QString &mimeTypeName) const;
|
QString fallbackParent(const QString &mimeTypeName) const;
|
||||||
|
|
||||||
const QString m_defaultMimeType;
|
const QString m_defaultMimeType;
|
||||||
mutable Providers m_providers;
|
mutable Providers m_providers; // most local first, most global last
|
||||||
QElapsedTimer m_lastCheck;
|
QElapsedTimer m_lastCheck;
|
||||||
|
|
||||||
// added for Qt Creator
|
// added for Qt Creator
|
||||||
@@ -109,6 +111,7 @@ public:
|
|||||||
QReadWriteLock m_initMutex;
|
QReadWriteLock m_initMutex;
|
||||||
std::atomic_bool m_initialized = false;
|
std::atomic_bool m_initialized = false;
|
||||||
int m_startupPhase = 0;
|
int m_startupPhase = 0;
|
||||||
|
QHash<QString, QString> m_preferredSuffix; // MIME name -> suffix
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Utils
|
} // namespace Utils
|
||||||
|
@@ -186,25 +186,11 @@ void MimeBinaryProvider::ensureLoaded()
|
|||||||
m_cacheFile.reset();
|
m_cacheFile.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
static MimeType mimeTypeForNameUnchecked(const QString &name)
|
bool MimeBinaryProvider::knowsMimeType(const QString &name)
|
||||||
{
|
|
||||||
MimeTypePrivate 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 MimeType(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
MimeType MimeBinaryProvider::mimeTypeForName(const QString &name)
|
|
||||||
{
|
{
|
||||||
if (!m_mimetypeListLoaded)
|
if (!m_mimetypeListLoaded)
|
||||||
loadMimeTypeList();
|
loadMimeTypeList();
|
||||||
if (!m_mimetypeNames.contains(name))
|
return m_mimetypeNames.contains(name);
|
||||||
return MimeType(); // unknown mimetype
|
|
||||||
return mimeTypeForNameUnchecked(name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MimeBinaryProvider::addFileNameMatches(const QString &fileName, MimeGlobMatchResult &result)
|
void MimeBinaryProvider::addFileNameMatches(const QString &fileName, MimeGlobMatchResult &result)
|
||||||
@@ -368,7 +354,7 @@ bool MimeBinaryProvider::matchMagicRule(MimeBinaryProvider::CacheFile *cacheFile
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MimeBinaryProvider::findByMagic(const QByteArray &data, int *accuracyPtr, MimeType &candidate)
|
void MimeBinaryProvider::findByMagic(const QByteArray &data, int *accuracyPtr, QString *candidate)
|
||||||
{
|
{
|
||||||
const int magicListOffset = m_cacheFile->getUint32(PosMagicListOffset);
|
const int magicListOffset = m_cacheFile->getUint32(PosMagicListOffset);
|
||||||
const int numMatches = m_cacheFile->getUint32(magicListOffset);
|
const int numMatches = m_cacheFile->getUint32(magicListOffset);
|
||||||
@@ -387,7 +373,7 @@ void MimeBinaryProvider::findByMagic(const QByteArray &data, int *accuracyPtr, M
|
|||||||
*accuracyPtr = m_cacheFile->getUint32(off);
|
*accuracyPtr = m_cacheFile->getUint32(off);
|
||||||
// Return the first match. We have no rules for conflicting magic data...
|
// 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?)
|
// (mime.cache itself is sorted, but what about local overrides with a lower prio?)
|
||||||
candidate = mimeTypeForNameUnchecked(QLatin1StringView(mimeType));
|
*candidate = QString::fromLatin1(mimeType);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -496,35 +482,63 @@ void MimeBinaryProvider::addAllMimeTypes(QList<MimeType> &result)
|
|||||||
if (result.isEmpty()) {
|
if (result.isEmpty()) {
|
||||||
result.reserve(m_mimetypeNames.size());
|
result.reserve(m_mimetypeNames.size());
|
||||||
for (const QString &name : std::as_const(m_mimetypeNames))
|
for (const QString &name : std::as_const(m_mimetypeNames))
|
||||||
result.append(mimeTypeForNameUnchecked(name));
|
result.append(MimeType(MimeTypePrivate(name)));
|
||||||
} else {
|
} else {
|
||||||
for (const QString &name : std::as_const(m_mimetypeNames))
|
for (const QString &name : std::as_const(m_mimetypeNames))
|
||||||
if (std::find_if(result.constBegin(), result.constEnd(), [name](const MimeType &mime) -> bool { return mime.name() == name; })
|
if (std::find_if(result.constBegin(), result.constEnd(), [name](const MimeType &mime) -> bool { return mime.name() == name; })
|
||||||
== result.constEnd())
|
== result.constEnd())
|
||||||
result.append(mimeTypeForNameUnchecked(name));
|
result.append(MimeType(MimeTypePrivate(name)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MimeBinaryProvider::loadMimeTypePrivate(MimeTypePrivate &data)
|
MimeTypePrivate::LocaleHash MimeBinaryProvider::localeComments(const QString &name)
|
||||||
|
{
|
||||||
|
MimeTypeExtraMap::const_iterator it = loadMimeTypeExtra(name);
|
||||||
|
if (it != m_mimetypeExtra.constEnd()) {
|
||||||
|
const MimeTypeExtra &e = it.value();
|
||||||
|
return e.localeComments;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MimeBinaryProvider::hasGlobDeleteAll(const QString &name)
|
||||||
|
{
|
||||||
|
MimeTypeExtraMap::const_iterator it = loadMimeTypeExtra(name);
|
||||||
|
if (it != m_mimetypeExtra.constEnd()) {
|
||||||
|
const MimeTypeExtra &e = it.value();
|
||||||
|
return e.hasGlobDeleteAll;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList MimeBinaryProvider::globPatterns(const QString &name)
|
||||||
|
{
|
||||||
|
MimeTypeExtraMap::const_iterator it = loadMimeTypeExtra(name);
|
||||||
|
if (it != m_mimetypeExtra.constEnd()) {
|
||||||
|
const MimeTypeExtra &e = it.value();
|
||||||
|
return e.globPatterns;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
MimeBinaryProvider::MimeTypeExtraMap::const_iterator
|
||||||
|
MimeBinaryProvider::loadMimeTypeExtra(const QString &mimeName)
|
||||||
{
|
{
|
||||||
#if QT_CONFIG(xmlstreamreader)
|
#if QT_CONFIG(xmlstreamreader)
|
||||||
if (data.loaded)
|
auto it = m_mimetypeExtra.constFind(mimeName);
|
||||||
return true;
|
|
||||||
|
|
||||||
auto it = m_mimetypeExtra.constFind(data.name);
|
|
||||||
if (it == m_mimetypeExtra.constEnd()) {
|
if (it == m_mimetypeExtra.constEnd()) {
|
||||||
// load comment and globPatterns
|
// load comment and globPatterns
|
||||||
|
|
||||||
// shared-mime-info since 1.3 lowercases the xml files
|
// 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 (!QFileInfo::exists(mimeFile))
|
if (!QFileInfo::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);
|
QFile qfile(mimeFile);
|
||||||
if (!qfile.open(QFile::ReadOnly))
|
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;
|
it = insertIt;
|
||||||
MimeTypeExtra &extra = insertIt.value();
|
MimeTypeExtra &extra = insertIt.value();
|
||||||
QString mainPattern;
|
QString mainPattern;
|
||||||
@@ -532,13 +546,13 @@ bool MimeBinaryProvider::loadMimeTypePrivate(MimeTypePrivate &data)
|
|||||||
QXmlStreamReader xml(&qfile);
|
QXmlStreamReader xml(&qfile);
|
||||||
if (xml.readNextStartElement()) {
|
if (xml.readNextStartElement()) {
|
||||||
if (xml.name() != "mime-type"_L1) {
|
if (xml.name() != "mime-type"_L1) {
|
||||||
return false;
|
return m_mimetypeExtra.constEnd();
|
||||||
}
|
}
|
||||||
const auto name = xml.attributes().value("type"_L1);
|
const auto name = xml.attributes().value("type"_L1);
|
||||||
if (name.isEmpty())
|
if (name.isEmpty())
|
||||||
return false;
|
return m_mimetypeExtra.constEnd();
|
||||||
if (name.compare(data.name, Qt::CaseInsensitive))
|
if (name.compare(mimeName, Qt::CaseInsensitive))
|
||||||
qWarning() << "Got name" << name << "in file" << mimeFile << "expected" << data.name;
|
qWarning() << "Got name" << name << "in file" << mimeFile << "expected" << mimeName;
|
||||||
|
|
||||||
while (xml.readNextStartElement()) {
|
while (xml.readNextStartElement()) {
|
||||||
const auto tag = xml.name();
|
const auto tag = xml.name();
|
||||||
@@ -551,8 +565,7 @@ bool MimeBinaryProvider::loadMimeTypePrivate(MimeTypePrivate &data)
|
|||||||
extra.localeComments.insert(lang, text);
|
extra.localeComments.insert(lang, text);
|
||||||
continue; // we called readElementText, so we're at the EndElement already.
|
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
|
} else if (tag == "glob-deleteall"_L1) { // as written out by shared-mime-info >= 0.70
|
||||||
extra.globPatterns.clear();
|
extra.hasGlobDeleteAll = true;
|
||||||
mainPattern.clear();
|
|
||||||
} else if (tag == "glob"_L1) { // as written out by shared-mime-info >= 0.70
|
} else if (tag == "glob"_L1) { // as written out by shared-mime-info >= 0.70
|
||||||
const QString pattern = xml.attributes().value("pattern"_L1).toString();
|
const QString pattern = xml.attributes().value("pattern"_L1).toString();
|
||||||
if (mainPattern.isEmpty() && pattern.startsWith(u'*')) {
|
if (mainPattern.isEmpty() && pattern.startsWith(u'*')) {
|
||||||
@@ -574,14 +587,11 @@ bool MimeBinaryProvider::loadMimeTypePrivate(MimeTypePrivate &data)
|
|||||||
extra.globPatterns.prepend(mainPattern);
|
extra.globPatterns.prepend(mainPattern);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const MimeTypeExtra &e = it.value();
|
return it;
|
||||||
data.localeComments = e.localeComments;
|
|
||||||
data.globPatterns = e.globPatterns;
|
|
||||||
return true;
|
|
||||||
#else
|
#else
|
||||||
Q_UNUSED(data);
|
Q_UNUSED(mimeName);
|
||||||
qWarning("Cannot load mime type since QXmlStreamReader is not available.");
|
qWarning("Cannot load mime type since QXmlStreamReader is not available.");
|
||||||
return false;
|
return m_mimetypeExtra.constEnd();
|
||||||
#endif // feature xmlstreamreader
|
#endif // feature xmlstreamreader
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -611,22 +621,16 @@ QLatin1StringView MimeBinaryProvider::iconForMime(CacheFile *cacheFile, int posL
|
|||||||
return QLatin1StringView();
|
return QLatin1StringView();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MimeBinaryProvider::loadIcon(MimeTypePrivate &data)
|
QString MimeBinaryProvider::icon(const QString &name)
|
||||||
{
|
{
|
||||||
const QByteArray inputMime = data.name.toLatin1();
|
const QByteArray inputMime = name.toLatin1();
|
||||||
const QLatin1StringView icon = iconForMime(m_cacheFile.get(), PosIconsListOffset, inputMime);
|
return iconForMime(m_cacheFile.get(), PosIconsListOffset, inputMime);
|
||||||
if (!icon.isEmpty()) {
|
|
||||||
data.iconName = icon;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MimeBinaryProvider::loadGenericIcon(MimeTypePrivate &data)
|
QString MimeBinaryProvider::genericIcon(const QString &name)
|
||||||
{
|
{
|
||||||
const QByteArray inputMime = data.name.toLatin1();
|
const QByteArray inputMime = name.toLatin1();
|
||||||
const QLatin1StringView icon = iconForMime(m_cacheFile.get(), PosGenericIconsListOffset, inputMime);
|
return iconForMime(m_cacheFile.get(), PosGenericIconsListOffset, inputMime);
|
||||||
if (!icon.isEmpty()) {
|
|
||||||
data.genericIconName = icon;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////
|
////
|
||||||
@@ -722,9 +726,9 @@ bool MimeXMLProvider::isInternalDatabase() const
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
MimeType MimeXMLProvider::mimeTypeForName(const QString &name)
|
bool MimeXMLProvider::knowsMimeType(const QString &name)
|
||||||
{
|
{
|
||||||
return m_nameMimeTypeMap.value(name);
|
return m_nameMimeTypeMap.contains(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MimeXMLProvider::addFileNameMatches(const QString &fileName, MimeGlobMatchResult &result)
|
void MimeXMLProvider::addFileNameMatches(const QString &fileName, MimeGlobMatchResult &result)
|
||||||
@@ -732,10 +736,8 @@ void MimeXMLProvider::addFileNameMatches(const QString &fileName, MimeGlobMatchR
|
|||||||
m_mimeTypeGlobs.matchingGlobs(fileName, result, m_overriddenMimeTypes);
|
m_mimeTypeGlobs.matchingGlobs(fileName, result, m_overriddenMimeTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MimeXMLProvider::findByMagic(const QByteArray &data, int *accuracyPtr, MimeType &candidate)
|
void MimeXMLProvider::findByMagic(const QByteArray &data, int *accuracyPtr, QString *candidate)
|
||||||
{
|
{
|
||||||
QString candidateName;
|
|
||||||
bool foundOne = false;
|
|
||||||
for (const MimeMagicRuleMatcher &matcher : std::as_const(m_magicMatchers)) {
|
for (const MimeMagicRuleMatcher &matcher : std::as_const(m_magicMatchers)) {
|
||||||
if (m_overriddenMimeTypes.contains(matcher.mimetype()))
|
if (m_overriddenMimeTypes.contains(matcher.mimetype()))
|
||||||
continue;
|
continue;
|
||||||
@@ -743,13 +745,10 @@ void MimeXMLProvider::findByMagic(const QByteArray &data, int *accuracyPtr, Mime
|
|||||||
const int priority = matcher.priority();
|
const int priority = matcher.priority();
|
||||||
if (priority > *accuracyPtr) {
|
if (priority > *accuracyPtr) {
|
||||||
*accuracyPtr = priority;
|
*accuracyPtr = priority;
|
||||||
candidateName = matcher.mimetype();
|
*candidate = matcher.mimetype();
|
||||||
foundOne = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (foundOne)
|
|
||||||
candidate = mimeTypeForName(candidateName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MimeXMLProvider::ensureLoaded()
|
void MimeXMLProvider::ensureLoaded()
|
||||||
@@ -779,6 +778,31 @@ void MimeXMLProvider::ensureLoaded()
|
|||||||
load(file);
|
load(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MimeTypePrivate::LocaleHash MimeXMLProvider::localeComments(const QString &name)
|
||||||
|
{
|
||||||
|
return m_nameMimeTypeMap.value(name).localeComments;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MimeXMLProvider::hasGlobDeleteAll(const QString &name)
|
||||||
|
{
|
||||||
|
return m_nameMimeTypeMap.value(name).hasGlobDeleteAll;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList MimeXMLProvider::globPatterns(const QString &name)
|
||||||
|
{
|
||||||
|
return m_nameMimeTypeMap.value(name).globPatterns;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString MimeXMLProvider::icon(const QString &name)
|
||||||
|
{
|
||||||
|
return m_nameMimeTypeMap.value(name).iconName;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString MimeXMLProvider::genericIcon(const QString &name)
|
||||||
|
{
|
||||||
|
return m_nameMimeTypeMap.value(name).genericIconName;
|
||||||
|
}
|
||||||
|
|
||||||
void MimeXMLProvider::load(const QString &fileName)
|
void MimeXMLProvider::load(const QString &fileName)
|
||||||
{
|
{
|
||||||
QString errorMessage;
|
QString errorMessage;
|
||||||
@@ -820,14 +844,11 @@ void MimeXMLProvider::addGlobPattern(const MimeGlobPattern &glob)
|
|||||||
m_mimeTypeGlobs.addGlob(glob);
|
m_mimeTypeGlobs.addGlob(glob);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MimeXMLProvider::addMimeType(const MimeType &mt)
|
void MimeXMLProvider::addMimeType(const MimeTypeXMLData &mt)
|
||||||
{
|
{
|
||||||
Q_ASSERT(!mt.d.data()->fromCache);
|
if (mt.hasGlobDeleteAll)
|
||||||
|
appendIfNew(m_mimeTypesWithDeletedGlobs, mt.name);
|
||||||
QString name = mt.name();
|
m_nameMimeTypeMap.insert(mt.name, mt);
|
||||||
if (mt.d->hasGlobDeleteAll)
|
|
||||||
appendIfNew(m_mimeTypesWithDeletedGlobs, name);
|
|
||||||
m_nameMimeTypeMap.insert(mt.name(), mt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -843,7 +864,7 @@ void MimeXMLProvider::excludeMimeTypeGlobs(const QStringList &toExclude)
|
|||||||
for (const auto &mt : toExclude) {
|
for (const auto &mt : toExclude) {
|
||||||
auto it = m_nameMimeTypeMap.find(mt);
|
auto it = m_nameMimeTypeMap.find(mt);
|
||||||
if (it != m_nameMimeTypeMap.end())
|
if (it != m_nameMimeTypeMap.end())
|
||||||
it->d->globPatterns.clear();
|
it->globPatterns.clear();
|
||||||
m_mimeTypeGlobs.removeMimeType(mt);
|
m_mimeTypeGlobs.removeMimeType(mt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -883,13 +904,16 @@ void MimeXMLProvider::addAlias(const QString &alias, const QString &name)
|
|||||||
void MimeXMLProvider::addAllMimeTypes(QList<MimeType> &result)
|
void MimeXMLProvider::addAllMimeTypes(QList<MimeType> &result)
|
||||||
{
|
{
|
||||||
if (result.isEmpty()) { // fast path
|
if (result.isEmpty()) { // fast path
|
||||||
result = m_nameMimeTypeMap.values();
|
for (auto it = m_nameMimeTypeMap.constBegin(), end = m_nameMimeTypeMap.constEnd();
|
||||||
|
it != end; ++it) {
|
||||||
|
result.append(MimeType(MimeTypePrivate(it.value().name)));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
for (auto it = m_nameMimeTypeMap.constBegin(), end = m_nameMimeTypeMap.constEnd() ; it != end ; ++it) {
|
for (auto it = m_nameMimeTypeMap.constBegin(), end = m_nameMimeTypeMap.constEnd() ; it != end ; ++it) {
|
||||||
const QString newMime = it.key();
|
const QString newMime = it.key();
|
||||||
if (std::find_if(result.constBegin(), result.constEnd(), [newMime](const MimeType &mime) -> bool { return mime.name() == newMime; })
|
if (std::find_if(result.constBegin(), result.constEnd(), [newMime](const MimeType &mime) -> bool { return mime.name() == newMime; })
|
||||||
== result.constEnd())
|
== result.constEnd())
|
||||||
result.append(it.value());
|
result.append(MimeType(MimeTypePrivate(it.value().name)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1003,9 +1027,7 @@ void MimeXMLProvider::setGlobPatternsForMimeType(const MimeType &mimeType,
|
|||||||
// add new patterns as case-insensitive default-weight patterns
|
// add new patterns as case-insensitive default-weight patterns
|
||||||
for (const QString &pattern : patterns)
|
for (const QString &pattern : patterns)
|
||||||
addGlobPattern(MimeGlobPattern(pattern, mimeType.name()));
|
addGlobPattern(MimeGlobPattern(pattern, mimeType.name()));
|
||||||
// the following is safe, because for XML provider mimetype private is always "loaded"
|
m_nameMimeTypeMap[mimeType.name()].globPatterns = patterns;
|
||||||
// (see comment in MimeDatabasePrivate::loadMimeTypePrivate)
|
|
||||||
mimeType.d->globPatterns = patterns;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Utils
|
} // namespace Utils
|
||||||
|
@@ -25,6 +25,7 @@
|
|||||||
namespace Utils {
|
namespace Utils {
|
||||||
|
|
||||||
class MimeMagicRuleMatcher;
|
class MimeMagicRuleMatcher;
|
||||||
|
class MimeTypeXMLData;
|
||||||
|
|
||||||
class MimeProviderBase
|
class MimeProviderBase
|
||||||
{
|
{
|
||||||
@@ -36,18 +37,20 @@ public:
|
|||||||
|
|
||||||
virtual bool isValid() = 0;
|
virtual bool isValid() = 0;
|
||||||
virtual bool isInternalDatabase() const = 0;
|
virtual bool isInternalDatabase() const = 0;
|
||||||
virtual MimeType mimeTypeForName(const QString &name) = 0;
|
virtual bool knowsMimeType(const QString &name) = 0;
|
||||||
virtual void addFileNameMatches(const QString &fileName, MimeGlobMatchResult &result) = 0;
|
virtual void addFileNameMatches(const QString &fileName, MimeGlobMatchResult &result) = 0;
|
||||||
virtual void addParents(const QString &mime, QStringList &result) = 0;
|
virtual void addParents(const QString &mime, QStringList &result) = 0;
|
||||||
virtual QString resolveAlias(const QString &name) = 0;
|
virtual QString resolveAlias(const QString &name) = 0;
|
||||||
virtual void addAliases(const QString &name, QStringList &result) = 0;
|
virtual void addAliases(const QString &name, QStringList &result) = 0;
|
||||||
virtual void findByMagic(const QByteArray &data, int *accuracyPtr, MimeType &candidate) = 0;
|
virtual void findByMagic(const QByteArray &data, int *accuracyPtr, QString *candidate) = 0;
|
||||||
virtual void addAllMimeTypes(QList<MimeType> &result) = 0;
|
virtual void addAllMimeTypes(QList<MimeType> &result) = 0;
|
||||||
virtual bool loadMimeTypePrivate(MimeTypePrivate &) { return false; }
|
virtual MimeTypePrivate::LocaleHash localeComments(const QString &name) = 0;
|
||||||
virtual void loadIcon(MimeTypePrivate &) {}
|
virtual bool hasGlobDeleteAll(const QString &name) = 0;
|
||||||
virtual void loadGenericIcon(MimeTypePrivate &) {}
|
virtual QStringList globPatterns(const QString &name) = 0;
|
||||||
virtual void ensureLoaded() {}
|
virtual QString icon(const QString &name) = 0;
|
||||||
virtual void excludeMimeTypeGlobs(const QStringList &) {}
|
virtual QString genericIcon(const QString &name) = 0;
|
||||||
|
virtual void ensureLoaded() { }
|
||||||
|
virtual void excludeMimeTypeGlobs(const QStringList &) { }
|
||||||
|
|
||||||
QString directory() const { return m_directory; }
|
QString directory() const { return m_directory; }
|
||||||
|
|
||||||
@@ -66,9 +69,9 @@ public:
|
|||||||
/*
|
/*
|
||||||
MimeTypes with "glob-deleteall" tags are handled differently by each provider
|
MimeTypes with "glob-deleteall" tags are handled differently by each provider
|
||||||
sub-class:
|
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
|
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
|
parsed with QMimeTypeParser
|
||||||
|
|
||||||
The two lists below are used to let both provider types (XML and Binary) communicate
|
The two lists below are used to let both provider types (XML and Binary) communicate
|
||||||
@@ -104,16 +107,18 @@ public:
|
|||||||
|
|
||||||
bool isValid() override;
|
bool isValid() override;
|
||||||
bool isInternalDatabase() const override;
|
bool isInternalDatabase() const override;
|
||||||
MimeType mimeTypeForName(const QString &name) override;
|
bool knowsMimeType(const QString &name) override;
|
||||||
void addFileNameMatches(const QString &fileName, MimeGlobMatchResult &result) override;
|
void addFileNameMatches(const QString &fileName, MimeGlobMatchResult &result) override;
|
||||||
void addParents(const QString &mime, QStringList &result) override;
|
void addParents(const QString &mime, QStringList &result) override;
|
||||||
QString resolveAlias(const QString &name) override;
|
QString resolveAlias(const QString &name) override;
|
||||||
void addAliases(const QString &name, QStringList &result) override;
|
void addAliases(const QString &name, QStringList &result) override;
|
||||||
void findByMagic(const QByteArray &data, int *accuracyPtr, MimeType &candidate) override;
|
void findByMagic(const QByteArray &data, int *accuracyPtr, QString *candidate) override;
|
||||||
void addAllMimeTypes(QList<MimeType> &result) override;
|
void addAllMimeTypes(QList<MimeType> &result) override;
|
||||||
bool loadMimeTypePrivate(MimeTypePrivate &) override;
|
MimeTypePrivate::LocaleHash localeComments(const QString &name) override;
|
||||||
void loadIcon(MimeTypePrivate &) override;
|
bool hasGlobDeleteAll(const QString &name) override;
|
||||||
void loadGenericIcon(MimeTypePrivate &) override;
|
QStringList globPatterns(const QString &name) override;
|
||||||
|
QString icon(const QString &name) override;
|
||||||
|
QString genericIcon(const QString &name) override;
|
||||||
void ensureLoaded() override;
|
void ensureLoaded() override;
|
||||||
void excludeMimeTypeGlobs(const QStringList &toExclude) override;
|
void excludeMimeTypeGlobs(const QStringList &toExclude) override;
|
||||||
|
|
||||||
@@ -137,8 +142,9 @@ private:
|
|||||||
const QString &fileName,
|
const QString &fileName,
|
||||||
qsizetype charPos,
|
qsizetype charPos,
|
||||||
bool caseSensitiveCheck);
|
bool caseSensitiveCheck);
|
||||||
bool matchMagicRule(CacheFile *cacheFile, int numMatchlets, int firstOffset, const QByteArray &data);
|
|
||||||
bool isMimeTypeGlobsExcluded(const char *name);
|
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);
|
QLatin1StringView iconForMime(CacheFile *cacheFile, int posListOffset, const QByteArray &inputMime);
|
||||||
void loadMimeTypeList();
|
void loadMimeTypeList();
|
||||||
bool checkCacheChanged();
|
bool checkCacheChanged();
|
||||||
@@ -149,11 +155,14 @@ private:
|
|||||||
bool m_mimetypeListLoaded;
|
bool m_mimetypeListLoaded;
|
||||||
struct MimeTypeExtra
|
struct MimeTypeExtra
|
||||||
{
|
{
|
||||||
// Both retrieved on demand in loadMimeTypePrivate
|
|
||||||
QHash<QString, QString> localeComments;
|
QHash<QString, QString> localeComments;
|
||||||
QStringList globPatterns;
|
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);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -176,19 +185,24 @@ public:
|
|||||||
|
|
||||||
bool isValid() override;
|
bool isValid() override;
|
||||||
bool isInternalDatabase() const override;
|
bool isInternalDatabase() const override;
|
||||||
MimeType mimeTypeForName(const QString &name) override;
|
bool knowsMimeType(const QString &name) override;
|
||||||
void addFileNameMatches(const QString &fileName, MimeGlobMatchResult &result) override;
|
void addFileNameMatches(const QString &fileName, MimeGlobMatchResult &result) override;
|
||||||
void addParents(const QString &mime, QStringList &result) override;
|
void addParents(const QString &mime, QStringList &result) override;
|
||||||
QString resolveAlias(const QString &name) override;
|
QString resolveAlias(const QString &name) override;
|
||||||
void addAliases(const QString &name, QStringList &result) override;
|
void addAliases(const QString &name, QStringList &result) override;
|
||||||
void findByMagic(const QByteArray &data, int *accuracyPtr, MimeType &candidate) override;
|
void findByMagic(const QByteArray &data, int *accuracyPtr, QString *candidate) override;
|
||||||
void addAllMimeTypes(QList<MimeType> &result) override;
|
void addAllMimeTypes(QList<MimeType> &result) override;
|
||||||
void ensureLoaded() override;
|
void ensureLoaded() override;
|
||||||
|
MimeTypePrivate::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);
|
bool load(const QString &fileName, QString *errorMessage);
|
||||||
|
|
||||||
// Called by the mimetype xml parser
|
// Called by the mimetype xml parser
|
||||||
void addMimeType(const MimeType &mt);
|
void addMimeType(const MimeTypeXMLData &mt);
|
||||||
void excludeMimeTypeGlobs(const QStringList &toExclude) override;
|
void excludeMimeTypeGlobs(const QStringList &toExclude) override;
|
||||||
void addGlobPattern(const MimeGlobPattern &glob);
|
void addGlobPattern(const MimeGlobPattern &glob);
|
||||||
void addParent(const QString &child, const QString &parent);
|
void addParent(const QString &child, const QString &parent);
|
||||||
@@ -207,7 +221,7 @@ private:
|
|||||||
void load(const QString &fileName);
|
void load(const QString &fileName);
|
||||||
void load(const char *data, qsizetype len);
|
void load(const char *data, qsizetype len);
|
||||||
|
|
||||||
typedef QHash<QString, MimeType> NameMimeTypeMap;
|
typedef QHash<QString, MimeTypeXMLData> NameMimeTypeMap;
|
||||||
NameMimeTypeMap m_nameMimeTypeMap;
|
NameMimeTypeMap m_nameMimeTypeMap;
|
||||||
|
|
||||||
typedef QHash<QString, QString> AliasHash;
|
typedef QHash<QString, QString> AliasHash;
|
||||||
|
@@ -6,9 +6,6 @@
|
|||||||
|
|
||||||
#include "mimetype_p.h"
|
#include "mimetype_p.h"
|
||||||
#include "mimedatabase_p.h"
|
#include "mimedatabase_p.h"
|
||||||
#include "mimeprovider_p.h"
|
|
||||||
|
|
||||||
#include "mimeglobpattern_p.h"
|
|
||||||
|
|
||||||
#include <QtCore/QDebug>
|
#include <QtCore/QDebug>
|
||||||
#include <QtCore/QLocale>
|
#include <QtCore/QLocale>
|
||||||
@@ -20,7 +17,7 @@ using namespace Qt::StringLiterals;
|
|||||||
|
|
||||||
namespace Utils {
|
namespace Utils {
|
||||||
|
|
||||||
static QString suffixFromPattern(const QString &pattern)
|
QString MimeType::suffixFromPattern(const QString &pattern)
|
||||||
{
|
{
|
||||||
// Not a simple suffix if it looks like: README or *. or *.* or *.JP*G or *.JP?
|
// Not a simple suffix if it looks like: README or *. or *.* or *.JP*G or *.JP?
|
||||||
if (pattern.startsWith("*."_L1) &&
|
if (pattern.startsWith("*."_L1) &&
|
||||||
@@ -31,33 +28,6 @@ static QString suffixFromPattern(const QString &pattern)
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
MimeTypePrivate::MimeTypePrivate()
|
|
||||||
: loaded(false), fromCache(false)
|
|
||||||
{}
|
|
||||||
|
|
||||||
MimeTypePrivate::MimeTypePrivate(const MimeType &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 MimeTypePrivate::clear()
|
|
||||||
{
|
|
||||||
name.clear();
|
|
||||||
localeComments.clear();
|
|
||||||
genericIconName.clear();
|
|
||||||
iconName.clear();
|
|
||||||
globPatterns.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MimeTypePrivate::addGlobPattern(const QString &pattern)
|
|
||||||
{
|
|
||||||
globPatterns.append(pattern);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\class MimeType
|
\class MimeType
|
||||||
\inmodule QtCore
|
\inmodule QtCore
|
||||||
@@ -230,7 +200,7 @@ QString MimeType::name() const
|
|||||||
*/
|
*/
|
||||||
QString MimeType::comment() const
|
QString MimeType::comment() const
|
||||||
{
|
{
|
||||||
MimeDatabasePrivate::instance()->loadMimeTypePrivate(const_cast<MimeTypePrivate&>(*d));
|
const auto localeComments = MimeDatabasePrivate::instance()->localeComments(d->name);
|
||||||
|
|
||||||
QStringList languageList = QLocale().uiLanguages();
|
QStringList languageList = QLocale().uiLanguages();
|
||||||
qsizetype defaultIndex = languageList.indexOf(u"en-US"_s);
|
qsizetype defaultIndex = languageList.indexOf(u"en-US"_s);
|
||||||
@@ -255,13 +225,13 @@ QString MimeType::comment() const
|
|||||||
// uiLanguages() uses '-' as separator, MIME database uses '_'
|
// uiLanguages() uses '-' as separator, MIME database uses '_'
|
||||||
const QString lang
|
const QString lang
|
||||||
= language == "C"_L1 ? u"en_US"_s : QString(language).replace(u'-', u'_');
|
= 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())
|
if (!comm.isEmpty())
|
||||||
return comm;
|
return comm;
|
||||||
const qsizetype cut = lang.indexOf(u'_');
|
const qsizetype cut = lang.indexOf(u'_');
|
||||||
// If "de_CH" is missing, check for "de" (and similar):
|
// If "de_CH" is missing, check for "de" (and similar):
|
||||||
if (cut != -1) {
|
if (cut != -1) {
|
||||||
comm = d->localeComments.value(lang.left(cut));
|
comm = localeComments.value(lang.left(cut));
|
||||||
if (!comm.isEmpty())
|
if (!comm.isEmpty())
|
||||||
return comm;
|
return comm;
|
||||||
}
|
}
|
||||||
@@ -287,8 +257,8 @@ QString MimeType::comment() const
|
|||||||
*/
|
*/
|
||||||
QString MimeType::genericIconName() const
|
QString MimeType::genericIconName() const
|
||||||
{
|
{
|
||||||
MimeDatabasePrivate::instance()->loadGenericIcon(const_cast<MimeTypePrivate&>(*d));
|
QString genericIconName = MimeDatabasePrivate::instance()->genericIcon(d->name);
|
||||||
if (d->genericIconName.isEmpty()) {
|
if (genericIconName.isEmpty()) {
|
||||||
// From the spec:
|
// From the spec:
|
||||||
// If the generic icon name is empty (not specified by the mimetype definition)
|
// If the generic icon name is empty (not specified by the mimetype definition)
|
||||||
// then the mimetype is used to generate the generic icon by using the top-level
|
// then the mimetype is used to generate the generic icon by using the top-level
|
||||||
@@ -301,7 +271,7 @@ QString MimeType::genericIconName() const
|
|||||||
groupRef = groupRef.left(slashindex);
|
groupRef = groupRef.left(slashindex);
|
||||||
return groupRef + "-x-generic"_L1;
|
return groupRef + "-x-generic"_L1;
|
||||||
}
|
}
|
||||||
return d->genericIconName;
|
return genericIconName;
|
||||||
}
|
}
|
||||||
|
|
||||||
static QString make_default_icon_name_from_mimetype_name(QString iconName)
|
static QString make_default_icon_name_from_mimetype_name(QString iconName)
|
||||||
@@ -323,11 +293,11 @@ static QString make_default_icon_name_from_mimetype_name(QString iconName)
|
|||||||
*/
|
*/
|
||||||
QString MimeType::iconName() const
|
QString MimeType::iconName() const
|
||||||
{
|
{
|
||||||
MimeDatabasePrivate::instance()->loadIcon(const_cast<MimeTypePrivate&>(*d));
|
QString iconName = MimeDatabasePrivate::instance()->icon(d->name);
|
||||||
if (d->iconName.isEmpty()) {
|
if (iconName.isEmpty()) {
|
||||||
return make_default_icon_name_from_mimetype_name(name());
|
return make_default_icon_name_from_mimetype_name(name());
|
||||||
}
|
}
|
||||||
return d->iconName;
|
return iconName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -339,8 +309,7 @@ QString MimeType::iconName() const
|
|||||||
*/
|
*/
|
||||||
QStringList MimeType::globPatterns() const
|
QStringList MimeType::globPatterns() const
|
||||||
{
|
{
|
||||||
MimeDatabasePrivate::instance()->loadMimeTypePrivate(const_cast<MimeTypePrivate&>(*d));
|
return MimeDatabasePrivate::instance()->globPatterns(d->name);
|
||||||
return d->globPatterns;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -434,10 +403,11 @@ QStringList MimeType::aliases() const
|
|||||||
*/
|
*/
|
||||||
QStringList MimeType::suffixes() const
|
QStringList MimeType::suffixes() const
|
||||||
{
|
{
|
||||||
MimeDatabasePrivate::instance()->loadMimeTypePrivate(const_cast<MimeTypePrivate&>(*d));
|
const QStringList patterns = globPatterns();
|
||||||
|
|
||||||
QStringList result;
|
QStringList result;
|
||||||
for (const QString &pattern : std::as_const(d->globPatterns)) {
|
result.reserve(patterns.size());
|
||||||
|
for (const QString &pattern : patterns) {
|
||||||
const QString suffix = suffixFromPattern(pattern);
|
const QString suffix = suffixFromPattern(pattern);
|
||||||
if (!suffix.isEmpty())
|
if (!suffix.isEmpty())
|
||||||
result.append(suffix);
|
result.append(suffix);
|
||||||
@@ -473,15 +443,15 @@ QString MimeType::preferredSuffix() const
|
|||||||
*/
|
*/
|
||||||
QString MimeType::filterString() const
|
QString MimeType::filterString() const
|
||||||
{
|
{
|
||||||
MimeDatabasePrivate::instance()->loadMimeTypePrivate(const_cast<MimeTypePrivate&>(*d));
|
const QStringList patterns = globPatterns();
|
||||||
QString filter;
|
QString filter;
|
||||||
|
|
||||||
if (!d->globPatterns.empty()) {
|
if (!patterns.empty()) {
|
||||||
filter += comment() + " ("_L1;
|
filter += comment() + " ("_L1;
|
||||||
for (int i = 0; i < d->globPatterns.size(); ++i) {
|
for (int i = 0; i < patterns.size(); ++i) {
|
||||||
if (i != 0)
|
if (i != 0)
|
||||||
filter += u' ';
|
filter += u' ';
|
||||||
filter += d->globPatterns.at(i);
|
filter += patterns.at(i);
|
||||||
}
|
}
|
||||||
filter += u')';
|
filter += u')';
|
||||||
}
|
}
|
||||||
@@ -522,16 +492,7 @@ bool MimeType::matchesName(const QString &nameOrAlias) const
|
|||||||
*/
|
*/
|
||||||
void MimeType::setPreferredSuffix(const QString &suffix)
|
void MimeType::setPreferredSuffix(const QString &suffix)
|
||||||
{
|
{
|
||||||
MimeDatabasePrivate::instance()->loadMimeTypePrivate(const_cast<MimeTypePrivate&>(*d));
|
MimeDatabasePrivate::instance()->setPreferredSuffix(d->name, suffix);
|
||||||
|
|
||||||
auto it = std::find_if(d->globPatterns.begin(),
|
|
||||||
d->globPatterns.end(),
|
|
||||||
[suffix](const QString &pattern) {
|
|
||||||
return suffixFromPattern(pattern) == suffix;
|
|
||||||
});
|
|
||||||
if (it != d->globPatterns.end())
|
|
||||||
d->globPatterns.erase(it);
|
|
||||||
d->globPatterns.prepend(QLatin1String("*.") + suffix);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QDebug operator<<(QDebug debug, const Utils::MimeType &mime)
|
QDebug operator<<(QDebug debug, const Utils::MimeType &mime)
|
||||||
|
@@ -82,6 +82,7 @@ public:
|
|||||||
// Qt Creator additions
|
// Qt Creator additions
|
||||||
bool matchesName(const QString &nameOrAlias) const;
|
bool matchesName(const QString &nameOrAlias) const;
|
||||||
void setPreferredSuffix(const QString &suffix);
|
void setPreferredSuffix(const QString &suffix);
|
||||||
|
static QString suffixFromPattern(const QString &pattern);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class MimeTypeParserBase;
|
friend class MimeTypeParserBase;
|
||||||
|
@@ -14,54 +14,24 @@
|
|||||||
// We mean it.
|
// We mean it.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "mimetype.h"
|
#include <QtCore/qshareddata.h>
|
||||||
|
|
||||||
#include <QtCore/qhash.h>
|
#include <QtCore/qhash.h>
|
||||||
#include <QtCore/qstringlist.h>
|
#include <QtCore/qstringlist.h>
|
||||||
|
|
||||||
namespace Utils {
|
namespace Utils {
|
||||||
|
|
||||||
|
class MimeBinaryProvider;
|
||||||
|
|
||||||
class MimeTypePrivate : public QSharedData
|
class MimeTypePrivate : public QSharedData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef QHash<QString, QString> LocaleHash;
|
typedef QHash<QString, QString> LocaleHash;
|
||||||
|
|
||||||
MimeTypePrivate();
|
MimeTypePrivate() { }
|
||||||
explicit MimeTypePrivate(const MimeType &other);
|
explicit MimeTypePrivate(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;
|
QString name;
|
||||||
LocaleHash localeComments;
|
|
||||||
QString genericIconName;
|
|
||||||
QString iconName;
|
|
||||||
QStringList globPatterns;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Utils
|
} // namespace Utils
|
||||||
|
|
||||||
#if 0
|
|
||||||
#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
|
|
||||||
|
@@ -163,8 +163,7 @@ static CreateMagicMatchRuleResult createMagicMatchRule(const QXmlStreamAttribute
|
|||||||
bool MimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString *errorMessage)
|
bool MimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString *errorMessage)
|
||||||
{
|
{
|
||||||
#if QT_CONFIG(xmlstreamreader)
|
#if QT_CONFIG(xmlstreamreader)
|
||||||
MimeTypePrivate data;
|
MimeTypeXMLData data;
|
||||||
data.loaded = true;
|
|
||||||
int priority = 50;
|
int priority = 50;
|
||||||
QStack<MimeMagicRule *> currentRules; // stack for the nesting of rules
|
QStack<MimeMagicRule *> currentRules; // stack for the nesting of rules
|
||||||
QList<MimeMagicRule> rules; // toplevel rules
|
QList<MimeMagicRule> rules; // toplevel rules
|
||||||
@@ -271,7 +270,7 @@ bool MimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString
|
|||||||
{
|
{
|
||||||
const auto elementName = reader.name();
|
const auto elementName = reader.name();
|
||||||
if (elementName == QLatin1StringView(mimeTypeTagC)) {
|
if (elementName == QLatin1StringView(mimeTypeTagC)) {
|
||||||
if (!process(MimeType(data), errorMessage))
|
if (!process(data, errorMessage))
|
||||||
return false;
|
return false;
|
||||||
data.clear();
|
data.clear();
|
||||||
} else if (elementName == QLatin1StringView(matchTagC)) {
|
} else if (elementName == QLatin1StringView(matchTagC)) {
|
||||||
@@ -312,4 +311,19 @@ bool MimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString
|
|||||||
#endif // feature xmlstreamreader
|
#endif // feature xmlstreamreader
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MimeTypeXMLData::clear()
|
||||||
|
{
|
||||||
|
hasGlobDeleteAll = false;
|
||||||
|
name.clear();
|
||||||
|
localeComments.clear();
|
||||||
|
genericIconName.clear();
|
||||||
|
iconName.clear();
|
||||||
|
globPatterns.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MimeTypeXMLData::addGlobPattern(const QString &pattern)
|
||||||
|
{
|
||||||
|
globPatterns.append(pattern);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Utils
|
} // namespace Utils
|
||||||
|
@@ -14,7 +14,7 @@
|
|||||||
// We mean it.
|
// We mean it.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "mimedatabase_p.h"
|
#include <QtCore/qtconfigmacros.h>
|
||||||
|
|
||||||
#include "mimeprovider_p.h"
|
#include "mimeprovider_p.h"
|
||||||
|
|
||||||
@@ -24,6 +24,21 @@ QT_END_NAMESPACE
|
|||||||
|
|
||||||
namespace Utils {
|
namespace Utils {
|
||||||
|
|
||||||
|
class MimeTypeXMLData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
void addGlobPattern(const QString &pattern);
|
||||||
|
|
||||||
|
bool hasGlobDeleteAll = false; // true if the mimetype has a glob-deleteall tag
|
||||||
|
QString name;
|
||||||
|
MimeTypePrivate::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 MimeTypeParserBase
|
class MimeTypeParserBase
|
||||||
{
|
{
|
||||||
Q_DISABLE_COPY_MOVE(MimeTypeParserBase)
|
Q_DISABLE_COPY_MOVE(MimeTypeParserBase)
|
||||||
@@ -37,7 +52,7 @@ public:
|
|||||||
static bool parseNumber(QStringView n, int *target, QString *errorMessage);
|
static bool parseNumber(QStringView n, int *target, QString *errorMessage);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool process(const MimeType &t, QString *errorMessage) = 0;
|
virtual bool process(const MimeTypeXMLData &t, QString *errorMessage) = 0;
|
||||||
virtual bool process(const MimeGlobPattern &t, QString *errorMessage) = 0;
|
virtual bool process(const MimeGlobPattern &t, QString *errorMessage) = 0;
|
||||||
virtual void processParent(const QString &child, const QString &parent) = 0;
|
virtual void processParent(const QString &child, const QString &parent) = 0;
|
||||||
virtual void processAlias(const QString &alias, const QString &name) = 0;
|
virtual void processAlias(const QString &alias, const QString &name) = 0;
|
||||||
@@ -71,7 +86,7 @@ public:
|
|||||||
explicit MimeTypeParser(MimeXMLProvider &provider) : m_provider(provider) {}
|
explicit MimeTypeParser(MimeXMLProvider &provider) : m_provider(provider) {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
inline bool process(const MimeType &t, QString *) override
|
inline bool process(const MimeTypeXMLData &t, QString *) override
|
||||||
{ m_provider.addMimeType(t); return true; }
|
{ m_provider.addMimeType(t); return true; }
|
||||||
|
|
||||||
inline bool process(const MimeGlobPattern &glob, QString *) override
|
inline bool process(const MimeGlobPattern &glob, QString *) override
|
||||||
|
Reference in New Issue
Block a user