Haskell: More compact settings/manager setup

Use PagedSettings, move related parts Manager interface there, too.

Change-Id: I079dad8bbbea39d2424a25867b08c34ab0234ad5
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
hjk
2023-05-15 15:15:17 +02:00
parent 21cb45e665
commit 22fa5f2d3a
12 changed files with 95 additions and 165 deletions

View File

@@ -12,9 +12,9 @@ add_qtc_plugin(Haskell
haskellplugin.cpp haskellplugin.h haskellplugin.cpp haskellplugin.h
haskellproject.cpp haskellproject.h haskellproject.cpp haskellproject.h
haskellrunconfiguration.cpp haskellrunconfiguration.h haskellrunconfiguration.cpp haskellrunconfiguration.h
haskellsettings.cpp haskellsettings.h
haskelltokenizer.cpp haskelltokenizer.h haskelltokenizer.cpp haskelltokenizer.h
haskelltr.h haskelltr.h
optionspage.cpp optionspage.h
stackbuildstep.cpp stackbuildstep.h stackbuildstep.cpp stackbuildstep.h
) )

View File

@@ -21,8 +21,8 @@ QtcPlugin {
"haskellplugin.cpp", "haskellplugin.h", "haskellplugin.cpp", "haskellplugin.h",
"haskellproject.cpp", "haskellproject.h", "haskellproject.cpp", "haskellproject.h",
"haskellrunconfiguration.cpp", "haskellrunconfiguration.h", "haskellrunconfiguration.cpp", "haskellrunconfiguration.h",
"haskellsettings.cpp", "haskellsettings.h",
"haskelltokenizer.cpp", "haskelltokenizer.h", "haskelltokenizer.cpp", "haskelltokenizer.h",
"optionspage.cpp", "optionspage.h",
"stackbuildstep.cpp", "stackbuildstep.h" "stackbuildstep.cpp", "stackbuildstep.h"
] ]
} }

View File

@@ -14,17 +14,14 @@
#include <texteditor/texteditoractionhandler.h> #include <texteditor/texteditoractionhandler.h>
#include <texteditor/textindenter.h> #include <texteditor/textindenter.h>
#include <QCoreApplication> namespace Haskell::Internal {
namespace Haskell { static QWidget *createEditorWidget(QObject *guard)
namespace Internal {
static QWidget *createEditorWidget()
{ {
auto widget = new TextEditor::TextEditorWidget; auto widget = new TextEditor::TextEditorWidget;
auto ghciButton = new Core::CommandButton(Constants::A_RUN_GHCI, widget); auto ghciButton = new Core::CommandButton(Constants::A_RUN_GHCI, widget);
ghciButton->setText(Tr::tr("GHCi")); ghciButton->setText(Tr::tr("GHCi"));
QObject::connect(ghciButton, &QToolButton::clicked, HaskellManager::instance(), [widget] { QObject::connect(ghciButton, &QToolButton::clicked, guard, [widget] {
HaskellManager::openGhci(widget->textDocument()->filePath()); HaskellManager::openGhci(widget->textDocument()->filePath());
}); });
widget->insertExtraToolBarWidget(TextEditor::TextEditorWidget::Left, ghciButton); widget->insertExtraToolBarWidget(TextEditor::TextEditorWidget::Left, ghciButton);
@@ -40,12 +37,11 @@ HaskellEditorFactory::HaskellEditorFactory()
| TextEditor::TextEditorActionHandler::FollowSymbolUnderCursor); | TextEditor::TextEditorActionHandler::FollowSymbolUnderCursor);
setDocumentCreator([] { return new TextEditor::TextDocument(Constants::C_HASKELLEDITOR_ID); }); setDocumentCreator([] { return new TextEditor::TextDocument(Constants::C_HASKELLEDITOR_ID); });
setIndenterCreator([](QTextDocument *doc) { return new TextEditor::TextIndenter(doc); }); setIndenterCreator([](QTextDocument *doc) { return new TextEditor::TextIndenter(doc); });
setEditorWidgetCreator(createEditorWidget); setEditorWidgetCreator([this] { return createEditorWidget(this); });
setCommentDefinition(Utils::CommentDefinition("--", "{-", "-}")); setCommentDefinition(Utils::CommentDefinition("--", "{-", "-}"));
setParenthesesMatchingEnabled(true); setParenthesesMatchingEnabled(true);
setMarksVisible(true); setMarksVisible(true);
setSyntaxHighlighterCreator([] { return new HaskellHighlighter(); }); setSyntaxHighlighterCreator([] { return new HaskellHighlighter(); });
} }
} // Internal } // Haskell::Internal
} // Haskell

View File

