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>
This commit is contained in:
parent
37cff48a27
commit
705118a554
@ -191,9 +191,8 @@ QMimeType QMimeDatabasePrivate::mimeTypeForName(const QString &nameOrAlias)
|
|||||||
{
|
{
|
||||||
const QString mimeName = resolveAlias(nameOrAlias);
|
const QString mimeName = resolveAlias(nameOrAlias);
|
||||||
for (const auto &provider : providers()) {
|
for (const auto &provider : providers()) {
|
||||||
QMimeType mime = provider->mimeTypeForName(mimeName);
|
if (provider->knowsMimeType(mimeName))
|
||||||
if (mime.isValid())
|
return QMimeType(QMimeTypePrivate(mimeName));
|
||||||
return mime;
|
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@ -218,54 +217,54 @@ QMimeGlobMatchResult QMimeDatabasePrivate::findByFileName(const QString &fileNam
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QMimeDatabasePrivate::loadMimeTypePrivate(QMimeTypePrivate &mimePrivate)
|
QMimeTypePrivate::LocaleHash QMimeDatabasePrivate::localeComments(const QString &name)
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&mutex);
|
QMutexLocker locker(&mutex);
|
||||||
if (mimePrivate.name.isEmpty())
|
for (const auto &provider : providers()) {
|
||||||
return; // invalid mimetype
|
auto comments = provider->localeComments(name);
|
||||||
if (!mimePrivate.loaded) { // XML provider sets loaded=true, binary provider does this on demand
|
if (!comments.isEmpty())
|
||||||
Q_ASSERT(mimePrivate.fromCache);
|
return comments; // maybe we want to merge in comments from more global providers, in
|
||||||
bool found = false;
|
// case of more translations?
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void QMimeDatabasePrivate::loadGenericIcon(QMimeTypePrivate &mimePrivate)
|
QStringList QMimeDatabasePrivate::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();
|
||||||
|
patterns += provider->globPatterns(name);
|
||||||
}
|
}
|
||||||
|
return patterns;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QMimeDatabasePrivate::loadIcon(QMimeTypePrivate &mimePrivate)
|
QString QMimeDatabasePrivate::genericIcon(const QString &name)
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&mutex);
|
QMutexLocker locker(&mutex);
|
||||||
if (mimePrivate.fromCache) {
|
for (const auto &provider : providers()) {
|
||||||
mimePrivate.iconName.clear();
|
QString genericIconName = provider->genericIcon(name);
|
||||||
for (const auto &provider : providers()) {
|
if (!genericIconName.isEmpty())
|
||||||
provider->loadIcon(mimePrivate);
|
return genericIconName;
|
||||||
if (!mimePrivate.iconName.isEmpty())
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
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 {};
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QMimeDatabasePrivate::fallbackParent(const QString &mimeTypeName) const
|
QString QMimeDatabasePrivate::fallbackParent(const QString &mimeTypeName) const
|
||||||
@ -346,12 +345,12 @@ QMimeType QMimeDatabasePrivate::findByData(const QByteArray &data, int *accuracy
|
|||||||
}
|
}
|
||||||
|
|
||||||
*accuracyPtr = 0;
|
*accuracyPtr = 0;
|
||||||
QMimeType 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 QMimeType(QMimeTypePrivate(candidate));
|
||||||
|
|
||||||
if (isTextFile(data)) {
|
if (isTextFile(data)) {
|
||||||
*accuracyPtr = 5;
|
*accuracyPtr = 5;
|
||||||
|
@ -66,9 +66,10 @@ public:
|
|||||||
QMimeGlobMatchResult findByFileName(const QString &fileName);
|
QMimeGlobMatchResult findByFileName(const QString &fileName);
|
||||||
|
|
||||||
// API for QMimeType. Takes care of locking the mutex.
|
// API for QMimeType. Takes care of locking the mutex.
|
||||||
void loadMimeTypePrivate(QMimeTypePrivate &mimePrivate);
|
QMimeTypePrivate::LocaleHash localeComments(const QString &name);
|
||||||
void loadGenericIcon(QMimeTypePrivate &mimePrivate);
|
QStringList globPatterns(const QString &name);
|
||||||
void loadIcon(QMimeTypePrivate &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);
|
||||||
@ -81,7 +82,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;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -186,25 +186,11 @@ void QMimeBinaryProvider::ensureLoaded()
|
|||||||
m_cacheFile.reset();
|
m_cacheFile.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
static QMimeType mimeTypeForNameUnchecked(const QString &name)
|
bool QMimeBinaryProvider::knowsMimeType(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)
|
|
||||||
{
|
{
|
||||||
if (!m_mimetypeListLoaded)
|
if (!m_mimetypeListLoaded)
|
||||||
loadMimeTypeList();
|
loadMimeTypeList();
|
||||||
if (!m_mimetypeNames.contains(name))
|
return m_mimetypeNames.contains(name);
|
||||||
return QMimeType(); // unknown mimetype
|
|
||||||
return mimeTypeForNameUnchecked(name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QMimeBinaryProvider::addFileNameMatches(const QString &fileName, QMimeGlobMatchResult &result)
|
void QMimeBinaryProvider::addFileNameMatches(const QString &fileName, QMimeGlobMatchResult &result)
|
||||||
@ -354,7 +340,7 @@ bool QMimeBinaryProvider::matchMagicRule(QMimeBinaryProvider::CacheFile *cacheFi
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
const int magicListOffset = m_cacheFile->getUint32(PosMagicListOffset);
|
||||||
const int numMatches = m_cacheFile->getUint32(magicListOffset);
|
const int numMatches = m_cacheFile->getUint32(magicListOffset);
|
||||||
@ -371,7 +357,7 @@ void QMimeBinaryProvider::findByMagic(const QByteArray &data, int *accuracyPtr,
|
|||||||
*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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -479,35 +465,63 @@ void QMimeBinaryProvider::addAllMimeTypes(QList<QMimeType> &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(QMimeType(QMimeTypePrivate(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 QMimeType &mime) -> bool { return mime.name() == name; })
|
if (std::find_if(result.constBegin(), result.constEnd(), [name](const QMimeType &mime) -> bool { return mime.name() == name; })
|
||||||
== result.constEnd())
|
== result.constEnd())
|
||||||
result.append(mimeTypeForNameUnchecked(name));
|
result.append(QMimeType(QMimeTypePrivate(name)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QMimeBinaryProvider::loadMimeTypePrivate(QMimeTypePrivate &data)
|
QMimeTypePrivate::LocaleHash QMimeBinaryProvider::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 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 {};
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
#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 (!QFile::exists(mimeFile))
|
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);
|
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;
|
||||||
@ -515,13 +529,13 @@ bool QMimeBinaryProvider::loadMimeTypePrivate(QMimeTypePrivate &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();
|
||||||
@ -534,8 +548,7 @@ bool QMimeBinaryProvider::loadMimeTypePrivate(QMimeTypePrivate &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'*')) {
|
||||||
@ -557,14 +570,11 @@ bool QMimeBinaryProvider::loadMimeTypePrivate(QMimeTypePrivate &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
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -594,22 +604,16 @@ QLatin1StringView QMimeBinaryProvider::iconForMime(CacheFile *cacheFile, int pos
|
|||||||
return QLatin1StringView();
|
return QLatin1StringView();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QMimeBinaryProvider::loadIcon(QMimeTypePrivate &data)
|
QString QMimeBinaryProvider::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 QMimeBinaryProvider::loadGenericIcon(QMimeTypePrivate &data)
|
QString QMimeBinaryProvider::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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////
|
////
|
||||||
@ -694,9 +698,9 @@ bool QMimeXMLProvider::isInternalDatabase() const
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
QMimeType QMimeXMLProvider::mimeTypeForName(const QString &name)
|
bool QMimeXMLProvider::knowsMimeType(const QString &name)
|
||||||
{
|
{
|
||||||
return m_nameMimeTypeMap.value(name);
|
return m_nameMimeTypeMap.contains(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QMimeXMLProvider::addFileNameMatches(const QString &fileName, QMimeGlobMatchResult &result)
|
void QMimeXMLProvider::addFileNameMatches(const QString &fileName, QMimeGlobMatchResult &result)
|
||||||
@ -704,22 +708,17 @@ void QMimeXMLProvider::addFileNameMatches(const QString &fileName, QMimeGlobMatc
|
|||||||
m_mimeTypeGlobs.matchingGlobs(fileName, result);
|
m_mimeTypeGlobs.matchingGlobs(fileName, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
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)) {
|
for (const QMimeMagicRuleMatcher &matcher : std::as_const(m_magicMatchers)) {
|
||||||
if (matcher.matches(data)) {
|
if (matcher.matches(data)) {
|
||||||
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 QMimeXMLProvider::ensureLoaded()
|
void QMimeXMLProvider::ensureLoaded()
|
||||||
@ -749,6 +748,31 @@ void QMimeXMLProvider::ensureLoaded()
|
|||||||
load(file);
|
load(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
void QMimeXMLProvider::load(const QString &fileName)
|
||||||
{
|
{
|
||||||
QString errorMessage;
|
QString errorMessage;
|
||||||
@ -790,14 +814,11 @@ void QMimeXMLProvider::addGlobPattern(const QMimeGlobPattern &glob)
|
|||||||
m_mimeTypeGlobs.addGlob(glob);
|
m_mimeTypeGlobs.addGlob(glob);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QMimeXMLProvider::addMimeType(const QMimeType &mt)
|
void QMimeXMLProvider::addMimeType(const QMimeTypeXMLData &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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -813,7 +834,7 @@ void QMimeXMLProvider::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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -853,13 +874,16 @@ void QMimeXMLProvider::addAlias(const QString &alias, const QString &name)
|
|||||||
void QMimeXMLProvider::addAllMimeTypes(QList<QMimeType> &result)
|
void QMimeXMLProvider::addAllMimeTypes(QList<QMimeType> &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(QMimeType(QMimeTypePrivate(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 QMimeType &mime) -> bool { return mime.name() == newMime; })
|
if (std::find_if(result.constBegin(), result.constEnd(), [newMime](const QMimeType &mime) -> bool { return mime.name() == newMime; })
|
||||||
== result.constEnd())
|
== result.constEnd())
|
||||||
result.append(it.value());
|
result.append(QMimeType(QMimeTypePrivate(it.value().name)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ QT_REQUIRE_CONFIG(mimetype);
|
|||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
class QMimeMagicRuleMatcher;
|
class QMimeMagicRuleMatcher;
|
||||||
|
class QMimeTypeXMLData;
|
||||||
|
|
||||||
class QMimeProviderBase
|
class QMimeProviderBase
|
||||||
{
|
{
|
||||||
@ -39,18 +40,20 @@ public:
|
|||||||
|
|
||||||
virtual bool isValid() = 0;
|
virtual bool isValid() = 0;
|
||||||
virtual bool isInternalDatabase() const = 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 addFileNameMatches(const QString &fileName, QMimeGlobMatchResult &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, QMimeType &candidate) = 0;
|
virtual void findByMagic(const QByteArray &data, int *accuracyPtr, QString *candidate) = 0;
|
||||||
virtual void addAllMimeTypes(QList<QMimeType> &result) = 0;
|
virtual void addAllMimeTypes(QList<QMimeType> &result) = 0;
|
||||||
virtual bool loadMimeTypePrivate(QMimeTypePrivate &) { return false; }
|
virtual QMimeTypePrivate::LocaleHash localeComments(const QString &name) = 0;
|
||||||
virtual void loadIcon(QMimeTypePrivate &) {}
|
virtual bool hasGlobDeleteAll(const QString &name) = 0;
|
||||||
virtual void loadGenericIcon(QMimeTypePrivate &) {}
|
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; }
|
||||||
|
|
||||||
@ -60,9 +63,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
|
||||||
@ -95,16 +98,18 @@ public:
|
|||||||
|
|
||||||
bool isValid() override;
|
bool isValid() override;
|
||||||
bool isInternalDatabase() const 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 addFileNameMatches(const QString &fileName, QMimeGlobMatchResult &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, QMimeType &candidate) override;
|
void findByMagic(const QByteArray &data, int *accuracyPtr, QString *candidate) override;
|
||||||
void addAllMimeTypes(QList<QMimeType> &result) override;
|
void addAllMimeTypes(QList<QMimeType> &result) override;
|
||||||
bool loadMimeTypePrivate(QMimeTypePrivate &) override;
|
QMimeTypePrivate::LocaleHash localeComments(const QString &name) override;
|
||||||
void loadIcon(QMimeTypePrivate &) override;
|
bool hasGlobDeleteAll(const QString &name) override;
|
||||||
void loadGenericIcon(QMimeTypePrivate &) 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;
|
||||||
|
|
||||||
@ -116,8 +121,9 @@ private:
|
|||||||
bool matchSuffixTree(QMimeGlobMatchResult &result, CacheFile *cacheFile, int numEntries,
|
bool matchSuffixTree(QMimeGlobMatchResult &result, CacheFile *cacheFile, int numEntries,
|
||||||
int firstOffset, const QString &fileName, qsizetype charPos,
|
int firstOffset, const QString &fileName, 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();
|
||||||
@ -128,11 +134,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);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -153,19 +162,24 @@ public:
|
|||||||
|
|
||||||
bool isValid() override;
|
bool isValid() override;
|
||||||
bool isInternalDatabase() const 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 addFileNameMatches(const QString &fileName, QMimeGlobMatchResult &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, QMimeType &candidate) override;
|
void findByMagic(const QByteArray &data, int *accuracyPtr, QString *candidate) override;
|
||||||
void addAllMimeTypes(QList<QMimeType> &result) override;
|
void addAllMimeTypes(QList<QMimeType> &result) override;
|
||||||
void ensureLoaded() 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);
|
bool load(const QString &fileName, QString *errorMessage);
|
||||||
|
|
||||||
// Called by the mimetype xml parser
|
// Called by the mimetype xml parser
|
||||||
void addMimeType(const QMimeType &mt);
|
void addMimeType(const QMimeTypeXMLData &mt);
|
||||||
void excludeMimeTypeGlobs(const QStringList &toExclude) override;
|
void excludeMimeTypeGlobs(const QStringList &toExclude) override;
|
||||||
void addGlobPattern(const QMimeGlobPattern &glob);
|
void addGlobPattern(const QMimeGlobPattern &glob);
|
||||||
void addParent(const QString &child, const QString &parent);
|
void addParent(const QString &child, const QString &parent);
|
||||||
@ -176,7 +190,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, QMimeType> NameMimeTypeMap;
|
typedef QHash<QString, QMimeTypeXMLData> NameMimeTypeMap;
|
||||||
NameMimeTypeMap m_nameMimeTypeMap;
|
NameMimeTypeMap m_nameMimeTypeMap;
|
||||||
|
|
||||||
typedef QHash<QString, QString> AliasHash;
|
typedef QHash<QString, QString> AliasHash;
|
||||||
|
@ -6,9 +6,6 @@
|
|||||||
|
|
||||||
#include "qmimetype_p.h"
|
#include "qmimetype_p.h"
|
||||||
#include "qmimedatabase_p.h"
|
#include "qmimedatabase_p.h"
|
||||||
#include "qmimeprovider_p.h"
|
|
||||||
|
|
||||||
#include "qmimeglobpattern_p.h"
|
|
||||||
|
|
||||||
#include <QtCore/QDebug>
|
#include <QtCore/QDebug>
|
||||||
#include <QtCore/QLocale>
|
#include <QtCore/QLocale>
|
||||||
@ -20,33 +17,6 @@ QT_BEGIN_NAMESPACE
|
|||||||
|
|
||||||
using namespace Qt::StringLiterals;
|
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
|
\class QMimeType
|
||||||
\inmodule QtCore
|
\inmodule QtCore
|
||||||
@ -219,7 +189,7 @@ QString QMimeType::name() const
|
|||||||
*/
|
*/
|
||||||
QString QMimeType::comment() const
|
QString QMimeType::comment() const
|
||||||
{
|
{
|
||||||
QMimeDatabasePrivate::instance()->loadMimeTypePrivate(const_cast<QMimeTypePrivate&>(*d));
|
const auto localeComments = QMimeDatabasePrivate::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);
|
||||||
@ -244,13 +214,13 @@ QString QMimeType::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;
|
||||||
}
|
}
|
||||||
@ -276,8 +246,8 @@ QString QMimeType::comment() const
|
|||||||
*/
|
*/
|
||||||
QString QMimeType::genericIconName() const
|
QString QMimeType::genericIconName() const
|
||||||
{
|
{
|
||||||
QMimeDatabasePrivate::instance()->loadGenericIcon(const_cast<QMimeTypePrivate&>(*d));
|
QString genericIconName = QMimeDatabasePrivate::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
|
||||||
@ -290,7 +260,7 @@ QString QMimeType::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)
|
||||||
@ -312,11 +282,11 @@ static QString make_default_icon_name_from_mimetype_name(QString iconName)
|
|||||||
*/
|
*/
|
||||||
QString QMimeType::iconName() const
|
QString QMimeType::iconName() const
|
||||||
{
|
{
|
||||||
QMimeDatabasePrivate::instance()->loadIcon(const_cast<QMimeTypePrivate&>(*d));
|
QString iconName = QMimeDatabasePrivate::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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -328,8 +298,7 @@ QString QMimeType::iconName() const
|
|||||||
*/
|
*/
|
||||||
QStringList QMimeType::globPatterns() const
|
QStringList QMimeType::globPatterns() const
|
||||||
{
|
{
|
||||||
QMimeDatabasePrivate::instance()->loadMimeTypePrivate(const_cast<QMimeTypePrivate&>(*d));
|
return QMimeDatabasePrivate::instance()->globPatterns(d->name);
|
||||||
return d->globPatterns;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -426,10 +395,11 @@ QStringList QMimeType::aliases() const
|
|||||||
*/
|
*/
|
||||||
QStringList QMimeType::suffixes() const
|
QStringList QMimeType::suffixes() const
|
||||||
{
|
{
|
||||||
QMimeDatabasePrivate::instance()->loadMimeTypePrivate(const_cast<QMimeTypePrivate&>(*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) {
|
||||||
// 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) &&
|
||||||
pattern.size() > 2 &&
|
pattern.size() > 2 &&
|
||||||
@ -469,15 +439,15 @@ QString QMimeType::preferredSuffix() const
|
|||||||
*/
|
*/
|
||||||
QString QMimeType::filterString() const
|
QString QMimeType::filterString() const
|
||||||
{
|
{
|
||||||
QMimeDatabasePrivate::instance()->loadMimeTypePrivate(const_cast<QMimeTypePrivate&>(*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')';
|
||||||
}
|
}
|
||||||
|
@ -16,13 +16,14 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#include <QtCore/private/qglobal_p.h>
|
#include <QtCore/private/qglobal_p.h>
|
||||||
#include "qmimetype.h"
|
#include <QtCore/qshareddata.h>
|
||||||
|
|
||||||
QT_REQUIRE_CONFIG(mimetype);
|
QT_REQUIRE_CONFIG(mimetype);
|
||||||
|
|
||||||
#include <QtCore/qhash.h>
|
#include <QtCore/qhash.h>
|
||||||
#include <QtCore/qstringlist.h>
|
#include <QtCore/qstringlist.h>
|
||||||
|
|
||||||
|
class QMimeBinaryProvider;
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
class Q_AUTOTEST_EXPORT QMimeTypePrivate : public QSharedData
|
class Q_AUTOTEST_EXPORT QMimeTypePrivate : public QSharedData
|
||||||
@ -30,42 +31,12 @@ class Q_AUTOTEST_EXPORT QMimeTypePrivate : public QSharedData
|
|||||||
public:
|
public:
|
||||||
typedef QHash<QString, QString> LocaleHash;
|
typedef QHash<QString, QString> LocaleHash;
|
||||||
|
|
||||||
QMimeTypePrivate();
|
QMimeTypePrivate() { }
|
||||||
explicit QMimeTypePrivate(const QMimeType &other);
|
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;
|
QString name;
|
||||||
LocaleHash localeComments;
|
|
||||||
QString genericIconName;
|
|
||||||
QString iconName;
|
|
||||||
QStringList globPatterns;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
#define QMIMETYPE_BUILDER_FROM_RVALUE_REFS \
|
#endif // QMIMETYPE_P_H
|
||||||
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
|
|
||||||
|
@ -165,8 +165,7 @@ static CreateMagicMatchRuleResult createMagicMatchRule(const QXmlStreamAttribute
|
|||||||
bool QMimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString *errorMessage)
|
bool QMimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString *errorMessage)
|
||||||
{
|
{
|
||||||
#if QT_CONFIG(xmlstreamreader)
|
#if QT_CONFIG(xmlstreamreader)
|
||||||
QMimeTypePrivate data;
|
QMimeTypeXMLData data;
|
||||||
data.loaded = true;
|
|
||||||
int priority = 50;
|
int priority = 50;
|
||||||
QStack<QMimeMagicRule *> currentRules; // stack for the nesting of rules
|
QStack<QMimeMagicRule *> currentRules; // stack for the nesting of rules
|
||||||
QList<QMimeMagicRule> rules; // toplevel rules
|
QList<QMimeMagicRule> rules; // toplevel rules
|
||||||
@ -273,7 +272,7 @@ bool QMimeTypeParserBase::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(QMimeType(data), errorMessage))
|
if (!process(data, errorMessage))
|
||||||
return false;
|
return false;
|
||||||
data.clear();
|
data.clear();
|
||||||
} else if (elementName == QLatin1StringView(matchTagC)) {
|
} else if (elementName == QLatin1StringView(matchTagC)) {
|
||||||
@ -314,4 +313,19 @@ bool QMimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString
|
|||||||
#endif // feature xmlstreamreader
|
#endif // feature xmlstreamreader
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
QT_END_NAMESPACE
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
// We mean it.
|
// We mean it.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "qmimedatabase_p.h"
|
#include <QtCore/qtconfigmacros.h>
|
||||||
|
|
||||||
QT_REQUIRE_CONFIG(mimetype);
|
QT_REQUIRE_CONFIG(mimetype);
|
||||||
|
|
||||||
@ -24,6 +24,21 @@ QT_REQUIRE_CONFIG(mimetype);
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
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;
|
class QIODevice;
|
||||||
|
|
||||||
class QMimeTypeParserBase
|
class QMimeTypeParserBase
|
||||||
@ -39,7 +54,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 QMimeType &t, QString *errorMessage) = 0;
|
virtual bool process(const QMimeTypeXMLData &t, QString *errorMessage) = 0;
|
||||||
virtual bool process(const QMimeGlobPattern &t, QString *errorMessage) = 0;
|
virtual bool process(const QMimeGlobPattern &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;
|
||||||
@ -73,7 +88,7 @@ public:
|
|||||||
explicit QMimeTypeParser(QMimeXMLProvider &provider) : m_provider(provider) {}
|
explicit QMimeTypeParser(QMimeXMLProvider &provider) : m_provider(provider) {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
inline bool process(const QMimeType &t, QString *) override
|
inline bool process(const QMimeTypeXMLData &t, QString *) override
|
||||||
{ m_provider.addMimeType(t); return true; }
|
{ m_provider.addMimeType(t); return true; }
|
||||||
|
|
||||||
inline bool process(const QMimeGlobPattern &glob, QString *) override
|
inline bool process(const QMimeGlobPattern &glob, QString *) override
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
|
||||||
|
<mime-type type="image/jpeg">
|
||||||
|
<glob pattern="*.jnewext"/>
|
||||||
|
<comment>JPEG Image</comment>
|
||||||
|
</mime-type>
|
||||||
|
</mime-info>
|
@ -25,6 +25,7 @@ qt_internal_add_test(tst_qmimedatabase-cache
|
|||||||
#)
|
#)
|
||||||
set(testdata_resource_files
|
set(testdata_resource_files
|
||||||
"../circular-inheritance.xml"
|
"../circular-inheritance.xml"
|
||||||
|
"../add-extension.xml"
|
||||||
"../invalid-magic1.xml"
|
"../invalid-magic1.xml"
|
||||||
"../invalid-magic2.xml"
|
"../invalid-magic2.xml"
|
||||||
"../invalid-magic3.xml"
|
"../invalid-magic3.xml"
|
||||||
|
@ -25,6 +25,7 @@ qt_internal_add_test(tst_qmimedatabase-xml
|
|||||||
#)
|
#)
|
||||||
set(testdata_resource_files
|
set(testdata_resource_files
|
||||||
"../circular-inheritance.xml"
|
"../circular-inheritance.xml"
|
||||||
|
"../add-extension.xml"
|
||||||
"../invalid-magic1.xml"
|
"../invalid-magic1.xml"
|
||||||
"../invalid-magic2.xml"
|
"../invalid-magic2.xml"
|
||||||
"../invalid-magic3.xml"
|
"../invalid-magic3.xml"
|
||||||
|
@ -38,6 +38,7 @@ static const std::array additionalGlobalMimeFiles = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const std::array additionalLocalMimeFiles = {
|
static const std::array additionalLocalMimeFiles = {
|
||||||
|
"add-extension.xml", // adds *.jnewext to image/jpeg
|
||||||
"yast2-metapackage-handler-mimetypes.xml",
|
"yast2-metapackage-handler-mimetypes.xml",
|
||||||
"qml-again.xml",
|
"qml-again.xml",
|
||||||
"text-x-objcsrc.xml",
|
"text-x-objcsrc.xml",
|
||||||
@ -1232,6 +1233,11 @@ void tst_QMimeDatabase::installNewLocalMimeType()
|
|||||||
QCOMPARE(mimes.at(0).name(), u"video/webm");
|
QCOMPARE(mimes.at(0).name(), u"video/webm");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// QTBUG-116905: globPatterns() should merge all locations
|
||||||
|
// add-extension.xml adds *.jnewext
|
||||||
|
const QStringList expectedJpegPatterns{ "*.jpg", "*.jpeg", "*.jpe", "*.jnewext" };
|
||||||
|
QCOMPARE(db.mimeTypeForName(QStringLiteral("image/jpeg")).globPatterns(), expectedJpegPatterns);
|
||||||
|
|
||||||
// Now that we have two directories with mime definitions, check that everything still works
|
// Now that we have two directories with mime definitions, check that everything still works
|
||||||
inheritance();
|
inheritance();
|
||||||
if (QTest::currentTestFailed())
|
if (QTest::currentTestFailed())
|
||||||
|
@ -21,7 +21,6 @@ private slots:
|
|||||||
void name();
|
void name();
|
||||||
void genericIconName();
|
void genericIconName();
|
||||||
void iconName();
|
void iconName();
|
||||||
void suffixes();
|
|
||||||
void gadget();
|
void gadget();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -36,52 +35,15 @@ void tst_qmimetype::initTestCase()
|
|||||||
|
|
||||||
static QString qMimeTypeName()
|
static QString qMimeTypeName()
|
||||||
{
|
{
|
||||||
static const QString result ("No name of the MIME type");
|
static const QString result("group/fake-mime");
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static QString qMimeTypeGenericIconName()
|
|
||||||
{
|
|
||||||
static const QString result ("No file name of an icon image that represents the MIME type");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static QString qMimeTypeIconName()
|
|
||||||
{
|
|
||||||
static const QString result ("No file name of an icon image that represents the MIME type");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static QStringList buildQMimeTypeFilenameExtensions()
|
|
||||||
{
|
|
||||||
QStringList result;
|
|
||||||
result << QString::fromLatin1("*.png");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static QStringList qMimeTypeGlobPatterns()
|
|
||||||
{
|
|
||||||
static const QStringList result (buildQMimeTypeFilenameExtensions());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
QMIMETYPE_BUILDER_FROM_RVALUE_REFS
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
void tst_qmimetype::isValid()
|
void tst_qmimetype::isValid()
|
||||||
{
|
{
|
||||||
QMimeType instantiatedQMimeType (
|
QMimeType instantiatedQMimeType{ QMimeTypePrivate(qMimeTypeName()) };
|
||||||
buildQMimeType (
|
|
||||||
qMimeTypeName(),
|
|
||||||
qMimeTypeGenericIconName(),
|
|
||||||
qMimeTypeIconName(),
|
|
||||||
qMimeTypeGlobPatterns()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
QVERIFY(instantiatedQMimeType.isValid());
|
QVERIFY(instantiatedQMimeType.isValid());
|
||||||
|
|
||||||
QMimeType otherQMimeType (instantiatedQMimeType);
|
QMimeType otherQMimeType (instantiatedQMimeType);
|
||||||
@ -98,23 +60,8 @@ void tst_qmimetype::isValid()
|
|||||||
|
|
||||||
void tst_qmimetype::name()
|
void tst_qmimetype::name()
|
||||||
{
|
{
|
||||||
QMimeType instantiatedQMimeType (
|
QMimeType instantiatedQMimeType{ QMimeTypePrivate(qMimeTypeName()) };
|
||||||
buildQMimeType (
|
QMimeType otherQMimeType{ QMimeTypePrivate(QString()) };
|
||||||
qMimeTypeName(),
|
|
||||||
qMimeTypeGenericIconName(),
|
|
||||||
qMimeTypeIconName(),
|
|
||||||
qMimeTypeGlobPatterns()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
QMimeType otherQMimeType (
|
|
||||||
buildQMimeType (
|
|
||||||
QString(),
|
|
||||||
qMimeTypeGenericIconName(),
|
|
||||||
qMimeTypeIconName(),
|
|
||||||
qMimeTypeGlobPatterns()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Verify that the Name is part of the equality test:
|
// Verify that the Name is part of the equality test:
|
||||||
QCOMPARE(instantiatedQMimeType.name(), qMimeTypeName());
|
QCOMPARE(instantiatedQMimeType.name(), qMimeTypeName());
|
||||||
@ -127,63 +74,23 @@ void tst_qmimetype::name()
|
|||||||
|
|
||||||
void tst_qmimetype::genericIconName()
|
void tst_qmimetype::genericIconName()
|
||||||
{
|
{
|
||||||
QMimeType instantiatedQMimeType (
|
const QMimeType instantiatedQMimeType{ QMimeTypePrivate(qMimeTypeName()) };
|
||||||
buildQMimeType (
|
QCOMPARE(instantiatedQMimeType.genericIconName(), "group-x-generic");
|
||||||
qMimeTypeName(),
|
|
||||||
qMimeTypeGenericIconName(),
|
|
||||||
qMimeTypeIconName(),
|
|
||||||
qMimeTypeGlobPatterns()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
QCOMPARE(instantiatedQMimeType.genericIconName(), qMimeTypeGenericIconName());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
void tst_qmimetype::iconName()
|
void tst_qmimetype::iconName()
|
||||||
{
|
{
|
||||||
QMimeType instantiatedQMimeType (
|
const QMimeType instantiatedQMimeType{ QMimeTypePrivate(qMimeTypeName()) };
|
||||||
buildQMimeType (
|
QCOMPARE(instantiatedQMimeType.iconName(), "group-fake-mime");
|
||||||
qMimeTypeName(),
|
|
||||||
qMimeTypeGenericIconName(),
|
|
||||||
qMimeTypeIconName(),
|
|
||||||
qMimeTypeGlobPatterns()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
QCOMPARE(instantiatedQMimeType.iconName(), qMimeTypeIconName());
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void tst_qmimetype::suffixes()
|
|
||||||
{
|
|
||||||
QMimeType instantiatedQMimeType (
|
|
||||||
buildQMimeType (
|
|
||||||
qMimeTypeName(),
|
|
||||||
qMimeTypeGenericIconName(),
|
|
||||||
qMimeTypeIconName(),
|
|
||||||
qMimeTypeGlobPatterns()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
QCOMPARE(instantiatedQMimeType.globPatterns(), qMimeTypeGlobPatterns());
|
|
||||||
QCOMPARE(instantiatedQMimeType.suffixes(), QStringList() << QString::fromLatin1("png"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
void tst_qmimetype::gadget()
|
void tst_qmimetype::gadget()
|
||||||
{
|
{
|
||||||
QMimeType instantiatedQMimeType (
|
QMimeType instantiatedQMimeType = QMimeDatabase().mimeTypeForName("text/plain");
|
||||||
buildQMimeType (
|
|
||||||
qMimeTypeName(),
|
|
||||||
qMimeTypeGenericIconName(),
|
|
||||||
qMimeTypeIconName(),
|
|
||||||
qMimeTypeGlobPatterns()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
const QMetaObject *metaObject = &instantiatedQMimeType.staticMetaObject;
|
const QMetaObject *metaObject = &instantiatedQMimeType.staticMetaObject;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user