forked from qt-creator/qt-creator
Delay modifications to MIME database until first use
Initialization of the MIME database takes time, and it is good to avoid this during startup. We nevertheless want to apply some modifications to the MIME database, so we need to delay these modifications until first use. Allow registration of additional initialization functions. Since the initialization functions access the MIME database, which does locking for thread- safety, we need to separate the initialization to outside these locking functions. Change-Id: I2b1706347768bcf081644e078ccfa45302d61641 Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -957,6 +957,7 @@ void PluginManagerPrivate::nextDelayedInitialize()
|
|||||||
break; // do next delayedInitialize after a delay
|
break; // do next delayedInitialize after a delay
|
||||||
}
|
}
|
||||||
if (delayedInitializeQueue.empty()) {
|
if (delayedInitializeQueue.empty()) {
|
||||||
|
Utils::setMimeStartupPhase(MimeStartupPhase::UpAndRunning);
|
||||||
m_isInitializationDone = true;
|
m_isInitializationDone = true;
|
||||||
delete delayedInitializeTimer;
|
delete delayedInitializeTimer;
|
||||||
delayedInitializeTimer = nullptr;
|
delayedInitializeTimer = nullptr;
|
||||||
@@ -1370,7 +1371,6 @@ void PluginManagerPrivate::loadPlugins()
|
|||||||
loadPlugin(spec, PluginSpec::Initialized);
|
loadPlugin(spec, PluginSpec::Initialized);
|
||||||
}
|
}
|
||||||
|
|
||||||
Utils::setMimeStartupPhase(MimeStartupPhase::PluginsDelayedInitializing);
|
|
||||||
{
|
{
|
||||||
NANOTRACE_SCOPE("ExtensionSystem", "ExtensionsInitialized");
|
NANOTRACE_SCOPE("ExtensionSystem", "ExtensionsInitialized");
|
||||||
Utils::reverseForeach(queue, [this](PluginSpec *spec) {
|
Utils::reverseForeach(queue, [this](PluginSpec *spec) {
|
||||||
@@ -1384,8 +1384,8 @@ void PluginManagerPrivate::loadPlugins()
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
emit q->pluginsChanged();
|
emit q->pluginsChanged();
|
||||||
Utils::setMimeStartupPhase(MimeStartupPhase::UpAndRunning);
|
|
||||||
|
|
||||||
|
Utils::setMimeStartupPhase(MimeStartupPhase::PluginsDelayedInitializing);
|
||||||
delayedInitializeTimer = new QTimer;
|
delayedInitializeTimer = new QTimer;
|
||||||
delayedInitializeTimer->setInterval(DELAYED_INITIALIZE_INTERVAL);
|
delayedInitializeTimer->setInterval(DELAYED_INITIALIZE_INTERVAL);
|
||||||
delayedInitializeTimer->setSingleShot(true);
|
delayedInitializeTimer->setSingleShot(true);
|
||||||
|
@@ -562,12 +562,9 @@ MimeDatabase::~MimeDatabase()
|
|||||||
*/
|
*/
|
||||||
MimeType MimeDatabase::mimeTypeForName(const QString &nameOrAlias) const
|
MimeType MimeDatabase::mimeTypeForName(const QString &nameOrAlias) const
|
||||||
{
|
{
|
||||||
|
d->checkInitPhase(nameOrAlias);
|
||||||
QMutexLocker locker(&d->mutex);
|
QMutexLocker locker(&d->mutex);
|
||||||
|
|
||||||
if (d->m_startupPhase <= int(MimeStartupPhase::PluginsInitializing))
|
|
||||||
qWarning("Accessing MimeDatabase for %s before plugins are initialized",
|
|
||||||
qPrintable(nameOrAlias));
|
|
||||||
|
|
||||||
return d->mimeTypeForName(nameOrAlias);
|
return d->mimeTypeForName(nameOrAlias);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -601,12 +598,9 @@ MimeType MimeDatabase::mimeTypeForName(const QString &nameOrAlias) const
|
|||||||
*/
|
*/
|
||||||
MimeType MimeDatabase::mimeTypeForFile(const QFileInfo &fileInfo, MatchMode mode) const
|
MimeType MimeDatabase::mimeTypeForFile(const QFileInfo &fileInfo, MatchMode mode) const
|
||||||
{
|
{
|
||||||
|
d->checkInitPhase(fileInfo.filePath());
|
||||||
QMutexLocker locker(&d->mutex);
|
QMutexLocker locker(&d->mutex);
|
||||||
|
|
||||||
if (d->m_startupPhase <= int(MimeStartupPhase::PluginsInitializing))
|
|
||||||
qWarning("Accessing MimeDatabase for %s before plugins are initialized",
|
|
||||||
qPrintable(fileInfo.filePath()));
|
|
||||||
|
|
||||||
if (fileInfo.isDir())
|
if (fileInfo.isDir())
|
||||||
return d->mimeTypeForName(QLatin1String("inode/directory"));
|
return d->mimeTypeForName(QLatin1String("inode/directory"));
|
||||||
|
|
||||||
@@ -659,12 +653,9 @@ MimeType MimeDatabase::mimeTypeForFile(const QFileInfo &fileInfo, MatchMode mode
|
|||||||
MimeType MimeDatabase::mimeTypeForFile(const QString &fileName, MatchMode mode) const
|
MimeType MimeDatabase::mimeTypeForFile(const QString &fileName, MatchMode mode) const
|
||||||
{
|
{
|
||||||
if (mode == MatchExtension) {
|
if (mode == MatchExtension) {
|
||||||
|
d->checkInitPhase(fileName);
|
||||||
QMutexLocker locker(&d->mutex);
|
QMutexLocker locker(&d->mutex);
|
||||||
|
|
||||||
if (d->m_startupPhase <= int(MimeStartupPhase::PluginsInitializing))
|
|
||||||
qWarning("Accessing MimeDatabase for %s before plugins are initialized",
|
|
||||||
qPrintable(fileName));
|
|
||||||
|
|
||||||
const QStringList matches = d->mimeTypeForFileName(fileName);
|
const QStringList matches = d->mimeTypeForFileName(fileName);
|
||||||
const int matchCount = matches.count();
|
const int matchCount = matches.count();
|
||||||
if (matchCount == 0) {
|
if (matchCount == 0) {
|
||||||
@@ -696,12 +687,9 @@ MimeType MimeDatabase::mimeTypeForFile(const QString &fileName, MatchMode mode)
|
|||||||
*/
|
*/
|
||||||
QList<MimeType> MimeDatabase::mimeTypesForFileName(const QString &fileName) const
|
QList<MimeType> MimeDatabase::mimeTypesForFileName(const QString &fileName) const
|
||||||
{
|
{
|
||||||
|
d->checkInitPhase(fileName);
|
||||||
QMutexLocker locker(&d->mutex);
|
QMutexLocker locker(&d->mutex);
|
||||||
|
|
||||||
if (d->m_startupPhase <= int(MimeStartupPhase::PluginsInitializing))
|
|
||||||
qWarning("Accessing MimeDatabase for %s before plugins are initialized",
|
|
||||||
qPrintable(fileName));
|
|
||||||
|
|
||||||
const QStringList matches = d->mimeTypeForFileName(fileName);
|
const QStringList matches = d->mimeTypeForFileName(fileName);
|
||||||
QList<MimeType> mimes;
|
QList<MimeType> mimes;
|
||||||
mimes.reserve(matches.count());
|
mimes.reserve(matches.count());
|
||||||
@@ -731,11 +719,9 @@ QString MimeDatabase::suffixForFileName(const QString &fileName) const
|
|||||||
*/
|
*/
|
||||||
MimeType MimeDatabase::mimeTypeForData(const QByteArray &data) const
|
MimeType MimeDatabase::mimeTypeForData(const QByteArray &data) const
|
||||||
{
|
{
|
||||||
|
d->checkInitPhase("data");
|
||||||
QMutexLocker locker(&d->mutex);
|
QMutexLocker locker(&d->mutex);
|
||||||
|
|
||||||
if (d->m_startupPhase <= int(MimeStartupPhase::PluginsInitializing))
|
|
||||||
qWarning("Accessing MimeDatabase for data before plugins are initialized");
|
|
||||||
|
|
||||||
int accuracy = 0;
|
int accuracy = 0;
|
||||||
return d->findByData(data, &accuracy);
|
return d->findByData(data, &accuracy);
|
||||||
}
|
}
|
||||||
@@ -863,11 +849,9 @@ MimeType MimeDatabase::mimeTypeForFileNameAndData(const QString &fileName, const
|
|||||||
*/
|
*/
|
||||||
QList<MimeType> MimeDatabase::allMimeTypes() const
|
QList<MimeType> MimeDatabase::allMimeTypes() const
|
||||||
{
|
{
|
||||||
|
d->checkInitPhase("all mime types");
|
||||||
QMutexLocker locker(&d->mutex);
|
QMutexLocker locker(&d->mutex);
|
||||||
|
|
||||||
if (d->m_startupPhase <= int(MimeStartupPhase::PluginsInitializing))
|
|
||||||
qWarning("Accessing MimeDatabase for all mime types before plugins are initialized");
|
|
||||||
|
|
||||||
return d->allMimeTypes();
|
return d->allMimeTypes();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -924,4 +908,27 @@ void MimeDatabasePrivate::setGlobPatternsForMimeType(const MimeType &mimeType,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MimeDatabasePrivate::checkInitPhase(const QString &info)
|
||||||
|
{
|
||||||
|
QReadLocker locker(&m_initMutex);
|
||||||
|
if (m_startupPhase <= int(MimeStartupPhase::PluginsInitializing)) {
|
||||||
|
qWarning("Accessing MimeDatabase for %s before plugins are initialized", qPrintable(info));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// run initialization functions and ensure providers are loaded
|
||||||
|
// the initializers will call other MIME database functions which "checkInitPhase" again,
|
||||||
|
// so make sure not to recurse
|
||||||
|
if (!m_initialized.exchange(true)) {
|
||||||
|
for (const std::function<void()> &f : m_initializers)
|
||||||
|
f();
|
||||||
|
QMutexLocker locker(&mutex);
|
||||||
|
providers();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MimeDatabasePrivate::addInitializer(const std::function<void()> &init)
|
||||||
|
{
|
||||||
|
m_initializers.append(init);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Utils
|
} // namespace Utils
|
||||||
|
@@ -25,8 +25,11 @@
|
|||||||
#include <QtCore/qlist.h>
|
#include <QtCore/qlist.h>
|
||||||
#include <QtCore/qmutex.h>
|
#include <QtCore/qmutex.h>
|
||||||
|
|
||||||
#include <vector>
|
#include <QReadWriteLock>
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QIODevice;
|
class QIODevice;
|
||||||
@@ -75,6 +78,8 @@ 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 checkInitPhase(const QString &info);
|
||||||
|
void addInitializer(const std::function<void()> &init);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using Providers = std::vector<std::unique_ptr<MimeProviderBase>>;
|
using Providers = std::vector<std::unique_ptr<MimeProviderBase>>;
|
||||||
@@ -86,6 +91,7 @@ private:
|
|||||||
QElapsedTimer m_lastCheck;
|
QElapsedTimer m_lastCheck;
|
||||||
|
|
||||||
// added for Qt Creator
|
// added for Qt Creator
|
||||||
|
QList<std::function<void()>> m_initializers;
|
||||||
QHash<QString, QByteArray> m_additionalData; // id -> data
|
QHash<QString, QByteArray> m_additionalData; // id -> data
|
||||||
bool m_forceLoad = true;
|
bool m_forceLoad = true;
|
||||||
|
|
||||||
@@ -94,6 +100,8 @@ public:
|
|||||||
QMutex mutex;
|
QMutex mutex;
|
||||||
|
|
||||||
// added for Qt Creator
|
// added for Qt Creator
|
||||||
|
QReadWriteLock m_initMutex;
|
||||||
|
std::atomic_bool m_initialized = false;
|
||||||
int m_startupPhase = 0;
|
int m_startupPhase = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -57,7 +57,7 @@ QList<MimeType> allMimeTypes()
|
|||||||
void setMimeStartupPhase(MimeStartupPhase phase)
|
void setMimeStartupPhase(MimeStartupPhase phase)
|
||||||
{
|
{
|
||||||
auto d = MimeDatabasePrivate::instance();
|
auto d = MimeDatabasePrivate::instance();
|
||||||
QMutexLocker locker(&d->mutex);
|
QWriteLocker locker(&d->m_initMutex);
|
||||||
if (int(phase) != d->m_startupPhase + 1) {
|
if (int(phase) != d->m_startupPhase + 1) {
|
||||||
qWarning("Unexpected jump in MimedDatabase lifetime from %d to %d",
|
qWarning("Unexpected jump in MimedDatabase lifetime from %d to %d",
|
||||||
d->m_startupPhase,
|
d->m_startupPhase,
|
||||||
@@ -69,12 +69,14 @@ void setMimeStartupPhase(MimeStartupPhase phase)
|
|||||||
void addMimeTypes(const QString &id, const QByteArray &data)
|
void addMimeTypes(const QString &id, const QByteArray &data)
|
||||||
{
|
{
|
||||||
auto d = MimeDatabasePrivate::instance();
|
auto d = MimeDatabasePrivate::instance();
|
||||||
QMutexLocker locker(&d->mutex);
|
{
|
||||||
|
QReadLocker locker(&d->m_initMutex);
|
||||||
if (d->m_startupPhase >= int(MimeStartupPhase::PluginsDelayedInitializing)) {
|
if (d->m_startupPhase >= int(MimeStartupPhase::PluginsDelayedInitializing)) {
|
||||||
qWarning("Adding items for ID \"%s\" to MimeDatabase after initialization time",
|
qWarning("Adding items for ID \"%s\" to MimeDatabase after initialization time",
|
||||||
qPrintable(id));
|
qPrintable(id));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
QMutexLocker locker(&d->mutex);
|
||||||
|
|
||||||
d->addMimeData(id, data);
|
d->addMimeData(id, data);
|
||||||
}
|
}
|
||||||
@@ -130,4 +132,14 @@ void visitMimeParents(const MimeType &mimeType,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
The \a init function will be executed once after the MIME database is first initialized.
|
||||||
|
It must be thread safe.
|
||||||
|
*/
|
||||||
|
void addMimeInitializer(const std::function<void()> &init)
|
||||||
|
{
|
||||||
|
auto d = MimeDatabasePrivate::instance();
|
||||||
|
d->addInitializer(init);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Utils
|
} // namespace Utils
|
||||||
|
@@ -43,6 +43,7 @@ enum class MimeStartupPhase {
|
|||||||
};
|
};
|
||||||
|
|
||||||
QTCREATOR_UTILS_EXPORT void setMimeStartupPhase(MimeStartupPhase);
|
QTCREATOR_UTILS_EXPORT void setMimeStartupPhase(MimeStartupPhase);
|
||||||
|
QTCREATOR_UTILS_EXPORT void addMimeInitializer(const std::function<void()> &init);
|
||||||
QTCREATOR_UTILS_EXPORT void addMimeTypes(const QString &id, const QByteArray &data);
|
QTCREATOR_UTILS_EXPORT void addMimeTypes(const QString &id, const QByteArray &data);
|
||||||
QTCREATOR_UTILS_EXPORT QMap<int, QList<MimeMagicRule>> magicRulesForMimeType(
|
QTCREATOR_UTILS_EXPORT QMap<int, QList<MimeMagicRule>> magicRulesForMimeType(
|
||||||
const MimeType &mimeType); // priority -> rules
|
const MimeType &mimeType); // priority -> rules
|
||||||
|
@@ -746,19 +746,25 @@ MimeTypeSettingsPrivate::UserMimeTypeHash MimeTypeSettingsPrivate::readUserModif
|
|||||||
return userMimeTypes;
|
return userMimeTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MimeTypeSettingsPrivate::applyUserModifiedMimeTypes(const UserMimeTypeHash &mimeTypes)
|
static void registerUserModifiedMimeTypes(const MimeTypeSettingsPrivate::UserMimeTypeHash &mimeTypes)
|
||||||
{
|
{
|
||||||
// register in mime data base, and remember for later
|
|
||||||
for (auto it = mimeTypes.constBegin(); it != mimeTypes.constEnd(); ++it) {
|
for (auto it = mimeTypes.constBegin(); it != mimeTypes.constEnd(); ++it) {
|
||||||
Utils::MimeType mt = Utils::mimeTypeForName(it.key());
|
Utils::MimeType mt = Utils::mimeTypeForName(it.key());
|
||||||
if (!mt.isValid()) // loaded from settings
|
if (!mt.isValid())
|
||||||
continue;
|
continue;
|
||||||
m_userModifiedMimeTypes.insert(it.key(), it.value());
|
|
||||||
Utils::setGlobPatternsForMimeType(mt, it.value().globPatterns);
|
Utils::setGlobPatternsForMimeType(mt, it.value().globPatterns);
|
||||||
Utils::setMagicRulesForMimeType(mt, it.value().rules);
|
Utils::setMagicRulesForMimeType(mt, it.value().rules);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MimeTypeSettingsPrivate::applyUserModifiedMimeTypes(const UserMimeTypeHash &mimeTypes)
|
||||||
|
{
|
||||||
|
// register in mime data base, and remember for later
|
||||||
|
for (auto it = mimeTypes.constBegin(); it != mimeTypes.constEnd(); ++it)
|
||||||
|
m_userModifiedMimeTypes.insert(it.key(), it.value());
|
||||||
|
registerUserModifiedMimeTypes(mimeTypes);
|
||||||
|
}
|
||||||
|
|
||||||
// MimeTypeSettingsPage
|
// MimeTypeSettingsPage
|
||||||
|
|
||||||
MimeTypeSettings::MimeTypeSettings()
|
MimeTypeSettings::MimeTypeSettings()
|
||||||
@@ -793,7 +799,8 @@ void MimeTypeSettings::restoreSettings()
|
|||||||
{
|
{
|
||||||
MimeTypeSettingsPrivate::UserMimeTypeHash mimetypes
|
MimeTypeSettingsPrivate::UserMimeTypeHash mimetypes
|
||||||
= MimeTypeSettingsPrivate::readUserModifiedMimeTypes();
|
= MimeTypeSettingsPrivate::readUserModifiedMimeTypes();
|
||||||
MimeTypeSettingsPrivate::applyUserModifiedMimeTypes(mimetypes);
|
MimeTypeSettingsPrivate::m_userModifiedMimeTypes = mimetypes;
|
||||||
|
Utils::addMimeInitializer([mimetypes] { registerUserModifiedMimeTypes(mimetypes); });
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget *MimeEditorDelegate::createEditor(QWidget *parent,
|
QWidget *MimeEditorDelegate::createEditor(QWidget *parent,
|
||||||
|
@@ -516,9 +516,7 @@ void CppEditorPlugin::initialize()
|
|||||||
void CppEditorPlugin::extensionsInitialized()
|
void CppEditorPlugin::extensionsInitialized()
|
||||||
{
|
{
|
||||||
d->m_fileSettings.fromSettings(ICore::settings());
|
d->m_fileSettings.fromSettings(ICore::settings());
|
||||||
if (!d->m_fileSettings.applySuffixesToMimeDB())
|
d->m_fileSettings.addMimeInitializer();
|
||||||
qWarning("Unable to apply cpp suffixes to mime database (cpp mime types not found).\n");
|
|
||||||
|
|
||||||
const auto fileNamesPanelFactory = new ProjectPanelFactory;
|
const auto fileNamesPanelFactory = new ProjectPanelFactory;
|
||||||
fileNamesPanelFactory->setPriority(99);
|
fileNamesPanelFactory->setPriority(99);
|
||||||
fileNamesPanelFactory->setDisplayName(Tr::tr("C++ File Naming"));
|
fileNamesPanelFactory->setDisplayName(Tr::tr("C++ File Naming"));
|
||||||
|
@@ -93,7 +93,7 @@ void CppFileSettings::fromSettings(QSettings *s)
|
|||||||
s->endGroup();
|
s->endGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CppFileSettings::applySuffixesToMimeDB()
|
static bool applySuffixes(const QString &sourceSuffix, const QString &headerSuffix)
|
||||||
{
|
{
|
||||||
Utils::MimeType mt;
|
Utils::MimeType mt;
|
||||||
mt = Utils::mimeTypeForName(QLatin1String(Constants::CPP_SOURCE_MIMETYPE));
|
mt = Utils::mimeTypeForName(QLatin1String(Constants::CPP_SOURCE_MIMETYPE));
|
||||||
@@ -107,6 +107,19 @@ bool CppFileSettings::applySuffixesToMimeDB()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CppFileSettings::addMimeInitializer() const
|
||||||
|
{
|
||||||
|
Utils::addMimeInitializer([sourceSuffix = sourceSuffix, headerSuffix = headerSuffix] {
|
||||||
|
if (!applySuffixes(sourceSuffix, headerSuffix))
|
||||||
|
qWarning("Unable to apply cpp suffixes to mime database (cpp mime types not found).\n");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CppFileSettings::applySuffixesToMimeDB()
|
||||||
|
{
|
||||||
|
return applySuffixes(sourceSuffix, headerSuffix);
|
||||||
|
}
|
||||||
|
|
||||||
bool CppFileSettings::equals(const CppFileSettings &rhs) const
|
bool CppFileSettings::equals(const CppFileSettings &rhs) const
|
||||||
{
|
{
|
||||||
return lowerCaseFiles == rhs.lowerCaseFiles
|
return lowerCaseFiles == rhs.lowerCaseFiles
|
||||||
|
@@ -38,6 +38,7 @@ public:
|
|||||||
|
|
||||||
void toSettings(QSettings *) const;
|
void toSettings(QSettings *) const;
|
||||||
void fromSettings(QSettings *);
|
void fromSettings(QSettings *);
|
||||||
|
void addMimeInitializer() const;
|
||||||
bool applySuffixesToMimeDB();
|
bool applySuffixesToMimeDB();
|
||||||
|
|
||||||
// Convenience to return a license template completely formatted.
|
// Convenience to return a license template completely formatted.
|
||||||
|
Reference in New Issue
Block a user