LanguageClient: Add generic way to provide specialized settings

Change-Id: Iab482220ec7fd73ecd4cbf3d8b1b121e93148059
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
David Schulz
2021-02-08 11:24:28 +01:00
parent 7dc82b1af9
commit 8106a01e9c
4 changed files with 73 additions and 16 deletions

View File

@@ -38,6 +38,7 @@ namespace Constants {
const char LANGUAGECLIENT_SETTINGS_CATEGORY[] = "ZY.LanguageClient"; const char LANGUAGECLIENT_SETTINGS_CATEGORY[] = "ZY.LanguageClient";
const char LANGUAGECLIENT_SETTINGS_PAGE[] = "LanguageClient.General"; const char LANGUAGECLIENT_SETTINGS_PAGE[] = "LanguageClient.General";
const char LANGUAGECLIENT_STDIO_SETTINGS_ID[] = "LanguageClient::StdIOSettingsID";
const char LANGUAGECLIENT_SETTINGS_TR[] = QT_TRANSLATE_NOOP("LanguageClient", "Language Client"); const char LANGUAGECLIENT_SETTINGS_TR[] = QT_TRANSLATE_NOOP("LanguageClient", "Language Client");
const char LANGUAGECLIENT_DOCUMENT_FILTER_ID[] = "Current Document Symbols"; const char LANGUAGECLIENT_DOCUMENT_FILTER_ID[] = "Current Document Symbols";
const char LANGUAGECLIENT_DOCUMENT_FILTER_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("LanguageClient", "Symbols in Current Document"); const char LANGUAGECLIENT_DOCUMENT_FILTER_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("LanguageClient", "Symbols in Current Document");

View File

@@ -51,6 +51,9 @@ LanguageClientPlugin *LanguageClientPlugin::instance()
bool LanguageClientPlugin::initialize(const QStringList & /*arguments*/, QString * /*errorString*/) bool LanguageClientPlugin::initialize(const QStringList & /*arguments*/, QString * /*errorString*/)
{ {
LanguageClientManager::init(); LanguageClientManager::init();
LanguageClientSettings::registerClientType({Constants::LANGUAGECLIENT_STDIO_SETTINGS_ID,
tr("Generic StdIO Language Server"),
[]() { return new StdIOSettings; }});
return true; return true;
} }

View File

@@ -58,6 +58,7 @@
#include <QJsonDocument> #include <QJsonDocument>
#include <QLabel> #include <QLabel>
#include <QListView> #include <QListView>
#include <QMenu>
#include <QMimeData> #include <QMimeData>
#include <QPushButton> #include <QPushButton>
#include <QSettings> #include <QSettings>
@@ -66,6 +67,7 @@
#include <QToolButton> #include <QToolButton>
#include <QTreeView> #include <QTreeView>
constexpr char typeIdKey[] = "typeId";
constexpr char nameKey[] = "name"; constexpr char nameKey[] = "name";
constexpr char idKey[] = "id"; constexpr char idKey[] = "id";
constexpr char enabledKey[] = "enabled"; constexpr char enabledKey[] = "enabled";
@@ -105,7 +107,7 @@ public:
void reset(const QList<BaseSettings *> &settings); void reset(const QList<BaseSettings *> &settings);
QList<BaseSettings *> settings() const { return m_settings; } QList<BaseSettings *> settings() const { return m_settings; }
void insertSettings(BaseSettings *settings); int insertSettings(BaseSettings *settings);
void enableSetting(const QString &id); void enableSetting(const QString &id);
QList<BaseSettings *> removed() const { return m_removed; } QList<BaseSettings *> removed() const { return m_removed; }
BaseSettings *settingForIndex(const QModelIndex &index) const; BaseSettings *settingForIndex(const QModelIndex &index) const;
@@ -134,7 +136,7 @@ private:
QWidget *widget = nullptr; QWidget *widget = nullptr;
} m_currentSettings; } m_currentSettings;
void addItem(); void addItem(const Utils::Id &clientTypeId);
void deleteItem(); void deleteItem();
}; };
@@ -163,6 +165,12 @@ private:
QPointer<LanguageClientSettingsPageWidget> m_widget; QPointer<LanguageClientSettingsPageWidget> m_widget;
}; };
QMap<Utils::Id, ClientType> &clientTypes()
{
static QMap<Utils::Id, ClientType> types;
return types;
}
LanguageClientSettingsPageWidget::LanguageClientSettingsPageWidget(LanguageClientSettingsModel &settings) LanguageClientSettingsPageWidget::LanguageClientSettingsPageWidget(LanguageClientSettingsModel &settings)
: m_settings(settings) : m_settings(settings)
, m_view(new QTreeView()) , m_view(new QTreeView())
@@ -181,7 +189,14 @@ LanguageClientSettingsPageWidget::LanguageClientSettingsPageWidget(LanguageClien
this, &LanguageClientSettingsPageWidget::currentChanged); this, &LanguageClientSettingsPageWidget::currentChanged);
auto buttonLayout = new QVBoxLayout(); auto buttonLayout = new QVBoxLayout();
auto addButton = new QPushButton(LanguageClientSettingsPage::tr("&Add")); auto addButton = new QPushButton(LanguageClientSettingsPage::tr("&Add"));
connect(addButton, &QPushButton::pressed, this, &LanguageClientSettingsPageWidget::addItem); auto addMenu = new QMenu;
addMenu->clear();
for (const ClientType &type : clientTypes()) {
auto action = new QAction(tr("New %1").arg(type.name));
connect(action, &QAction::triggered, this, [this, id = type.id]() { addItem(id); });
addMenu->addAction(action);
}
addButton->setMenu(addMenu);
auto deleteButton = new QPushButton(LanguageClientSettingsPage::tr("&Delete")); auto deleteButton = new QPushButton(LanguageClientSettingsPage::tr("&Delete"));
connect(deleteButton, &QPushButton::pressed, this, &LanguageClientSettingsPageWidget::deleteItem); connect(deleteButton, &QPushButton::pressed, this, &LanguageClientSettingsPageWidget::deleteItem);
mainLayout->addLayout(layout); mainLayout->addLayout(layout);
@@ -239,11 +254,21 @@ void LanguageClientSettingsPageWidget::applyCurrentSettings()
} }
} }
void LanguageClientSettingsPageWidget::addItem() BaseSettings *generateSettings(const Utils::Id &clientTypeId)
{ {
const int row = m_settings.rowCount(); if (auto generator = clientTypes().value(clientTypeId).generator) {
m_settings.insertRows(row); auto settings = generator();
m_view->setCurrentIndex(m_settings.index(row)); settings->m_settingsTypeId = clientTypeId;
return settings;
}
return nullptr;
}
void LanguageClientSettingsPageWidget::addItem(const Utils::Id &clientTypeId)
{
auto newSettings = generateSettings(clientTypeId);
QTC_ASSERT(newSettings, return);
m_view->setCurrentIndex(m_settings.index(m_settings.insertSettings(newSettings)));
} }
void LanguageClientSettingsPageWidget::deleteItem() void LanguageClientSettingsPageWidget::deleteItem()
@@ -457,12 +482,13 @@ void LanguageClientSettingsModel::reset(const QList<BaseSettings *> &settings)
endResetModel(); endResetModel();
} }
void LanguageClientSettingsModel::insertSettings(BaseSettings *settings) int LanguageClientSettingsModel::insertSettings(BaseSettings *settings)
{ {
int row = rowCount(); int row = rowCount();
beginInsertRows(QModelIndex(), row, row); beginInsertRows(QModelIndex(), row, row);
m_settings.insert(row, settings); m_settings.insert(row, settings);
endInsertRows(); endInsertRows();
return row;
} }
void LanguageClientSettingsModel::enableSetting(const QString &id) void LanguageClientSettingsModel::enableSetting(const QString &id)
@@ -545,6 +571,7 @@ Client *BaseSettings::createClient()
QVariantMap BaseSettings::toMap() const QVariantMap BaseSettings::toMap() const
{ {
QVariantMap map; QVariantMap map;
map.insert(typeIdKey, m_settingsTypeId.toSetting());
map.insert(nameKey, m_name); map.insert(nameKey, m_name);
map.insert(idKey, m_id); map.insert(idKey, m_id);
map.insert(enabledKey, m_enabled); map.insert(enabledKey, m_enabled);
@@ -582,14 +609,19 @@ void LanguageClientSettings::init()
QList<BaseSettings *> LanguageClientSettings::fromSettings(QSettings *settingsIn) QList<BaseSettings *> LanguageClientSettings::fromSettings(QSettings *settingsIn)
{ {
settingsIn->beginGroup(settingsGroupKey); settingsIn->beginGroup(settingsGroupKey);
auto variants = settingsIn->value(clientsKey).toList(); QList<BaseSettings *> result;
auto settings = Utils::transform(variants, [](const QVariant& var){ for (const QVariant& var : settingsIn->value(clientsKey).toList()) {
BaseSettings *settings = new StdIOSettings(); const QMap<QString, QVariant> &map = var.toMap();
settings->fromMap(var.toMap()); Utils::Id typeId = Utils::Id::fromSetting(map.value(typeIdKey));
return settings; if (!typeId.isValid())
}); typeId = Constants::LANGUAGECLIENT_STDIO_SETTINGS_ID;
if (BaseSettings *settings = generateSettings(typeId)) {
settings->fromMap(var.toMap());
result << settings;
}
}
settingsIn->endGroup(); settingsIn->endGroup();
return settings; return result;
} }
QList<BaseSettings *> LanguageClientSettings::pageSettings() QList<BaseSettings *> LanguageClientSettings::pageSettings()
@@ -602,6 +634,12 @@ QList<BaseSettings *> LanguageClientSettings::changedSettings()
return settingsPage().changedSettings(); return settingsPage().changedSettings();
} }
void LanguageClientSettings::registerClientType(const ClientType &type)
{
QTC_ASSERT(!clientTypes().contains(type.id), return);
clientTypes()[type.id] = type;
}
void LanguageClientSettings::addSettings(BaseSettings *settings) void LanguageClientSettings::addSettings(BaseSettings *settings)
{ {
settingsPage().addSettings(settings); settingsPage().addSettings(settings);

View File

@@ -83,6 +83,7 @@ public:
QString m_name = QString("New Language Server"); QString m_name = QString("New Language Server");
QString m_id = QUuid::createUuid().toString(); QString m_id = QUuid::createUuid().toString();
Utils::Id m_settingsTypeId;
bool m_enabled = true; bool m_enabled = true;
StartBehavior m_startBehavior = RequiresFile; StartBehavior m_startBehavior = RequiresFile;
LanguageFilter m_languageFilter; LanguageFilter m_languageFilter;
@@ -137,13 +138,27 @@ protected:
StdIOSettings &operator=(StdIOSettings &&other) = default; StdIOSettings &operator=(StdIOSettings &&other) = default;
}; };
class LanguageClientSettings struct ClientType {
Utils::Id id;
QString name;
using SettingsGenerator = std::function<BaseSettings*()>;
SettingsGenerator generator = nullptr;
};
class LANGUAGECLIENT_EXPORT LanguageClientSettings
{ {
Q_DECLARE_TR_FUNCTIONS(LanguageClientSettings)
public: public:
static void init(); static void init();
static QList<BaseSettings *> fromSettings(QSettings *settings); static QList<BaseSettings *> fromSettings(QSettings *settings);
static QList<BaseSettings *> pageSettings(); static QList<BaseSettings *> pageSettings();
static QList<BaseSettings *> changedSettings(); static QList<BaseSettings *> changedSettings();
/**
* must be called before the delayed initialize phase
* otherwise the settings are not loaded correctly
*/
static void registerClientType(const ClientType &type);
static void addSettings(BaseSettings *settings); static void addSettings(BaseSettings *settings);
static void enableSettings(const QString &id); static void enableSettings(const QString &id);
static void toSettings(QSettings *settings, const QList<BaseSettings *> &languageClientSettings); static void toSettings(QSettings *settings, const QList<BaseSettings *> &languageClientSettings);