aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/languageclient
diff options
context:
space:
mode:
authorDavid Schulz <david.schulz@qt.io>2019-03-15 11:25:48 +0100
committerDavid Schulz <david.schulz@qt.io>2019-04-29 09:52:02 +0000
commit0ea840c2bda03251318263aa96c5b1bc9b4a94e1 (patch)
treed6c33d6456c89da2fffbfad81fcc0d4a3ecd4ecf /src/plugins/languageclient
parent132d813343bd8dece5a39ed86db845f10f9dce47 (diff)
LanguageClient: add option to start client per project
Some server like rust or haskell require a project at server startup. Add option that postpones the server start until we can assign a project to an open file. Change-Id: Iaa475289e833b27a730a90ea228f5d85ecc30338 Reviewed-by: Christian Stenger <christian.stenger@qt.io>
Diffstat (limited to 'src/plugins/languageclient')
-rw-r--r--src/plugins/languageclient/client.cpp26
-rw-r--r--src/plugins/languageclient/client.h3
-rw-r--r--src/plugins/languageclient/languageclientmanager.cpp106
-rw-r--r--src/plugins/languageclient/languageclientmanager.h7
-rw-r--r--src/plugins/languageclient/languageclientsettings.cpp95
-rw-r--r--src/plugins/languageclient/languageclientsettings.h20
6 files changed, 199 insertions, 58 deletions
diff --git a/src/plugins/languageclient/client.cpp b/src/plugins/languageclient/client.cpp
index dd544f37e9f..c84bc048666 100644
--- a/src/plugins/languageclient/client.cpp
+++ b/src/plugins/languageclient/client.cpp
@@ -215,10 +215,10 @@ void Client::initialize()
QTC_ASSERT(m_state == Uninitialized, return);
qCDebug(LOGLSPCLIENT) << "initializing language server " << m_displayName;
auto initRequest = new InitializeRequest();
- if (auto startupProject = SessionManager::startupProject()) {
+ if (m_project) {
auto params = initRequest->params().value_or(InitializeParams());
params.setCapabilities(generateClientCapabilities());
- params.setRootUri(DocumentUri::fromFileName(startupProject->projectDirectory()));
+ params.setRootUri(DocumentUri::fromFileName(m_project->projectDirectory()));
initRequest->setParams(params);
params.setWorkSpaceFolders(Utils::transform(SessionManager::projects(), [](Project *pro){
return WorkSpaceFolder(pro->projectDirectory().toString(), pro->displayName());
@@ -730,6 +730,16 @@ void Client::executeCommand(const Command &command)
sendContent(request);
}
+const ProjectExplorer::Project *Client::project() const
+{
+ return m_project;
+}
+
+void Client::setCurrentProject(ProjectExplorer::Project *project)
+{
+ m_project = project;
+}
+
void Client::projectOpened(ProjectExplorer::Project *project)
{
if (!sendWorkspceFolderChanges())
@@ -744,10 +754,19 @@ void Client::projectOpened(ProjectExplorer::Project *project)
void Client::projectClosed(ProjectExplorer::Project *project)
{
+ if (project == m_project) {
+ if (m_state == Initialized) {
+ shutdown();
+ } else {
+ m_state = Shutdown; // otherwise the manager would try to restart this server
+ emit finished();
+ }
+ }
if (!sendWorkspceFolderChanges())
return;
WorkspaceFoldersChangeEvent event;
- event.setRemoved({WorkSpaceFolder(project->projectDirectory().toString(), project->displayName())});
+ event.setRemoved(
+ {WorkSpaceFolder(project->projectDirectory().toString(), project->displayName())});
DidChangeWorkspaceFoldersParams params;
params.setEvent(event);
DidChangeWorkspaceFoldersNotification change(params);
@@ -811,6 +830,7 @@ bool Client::reset()
m_openedDocument.clear();
m_serverCapabilities = ServerCapabilities();
m_dynamicCapabilities.reset();
+ m_project = nullptr;
for (const DocumentUri &uri : m_diagnostics.keys())
removeDiagnostics(uri);
return true;
diff --git a/src/plugins/languageclient/client.h b/src/plugins/languageclient/client.h
index f2f92cbfe6a..9769d4d664c 100644
--- a/src/plugins/languageclient/client.h
+++ b/src/plugins/languageclient/client.h
@@ -112,6 +112,8 @@ public:
void executeCommand(const LanguageServerProtocol::Command &command);
// workspace control
+ void setCurrentProject(ProjectExplorer::Project *project);
+ const ProjectExplorer::Project *project() const;
void projectOpened(ProjectExplorer::Project *project);
void projectClosed(ProjectExplorer::Project *project);
@@ -200,6 +202,7 @@ private:
QScopedPointer<BaseClientInterface> m_clientInterface;
QMap<LanguageServerProtocol::DocumentUri, QList<TextMark *>> m_diagnostics;
DocumentSymbolCache m_documentSymbolCache;
+ const ProjectExplorer::Project *m_project = nullptr;
};
} // namespace LanguageClient
diff --git a/src/plugins/languageclient/languageclientmanager.cpp b/src/plugins/languageclient/languageclientmanager.cpp
index 6f3249b9ec0..75fae98545b 100644
--- a/src/plugins/languageclient/languageclientmanager.cpp
+++ b/src/plugins/languageclient/languageclientmanager.cpp
@@ -112,15 +112,16 @@ void LanguageClientManager::startClient(Client *client)
managerInstance->clientFinished(client);
}
-void LanguageClientManager::startClient(BaseSettings *setting)
+void LanguageClientManager::startClient(BaseSettings *setting, ProjectExplorer::Project *project)
{
QTC_ASSERT(managerInstance, return);
QTC_ASSERT(setting, return);
QTC_ASSERT(setting->isValid(), return);
Client *client = setting->createClient();
QTC_ASSERT(client, return);
+ client->setCurrentProject(project);
startClient(client);
- managerInstance->m_clientsForSetting[setting->m_id] = client;
+ managerInstance->m_clientsForSetting[setting->m_id].append(QPointer<Client>(client));
}
QVector<Client *> LanguageClientManager::clients()
@@ -207,14 +208,42 @@ void LanguageClientManager::applySettings()
});
for (BaseSettings *setting : restarts) {
- if (auto client = clientForSetting(setting)) {
+ for (const QPointer<Client> &client : clientForSetting(setting)) {
if (client->reachable())
client->shutdown();
else
deleteClient(client);
}
- if (setting->canStartClient())
+ if (!setting->isValid() || !setting->m_enabled)
+ continue;
+ switch (setting->m_startBehavior) {
+ case BaseSettings::AlwaysOn:
startClient(setting);
+ break;
+ case BaseSettings::RequiresFile:
+ if (Utils::anyOf(Core::DocumentModel::openedDocuments(),
+ [filter = setting->m_languageFilter](Core::IDocument *doc) {
+ return filter.isSupported(doc);
+ })) {
+ startClient(setting);
+ }
+ break;
+ case BaseSettings::RequiresProject: {
+ for (Core::IDocument *doc : Core::DocumentModel::openedDocuments()) {
+ if (setting->m_languageFilter.isSupported(doc)) {
+ const Utils::FileName filePath = doc->filePath();
+ for (ProjectExplorer::Project *project :
+ ProjectExplorer::SessionManager::projects()) {
+ if (project->isKnownFile(filePath))
+ startClient(setting, project);
+ }
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
}
}
@@ -224,10 +253,26 @@ QList<BaseSettings *> LanguageClientManager::currentSettings()
return managerInstance->m_currentSettings;
}
-Client *LanguageClientManager::clientForSetting(const BaseSettings *setting)
+QVector<QPointer<Client>> LanguageClientManager::clientForSetting(const BaseSettings *setting)
+{
+ QTC_ASSERT(managerInstance, return {});
+ return managerInstance->m_clientsForSetting.value(setting->m_id);
+}
+
+const BaseSettings *LanguageClientManager::settingForClient(Client *client)
{
QTC_ASSERT(managerInstance, return nullptr);
- return managerInstance->m_clientsForSetting.value(setting->m_id, nullptr);
+ for (const QString &id : managerInstance->m_clientsForSetting.keys()) {
+ for (const QPointer<Client> &settingClient : managerInstance->m_clientsForSetting[id]) {
+ if (settingClient == client) {
+ return Utils::findOrDefault(managerInstance->m_currentSettings,
+ [id](BaseSettings *setting) {
+ return setting->m_id == id;
+ });
+ }
+ }
+ }
+ return nullptr;
}
QVector<Client *> LanguageClientManager::reachableClients()
@@ -255,7 +300,7 @@ void LanguageClientManager::clientFinished(Client *client)
client->disconnect(this);
client->log(tr("Unexpectedly finished. Restarting in %1 seconds.").arg(restartTimeoutS),
Core::MessageManager::Flash);
- QTimer::singleShot(restartTimeoutS * 1000, client, [client](){ startClient(client); });
+ QTimer::singleShot(restartTimeoutS * 1000, client, [client]() { startClient(client); });
} else {
if (unexpectedFinish && !m_shuttingDown)
client->log(tr("Unexpectedly finished."), Core::MessageManager::Flash);
@@ -299,9 +344,32 @@ void LanguageClientManager::editorOpened(Core::IEditor *editor)
void LanguageClientManager::documentOpened(Core::IDocument *document)
{
+ // check whether we have to start servers for this document
for (BaseSettings *setting : LanguageClientSettings::currentPageSettings()) {
- if (clientForSetting(setting) == nullptr && setting->canStartClient())
- startClient(setting);
+ const QVector<QPointer<Client>> clients = clientForSetting(setting);
+ if (setting->isValid() && setting->m_enabled
+ && setting->m_languageFilter.isSupported(document)) {
+ if (setting->m_startBehavior == BaseSettings::RequiresProject) {
+ const Utils::FileName filePath = document->filePath();
+ for (ProjectExplorer::Project *project :
+ ProjectExplorer::SessionManager::projects()) {
+ // check whether file is part of this project
+ if (!project->isKnownFile(filePath))
+ continue;
+
+ // check whether we already have a client running for this project
+ if (Utils::findOrDefault(clients,
+ [project](QPointer<Client> client) {
+ return client->project() == project;
+ })) {
+ continue;
+ }
+ startClient(setting, project);
+ }
+ } else if (setting->m_startBehavior == BaseSettings::RequiresFile && clients.isEmpty()) {
+ startClient(setting);
+ }
+ }
}
for (Client *interface : reachableClients())
interface->openDocument(document);
@@ -427,13 +495,31 @@ void LanguageClientManager::findUsages(const Utils::FileName &filePath, const QT
void LanguageClientManager::projectAdded(ProjectExplorer::Project *project)
{
+ for (BaseSettings *setting : m_currentSettings) {
+ if (setting->isValid()
+ && setting->m_enabled
+ && setting->m_startBehavior == BaseSettings::RequiresProject) {
+ if (Utils::findOrDefault(clientForSetting(setting),
+ [project](QPointer<Client> client) {
+ return client->project() == project;
+ })
+ .isNull()) {
+ for (Core::IDocument *doc : Core::DocumentModel::openedDocuments()) {
+ if (setting->m_languageFilter.isSupported(doc)) {
+ if (project->isKnownFile(doc->filePath()))
+ startClient(setting, project);
+ }
+ }
+ }
+ }
+ }
for (Client *interface : reachableClients())
interface->projectOpened(project);
}
void LanguageClientManager::projectRemoved(ProjectExplorer::Project *project)
{
- for (Client *interface : reachableClients())
+ for (Client *interface : m_clients)
interface->projectClosed(project);
}
diff --git a/src/plugins/languageclient/languageclientmanager.h b/src/plugins/languageclient/languageclientmanager.h
index 93273e1595a..0252c996eeb 100644
--- a/src/plugins/languageclient/languageclientmanager.h
+++ b/src/plugins/languageclient/languageclientmanager.h
@@ -56,7 +56,7 @@ public:
static void init();
static void startClient(Client *client);
- static void startClient(BaseSettings *setting);
+ static void startClient(BaseSettings *setting, ProjectExplorer::Project *project = nullptr);
static QVector<Client *> clients();
static void addExclusiveRequest(const LanguageServerProtocol::MessageId &id, Client *client);
@@ -72,7 +72,8 @@ public:
static void applySettings();
static QList<BaseSettings *> currentSettings();
- static Client *clientForSetting(const BaseSettings *setting);
+ static QVector<QPointer<Client> > clientForSetting(const BaseSettings *setting);
+ static const BaseSettings *settingForClient(Client *setting);
signals:
void shutdownFinished();
@@ -100,7 +101,7 @@ private:
bool m_shuttingDown = false;
QVector<Client *> m_clients;
QList<BaseSettings *> m_currentSettings; // owned
- QMap<QString, QPointer<Client>> m_clientsForSetting;
+ QMap<QString, QVector<QPointer<Client>>> m_clientsForSetting;
QHash<LanguageServerProtocol::MessageId, QList<Client *>> m_exclusiveRequests;
};
} // namespace LanguageClient
diff --git a/src/plugins/languageclient/languageclientsettings.cpp b/src/plugins/languageclient/languageclientsettings.cpp
index f39ccade062..77702484eee 100644
--- a/src/plugins/languageclient/languageclientsettings.cpp
+++ b/src/plugins/languageclient/languageclientsettings.cpp
@@ -34,6 +34,8 @@
#include <coreplugin/icore.h>
#include <coreplugin/idocument.h>
#include <coreplugin/variablechooser.h>
+#include <projectexplorer/project.h>
+#include <projectexplorer/session.h>
#include <utils/algorithm.h>
#include <utils/delegates.h>
#include <utils/fancylineedit.h>
@@ -41,7 +43,6 @@
#include <utils/jsontreeitem.h>
#include <QBoxLayout>
-#include <QCheckBox>
#include <QComboBox>
#include <QCompleter>
#include <QCoreApplication>
@@ -61,7 +62,7 @@
constexpr char nameKey[] = "name";
constexpr char idKey[] = "id";
constexpr char enabledKey[] = "enabled";
-constexpr char alwaysOnKey[] = "alwaysOn";
+constexpr char startupBehaviorKey[] = "startupBehavior";
constexpr char mimeTypeKey[] = "mimeType";
constexpr char filePatternKey[] = "filePattern";
constexpr char executableKey[] = "executable";
@@ -261,7 +262,7 @@ void LanguageClientSettingsPage::apply()
LanguageClientManager::applySettings();
for (BaseSettings *setting : m_model.removed()) {
- if (Client *client = LanguageClientManager::clientForSetting(setting)) {
+ for (Client *client : LanguageClientManager::clientForSetting(setting)) {
if (client->reachable())
client->shutdown();
else
@@ -374,7 +375,7 @@ void BaseSettings::applyFromSettingsWidget(QWidget *widget)
if (auto settingsWidget = qobject_cast<BaseSettingsWidget *>(widget)) {
m_name = settingsWidget->name();
m_languageFilter = settingsWidget->filter();
- m_alwaysOn = settingsWidget->alwaysOn();
+ m_startBehavior = settingsWidget->startupBehavior();
}
}
@@ -385,18 +386,14 @@ QWidget *BaseSettings::createSettingsWidget(QWidget *parent) const
bool BaseSettings::needsRestart() const
{
- Client *client = LanguageClientManager::clientForSetting(this);
- return client ? !m_enabled || client->needsRestart(this) : m_enabled;
-}
-
-bool BaseSettings::canStartClient() const
-{
- using namespace Core;
- if (!isValid() || !m_enabled)
- return false;
- return m_alwaysOn || Utils::anyOf(DocumentModel::openedDocuments(), [this](IDocument *doc) {
- return m_languageFilter.isSupported(doc);
- });
+ const QVector<QPointer<Client>> clients = LanguageClientManager::clientForSetting(this);
+ if (clients.isEmpty())
+ return m_enabled;
+ if (!m_enabled)
+ return true;
+ return Utils::anyOf(clients, [this](const QPointer<Client> &client) {
+ return client->needsRestart(this);
+ });
}
bool BaseSettings::isValid() const
@@ -422,7 +419,7 @@ QVariantMap BaseSettings::toMap() const
map.insert(nameKey, m_name);
map.insert(idKey, m_id);
map.insert(enabledKey, m_enabled);
- map.insert(alwaysOnKey, m_alwaysOn);
+ map.insert(startupBehaviorKey, m_startBehavior);
map.insert(mimeTypeKey, m_languageFilter.mimeTypes);
map.insert(filePatternKey, m_languageFilter.filePattern);
return map;
@@ -433,7 +430,8 @@ void BaseSettings::fromMap(const QVariantMap &map)
m_name = map[nameKey].toString();
m_id = map.value(idKey, QUuid::createUuid().toString()).toString();
m_enabled = map[enabledKey].toBool();
- m_alwaysOn = map.value(alwaysOnKey, false).toBool();
+ m_startBehavior = BaseSettings::StartBehavior(
+ map.value(startupBehaviorKey, BaseSettings::RequiresFile).toInt());
m_languageFilter.mimeTypes = map[mimeTypeKey].toStringList();
m_languageFilter.filePattern = map[filePatternKey].toStringList();
}
@@ -496,11 +494,13 @@ bool StdIOSettings::needsRestart() const
{
if (BaseSettings::needsRestart())
return true;
- if (Client *client = LanguageClientManager::clientForSetting(this))
- if (auto stdIOInterface = qobject_cast<const StdIOClientInterface *>(
- client->clientInterface()))
- return stdIOInterface->needsRestart(this);
- return false;
+ return Utils::anyOf(LanguageClientManager::clientForSetting(this),
+ [this](QPointer<Client> client) {
+ if (auto stdIOInterface = qobject_cast<const StdIOClientInterface *>(
+ client->clientInterface()))
+ return stdIOInterface->needsRestart(this);
+ return false;
+ });
}
bool StdIOSettings::isValid() const
@@ -533,10 +533,9 @@ BaseClientInterface *StdIOSettings::createInterface() const
return new StdIOClientInterface(m_executable, arguments());
}
-static QWidget *createCapabilitiesView(
- const LanguageServerProtocol::ServerCapabilities &capabilities)
+static QWidget *createCapabilitiesView(const QJsonValue &capabilities)
{
- auto root = new Utils::JsonTreeItem("Capabilities", QJsonValue(capabilities));
+ auto root = new Utils::JsonTreeItem("Capabilities", capabilities);
if (root->canFetchMore())
root->fetchMore();
@@ -551,12 +550,28 @@ static QWidget *createCapabilitiesView(
return capabilitiesView;
}
+static QString startupBehaviorString(BaseSettings::StartBehavior behavior)
+{
+ switch (behavior) {
+ case BaseSettings::AlwaysOn:
+ return QCoreApplication::translate("LanguageClient::BaseSettings", "Always On");
+ case BaseSettings::RequiresFile:
+ return QCoreApplication::translate("LanguageClient::BaseSettings", "Requires an Open File");
+ case BaseSettings::RequiresProject:
+ return QCoreApplication::translate("LanguageClient::BaseSettings",
+ "Start Server per Project");
+ default:
+ break;
+ }
+ return {};
+}
+
BaseSettingsWidget::BaseSettingsWidget(const BaseSettings *settings, QWidget *parent)
: QWidget(parent)
, m_name(new QLineEdit(settings->m_name, this))
, m_mimeTypes(new QLabel(settings->m_languageFilter.mimeTypes.join(filterSeparator), this))
, m_filePattern(new QLineEdit(settings->m_languageFilter.filePattern.join(filterSeparator), this))
- , m_alwaysOn(new QCheckBox())
+ , m_startupBehavior(new QComboBox)
{
int row = 0;
auto *mainLayout = new QGridLayout;
@@ -573,9 +588,12 @@ BaseSettingsWidget::BaseSettingsWidget(const BaseSettings *settings, QWidget *pa
mainLayout->addLayout(mimeLayout, row, 1);
m_filePattern->setPlaceholderText(tr("File pattern"));
mainLayout->addWidget(m_filePattern, ++row, 1);
- mainLayout->addWidget(new QLabel(tr("Always On:")), ++row, 0);
- mainLayout->addWidget(m_alwaysOn, row, 1);
- m_alwaysOn->setChecked(settings->m_alwaysOn);
+ mainLayout->addWidget(new QLabel(tr("Startup Behavior:")), ++row, 0);
+ for (int behavior = 0; behavior < BaseSettings::LastSentinel ; ++behavior)
+ m_startupBehavior->addItem(startupBehaviorString(BaseSettings::StartBehavior(behavior)));
+ m_startupBehavior->setCurrentIndex(settings->m_startBehavior);
+ mainLayout->addWidget(m_startupBehavior, row, 1);
+
connect(addMimeTypeButton, &QPushButton::pressed,
this, &BaseSettingsWidget::showAddMimeTypeDialog);
@@ -585,9 +603,13 @@ BaseSettingsWidget::BaseSettingsWidget(const BaseSettings *settings, QWidget *pa
};
mainLayout->addWidget(new QLabel(tr("Capabilities:")), ++row, 0, Qt::AlignTop);
- if (Client *client = LanguageClientManager::clientForSetting(settings)) {
+ QVector<QPointer<Client> > clients = LanguageClientManager::clientForSetting(settings);
+ if (clients.isEmpty()) {
+ mainLayout->addWidget(createInfoLabel());
+ } else { // TODO move the capabilities view into a new widget outside of the settings
+ Client *client = clients.first();
if (client->state() == Client::Initialized)
- mainLayout->addWidget(createCapabilitiesView(client->capabilities()));
+ mainLayout->addWidget(createCapabilitiesView(QJsonValue(client->capabilities())));
else
mainLayout->addWidget(createInfoLabel(), row, 1);
connect(client, &Client::finished, mainLayout, [mainLayout, row, createInfoLabel]() {
@@ -598,12 +620,9 @@ BaseSettingsWidget::BaseSettingsWidget(const BaseSettings *settings, QWidget *pa
[mainLayout, row](
const LanguageServerProtocol::ServerCapabilities &capabilities) {
delete mainLayout->itemAtPosition(row, 1)->widget();
- mainLayout->addWidget(createCapabilitiesView(capabilities), row, 1);
+ mainLayout->addWidget(createCapabilitiesView(QJsonValue(capabilities)), row, 1);
});
- } else {
- mainLayout->addWidget(createInfoLabel());
}
-
setLayout(mainLayout);
}
@@ -618,9 +637,9 @@ LanguageFilter BaseSettingsWidget::filter() const
m_filePattern->text().split(filterSeparator)};
}
-bool BaseSettingsWidget::alwaysOn() const
+BaseSettings::StartBehavior BaseSettingsWidget::startupBehavior() const
{
- return m_alwaysOn->isChecked();
+ return BaseSettings::StartBehavior(m_startupBehavior->currentIndex());
}
class MimeTypeModel : public QStringListModel
diff --git a/src/plugins/languageclient/languageclientsettings.h b/src/plugins/languageclient/languageclientsettings.h
index ac6d2e23c0f..aed2bf585a4 100644
--- a/src/plugins/languageclient/languageclientsettings.h
+++ b/src/plugins/languageclient/languageclientsettings.h
@@ -34,7 +34,7 @@
#include <QWidget>
QT_BEGIN_NAMESPACE
-class QCheckBox;
+class QComboBox;
class QLineEdit;
QT_END_NAMESPACE
@@ -44,6 +44,7 @@ class PathChooser;
} // namespace Utils
namespace Core { class IDocument; }
+namespace ProjectExplorer { class Project; }
namespace LanguageClient {
@@ -67,17 +68,23 @@ public:
virtual ~BaseSettings() = default;
+ enum StartBehavior {
+ AlwaysOn = 0,
+ RequiresFile,
+ RequiresProject,
+ LastSentinel
+ };
+
QString m_name = QString("New Language Server");
QString m_id = QUuid::createUuid().toString();
bool m_enabled = true;
- bool m_alwaysOn = false;
+ StartBehavior m_startBehavior = RequiresFile;
LanguageFilter m_languageFilter;
virtual void applyFromSettingsWidget(QWidget *widget);
virtual QWidget *createSettingsWidget(QWidget *parent = nullptr) const;
virtual BaseSettings *copy() const { return new BaseSettings(*this); }
virtual bool needsRestart() const;
- virtual bool canStartClient() const;
virtual bool isValid() const;
Client *createClient();
virtual QVariantMap toMap() const;
@@ -90,6 +97,9 @@ protected:
BaseSettings(BaseSettings &&other) = default;
BaseSettings &operator=(const BaseSettings &other) = default;
BaseSettings &operator=(BaseSettings &&other) = default;
+
+private:
+ bool canStart(QList<const Core::IDocument *> documents) const;
};
class StdIOSettings : public BaseSettings
@@ -137,7 +147,9 @@ public:
QString name() const;
LanguageFilter filter() const;
+ BaseSettings::StartBehavior startupBehavior() const;
bool alwaysOn() const;
+ bool requiresProject() const;
private:
void showAddMimeTypeDialog();
@@ -145,7 +157,7 @@ private:
QLineEdit *m_name = nullptr;
QLabel *m_mimeTypes = nullptr;
QLineEdit *m_filePattern = nullptr;
- QCheckBox *m_alwaysOn = nullptr;
+ QComboBox *m_startupBehavior = nullptr;
static constexpr char filterSeparator = ';';
};