2018-07-13 12:33:46 +02:00
|
|
|
/****************************************************************************
|
|
|
|
|
**
|
|
|
|
|
** Copyright (C) 2018 The Qt Company Ltd.
|
|
|
|
|
** Contact: https://www.qt.io/licensing/
|
|
|
|
|
**
|
|
|
|
|
** This file is part of Qt Creator.
|
|
|
|
|
**
|
|
|
|
|
** Commercial License Usage
|
|
|
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
|
|
|
** accordance with the commercial license agreement provided with the
|
|
|
|
|
** Software or, alternatively, in accordance with the terms contained in
|
|
|
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
|
|
|
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
|
|
|
** information use the contact form at https://www.qt.io/contact-us.
|
|
|
|
|
**
|
|
|
|
|
** GNU General Public License Usage
|
|
|
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
|
|
|
** General Public License version 3 as published by the Free Software
|
|
|
|
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
|
|
|
|
** included in the packaging of this file. Please review the following
|
|
|
|
|
** information to ensure the GNU General Public License requirements will
|
|
|
|
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
|
|
|
|
**
|
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
|
|
#include "languageclientsettings.h"
|
2018-09-18 10:43:17 +02:00
|
|
|
|
|
|
|
|
#include "baseclient.h"
|
|
|
|
|
#include "languageclientmanager.h"
|
2018-07-13 12:33:46 +02:00
|
|
|
#include "languageclient_global.h"
|
|
|
|
|
|
|
|
|
|
#include <coreplugin/icore.h>
|
|
|
|
|
#include <utils/algorithm.h>
|
|
|
|
|
#include <utils/delegates.h>
|
2018-10-19 22:47:07 +02:00
|
|
|
#include <utils/fancylineedit.h>
|
2018-09-10 15:15:37 +02:00
|
|
|
#include <utils/qtcprocess.h>
|
2018-09-05 13:38:08 +02:00
|
|
|
#include <utils/mimetypes/mimedatabase.h>
|
2018-07-13 12:33:46 +02:00
|
|
|
#include <languageserverprotocol/lsptypes.h>
|
|
|
|
|
|
|
|
|
|
#include <QBoxLayout>
|
2018-09-18 15:24:23 +02:00
|
|
|
#include <QCheckBox>
|
2018-07-13 12:33:46 +02:00
|
|
|
#include <QComboBox>
|
2018-09-05 13:38:08 +02:00
|
|
|
#include <QCompleter>
|
2018-07-13 12:33:46 +02:00
|
|
|
#include <QCoreApplication>
|
2018-10-10 14:26:57 +02:00
|
|
|
#include <QDialog>
|
|
|
|
|
#include <QDialogButtonBox>
|
2018-09-18 15:24:23 +02:00
|
|
|
#include <QDir>
|
2018-07-13 12:33:46 +02:00
|
|
|
#include <QFileInfo>
|
|
|
|
|
#include <QHeaderView>
|
2018-09-18 15:24:23 +02:00
|
|
|
#include <QLabel>
|
2018-10-10 14:26:57 +02:00
|
|
|
#include <QListView>
|
2018-07-13 12:33:46 +02:00
|
|
|
#include <QPushButton>
|
|
|
|
|
#include <QSettings>
|
2018-10-10 14:26:57 +02:00
|
|
|
#include <QSortFilterProxyModel>
|
|
|
|
|
#include <QStringListModel>
|
2018-07-13 12:33:46 +02:00
|
|
|
#include <QTreeView>
|
|
|
|
|
|
|
|
|
|
constexpr char nameKey[] = "name";
|
|
|
|
|
constexpr char enabledKey[] = "enabled";
|
2018-09-05 13:38:08 +02:00
|
|
|
constexpr char mimeTypeKey[] = "mimeType";
|
2018-10-10 14:26:57 +02:00
|
|
|
constexpr char filePatternKey[] = "filePattern";
|
2018-07-13 12:33:46 +02:00
|
|
|
constexpr char executableKey[] = "executable";
|
|
|
|
|
constexpr char argumentsKey[] = "arguments";
|
|
|
|
|
constexpr char settingsGroupKey[] = "LanguageClient";
|
|
|
|
|
constexpr char clientsKey[] = "clients";
|
|
|
|
|
|
|
|
|
|
namespace LanguageClient {
|
|
|
|
|
|
2018-09-18 15:24:23 +02:00
|
|
|
class LanguageClientSettingsModel : public QAbstractListModel
|
2018-07-13 12:33:46 +02:00
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
LanguageClientSettingsModel() = default;
|
2018-09-18 12:28:48 +02:00
|
|
|
~LanguageClientSettingsModel();
|
2018-07-13 12:33:46 +02:00
|
|
|
|
|
|
|
|
// QAbstractItemModel interface
|
2018-09-18 15:24:23 +02:00
|
|
|
int rowCount(const QModelIndex &/*parent*/ = QModelIndex()) const final { return m_settings.count(); }
|
|
|
|
|
QVariant data(const QModelIndex &index, int role) const final;
|
|
|
|
|
bool removeRows(int row, int count = 1, const QModelIndex &parent = QModelIndex()) final;
|
|
|
|
|
bool insertRows(int row, int count = 1, const QModelIndex &parent = QModelIndex()) final;
|
|
|
|
|
bool setData(const QModelIndex &index, const QVariant &value, int role) final;
|
|
|
|
|
Qt::ItemFlags flags(const QModelIndex &index) const final;
|
2018-07-13 12:33:46 +02:00
|
|
|
|
2018-09-18 10:43:17 +02:00
|
|
|
void reset(const QList<StdIOSettings *> &settings);
|
|
|
|
|
QList<StdIOSettings *> settings() const { return m_settings; }
|
|
|
|
|
QList<StdIOSettings *> removed() const { return m_removed; }
|
2018-09-18 15:24:23 +02:00
|
|
|
StdIOSettings *settingForIndex(const QModelIndex &index) const;
|
|
|
|
|
QModelIndex indexForSetting(StdIOSettings *setting) const;
|
2018-07-13 12:33:46 +02:00
|
|
|
|
|
|
|
|
private:
|
2018-09-18 10:43:17 +02:00
|
|
|
QList<StdIOSettings *> m_settings; // owned
|
|
|
|
|
QList<StdIOSettings *> m_removed;
|
2018-07-13 12:33:46 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class LanguageClientSettingsPageWidget : public QWidget
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
LanguageClientSettingsPageWidget(LanguageClientSettingsModel &settings);
|
2018-09-18 15:24:23 +02:00
|
|
|
void currentChanged(const QModelIndex &index);
|
|
|
|
|
int currentRow() const;
|
|
|
|
|
void resetCurrentSettings(int row);
|
|
|
|
|
void applyCurrentSettings();
|
2018-07-13 12:33:46 +02:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
LanguageClientSettingsModel &m_settings;
|
2018-09-18 15:24:23 +02:00
|
|
|
QTreeView *m_view = nullptr;
|
|
|
|
|
struct CurrentSettings {
|
|
|
|
|
StdIOSettings *setting = nullptr;
|
|
|
|
|
QWidget *widget = nullptr;
|
|
|
|
|
} m_currentSettings;
|
2018-07-13 12:33:46 +02:00
|
|
|
|
|
|
|
|
void addItem();
|
|
|
|
|
void deleteItem();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class LanguageClientSettingsPage : public Core::IOptionsPage
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
LanguageClientSettingsPage();
|
|
|
|
|
~LanguageClientSettingsPage() override;
|
|
|
|
|
|
|
|
|
|
void init();
|
|
|
|
|
|
|
|
|
|
// IOptionsPage interface
|
|
|
|
|
QWidget *widget() override;
|
|
|
|
|
void apply() override;
|
|
|
|
|
void finish() override;
|
|
|
|
|
|
|
|
|
|
private:
|
2018-09-18 12:28:48 +02:00
|
|
|
LanguageClientSettingsModel m_model;
|
2018-09-18 10:43:17 +02:00
|
|
|
QList<StdIOSettings *> m_settings; // owned
|
2018-07-13 12:33:46 +02:00
|
|
|
QPointer<LanguageClientSettingsPageWidget> m_widget;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
LanguageClientSettingsPageWidget::LanguageClientSettingsPageWidget(LanguageClientSettingsModel &settings)
|
|
|
|
|
: m_settings(settings)
|
|
|
|
|
, m_view(new QTreeView())
|
|
|
|
|
{
|
2018-09-18 15:24:23 +02:00
|
|
|
auto mainLayout = new QVBoxLayout();
|
2018-07-13 12:33:46 +02:00
|
|
|
auto layout = new QHBoxLayout();
|
|
|
|
|
m_view->setModel(&m_settings);
|
2018-09-18 15:24:23 +02:00
|
|
|
m_view->setHeaderHidden(true);
|
|
|
|
|
m_view->setSelectionMode(QAbstractItemView::SingleSelection);
|
|
|
|
|
m_view->setSelectionBehavior(QAbstractItemView::SelectItems);
|
|
|
|
|
connect(m_view->selectionModel(), &QItemSelectionModel::currentChanged,
|
|
|
|
|
this, &LanguageClientSettingsPageWidget::currentChanged);
|
2018-09-05 13:38:08 +02:00
|
|
|
auto mimeTypes = Utils::transform(Utils::allMimeTypes(), [](const Utils::MimeType &mimeType){
|
|
|
|
|
return mimeType.name();
|
|
|
|
|
});
|
2018-07-13 12:33:46 +02:00
|
|
|
auto buttonLayout = new QVBoxLayout();
|
|
|
|
|
auto addButton = new QPushButton(tr("&Add"));
|
|
|
|
|
connect(addButton, &QPushButton::pressed, this, &LanguageClientSettingsPageWidget::addItem);
|
|
|
|
|
auto deleteButton = new QPushButton(tr("&Delete"));
|
|
|
|
|
connect(deleteButton, &QPushButton::pressed, this, &LanguageClientSettingsPageWidget::deleteItem);
|
|
|
|
|
|
2018-09-18 15:24:23 +02:00
|
|
|
mainLayout->addLayout(layout);
|
|
|
|
|
setLayout(mainLayout);
|
2018-07-13 12:33:46 +02:00
|
|
|
layout->addWidget(m_view);
|
|
|
|
|
layout->addLayout(buttonLayout);
|
|
|
|
|
buttonLayout->addWidget(addButton);
|
|
|
|
|
buttonLayout->addWidget(deleteButton);
|
|
|
|
|
buttonLayout->addStretch(10);
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-18 15:24:23 +02:00
|
|
|
void LanguageClientSettingsPageWidget::currentChanged(const QModelIndex &index)
|
|
|
|
|
{
|
|
|
|
|
if (m_currentSettings.widget) {
|
|
|
|
|
applyCurrentSettings();
|
|
|
|
|
layout()->removeWidget(m_currentSettings.widget);
|
|
|
|
|
delete m_currentSettings.widget;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (index.isValid()) {
|
|
|
|
|
m_currentSettings.setting = m_settings.settingForIndex(index);
|
|
|
|
|
m_currentSettings.widget = m_currentSettings.setting->createSettingsWidget(this);
|
|
|
|
|
layout()->addWidget(m_currentSettings.widget);
|
|
|
|
|
} else {
|
|
|
|
|
m_currentSettings.setting = nullptr;
|
|
|
|
|
m_currentSettings.widget = nullptr;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int LanguageClientSettingsPageWidget::currentRow() const
|
|
|
|
|
{
|
|
|
|
|
return m_settings.indexForSetting(m_currentSettings.setting).row();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LanguageClientSettingsPageWidget::resetCurrentSettings(int row)
|
|
|
|
|
{
|
|
|
|
|
if (m_currentSettings.widget) {
|
|
|
|
|
layout()->removeWidget(m_currentSettings.widget);
|
|
|
|
|
delete m_currentSettings.widget;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_currentSettings.setting = nullptr;
|
|
|
|
|
m_currentSettings.widget = nullptr;
|
|
|
|
|
m_view->setCurrentIndex(m_settings.index(row));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LanguageClientSettingsPageWidget::applyCurrentSettings()
|
|
|
|
|
{
|
|
|
|
|
if (!m_currentSettings.setting)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
m_currentSettings.setting->applyFromSettingsWidget(m_currentSettings.widget);
|
|
|
|
|
auto index = m_settings.indexForSetting(m_currentSettings.setting);
|
|
|
|
|
m_settings.dataChanged(index, index);
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-13 12:33:46 +02:00
|
|
|
void LanguageClientSettingsPageWidget::addItem()
|
|
|
|
|
{
|
|
|
|
|
const int row = m_settings.rowCount();
|
|
|
|
|
m_settings.insertRows(row);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LanguageClientSettingsPageWidget::deleteItem()
|
|
|
|
|
{
|
|
|
|
|
auto index = m_view->currentIndex();
|
|
|
|
|
if (index.isValid())
|
|
|
|
|
m_settings.removeRows(index.row());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LanguageClientSettingsPage::LanguageClientSettingsPage()
|
|
|
|
|
{
|
|
|
|
|
setId("LanguageClient.General");
|
|
|
|
|
setDisplayName(tr("General"));
|
|
|
|
|
setCategory(Constants::LANGUAGECLIENT_SETTINGS_CATEGORY);
|
|
|
|
|
setDisplayCategory(QCoreApplication::translate("LanguageClient",
|
|
|
|
|
Constants::LANGUAGECLIENT_SETTINGS_TR));
|
2018-10-05 01:24:49 +02:00
|
|
|
setCategoryIcon(Utils::Icon({{":/languageclient/images/settingscategory_languageclient.png",
|
|
|
|
|
Utils::Theme::PanelTextColorDark}}, Utils::Icon::Tint));
|
2018-07-13 12:33:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LanguageClientSettingsPage::~LanguageClientSettingsPage()
|
|
|
|
|
{
|
|
|
|
|
if (m_widget)
|
|
|
|
|
delete m_widget;
|
2018-09-18 12:28:48 +02:00
|
|
|
qDeleteAll(m_settings);
|
2018-07-13 12:33:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LanguageClientSettingsPage::init()
|
|
|
|
|
{
|
2018-09-18 12:28:48 +02:00
|
|
|
m_model.reset(LanguageClientSettings::fromSettings(Core::ICore::settings()));
|
|
|
|
|
apply();
|
2018-10-15 08:30:11 +02:00
|
|
|
finish();
|
2018-07-13 12:33:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QWidget *LanguageClientSettingsPage::widget()
|
|
|
|
|
{
|
|
|
|
|
if (!m_widget)
|
2018-09-18 12:28:48 +02:00
|
|
|
m_widget = new LanguageClientSettingsPageWidget(m_model);
|
2018-07-13 12:33:46 +02:00
|
|
|
return m_widget;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LanguageClientSettingsPage::apply()
|
|
|
|
|
{
|
2018-09-18 12:28:48 +02:00
|
|
|
qDeleteAll(m_settings);
|
2018-09-18 15:24:23 +02:00
|
|
|
if (m_widget)
|
|
|
|
|
m_widget->applyCurrentSettings();
|
2018-09-18 10:43:17 +02:00
|
|
|
m_settings = Utils::transform(m_model.settings(), [](const StdIOSettings *other){
|
|
|
|
|
return dynamic_cast<StdIOSettings *>(other->copy());
|
2018-09-18 12:28:48 +02:00
|
|
|
});
|
|
|
|
|
LanguageClientSettings::toSettings(Core::ICore::settings(), m_settings);
|
|
|
|
|
|
2018-09-18 10:43:17 +02:00
|
|
|
QList<StdIOSettings *> restarts = Utils::filtered(m_settings, &StdIOSettings::needsRestart);
|
|
|
|
|
for (auto setting : restarts + m_model.removed()) {
|
|
|
|
|
if (auto client = setting->m_client) {
|
|
|
|
|
if (client->reachable())
|
|
|
|
|
client->shutdown();
|
|
|
|
|
else
|
|
|
|
|
LanguageClientManager::deleteClient(client);
|
2018-09-18 12:28:48 +02:00
|
|
|
}
|
|
|
|
|
}
|
2018-09-18 10:43:17 +02:00
|
|
|
for (StdIOSettings *setting : restarts) {
|
|
|
|
|
if (setting && setting->isValid() && setting->m_enabled) {
|
|
|
|
|
if (auto client = setting->createClient()) {
|
|
|
|
|
setting->m_client = client;
|
|
|
|
|
LanguageClientManager::startClient(client);
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-09-18 12:28:48 +02:00
|
|
|
}
|
2018-09-18 15:24:23 +02:00
|
|
|
|
|
|
|
|
if (m_widget) {
|
|
|
|
|
int row = m_widget->currentRow();
|
|
|
|
|
m_model.reset(m_settings);
|
|
|
|
|
m_widget->resetCurrentSettings(row);
|
|
|
|
|
} else {
|
|
|
|
|
m_model.reset(m_settings);
|
|
|
|
|
}
|
2018-07-13 12:33:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LanguageClientSettingsPage::finish()
|
|
|
|
|
{
|
2018-09-18 15:24:23 +02:00
|
|
|
m_model.reset(m_settings);
|
2018-09-18 12:28:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LanguageClientSettingsModel::~LanguageClientSettingsModel()
|
|
|
|
|
{
|
|
|
|
|
qDeleteAll(m_settings);
|
2018-07-13 12:33:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QVariant LanguageClientSettingsModel::data(const QModelIndex &index, int role) const
|
|
|
|
|
{
|
2018-09-18 15:24:23 +02:00
|
|
|
StdIOSettings *setting = settingForIndex(index);
|
|
|
|
|
if (!setting)
|
2018-07-13 12:33:46 +02:00
|
|
|
return QVariant();
|
2018-09-18 15:24:23 +02:00
|
|
|
if (role == Qt::DisplayRole)
|
|
|
|
|
return setting->m_name;
|
|
|
|
|
else if (role == Qt::CheckStateRole)
|
2018-09-17 14:37:34 +02:00
|
|
|
return setting->m_enabled ? Qt::Checked : Qt::Unchecked;
|
2018-07-13 12:33:46 +02:00
|
|
|
return QVariant();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool LanguageClientSettingsModel::removeRows(int row, int count, const QModelIndex &parent)
|
|
|
|
|
{
|
|
|
|
|
if (row >= int(m_settings.size()))
|
|
|
|
|
return false;
|
|
|
|
|
const int end = qMin(row + count - 1, int(m_settings.size()) - 1);
|
|
|
|
|
beginRemoveRows(parent, row, end);
|
2018-09-17 14:37:34 +02:00
|
|
|
for (auto i = end; i >= row; --i)
|
2018-09-18 10:43:17 +02:00
|
|
|
m_removed << m_settings.takeAt(i);
|
2018-07-13 12:33:46 +02:00
|
|
|
endRemoveRows();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool LanguageClientSettingsModel::insertRows(int row, int count, const QModelIndex &parent)
|
|
|
|
|
{
|
|
|
|
|
if (row > m_settings.size() || row < 0)
|
|
|
|
|
return false;
|
|
|
|
|
beginInsertRows(parent, row, row + count - 1);
|
|
|
|
|
for (int i = 0; i < count; ++i)
|
2018-09-18 10:43:17 +02:00
|
|
|
m_settings.insert(row + i, new StdIOSettings());
|
2018-07-13 12:33:46 +02:00
|
|
|
endInsertRows();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool LanguageClientSettingsModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
|
|
|
|
{
|
2018-09-18 15:24:23 +02:00
|
|
|
StdIOSettings *setting = settingForIndex(index);
|
|
|
|
|
if (!setting || role != Qt::CheckStateRole)
|
2018-07-13 12:33:46 +02:00
|
|
|
return false;
|
2018-09-18 10:43:17 +02:00
|
|
|
|
2018-09-18 15:24:23 +02:00
|
|
|
if (setting->m_enabled != value.toBool()) {
|
|
|
|
|
setting->m_enabled = !setting->m_enabled;
|
|
|
|
|
emit dataChanged(index, index, { Qt::CheckStateRole });
|
2018-07-13 12:33:46 +02:00
|
|
|
}
|
2018-09-18 15:24:23 +02:00
|
|
|
return true;
|
2018-07-13 12:33:46 +02:00
|
|
|
}
|
|
|
|
|
|
2018-09-18 15:24:23 +02:00
|
|
|
Qt::ItemFlags LanguageClientSettingsModel::flags(const QModelIndex &/*index*/) const
|
2018-07-13 12:33:46 +02:00
|
|
|
{
|
2018-09-18 15:24:23 +02:00
|
|
|
return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
|
2018-07-13 12:33:46 +02:00
|
|
|
}
|
|
|
|
|
|
2018-09-18 10:43:17 +02:00
|
|
|
void LanguageClientSettingsModel::reset(const QList<StdIOSettings *> &settings)
|
2018-07-13 12:33:46 +02:00
|
|
|
{
|
2018-09-18 12:28:48 +02:00
|
|
|
beginResetModel();
|
|
|
|
|
qDeleteAll(m_settings);
|
2018-09-18 10:43:17 +02:00
|
|
|
qDeleteAll(m_removed);
|
|
|
|
|
m_removed.clear();
|
|
|
|
|
m_settings = Utils::transform(settings, [](const StdIOSettings *other){
|
|
|
|
|
return dynamic_cast<StdIOSettings *>(other->copy());
|
2018-07-13 12:33:46 +02:00
|
|
|
});
|
2018-09-18 12:28:48 +02:00
|
|
|
endResetModel();
|
2018-07-13 12:33:46 +02:00
|
|
|
}
|
|
|
|
|
|
2018-09-18 15:24:23 +02:00
|
|
|
StdIOSettings *LanguageClientSettingsModel::settingForIndex(const QModelIndex &index) const
|
|
|
|
|
{
|
|
|
|
|
if (!index.isValid() || index.row() >= m_settings.size())
|
|
|
|
|
return nullptr;
|
|
|
|
|
return m_settings[index.row()];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QModelIndex LanguageClientSettingsModel::indexForSetting(StdIOSettings *setting) const
|
|
|
|
|
{
|
|
|
|
|
const int index = m_settings.indexOf(setting);
|
|
|
|
|
return index < 0 ? QModelIndex() : createIndex(index, 0, setting);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BaseSettings::applyFromSettingsWidget(QWidget *widget)
|
|
|
|
|
{
|
|
|
|
|
if (auto settingsWidget = qobject_cast<BaseSettingsWidget *>(widget)) {
|
|
|
|
|
m_name = settingsWidget->name();
|
2018-10-10 14:26:57 +02:00
|
|
|
m_languageFilter = settingsWidget->filter();
|
2018-09-18 15:24:23 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QWidget *BaseSettings::createSettingsWidget(QWidget *parent) const
|
|
|
|
|
{
|
|
|
|
|
return new BaseSettingsWidget(this, parent);
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-18 10:43:17 +02:00
|
|
|
bool BaseSettings::needsRestart() const
|
2018-07-13 12:33:46 +02:00
|
|
|
{
|
2018-09-18 10:43:17 +02:00
|
|
|
return m_client ? !m_enabled || m_client->needsRestart(this) : m_enabled;
|
2018-07-13 12:33:46 +02:00
|
|
|
}
|
|
|
|
|
|
2018-09-18 10:43:17 +02:00
|
|
|
bool BaseSettings::isValid() const
|
2018-09-17 13:55:26 +02:00
|
|
|
{
|
2018-09-18 10:43:17 +02:00
|
|
|
return !m_name.isEmpty();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BaseClient *BaseSettings::createClient() const
|
|
|
|
|
{
|
|
|
|
|
return nullptr;
|
2018-09-17 13:55:26 +02:00
|
|
|
}
|
|
|
|
|
|
2018-09-17 14:46:30 +02:00
|
|
|
QVariantMap BaseSettings::toMap() const
|
2018-07-13 12:33:46 +02:00
|
|
|
{
|
|
|
|
|
QVariantMap map;
|
|
|
|
|
map.insert(nameKey, m_name);
|
|
|
|
|
map.insert(enabledKey, m_enabled);
|
2018-10-10 14:26:57 +02:00
|
|
|
map.insert(mimeTypeKey, m_languageFilter.mimeTypes);
|
|
|
|
|
map.insert(filePatternKey, m_languageFilter.filePattern);
|
2018-07-13 12:33:46 +02:00
|
|
|
return map;
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-17 15:29:05 +02:00
|
|
|
void BaseSettings::fromMap(const QVariantMap &map)
|
2018-07-13 12:33:46 +02:00
|
|
|
{
|
2018-09-17 15:29:05 +02:00
|
|
|
m_name = map[nameKey].toString();
|
|
|
|
|
m_enabled = map[enabledKey].toBool();
|
2018-10-10 14:26:57 +02:00
|
|
|
m_languageFilter.mimeTypes = map[mimeTypeKey].toStringList();
|
|
|
|
|
m_languageFilter.filePattern = map[filePatternKey].toStringList();
|
2018-07-13 12:33:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LanguageClientSettings::init()
|
|
|
|
|
{
|
|
|
|
|
static LanguageClientSettingsPage settingsPage;
|
|
|
|
|
settingsPage.init();
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-18 10:43:17 +02:00
|
|
|
QList<StdIOSettings *> LanguageClientSettings::fromSettings(QSettings *settingsIn)
|
2018-09-18 12:28:48 +02:00
|
|
|
{
|
|
|
|
|
settingsIn->beginGroup(settingsGroupKey);
|
|
|
|
|
auto variants = settingsIn->value(clientsKey).toList();
|
|
|
|
|
auto settings = Utils::transform(variants, [](const QVariant& var){
|
2018-09-18 10:43:17 +02:00
|
|
|
auto settings = new StdIOSettings();
|
2018-09-18 12:28:48 +02:00
|
|
|
settings->fromMap(var.toMap());
|
|
|
|
|
return settings;
|
|
|
|
|
});
|
|
|
|
|
settingsIn->endGroup();
|
|
|
|
|
return settings;
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-18 10:43:17 +02:00
|
|
|
void LanguageClientSettings::toSettings(QSettings *settings, const QList<StdIOSettings *> &languageClientSettings)
|
2018-09-18 12:28:48 +02:00
|
|
|
{
|
|
|
|
|
settings->beginGroup(settingsGroupKey);
|
|
|
|
|
settings->setValue(clientsKey, Utils::transform(languageClientSettings,
|
2018-09-18 10:43:17 +02:00
|
|
|
[](const StdIOSettings *setting){
|
2018-09-18 12:28:48 +02:00
|
|
|
return QVariant(setting->toMap());
|
|
|
|
|
}));
|
|
|
|
|
settings->endGroup();
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-18 15:24:23 +02:00
|
|
|
void StdIOSettings::applyFromSettingsWidget(QWidget *widget)
|
|
|
|
|
{
|
|
|
|
|
if (auto settingsWidget = qobject_cast<StdIOSettingsWidget *>(widget)) {
|
|
|
|
|
BaseSettings::applyFromSettingsWidget(settingsWidget);
|
|
|
|
|
m_executable = settingsWidget->executable();
|
|
|
|
|
m_arguments = settingsWidget->arguments();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QWidget *StdIOSettings::createSettingsWidget(QWidget *parent) const
|
|
|
|
|
{
|
|
|
|
|
return new StdIOSettingsWidget(this, parent);
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-18 10:43:17 +02:00
|
|
|
bool StdIOSettings::needsRestart() const
|
|
|
|
|
{
|
|
|
|
|
if (BaseSettings::needsRestart())
|
|
|
|
|
return true;
|
|
|
|
|
if (auto stdIOClient = qobject_cast<StdIOClient *>(m_client))
|
|
|
|
|
return stdIOClient->needsRestart(this);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool StdIOSettings::isValid() const
|
|
|
|
|
{
|
|
|
|
|
return BaseSettings::isValid() && !m_executable.isEmpty();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BaseClient *StdIOSettings::createClient() const
|
|
|
|
|
{
|
|
|
|
|
auto client = new StdIOClient(m_executable, m_arguments);
|
|
|
|
|
client->setName(m_name);
|
2018-10-10 14:26:57 +02:00
|
|
|
client->setSupportedLanguage(m_languageFilter);
|
2018-09-18 10:43:17 +02:00
|
|
|
return client;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QVariantMap StdIOSettings::toMap() const
|
|
|
|
|
{
|
|
|
|
|
QVariantMap map = BaseSettings::toMap();
|
|
|
|
|
map.insert(executableKey, m_executable);
|
|
|
|
|
map.insert(argumentsKey, m_arguments);
|
|
|
|
|
return map;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void StdIOSettings::fromMap(const QVariantMap &map)
|
|
|
|
|
{
|
|
|
|
|
BaseSettings::fromMap(map);
|
|
|
|
|
m_executable = map[executableKey].toString();
|
|
|
|
|
m_arguments = map[argumentsKey].toString();
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-18 15:24:23 +02:00
|
|
|
BaseSettingsWidget::BaseSettingsWidget(const BaseSettings *settings, QWidget *parent)
|
|
|
|
|
: QWidget(parent)
|
|
|
|
|
, m_name(new QLineEdit(settings->m_name, this))
|
2018-10-10 14:26:57 +02:00
|
|
|
, m_mimeTypes(new QLabel(settings->m_languageFilter.mimeTypes.join(filterSeparator), this))
|
|
|
|
|
, m_filePattern(new QLineEdit(settings->m_languageFilter.filePattern.join(filterSeparator), this))
|
|
|
|
|
{
|
|
|
|
|
int row = 0;
|
|
|
|
|
auto *mainLayout = new QGridLayout;
|
|
|
|
|
mainLayout->addWidget(new QLabel(tr("Name:")), row, 0);
|
|
|
|
|
mainLayout->addWidget(m_name, row, 1);
|
|
|
|
|
mainLayout->addWidget(new QLabel(tr("Language:")), ++row, 0);
|
|
|
|
|
auto mimeLayout = new QHBoxLayout;
|
|
|
|
|
mimeLayout->addWidget(m_mimeTypes);
|
|
|
|
|
mimeLayout->addStretch();
|
|
|
|
|
auto addMimeTypeButton = new QPushButton(tr("Set MIME Types..."), this);
|
|
|
|
|
mimeLayout->addWidget(addMimeTypeButton);
|
|
|
|
|
mainLayout->addLayout(mimeLayout, row, 1);
|
|
|
|
|
m_filePattern->setPlaceholderText(tr("File pattern"));
|
|
|
|
|
mainLayout->addWidget(m_filePattern, ++row, 1);
|
|
|
|
|
|
|
|
|
|
connect(addMimeTypeButton, &QPushButton::pressed,
|
|
|
|
|
this, &BaseSettingsWidget::showAddMimeTypeDialog);
|
2018-09-18 15:24:23 +02:00
|
|
|
|
|
|
|
|
setLayout(mainLayout);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString BaseSettingsWidget::name() const
|
|
|
|
|
{
|
|
|
|
|
return m_name->text();
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-10 14:26:57 +02:00
|
|
|
LanguageFilter BaseSettingsWidget::filter() const
|
|
|
|
|
{
|
|
|
|
|
return {m_mimeTypes->text().split(filterSeparator),
|
|
|
|
|
m_filePattern->text().split(filterSeparator)};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class MimeTypeModel : public QStringListModel
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
using QStringListModel::QStringListModel;
|
|
|
|
|
QVariant data(const QModelIndex &index, int role) const final
|
|
|
|
|
{
|
|
|
|
|
if (index.isValid() && role == Qt::CheckStateRole)
|
|
|
|
|
return m_selectedMimeTypes.contains(index.data().toString()) ? Qt::Checked : Qt::Unchecked;
|
|
|
|
|
return QStringListModel::data(index, role);
|
|
|
|
|
}
|
|
|
|
|
bool setData(const QModelIndex &index, const QVariant &value, int role) final
|
|
|
|
|
{
|
|
|
|
|
if (index.isValid() && role == Qt::CheckStateRole) {
|
|
|
|
|
QString mimeType = index.data().toString();
|
|
|
|
|
if (value.toInt() == Qt::Checked) {
|
|
|
|
|
if (!m_selectedMimeTypes.contains(mimeType))
|
|
|
|
|
m_selectedMimeTypes.append(index.data().toString());
|
|
|
|
|
} else {
|
|
|
|
|
m_selectedMimeTypes.removeAll(index.data().toString());
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return QStringListModel::setData(index, value, role);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Qt::ItemFlags flags(const QModelIndex &index) const final
|
|
|
|
|
{
|
|
|
|
|
if (!index.isValid())
|
|
|
|
|
return Qt::NoItemFlags;
|
|
|
|
|
return (QStringListModel::flags(index)
|
|
|
|
|
& ~(Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled))
|
|
|
|
|
| Qt::ItemIsUserCheckable;
|
|
|
|
|
}
|
|
|
|
|
QStringList m_selectedMimeTypes;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class MimeTypeDialog : public QDialog
|
2018-09-18 15:24:23 +02:00
|
|
|
{
|
2018-10-10 14:26:57 +02:00
|
|
|
public:
|
|
|
|
|
explicit MimeTypeDialog(const QStringList &selectedMimeTypes, QWidget *parent = nullptr)
|
|
|
|
|
: QDialog(parent)
|
|
|
|
|
{
|
|
|
|
|
setWindowTitle(tr("Select MIME Types"));
|
|
|
|
|
auto mainLayout = new QVBoxLayout;
|
2018-10-19 22:47:07 +02:00
|
|
|
auto filter = new Utils::FancyLineEdit(this);
|
|
|
|
|
filter->setFiltering(true);
|
2018-10-10 14:26:57 +02:00
|
|
|
mainLayout->addWidget(filter);
|
|
|
|
|
auto listView = new QListView(this);
|
|
|
|
|
mainLayout->addWidget(listView);
|
|
|
|
|
auto buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
|
|
|
|
|
mainLayout->addWidget(buttons);
|
|
|
|
|
setLayout(mainLayout);
|
|
|
|
|
|
|
|
|
|
filter->setPlaceholderText(tr("Filter"));
|
|
|
|
|
connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
|
|
|
|
connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
|
|
|
|
auto proxy = new QSortFilterProxyModel(this);
|
|
|
|
|
m_mimeTypeModel = new MimeTypeModel(Utils::transform(Utils::allMimeTypes(),
|
|
|
|
|
&Utils::MimeType::name), this);
|
|
|
|
|
m_mimeTypeModel->m_selectedMimeTypes = selectedMimeTypes;
|
|
|
|
|
proxy->setSourceModel(m_mimeTypeModel);
|
2018-10-19 06:53:10 +02:00
|
|
|
proxy->sort(0);
|
2018-10-10 14:26:57 +02:00
|
|
|
connect(filter, &QLineEdit::textChanged, proxy, &QSortFilterProxyModel::setFilterWildcard);
|
|
|
|
|
listView->setModel(proxy);
|
|
|
|
|
|
|
|
|
|
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
|
|
|
|
setModal(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MimeTypeDialog(const MimeTypeDialog &other) = delete;
|
|
|
|
|
MimeTypeDialog(MimeTypeDialog &&other) = delete;
|
|
|
|
|
|
|
|
|
|
MimeTypeDialog operator=(const MimeTypeDialog &other) = delete;
|
|
|
|
|
MimeTypeDialog operator=(MimeTypeDialog &&other) = delete;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
QStringList mimeTypes() const
|
|
|
|
|
{
|
|
|
|
|
return m_mimeTypeModel->m_selectedMimeTypes;
|
|
|
|
|
}
|
|
|
|
|
private:
|
|
|
|
|
MimeTypeModel *m_mimeTypeModel = nullptr;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
void BaseSettingsWidget::showAddMimeTypeDialog()
|
|
|
|
|
{
|
|
|
|
|
MimeTypeDialog dialog(m_mimeTypes->text().split(filterSeparator, QString::SkipEmptyParts),
|
|
|
|
|
Core::ICore::dialogParent());
|
|
|
|
|
if (dialog.exec() == QDialog::Rejected)
|
|
|
|
|
return;
|
|
|
|
|
m_mimeTypes->setText(dialog.mimeTypes().join(filterSeparator));
|
2018-09-18 15:24:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
StdIOSettingsWidget::StdIOSettingsWidget(const StdIOSettings *settings, QWidget *parent)
|
|
|
|
|
: BaseSettingsWidget(settings, parent)
|
|
|
|
|
, m_executable(new Utils::PathChooser(this))
|
|
|
|
|
, m_arguments(new QLineEdit(settings->m_arguments, this))
|
|
|
|
|
{
|
|
|
|
|
auto mainLayout = qobject_cast<QGridLayout *>(layout());
|
|
|
|
|
QTC_ASSERT(mainLayout, return);
|
|
|
|
|
const int baseRows = mainLayout->rowCount();
|
|
|
|
|
mainLayout->addWidget(new QLabel(tr("Executable:")), baseRows, 0);
|
|
|
|
|
mainLayout->addWidget(m_executable, baseRows, 1);
|
|
|
|
|
mainLayout->addWidget(new QLabel(tr("Arguments:")), baseRows + 1, 0);
|
2018-10-10 10:33:44 +02:00
|
|
|
m_executable->setExpectedKind(Utils::PathChooser::ExistingCommand);
|
2018-09-18 15:24:23 +02:00
|
|
|
m_executable->setPath(QDir::toNativeSeparators(settings->m_executable));
|
|
|
|
|
mainLayout->addWidget(m_arguments, baseRows + 1, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString StdIOSettingsWidget::executable() const
|
|
|
|
|
{
|
|
|
|
|
return m_executable->path();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString StdIOSettingsWidget::arguments() const
|
|
|
|
|
{
|
|
|
|
|
return m_arguments->text();
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-13 12:33:46 +02:00
|
|
|
} // namespace LanguageClient
|