QmlJSEditor: Add project specific settings for qmlls

Add a new ProjectSettings class for project-specific qmlls settings.
Currently only two checkboxes exist, 'Use General Settings' to ignore the
other project specific settings, and 'Turn on' to turn qmlls on or off.

Create a QmlJSEditingProjectSettingsWidget and a
QmlJSEditingProjectPanelFactory to display the ProjectSettings.

Make sure to emit QmllsSettingsManager::instance()->settingsChanged()
when the project specific settings are changed to make sure that qmlls
project specific preferences are followed. Make
QmllsSettingsManager::useQmlls() aware of the existence of project
specific settings.

Fixes: QTCREATORBUG-31473
Change-Id: Ia8e2d03837eabe96caafba5d13728ed8e1c8615c
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Sami Shalayel
2024-09-23 17:44:27 +02:00
parent fb8f59028c
commit 0b47768ba1
5 changed files with 132 additions and 6 deletions

View File

@@ -18,6 +18,8 @@
#include <coreplugin/coreconstants.h>
#include <coreplugin/modemanager.h>
#include <projectexplorer/projectmanager.h>
#include <qmljstools/qmljsindenter.h>
#include <qmljstools/qmljsmodelmanager.h>
#include <qmljstools/qmljsqtstylecodeformatter.h>
@@ -741,7 +743,8 @@ void QmlJSEditorDocumentPrivate::setSourcesWithCapabilities(
static FilePath qmllsForFile(const FilePath &file, QmlJS::ModelManagerInterface *modelManager)
{
QmllsSettingsManager *settingsManager = QmllsSettingsManager::instance();
bool enabled = settingsManager->useQmlls();
ProjectExplorer::Project *project = ProjectExplorer::ProjectManager::projectForFile(file);
const bool enabled = settingsManager->useQmlls(project);
if (!enabled)
return {};
if (settingsManager->useLatestQmlls())

View File

@@ -331,6 +331,7 @@ class QmlJSEditorPlugin final : public ExtensionSystem::IPlugin
dd = new QmlJSEditorPluginPrivate;
setupQmlJSEditor();
setupQmlJsEditingProjectPanel();
}
void extensionsInitialized() final

View File

@@ -8,6 +8,10 @@
#include <coreplugin/coreconstants.h>
#include <coreplugin/icore.h>
#include <projectexplorer/projectpanelfactory.h>
#include <projectexplorer/projectsettingswidget.h>
#include <projectexplorer/projecttree.h>
#include <qmljs/qmljscheck.h>
#include <qmljs/qmljsmodelmanagerinterface.h>
#include <qmljs/qmljsstaticanalysismessage.h>
@@ -41,16 +45,19 @@
using namespace QmlJSEditor::Internal;
using namespace QtSupport;
using namespace Utils;
using namespace ProjectExplorer;
namespace QmlJSEditor::Internal {
static Q_LOGGING_CATEGORY(qmllsLog, "qtc.qmlls.settings", QtWarningMsg)
const char SETTINGS_KEY_MAIN[] = "QmlJSEditor";
const char AUTO_FORMAT_ON_SAVE[] = "QmlJSEditor.AutoFormatOnSave";
const char AUTO_FORMAT_ONLY_CURRENT_PROJECT[] = "QmlJSEditor.AutoFormatOnlyCurrentProject";
const char QML_CONTEXTPANE_KEY[] = "QmlJSEditor.ContextPaneEnabled";
const char QML_CONTEXTPANEPIN_KEY[] = "QmlJSEditor.ContextPanePinned";
const char FOLD_AUX_DATA[] = "QmlJSEditor.FoldAuxData";
const char USE_GLOBAL_SETTINGS[] = "QmlJSEditor.UseGlobalSettings";
const char USE_QMLLS[] = "QmlJSEditor.UseQmlls";
const char USE_LATEST_QMLLS[] = "QmlJSEditor.UseLatestQmlls";
const char IGNORE_MINIMUM_QMLLS_VERSION[] = "QmlJSEditor.IgnoreMinimumQmllsVersion";
@@ -65,6 +72,7 @@ const char DISABLED_MESSAGES[] = "QmlJSEditor.disabledMessages";
const char DISABLED_MESSAGES_NONQUICKUI[] = "QmlJSEditor.disabledMessagesNonQuickUI";
const char DEFAULT_CUSTOM_FORMAT_COMMAND[]
= "%{CurrentDocument:Project:QT_HOST_BINS}/qmlformat%{HostOs:ExecutableSuffix}";
const char SETTINGS_PAGE[] = "C.QmlJsEditing";
QmlJsEditingSettings &settings()
{
@@ -162,9 +170,15 @@ bool QmllsSettingsManager::useLatestQmlls() const
return m_useLatestQmlls;
}
bool QmllsSettingsManager::useQmlls() const
bool QmllsSettingsManager::useQmlls(Project* onProject) const
{
return m_useQmlls;
// check if disabled via project specific settings
ProjectSettings projectSettings{onProject};
const bool result = projectSettings.useGlobalSettings() ? m_useQmlls
: projectSettings.useQmlls();
return result;
}
static QList<int> defaultDisabledMessages()
@@ -485,10 +499,98 @@ private:
QmlJsEditingSettingsPage::QmlJsEditingSettingsPage()
{
setId("C.QmlJsEditing");
setId(SETTINGS_PAGE);
setDisplayName(::QmlJSEditor::Tr::tr("QML/JS Editing"));
setCategory(Constants::SETTINGS_CATEGORY_QML);
setWidgetCreator([] { return new QmlJsEditingSettingsPageWidget; });
setSettingsProvider([] { return &settings(); });
}
ProjectSettings::ProjectSettings(Project *project)
{
setAutoApply(true);
const Key group = QmlJSEditor::Constants::SETTINGS_CATEGORY_QML;
useQmlls.setSettingsKey(group, USE_QMLLS);
useQmlls.setDefaultValue(true);
useQmlls.setLabelText(Tr::tr("Turn on"));
useQmlls.setToolTip(Tr::tr("Enable QML Language Server on this project."));
useGlobalSettings.setSettingsKey(group, USE_GLOBAL_SETTINGS);
useGlobalSettings.setDefaultValue(true);
Store map = storeFromVariant(project->namedSettings(SETTINGS_KEY_MAIN));
fromMap(map);
useQmlls.addOnChanged(this, [this, project] { save(project); });
useGlobalSettings.addOnChanged(this, [this, project] { save(project); });
}
void ProjectSettings::save(Project *project)
{
Store map;
toMap(map);
project->setNamedSettings(SETTINGS_KEY_MAIN, variantFromStore(map));
emit QmllsSettingsManager::instance()->settingsChanged();
}
class QmlJsEditingProjectSettingsWidget final : public ProjectSettingsWidget
{
public:
explicit QmlJsEditingProjectSettingsWidget(Project *project)
: m_settings{project}
{
setUseGlobalSettingsCheckBoxVisible(true);
setGlobalSettingsId(SETTINGS_PAGE);
setExpanding(true);
setUseGlobalSettings(m_settings.useGlobalSettings());
setEnabled(!m_settings.useGlobalSettings());
using namespace Layouting;
// clang-format off
Column {
Group{
title(Tr::tr("QML Language Server")),
Column{
&m_settings.useQmlls,
},
},
st,
}.attachTo(this);
// clang-format on
connect(
this, &ProjectSettingsWidget::useGlobalSettingsChanged, this, [this](bool newUseGlobal) {
setEnabled(!newUseGlobal);
m_settings.useGlobalSettings.setValue(newUseGlobal);
});
}
private:
ProjectSettings m_settings;
};
class QmlJsEditingProjectPanelFactory : public ProjectPanelFactory
{
public:
QmlJsEditingProjectPanelFactory()
{
setPriority(34); // just before the LanguageClientProjectPanelFactory
setDisplayName(Tr::tr("Qt Quick"));
setCreateWidgetFunction([](Project *project) {
return new QmlJsEditingProjectSettingsWidget(project);
});
}
};
void setupQmlJsEditingProjectPanel()
{
static QmlJsEditingProjectPanelFactory theQmlJsEditingProjectPanelFactory;
}
} // QmlJsEditor::Internal

View File

@@ -5,6 +5,8 @@
#include <coreplugin/dialogs/ioptionspage.h>
#include <projectexplorer/project.h>
#include <utils/filepath.h>
#include <QMutex>
@@ -51,7 +53,7 @@ public:
Utils::FilePath latestQmlls();
void setupAutoupdate();
bool useQmlls() const;
bool useQmlls(ProjectExplorer::Project* project) const;
bool useLatestQmlls() const;
public slots:
@@ -76,4 +78,17 @@ public:
QmlJsEditingSettingsPage();
};
class ProjectSettings : public Utils::AspectContainer
{
public:
ProjectSettings(ProjectExplorer::Project *project);
Utils::BoolAspect useQmlls{this};
Utils::BoolAspect useGlobalSettings{this};
void save(ProjectExplorer::Project *project);
};
void setupQmlJsEditingProjectPanel();
} // QmlJSEditor::Internal

View File

@@ -120,8 +120,13 @@ static void triggerQmllintCMakeTarget()
void QmlTaskManager::updateSemanticMessagesNow()
{
// note: this can only be called for the startup project
Project *project = ProjectManager::startupProject();
if (!project)
return;
// heuristic: qmllint will output meaningful warnings if qmlls is enabled
if (QmllsSettingsManager::instance()->useQmlls()) {
if (QmllsSettingsManager::instance()->useQmlls(project)) {
// abort any update that's going on already, and remove old codemodel warnings
m_messageCollector.cancel();
removeAllTasks(true);