@@ -5,8 +5,7 @@
#include <texteditor/texteditor.h> #include <texteditor/texteditor.h>
namespace Haskell { namespace Haskell::Internal {
namespace Internal {
class HaskellEditorFactory : public TextEditor::TextEditorFactory class HaskellEditorFactory : public TextEditor::TextEditorFactory
{ {
@@ -14,5 +13,4 @@ public:
HaskellEditorFactory(); HaskellEditorFactory();
}; };
} // Internal } // Haskell::Internal
} // Haskell

View File

@@ -3,9 +3,9 @@
#include "haskellmanager.h" #include "haskellmanager.h"
#include "haskellsettings.h"
#include "haskelltr.h" #include "haskelltr.h"
#include <coreplugin/messagemanager.h>
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/commandline.h> #include <utils/commandline.h>
#include <utils/hostosinfo.h> #include <utils/hostosinfo.h>
@@ -13,33 +13,12 @@
#include <utils/process.h> #include <utils/process.h>
#include <utils/processenums.h> #include <utils/processenums.h>
#include <QCoreApplication>
#include <QDir> #include <QDir>
#include <QFileInfo> #include <QFileInfo>
#include <QSettings>
#include <unordered_map>
static const char kStackExecutableKey[] = "Haskell/StackExecutable";
using namespace Utils; using namespace Utils;
namespace Haskell { namespace Haskell::Internal {
namespace Internal {
class HaskellManagerPrivate
{
public:
FilePath stackExecutable;
};
Q_GLOBAL_STATIC(HaskellManagerPrivate, m_d)
Q_GLOBAL_STATIC(HaskellManager, m_instance)
HaskellManager *HaskellManager::instance()
{
return m_instance;
}
FilePath HaskellManager::findProjectDirectory(const FilePath &filePath) FilePath HaskellManager::findProjectDirectory(const FilePath &filePath)
{ {
@@ -57,28 +36,6 @@ FilePath HaskellManager::findProjectDirectory(const FilePath &filePath)
return {}; return {};
} }
FilePath defaultStackExecutable()
{
// stack from brew or the installer script from https://docs.haskellstack.org
// install to /usr/local/bin.
if (HostOsInfo::isAnyUnixHost())
return FilePath::fromString("/usr/local/bin/stack");
return FilePath::fromString("stack");
}
FilePath HaskellManager::stackExecutable()
{
return m_d->stackExecutable;
}
void HaskellManager::setStackExecutable(const FilePath &filePath)
{
if (filePath == m_d->stackExecutable)
return;
m_d->stackExecutable = filePath;
emit m_instance->stackExecutableChanged(m_d->stackExecutable);
}
void HaskellManager::openGhci(const FilePath &haskellFile) void HaskellManager::openGhci(const FilePath &haskellFile)
{ {
const QList<MimeType> mimeTypes = mimeTypesForFileName(haskellFile.toString()); const QList<MimeType> mimeTypes = mimeTypesForFileName(haskellFile.toString());
@@ -89,25 +46,9 @@ void HaskellManager::openGhci(const FilePath &haskellFile)
+ (isHaskell ? QStringList{haskellFile.fileName()} : QStringList()); + (isHaskell ? QStringList{haskellFile.fileName()} : QStringList());
Process p; Process p;
p.setTerminalMode(TerminalMode::Detached); p.setTerminalMode(TerminalMode::Detached);
p.setCommand({stackExecutable(), args}); p.setCommand({settings().stackPath.filePath(), args});
p.setWorkingDirectory(haskellFile.absolutePath()); p.setWorkingDirectory(haskellFile.absolutePath());
p.start(); p.start();
} }
void HaskellManager::readSettings(QSettings *settings) } // Haskell::Internal
{
m_d->stackExecutable = FilePath::fromString(
settings->value(kStackExecutableKey, defaultStackExecutable().toString()).toString());
emit m_instance->stackExecutableChanged(m_d->stackExecutable);
}
void HaskellManager::writeSettings(QSettings *settings)
{
if (m_d->stackExecutable == defaultStackExecutable())
settings->remove(kStackExecutableKey);
else
settings->setValue(kStackExecutableKey, m_d->stackExecutable.toString());
}
} // namespace Internal
} // namespace Haskell

View File

@@ -7,30 +7,15 @@
#include <utils/fileutils.h> #include <utils/fileutils.h>
QT_BEGIN_NAMESPACE namespace Haskell::Internal {
class QSettings;
QT_END_NAMESPACE
namespace Haskell { class HaskellManager
namespace Internal {
class HaskellManager : public QObject
{ {
Q_OBJECT
public: public:
static HaskellManager *instance(); static HaskellManager *instance();
static Utils::FilePath findProjectDirectory(const Utils::FilePath &filePath); static Utils::FilePath findProjectDirectory(const Utils::FilePath &filePath);
static Utils::FilePath stackExecutable();
static void setStackExecutable(const Utils::FilePath &filePath);
static void openGhci(const Utils::FilePath &haskellFile); static void openGhci(const Utils::FilePath &haskellFile);
static void readSettings(QSettings *settings);
static void writeSettings(QSettings *settings);
signals:
void stackExecutableChanged(const Utils::FilePath &filePath);
}; };
} // namespace Internal } // Haskell::Internal
} // namespace Haskell

View File

@@ -9,8 +9,8 @@
#include "haskellmanager.h" #include "haskellmanager.h"
#include "haskellproject.h" #include "haskellproject.h"
#include "haskellrunconfiguration.h" #include "haskellrunconfiguration.h"
#include "haskellsettings.h"
#include "haskelltr.h" #include "haskelltr.h"
#include "optionspage.h"
#include "stackbuildstep.h" #include "stackbuildstep.h"
#include <coreplugin/actionmanager/actionmanager.h> #include <coreplugin/actionmanager/actionmanager.h>
@@ -28,8 +28,8 @@ namespace Internal {
class HaskellPluginPrivate class HaskellPluginPrivate
{ {
public: public:
HaskellSettings settings;
HaskellEditorFactory editorFactory; HaskellEditorFactory editorFactory;
OptionsPage optionsPage;
HaskellBuildConfigurationFactory buildConfigFactory; HaskellBuildConfigurationFactory buildConfigFactory;
StackBuildStepFactory stackBuildStepFactory; StackBuildStepFactory stackBuildStepFactory;
HaskellRunConfigurationFactory runConfigFactory; HaskellRunConfigurationFactory runConfigFactory;
@@ -41,11 +41,11 @@ HaskellPlugin::~HaskellPlugin()
delete d; delete d;
} }
static void registerGhciAction() static void registerGhciAction(QObject *guard)
{ {
QAction *action = new QAction(Tr::tr("Run GHCi"), HaskellManager::instance()); QAction *action = new QAction(Tr::tr("Run GHCi"), guard);
Core::ActionManager::registerAction(action, Constants::A_RUN_GHCI); Core::ActionManager::registerAction(action, Constants::A_RUN_GHCI);
QObject::connect(action, &QAction::triggered, HaskellManager::instance(), [] { QObject::connect(action, &QAction::triggered, guard, [] {
if (Core::IDocument *doc = Core::EditorManager::currentDocument()) if (Core::IDocument *doc = Core::EditorManager::currentDocument())
HaskellManager::openGhci(doc->filePath()); HaskellManager::openGhci(doc->filePath());
}); });
@@ -63,13 +63,7 @@ bool HaskellPlugin::initialize(const QStringList &arguments, QString *errorStrin
TextEditor::SnippetProvider::registerGroup(Constants::C_HASKELLSNIPPETSGROUP_ID, TextEditor::SnippetProvider::registerGroup(Constants::C_HASKELLSNIPPETSGROUP_ID,
Tr::tr("Haskell", "SnippetProvider")); Tr::tr("Haskell", "SnippetProvider"));
connect(Core::ICore::instance(), &Core::ICore::saveSettingsRequested, this, [] { registerGhciAction(this);
HaskellManager::writeSettings(Core::ICore::settings());
});
registerGhciAction();
HaskellManager::readSettings(Core::ICore::settings());
ProjectExplorer::JsonWizardFactory::addWizardPath(":/haskell/share/wizards/"); ProjectExplorer::JsonWizardFactory::addWizardPath(":/haskell/share/wizards/");
return true; return true;

View File

@@ -4,9 +4,9 @@
#include "haskellrunconfiguration.h" #include "haskellrunconfiguration.h"
#include "haskellconstants.h" #include "haskellconstants.h"
#include "haskellmanager.h"
#include "haskellproject.h" #include "haskellproject.h"
#include "haskelltr.h" #include "haskelltr.h"
#include "haskellsettings.h"
#include <projectexplorer/buildconfiguration.h> #include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/localenvironmentaspect.h> #include <projectexplorer/localenvironmentaspect.h>
@@ -68,7 +68,7 @@ Runnable HaskellRunConfiguration::runnable() const
r.workingDirectory = projectDirectory; r.workingDirectory = projectDirectory;
r.environment = aspect<LocalEnvironmentAspect>()->environment(); r.environment = aspect<LocalEnvironmentAspect>()->environment();
r.command = {r.environment.searchInPath(HaskellManager::stackExecutable().toString()), args}; r.command = {r.environment.searchInPath(settings().stackPath()), args};
return r; return r;
} }

View File

@@ -0,0 +1,63 @@
// Copyright (c) 2017 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "haskellsettings.h"
#include "haskellconstants.h"
#include "haskelltr.h"
#include <coreplugin/icore.h>
#include <utils/hostosinfo.h>
#include <utils/pathchooser.h>
#include <utils/layoutbuilder.h>
using namespace Utils;
namespace Haskell::Internal {
static HaskellSettings *theSettings;
HaskellSettings &settings()
{
return *theSettings;
}
HaskellSettings::HaskellSettings()
{
theSettings = this;
setId(Constants::OPTIONS_GENERAL);
setDisplayName(Tr::tr("General"));
setCategory("J.Z.Haskell");
setDisplayCategory(Tr::tr("Haskell"));
setCategoryIconPath(":/haskell/images/settingscategory_haskell.png");
registerAspect(&stackPath);
stackPath.setSettingsKey("Haskell/StackExecutable");
stackPath.setDisplayStyle(StringAspect::PathChooserDisplay);
stackPath.setExpectedKind(PathChooser::ExistingCommand);
stackPath.setPromptDialogTitle(Tr::tr("Choose Stack Executable"));
stackPath.setCommandVersionArguments({"--version"});
// stack from brew or the installer script from https://docs.haskellstack.org
// install to /usr/local/bin.
stackPath.setDefaultFilePath(HostOsInfo::isAnyUnixHost()
? FilePath::fromString("/usr/local/bin/stack")
: FilePath::fromString("stack"));
setLayouter([this](QWidget *widget) {
using namespace Layouting;
Column {
Group {
title(Tr::tr("General")),
Row { Tr::tr("Stack executable:"), stackPath }
},
st,
}.attachTo(widget);
});
readSettings(Core::ICore::settings());
}
} // Haskell::Internal

View File

@@ -7,10 +7,14 @@
namespace Haskell::Internal { namespace Haskell::Internal {
class OptionsPage : public Core::IOptionsPage class HaskellSettings : public Core::PagedSettings
{ {
public: public:
OptionsPage(); HaskellSettings();
Utils::StringAspect stackPath;
}; };
HaskellSettings &settings();
} // Haskell::Internal } // Haskell::Internal

View File

@@ -1,51 +0,0 @@
// Copyright (c) 2017 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "optionspage.h"
#include "haskellconstants.h"
#include "haskellmanager.h"
#include "haskelltr.h"
#include <utils/pathchooser.h>
#include <utils/layoutbuilder.h>
using namespace Utils;
namespace Haskell::Internal {
class HaskellOptionsPageWidget : public Core::IOptionsPageWidget
{
public:
HaskellOptionsPageWidget()
{
auto stackPath = new PathChooser;
stackPath->setExpectedKind(PathChooser::ExistingCommand);
stackPath->setPromptDialogTitle(Tr::tr("Choose Stack Executable"));
stackPath->setFilePath(HaskellManager::stackExecutable());
stackPath->setCommandVersionArguments({"--version"});
setOnApply([stackPath] { HaskellManager::setStackExecutable(stackPath->rawFilePath()); });
using namespace Layouting;
Column {
Group {
title(Tr::tr("General")),
Row { Tr::tr("Stack executable:"), stackPath }
},
st,
}.attachTo(this);
}
};
OptionsPage::OptionsPage()
{
setId(Constants::OPTIONS_GENERAL);
setDisplayName(Tr::tr("General"));
setCategory("J.Z.Haskell");
setDisplayCategory(Tr::tr("Haskell"));
setCategoryIconPath(":/haskell/images/settingscategory_haskell.png");
setWidgetCreator([] { return new HaskellOptionsPageWidget; });
}
} // Haskell::Internal

View File

@@ -4,7 +4,7 @@
#include "stackbuildstep.h" #include "stackbuildstep.h"
#include "haskellconstants.h" #include "haskellconstants.h"
#include "haskellmanager.h" #include "haskellsettings.h"
#include "haskelltr.h" #include "haskelltr.h"
#include <projectexplorer/buildconfiguration.h> #include <projectexplorer/buildconfiguration.h>
@@ -38,7 +38,7 @@ bool StackBuildStep::init()
if (AbstractProcessStep::init()) { if (AbstractProcessStep::init()) {
const auto projectDir = QDir(project()->projectDirectory().toString()); const auto projectDir = QDir(project()->projectDirectory().toString());
processParameters()->setCommandLine( processParameters()->setCommandLine(
{HaskellManager::stackExecutable(), {settings().stackPath.filePath(),
{"build", "--work-dir", projectDir.relativeFilePath(buildDirectory().toString())}}); {"build", "--work-dir", projectDir.relativeFilePath(buildDirectory().toString())}});
processParameters()->setEnvironment(buildEnvironment()); processParameters()->setEnvironment(buildEnvironment());
} }