summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Faure <faure@kde.org>2012-01-14 00:48:30 +0100
committerWolf-Michael Bolle <wolf-michael.bolle@nokia.com>2012-01-23 13:38:29 +0100
commitab50d0312ecec6fdc7f570ba32a13428c8c8f090 (patch)
tree1ce60fb5bbf8336ed3a9eb9dca45f053fa7de1ca
parente8a26d9f4e081f8fab37dec38322515e72272556 (diff)
Implement support for noticing new or modified mimetypes at runtime.
The binary provider checks the mtime of the mime.cache files, and re-lists mime.cache files (not more often than once every 5 seconds). Upon a change, it simply has to close, open and map() the file again. The XML provider checks the list of xml files found (not more often than once every 5 seconds) and if the list changes, reloads everything. With unit tests for adding and removing a mimetype xml file, both in an existing dir (global) and into a new dir (local). Change-Id: I6347b95502c26b76c05e7fbc7028b62acb240005 Sanity-Review: Qt Sanity Bot <qt_sanity_bot@ovi.com> Reviewed-by: Wolf-Michael Bolle <wolf-michael.bolle@nokia.com>
-rw-r--r--src/mimetypes/qmimeglobpattern.cpp7
-rw-r--r--src/mimetypes/qmimeglobpattern_p.h1
-rw-r--r--src/mimetypes/qmimeprovider.cpp152
-rw-r--r--src/mimetypes/qmimeprovider_p.h17
-rw-r--r--tests/auto/qmimedatabase/qmimedatabase-cache/tst_qmimedatabase-cache.cpp20
-rw-r--r--tests/auto/qmimedatabase/qmimedatabase-xml/tst_qmimedatabase-xml.cpp5
-rw-r--r--tests/auto/qmimedatabase/tst_qmimedatabase.cpp140
-rw-r--r--tests/auto/qmimedatabase/tst_qmimedatabase.h9
-rw-r--r--tests/auto/qmimedatabase/yast2-metapackage-handler-mimetypes.xml15
9 files changed, 319 insertions, 47 deletions
diff --git a/src/mimetypes/qmimeglobpattern.cpp b/src/mimetypes/qmimeglobpattern.cpp
index 40e6478..61bb02a 100644
--- a/src/mimetypes/qmimeglobpattern.cpp
+++ b/src/mimetypes/qmimeglobpattern.cpp
@@ -188,3 +188,10 @@ QStringList QMimeAllGlobPatterns::matchingGlobs(const QString &fileName, QString
*foundSuffix = result.m_foundSuffix;
return result.m_matchingMimeTypes;
}
+
+void QMimeAllGlobPatterns::clear()
+{
+ m_fastPatterns.clear();
+ m_highWeightGlobs.clear();
+ m_lowWeightGlobs.clear();
+}
diff --git a/src/mimetypes/qmimeglobpattern_p.h b/src/mimetypes/qmimeglobpattern_p.h
index 1547101..1bea4c9 100644
--- a/src/mimetypes/qmimeglobpattern_p.h
+++ b/src/mimetypes/qmimeglobpattern_p.h
@@ -95,6 +95,7 @@ public:
void addGlob(const QMimeGlobPattern &glob);
void removeMimeType(const QString &mimeType);
QStringList matchingGlobs(const QString &fileName, QString *foundSuffix) const;
+ void clear();
PatternsMap m_fastPatterns; // example: "doc" -> "application/msword", "text/plain"
QMimeGlobPatternList m_highWeightGlobs;
diff --git a/src/mimetypes/qmimeprovider.cpp b/src/mimetypes/qmimeprovider.cpp
index 3a70bb3..29f4646 100644
--- a/src/mimetypes/qmimeprovider.cpp
+++ b/src/mimetypes/qmimeprovider.cpp
@@ -29,6 +29,7 @@
#include <QFile>
#include <QByteArrayMatcher>
#include <QDebug>
+#include <QDateTime>
#include <qendian.h>
static QString fallbackParent(const QString& mimeTypeName)
@@ -52,6 +53,17 @@ QMimeProviderBase::QMimeProviderBase(QMimeDatabasePrivate *db)
{
}
+QMIME_EXPORT int qmime_secondsBetweenChecks = 5; // exported for the unit test
+
+bool QMimeProviderBase::shouldCheck()
+{
+ const QDateTime now = QDateTime::currentDateTime();
+ if (m_lastCheck.isValid() && m_lastCheck.secsTo(now) < qmime_secondsBetweenChecks)
+ return false;
+ m_lastCheck = now;
+ return true;
+}
+
QMimeBinaryProvider::QMimeBinaryProvider(QMimeDatabasePrivate *db)
: QMimeProviderBase(db), m_mimetypeListLoaded(false)
{
@@ -76,26 +88,59 @@ struct QMimeBinaryProvider::CacheFile
inline const char* getCharStar(int offset) const {
return reinterpret_cast<const char *>(data + offset);
}
+ bool load();
+ bool reload();
QFile *file;
uchar *data;
+ QDateTime m_mtime;
bool m_valid;
};
QMimeBinaryProvider::CacheFile::CacheFile(QFile *f)
: file(f), m_valid(false)
{
+ load();
+}
+
+QMimeBinaryProvider::CacheFile::~CacheFile()
+{
+ delete file;
+}
+
+bool QMimeBinaryProvider::CacheFile::load()
+{
data = file->map(0, file->size());
if (data) {
const int major = getUint16(0);
const int minor = getUint16(2);
m_valid = (major == 1 && minor >= 1 && minor <= 2);
}
+ m_mtime = QFileInfo(*file).lastModified();
+ return m_valid;
}
-QMimeBinaryProvider::CacheFile::~CacheFile()
+bool QMimeBinaryProvider::CacheFile::reload()
{
- delete file;
+ //qDebug() << "reload!" << file->fileName();
+ m_valid = false;
+ if (file->isOpen()) {
+ file->close();
+ if (!file->open(QIODevice::ReadOnly)) {
+ return false;
+ }
+ }
+ data = 0;
+ return load();
+}
+
+QMimeBinaryProvider::CacheFile* QMimeBinaryProvider::CacheFileList::findCacheFile(const QString& fileName) const
+{
+ for (const_iterator it = begin(); it != end(); ++it) {
+ if ((*it)->file->fileName() == fileName)
+ return *it;
+ }
+ return 0;
}
QMimeBinaryProvider::~QMimeBinaryProvider()
@@ -122,22 +167,8 @@ bool QMimeBinaryProvider::isValid()
return false;
}
- const QStringList cacheFilenames = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("mime/mime.cache"));
- qDeleteAll(m_cacheFiles);
- m_cacheFiles.clear();
-
- // Verify version
- foreach (const QString& cacheFilename, cacheFilenames) {
- QFile *file = new QFile(cacheFilename);
- if (file->open(QIODevice::ReadOnly)) {
- CacheFile *cacheFile = new CacheFile(file);
- if (cacheFile->isValid())
- m_cacheFiles.append(cacheFile);
- else
- delete cacheFile;
- } else
- delete file;
- }
+ Q_ASSERT(m_cacheFiles.isEmpty()); // this method is only ever called once
+ checkCache();
if (m_cacheFiles.count() > 1)
return true;
@@ -154,6 +185,61 @@ bool QMimeBinaryProvider::isValid()
#endif
}
+bool QMimeBinaryProvider::CacheFileList::checkCacheChanged()
+{
+ bool somethingChanged = false;
+ QMutableListIterator<CacheFile *> it(*this);
+ while (it.hasNext()) {
+ CacheFile* cacheFile = it.next();
+ QFileInfo fileInfo(*cacheFile->file);
+ if (!fileInfo.exists()) { // This can't happen by just running update-mime-database. But the user could use rm -rf :-)
+ delete cacheFile;
+ it.remove();
+ somethingChanged = true;
+ } else if (fileInfo.lastModified() > cacheFile->m_mtime) {
+ if (!cacheFile->reload()) {
+ delete cacheFile;
+ it.remove();
+ }
+ somethingChanged = true;
+ }
+ }
+ return somethingChanged;
+}
+
+void QMimeBinaryProvider::checkCache()
+{
+ if (!shouldCheck())
+ return;
+
+ // First iterate over existing known cache files and check for uptodate
+ if (m_cacheFiles.checkCacheChanged())
+ m_mimetypeListLoaded = false;
+
+ // Then check if new cache files appeared
+ const QStringList cacheFileNames = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("mime/mime.cache"));
+ if (cacheFileNames != m_cacheFileNames) {
+ foreach (const QString& cacheFileName, cacheFileNames) {
+ CacheFile* cacheFile = m_cacheFiles.findCacheFile(cacheFileName);
+ if (!cacheFile) {
+ //qDebug() << "new file:" << cacheFileName;
+ QFile *file = new QFile(cacheFileName);
+ if (file->open(QIODevice::ReadOnly)) {
+ cacheFile = new CacheFile(file);
+ if (cacheFile->isValid()) { // verify version
+ m_cacheFiles.append(cacheFile);
+ }
+ else
+ delete cacheFile;
+ } else
+ delete file;
+ }
+ }
+ m_cacheFileNames = cacheFileNames;
+ m_mimetypeListLoaded = false;
+ }
+}
+
static QMimeType mimeTypeForNameUnchecked(const QString &name)
{
QMimeTypePrivate data;
@@ -167,6 +253,7 @@ static QMimeType mimeTypeForNameUnchecked(const QString &name)
QMimeType QMimeBinaryProvider::mimeTypeForName(const QString &name)
{
+ checkCache();
if (!m_mimetypeListLoaded)
loadMimeTypeList();
if (!m_mimetypeNames.contains(name))
@@ -176,6 +263,7 @@ QMimeType QMimeBinaryProvider::mimeTypeForName(const QString &name)
QStringList QMimeBinaryProvider::findByName(const QString &fileName, QString *foundSuffix)
{
+ checkCache();
const QString lowerFileName = fileName.toLower();
QMimeGlobMatchResult result;
// TODO this parses in the order (local, global). Check that it handles "NOGLOBS" correctly.
@@ -290,6 +378,7 @@ bool QMimeBinaryProvider::matchMagicRule(QMimeBinaryProvider::CacheFile *cacheFi
QMimeType QMimeBinaryProvider::findByMagic(const QByteArray &data, int *accuracyPtr)
{
+ checkCache();
foreach (CacheFile *cacheFile, m_cacheFiles) {
const int magicListOffset = cacheFile->getUint32(PosMagicListOffset);
const int numMatches = cacheFile->getUint32(magicListOffset);
@@ -315,6 +404,7 @@ QMimeType QMimeBinaryProvider::findByMagic(const QByteArray &data, int *accuracy
QStringList QMimeBinaryProvider::parents(const QString &mime)
{
+ checkCache();
const QByteArray mimeStr = mime.toLatin1();
QStringList result;
foreach (CacheFile *cacheFile, m_cacheFiles) {
@@ -355,6 +445,7 @@ QStringList QMimeBinaryProvider::parents(const QString &mime)
QString QMimeBinaryProvider::resolveAlias(const QString &name)
{
+ checkCache();
const QByteArray input = name.toLatin1();
foreach (CacheFile *cacheFile, m_cacheFiles) {
const int aliasListOffset = cacheFile->getUint32(PosAliasListOffset);
@@ -521,6 +612,7 @@ QString QMimeBinaryProvider::iconForMime(CacheFile *cacheFile, int posListOffset
void QMimeBinaryProvider::loadIcon(QMimeTypePrivate &data)
{
+ checkCache();
const QByteArray inputMime = data.name.toLatin1();
foreach (CacheFile *cacheFile, m_cacheFiles) {
const QString icon = iconForMime(cacheFile, PosIconsListOffset, inputMime);
@@ -533,6 +625,7 @@ void QMimeBinaryProvider::loadIcon(QMimeTypePrivate &data)
void QMimeBinaryProvider::loadGenericIcon(QMimeTypePrivate &data)
{
+ checkCache();
const QByteArray inputMime = data.name.toLatin1();
foreach (CacheFile *cacheFile, m_cacheFiles) {
const QString icon = iconForMime(cacheFile, PosGenericIconsListOffset, inputMime);
@@ -590,11 +683,12 @@ QMimeType QMimeXMLProvider::findByMagic(const QByteArray &data, int *accuracyPtr
void QMimeXMLProvider::ensureLoaded()
{
- if (!m_loaded) {
+ if (!m_loaded || shouldCheck()) {
bool fdoXmlFound = false;
QStringList allFiles;
const QStringList packageDirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("mime/packages"), QStandardPaths::LocateDirectory);
+ //qDebug() << "packageDirs=" << packageDirs;
foreach (const QString &packageDir, packageDirs) {
QDir dir(packageDir);
const QStringList files = dir.entryList(QDir::Files | QDir::NoDotAndDotDot);
@@ -608,11 +702,22 @@ void QMimeXMLProvider::ensureLoaded()
}
if (!fdoXmlFound) {
- // TODO: putting the xml file in the resource is a hack for now
- // We should instead install the file as part of installing Qt
- load(QLatin1String(":/qmime/freedesktop.org.xml"));
+ // We could instead install the file as part of installing Qt?
+ allFiles.prepend(QLatin1String(":/qmime/freedesktop.org.xml"));
}
+ if (m_allFiles == allFiles)
+ return;
+ m_allFiles = allFiles;
+
+ m_nameMimeTypeMap.clear();
+ m_aliases.clear();
+ m_parents.clear();
+ m_mimeTypeGlobs.clear();
+ m_magicMatchers.clear();
+
+ //qDebug() << "Loading" << m_allFiles;
+
foreach (const QString& file, allFiles)
load(file);
}
@@ -655,6 +760,7 @@ void QMimeXMLProvider::addMimeType(const QMimeType &mt)
QStringList QMimeXMLProvider::parents(const QString &mime)
{
+ ensureLoaded();
QStringList result = m_parents.value(mime);
if (result.isEmpty()) {
const QString parent = fallbackParent(mime);
@@ -671,6 +777,7 @@ void QMimeXMLProvider::addParent(const QString &child, const QString &parent)
QString QMimeXMLProvider::resolveAlias(const QString &name)
{
+ ensureLoaded();
return m_aliases.value(name, name);
}
@@ -681,6 +788,7 @@ void QMimeXMLProvider::addAlias(const QString &alias, const QString &name)
QList<QMimeType> QMimeXMLProvider::allMimeTypes()
{
+ ensureLoaded();
return m_nameMimeTypeMap.values();
}
diff --git a/src/mimetypes/qmimeprovider_p.h b/src/mimetypes/qmimeprovider_p.h
index ffdec32..21ed2ae 100644
--- a/src/mimetypes/qmimeprovider_p.h
+++ b/src/mimetypes/qmimeprovider_p.h
@@ -21,6 +21,7 @@
#ifndef QMIMEPROVIDER_P_H
#define QMIMEPROVIDER_P_H
+#include <QDateTime>
#include "qmimedatabase_p.h"
#include <QtCore/QSet>
class QMimeMagicRuleMatcher;
@@ -43,6 +44,9 @@ public:
virtual void loadGenericIcon(QMimeTypePrivate &) {}
QMimeDatabasePrivate* m_db;
+protected:
+ bool shouldCheck();
+ QDateTime m_lastCheck;
};
/*
@@ -73,8 +77,16 @@ private:
bool matchMagicRule(CacheFile *cacheFile, int numMatchlets, int firstOffset, const QByteArray &data);
QString iconForMime(CacheFile *cacheFile, int posListOffset, const QByteArray& inputMime);
void loadMimeTypeList();
-
- QList<CacheFile *> m_cacheFiles;
+ void checkCache();
+
+ class CacheFileList : public QList<CacheFile *>
+ {
+ public:
+ CacheFile* findCacheFile(const QString& fileName) const;
+ bool checkCacheChanged();
+ };
+ CacheFileList m_cacheFiles;
+ QStringList m_cacheFileNames;
QSet<QString> m_mimetypeNames;
bool m_mimetypeListLoaded;
};
@@ -121,6 +133,7 @@ private:
QMimeAllGlobPatterns m_mimeTypeGlobs;
QList<QMimeMagicRuleMatcher> m_magicMatchers;
+ QStringList m_allFiles;
};
#endif // QMIMEPROVIDER_P_H
diff --git a/tests/auto/qmimedatabase/qmimedatabase-cache/tst_qmimedatabase-cache.cpp b/tests/auto/qmimedatabase/qmimedatabase-cache/tst_qmimedatabase-cache.cpp
index 6f5dd7c..749ac0b 100644
--- a/tests/auto/qmimedatabase/qmimedatabase-cache/tst_qmimedatabase-cache.cpp
+++ b/tests/auto/qmimedatabase/qmimedatabase-cache/tst_qmimedatabase-cache.cpp
@@ -8,26 +8,8 @@
tst_qmimedatabase::tst_qmimedatabase()
{
- qputenv("XDG_DATA_HOME", QByteArray("doesnotexist"));
- // Copy SRCDIR "../../../src/mimetypes/mime to a temp dir
- // then run update-mime-database
- // then set XDG_DATA_DIRS to the TEMP dir
-
QDir here = QDir::currentPath();
- here.mkpath(QString::fromLatin1("mime/packages"));
- QFile xml(QFile::decodeName(SRCDIR "../../../src/mimetypes/mime/packages/freedesktop.org.xml"));
const QString tempMime = here.absolutePath() + QString::fromLatin1("/mime");
- xml.copy(tempMime + QString::fromLatin1("/packages/freedesktop.org.xml"));
-
- const QString umd = QStandardPaths::findExecutable(QString::fromLatin1("update-mime-database"));
- if (umd.isEmpty())
- QSKIP("shared-mime-info not found, skipping mime.cache test", SkipAll);
-
- QProcess proc;
- proc.setProcessChannelMode(QProcess::MergedChannels); // silence output
- proc.start(umd, QStringList() << tempMime);
- proc.waitForFinished();
-
+ runUpdateMimeDatabase(tempMime);
QVERIFY(QFile::exists(tempMime + QString::fromLatin1("/mime.cache")));
- qputenv("XDG_DATA_DIRS", QFile::encodeName(here.absolutePath()));
}
diff --git a/tests/auto/qmimedatabase/qmimedatabase-xml/tst_qmimedatabase-xml.cpp b/tests/auto/qmimedatabase/qmimedatabase-xml/tst_qmimedatabase-xml.cpp
index 58f4305..81e670f 100644
--- a/tests/auto/qmimedatabase/qmimedatabase-xml/tst_qmimedatabase-xml.cpp
+++ b/tests/auto/qmimedatabase/qmimedatabase-xml/tst_qmimedatabase-xml.cpp
@@ -1,10 +1,9 @@
#include "../tst_qmimedatabase.h"
+#include <QDebug>
+#include <QDir>
tst_qmimedatabase::tst_qmimedatabase()
{
- // To make sure that other mime packages don't change our test results
- qputenv("XDG_DATA_DIRS", SRCDIR "../../../src/mimetypes/mime");
- qputenv("XDG_DATA_HOME", QByteArray("doesnotexist"));
qputenv("QT_NO_MIME_CACHE", "1");
}
diff --git a/tests/auto/qmimedatabase/tst_qmimedatabase.cpp b/tests/auto/qmimedatabase/tst_qmimedatabase.cpp
index 2713d55..8340c76 100644
--- a/tests/auto/qmimedatabase/tst_qmimedatabase.cpp
+++ b/tests/auto/qmimedatabase/tst_qmimedatabase.cpp
@@ -36,6 +36,39 @@ tst_qmimedatabase::~tst_qmimedatabase()
void tst_qmimedatabase::initTestCase()
{
+ // Create a "global" and a "local" XDG data dir, right here.
+ // The local dir will be empty initially, while the global dir will contain a copy of freedesktop.org.xml
+
+ QDir here = QDir::currentPath();
+
+ qputenv("XDG_DATA_DIRS", QFile::encodeName(here.absolutePath()));
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
+ QDir(here.absolutePath() + "/mime").removeRecursively();
+#endif
+ here.mkpath(QString::fromLatin1("mime/packages"));
+
+ QFile xml(QFile::decodeName(SRCDIR "../../../src/mimetypes/mime/packages/freedesktop.org.xml"));
+ const QString mimeDir = here.absolutePath() + QLatin1String("/mime");
+ xml.copy(mimeDir + QLatin1String("/packages/freedesktop.org.xml"));
+
+ m_dataHome = here.absolutePath() + QLatin1String("/../datahome");
+ qputenv("XDG_DATA_HOME", QFile::encodeName(m_dataHome));
+ //qDebug() << "XDG_DATA_HOME=" << m_dataHome;
+
+ // Make sure we start clean
+ cleanupTestCase();
+}
+
+void tst_qmimedatabase::cleanupTestCase()
+{
+ QDir here = QDir::currentPath();
+ here.remove(QString::fromLatin1("mime/packages/yast2-metapackage-handler-mimetypes.xml"));
+
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
+ QDir(m_dataHome).removeRecursively();
+#else
+ QFile::remove(m_dataHome + QLatin1String("/mime/packages/yast2-metapackage-handler-mimetypes.xml"));
+#endif
}
void tst_qmimedatabase::test_mimeTypeForName()
@@ -630,11 +663,116 @@ void tst_qmimedatabase::test_fromThreads()
#endif
}
+static void runUpdateMimeDatabase(const QString &path) // TODO make it a QMimeDatabase method?
+{
+ const QString umd = QStandardPaths::findExecutable(QString::fromLatin1("update-mime-database"));
+ if (umd.isEmpty())
+ QSKIP("shared-mime-info not found, skipping mime.cache test", SkipAll);
+
+ QProcess proc;
+ proc.setProcessChannelMode(QProcess::MergedChannels); // silence output
+ proc.start(umd, QStringList() << path);
+ proc.waitForFinished();
+ //qDebug() << "runUpdateMimeDatabase" << path;
+}
+
+static void waitAndRunUpdateMimeDatabase(const QString &path)
+{
+ QFileInfo mimeCacheInfo(path + QString::fromLatin1("/mime.cache"));
+ if (mimeCacheInfo.exists()) {
+ // Wait until the begining of the next second
+ while (mimeCacheInfo.lastModified().secsTo(QDateTime::currentDateTime()) == 0) {
+ QTest::qSleep(200);
+ }
+ }
+ runUpdateMimeDatabase(path);
+}
+
+static void checkHasMimeType(const QString &mimeType)
+{
+ QMimeDatabase db;
+ QVERIFY(db.mimeTypeForName(mimeType).isValid());
+
+ bool found = false;
+ foreach (const QMimeType& mt, db.allMimeTypes()) {
+ if (mt.name() == mimeType) {
+ found = true;
+ break;
+ }
+ }
+ QVERIFY(found);
+}
+
+extern QMIME_EXPORT int qmime_secondsBetweenChecks; // see qmimeprovider.cpp
+
+void tst_qmimedatabase::installNewGlobalMimeType()
+{
+ qmime_secondsBetweenChecks = 0;
+
+ QMimeDatabase db;
+ QVERIFY(!db.mimeTypeForName(QLatin1String("text/x-suse-ymp")).isValid());
+
+ const QString fileName = QLatin1String("yast2-metapackage-handler-mimetypes.xml");
+ const QString srcFile = QFile::decodeName(SRCDIR) + fileName;
+
+ QDir here = QDir::currentPath();
+ const QString mimeDir = here.absolutePath() + QLatin1String("/mime");
+ const QString destDir = mimeDir + QLatin1String("/packages/");
+ const QString destFile = destDir + fileName;
+ QFile::remove(destFile);
+ //qDebug() << destFile;
+ QVERIFY(QFile::copy(srcFile, destFile));
+ waitAndRunUpdateMimeDatabase(mimeDir);
+
+ QCOMPARE(db.findByName(QLatin1String("foo.ymu")).name(), QString::fromLatin1("text/x-suse-ymu"));
+ QVERIFY(db.mimeTypeForName(QLatin1String("text/x-suse-ymp")).isValid());
+ checkHasMimeType("text/x-suse-ymp");
+
+ // Now test removing it again
+ QFile::remove(destFile);
+ waitAndRunUpdateMimeDatabase(mimeDir);
+ QCOMPARE(db.findByName(QLatin1String("foo.ymu")).name(), QString::fromLatin1("application/octet-stream"));
+ QVERIFY(!db.mimeTypeForName(QLatin1String("text/x-suse-ymp")).isValid());
+}
+
+void tst_qmimedatabase::installNewLocalMimeType()
+{
+ qmime_secondsBetweenChecks = 0;
+
+ QMimeDatabase db;
+ QVERIFY(!db.mimeTypeForName(QLatin1String("text/x-suse-ymp")).isValid());
+
+ const QString fileName = QLatin1String("yast2-metapackage-handler-mimetypes.xml");
+ const QString srcFile = QFile::decodeName(SRCDIR) + fileName;
+ const QString mimeDir = m_dataHome + QLatin1String("/mime");
+ const QString destDir = mimeDir + QLatin1String("/packages/");
+ QDir().mkpath(destDir);
+ const QString destFile = destDir + fileName;
+ QFile::remove(destFile);
+ QVERIFY(QFile::copy(srcFile, destFile));
+ runUpdateMimeDatabase(mimeDir);
+
+ QCOMPARE(db.findByName(QLatin1String("foo.ymu")).name(), QString::fromLatin1("text/x-suse-ymu"));
+ QVERIFY(db.mimeTypeForName(QLatin1String("text/x-suse-ymp")).isValid());
+ checkHasMimeType("text/x-suse-ymp");
+
+ // Now test removing it again (note, this leaves a mostly-empty mime.cache file)
+ QFile::remove(destFile);
+ waitAndRunUpdateMimeDatabase(mimeDir);
+ QCOMPARE(db.findByName(QLatin1String("foo.ymu")).name(), QString::fromLatin1("application/octet-stream"));
+ QVERIFY(!db.mimeTypeForName(QLatin1String("text/x-suse-ymp")).isValid());
+
+ // And now the user goes wild and uses rm -rf
+ QFile::remove(mimeDir + QString::fromLatin1("/mime.cache"));
+ QCOMPARE(db.findByName(QLatin1String("foo.ymu")).name(), QString::fromLatin1("application/octet-stream"));
+ QVERIFY(!db.mimeTypeForName(QLatin1String("text/x-suse-ymp")).isValid());
+}
+
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
//QTEST_MAIN(tst_qmimedatabase)
QTEST_GUILESS_MAIN(tst_qmimedatabase)
#else
// If tests with icons were activated in Qt4 we'd use QTEST_MAIN:
//QTEST_MAIN(tst_qmimedatabase)
-QTEST_MAIN(tst_qmimedatabase)
+ QTEST_MAIN(tst_qmimedatabase)
#endif
diff --git a/tests/auto/qmimedatabase/tst_qmimedatabase.h b/tests/auto/qmimedatabase/tst_qmimedatabase.h
index 7068cef..4fec1c9 100644
--- a/tests/auto/qmimedatabase/tst_qmimedatabase.h
+++ b/tests/auto/qmimedatabase/tst_qmimedatabase.h
@@ -19,6 +19,7 @@ public:
private slots:
void initTestCase();
+ void cleanupTestCase();
void test_mimeTypeForName();
void test_findByName_data();
@@ -51,6 +52,14 @@ private slots:
void findByFile_data();
void findByFile();
+
+ //
+
+ void installNewGlobalMimeType();
+ void installNewLocalMimeType();
+
+private:
+ QString m_dataHome;
};
#endif // TST_QMIMEDATABASE_H_INCLUDED
diff --git a/tests/auto/qmimedatabase/yast2-metapackage-handler-mimetypes.xml b/tests/auto/qmimedatabase/yast2-metapackage-handler-mimetypes.xml
new file mode 100644
index 0000000..ef3035e
--- /dev/null
+++ b/tests/auto/qmimedatabase/yast2-metapackage-handler-mimetypes.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0"?>
+<!-- http://www.freedesktop.org/wiki/Specifications/shared-mime-info-spec -->
+<!-- to to ${PREFIX-~/.local}/share/mime/packages -->
+<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>
+ <mime-type type="text/x-suse-ymp">
+ <comment>YaST Meta Package</comment>
+ <glob pattern="*.ymp"/>
+ </mime-type>
+
+ <mime-type type="text/x-suse-ymu">
+ <comment>URL of a YaST Meta Package</comment>
+ <glob pattern="*.ymu"/>
+ </mime-type>
+</mime-info>
+