forked from qt-creator/qt-creator
ProjectExplorer: Refactor task handlers setup
The new approach no longer assumes a fixed list, making dynamic creation of ITaskHandler subclasses possible. Change-Id: I86c53eaee5fc30844ce9f2d9399d5319bbf5658b Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -24,7 +24,7 @@ void SearchTaskHandler::handle(const ProjectExplorer::Task &task)
|
|||||||
emit search(QUrl("https://www.google.com/search?q=" + task.summary));
|
emit search(QUrl("https://www.google.com/search?q=" + task.summary));
|
||||||
}
|
}
|
||||||
|
|
||||||
QAction *SearchTaskHandler::createAction(QObject *parent) const
|
QAction *SearchTaskHandler::createAction() const
|
||||||
{
|
{
|
||||||
return new QAction(Tr::tr("Get Help Online"), parent);
|
return new QAction(Tr::tr("Get Help Online"));
|
||||||
}
|
}
|
||||||
|
@@ -17,12 +17,15 @@ class SearchTaskHandler : public ProjectExplorer::ITaskHandler
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool canHandle(const ProjectExplorer::Task &task) const override;
|
SearchTaskHandler() : ProjectExplorer::ITaskHandler(createAction()) {}
|
||||||
void handle(const ProjectExplorer::Task &task) override;
|
|
||||||
QAction *createAction(QObject *parent) const override;
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void search(const QUrl &url);
|
void search(const QUrl &url);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool canHandle(const ProjectExplorer::Task &task) const override;
|
||||||
|
void handle(const ProjectExplorer::Task &task) override;
|
||||||
|
QAction *createAction() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
@@ -73,7 +73,6 @@
|
|||||||
#include "simpleprojectwizard.h"
|
#include "simpleprojectwizard.h"
|
||||||
#include "target.h"
|
#include "target.h"
|
||||||
#include "taskfile.h"
|
#include "taskfile.h"
|
||||||
#include "taskhandlers.h"
|
|
||||||
#include "taskhub.h"
|
#include "taskhub.h"
|
||||||
#include "toolchainmanager.h"
|
#include "toolchainmanager.h"
|
||||||
#include "toolchainoptionspage.h"
|
#include "toolchainoptionspage.h"
|
||||||
@@ -823,8 +822,6 @@ Result<> ProjectExplorerPlugin::initialize(const QStringList &arguments)
|
|||||||
|
|
||||||
setupSanitizerOutputParser();
|
setupSanitizerOutputParser();
|
||||||
|
|
||||||
setupTaskHandlers();
|
|
||||||
|
|
||||||
setupJsonWizardPages();
|
setupJsonWizardPages();
|
||||||
setupJsonWizardFileGenerator();
|
setupJsonWizardFileGenerator();
|
||||||
setupJsonWizardScannerGenerator();
|
setupJsonWizardScannerGenerator();
|
||||||
|
@@ -15,9 +15,13 @@
|
|||||||
namespace ProjectExplorer {
|
namespace ProjectExplorer {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
ShowOutputTaskHandler::ShowOutputTaskHandler(Core::IOutputPane *window, const QString &text,
|
ShowOutputTaskHandler::ShowOutputTaskHandler(
|
||||||
const QString &tooltip, const QString &shortcut)
|
Core::IOutputPane *window, const QString &text, const QString &tooltip, const QString &shortcut)
|
||||||
: m_window(window), m_text(text), m_tooltip(tooltip), m_shortcut(shortcut)
|
: ITaskHandler(createAction(text, tooltip, shortcut))
|
||||||
|
, m_window(window)
|
||||||
|
, m_text(text)
|
||||||
|
, m_tooltip(tooltip)
|
||||||
|
, m_shortcut(shortcut)
|
||||||
{
|
{
|
||||||
QTC_CHECK(m_window);
|
QTC_CHECK(m_window);
|
||||||
QTC_CHECK(!m_text.isEmpty());
|
QTC_CHECK(!m_text.isEmpty());
|
||||||
@@ -44,13 +48,14 @@ void ShowOutputTaskHandler::handle(const Task &task)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QAction *ShowOutputTaskHandler::createAction(QObject *parent) const
|
QAction *ShowOutputTaskHandler::createAction(const QString &text, const QString &tooltip,
|
||||||
|
const QString &shortcut)
|
||||||
{
|
{
|
||||||
QAction * const outputAction = new QAction(m_text, parent);
|
QAction * const outputAction = new QAction(text);
|
||||||
if (!m_tooltip.isEmpty())
|
if (!tooltip.isEmpty())
|
||||||
outputAction->setToolTip(m_tooltip);
|
outputAction->setToolTip(tooltip);
|
||||||
if (!m_shortcut.isEmpty())
|
if (!shortcut.isEmpty())
|
||||||
outputAction->setShortcut(QKeySequence(m_shortcut));
|
outputAction->setShortcut(QKeySequence(shortcut));
|
||||||
outputAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
|
outputAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
|
||||||
return outputAction;
|
return outputAction;
|
||||||
}
|
}
|
||||||
|
@@ -18,11 +18,12 @@ public:
|
|||||||
explicit ShowOutputTaskHandler(Core::IOutputPane *window, const QString &text,
|
explicit ShowOutputTaskHandler(Core::IOutputPane *window, const QString &text,
|
||||||
const QString &tooltip, const QString &shortcut);
|
const QString &tooltip, const QString &shortcut);
|
||||||
|
|
||||||
|
private:
|
||||||
bool canHandle(const Task &) const override;
|
bool canHandle(const Task &) const override;
|
||||||
void handle(const Task &task) override;
|
void handle(const Task &task) override;
|
||||||
QAction *createAction(QObject *parent) const override;
|
static QAction *createAction(const QString &text, const QString &tooltip,
|
||||||
|
const QString &shortcut);
|
||||||
|
|
||||||
private:
|
|
||||||
Core::IOutputPane * const m_window;
|
Core::IOutputPane * const m_window;
|
||||||
const QString m_text;
|
const QString m_text;
|
||||||
const QString m_tooltip;
|
const QString m_tooltip;
|
||||||
|
@@ -226,11 +226,11 @@ void StopMonitoringHandler::handle(const ProjectExplorer::Task &task)
|
|||||||
TaskFile::stopMonitoring();
|
TaskFile::stopMonitoring();
|
||||||
}
|
}
|
||||||
|
|
||||||
QAction *StopMonitoringHandler::createAction(QObject *parent) const
|
QAction *StopMonitoringHandler::createAction() const
|
||||||
{
|
{
|
||||||
const QString text = Tr::tr("Stop Monitoring");
|
const QString text = Tr::tr("Stop Monitoring");
|
||||||
const QString toolTip = Tr::tr("Stop monitoring task files.");
|
const QString toolTip = Tr::tr("Stop monitoring task files.");
|
||||||
auto stopMonitoringAction = new QAction(text, parent);
|
auto stopMonitoringAction = new QAction(text);
|
||||||
stopMonitoringAction->setToolTip(toolTip);
|
stopMonitoringAction->setToolTip(toolTip);
|
||||||
return stopMonitoringAction;
|
return stopMonitoringAction;
|
||||||
}
|
}
|
||||||
|
@@ -13,9 +13,12 @@ namespace Internal {
|
|||||||
class StopMonitoringHandler : public ITaskHandler
|
class StopMonitoringHandler : public ITaskHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
StopMonitoringHandler() : ITaskHandler(createAction()) {}
|
||||||
|
|
||||||
|
private:
|
||||||
bool canHandle(const ProjectExplorer::Task &) const override;
|
bool canHandle(const ProjectExplorer::Task &) const override;
|
||||||
void handle(const ProjectExplorer::Task &) override;
|
void handle(const ProjectExplorer::Task &) override;
|
||||||
QAction *createAction(QObject *parent) const override;
|
QAction *createAction() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TaskFile : public Core::IDocument
|
class TaskFile : public Core::IDocument
|
||||||
|
@@ -7,29 +7,105 @@
|
|||||||
#include "projectexplorertr.h"
|
#include "projectexplorertr.h"
|
||||||
#include "taskhub.h"
|
#include "taskhub.h"
|
||||||
|
|
||||||
|
#include <coreplugin/actionmanager/actionmanager.h>
|
||||||
|
#include <coreplugin/actionmanager/command.h>
|
||||||
#include <coreplugin/coreconstants.h>
|
#include <coreplugin/coreconstants.h>
|
||||||
#include <coreplugin/customlanguagemodels.h>
|
#include <coreplugin/customlanguagemodels.h>
|
||||||
#include <coreplugin/editormanager/editormanager.h>
|
#include <coreplugin/editormanager/editormanager.h>
|
||||||
|
#include <coreplugin/icontext.h>
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
#include <coreplugin/iversioncontrol.h>
|
#include <coreplugin/iversioncontrol.h>
|
||||||
#include <coreplugin/messagemanager.h>
|
#include <coreplugin/messagemanager.h>
|
||||||
#include <coreplugin/vcsmanager.h>
|
#include <coreplugin/vcsmanager.h>
|
||||||
|
#include <utils/algorithm.h>
|
||||||
#include <utils/qtcprocess.h>
|
#include <utils/qtcprocess.h>
|
||||||
#include <utils/stringutils.h>
|
#include <utils/stringutils.h>
|
||||||
|
|
||||||
|
#include <QHash>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
using namespace Core;
|
using namespace Core;
|
||||||
using namespace Utils;
|
using namespace Utils;
|
||||||
|
|
||||||
namespace ProjectExplorer::Internal {
|
namespace ProjectExplorer {
|
||||||
|
namespace {
|
||||||
|
static QObject *g_actionParent = nullptr;
|
||||||
|
static Core::Context g_cmdContext;
|
||||||
|
static Internal::RegisterHandlerAction g_onCreateAction;
|
||||||
|
static Internal::GetHandlerTasks g_getTasks;
|
||||||
|
static QList<ITaskHandler *> g_toRegister;
|
||||||
|
static QList<ITaskHandler *> g_taskHandlers;
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
ITaskHandler::ITaskHandler(QAction *action, const Id &actionId, bool isMultiHandler)
|
||||||
|
: m_action(action), m_actionId(actionId), m_isMultiHandler(isMultiHandler)
|
||||||
|
{
|
||||||
|
if (g_actionParent)
|
||||||
|
registerHandler();
|
||||||
|
else
|
||||||
|
g_toRegister << this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ITaskHandler::~ITaskHandler()
|
||||||
|
{
|
||||||
|
g_toRegister.removeOne(this);
|
||||||
|
deregisterHandler();
|
||||||
|
delete m_action;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ITaskHandler::handle(const Task &task)
|
||||||
|
{
|
||||||
|
QTC_ASSERT(m_isMultiHandler, return);
|
||||||
|
handle(Tasks{task});
|
||||||
|
}
|
||||||
|
|
||||||
|
void ITaskHandler::handle(const Tasks &tasks)
|
||||||
|
{
|
||||||
|
QTC_ASSERT(canHandle(tasks), return);
|
||||||
|
QTC_ASSERT(!m_isMultiHandler, return);
|
||||||
|
handle(tasks.first());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ITaskHandler::canHandle(const Tasks &tasks) const
|
||||||
|
{
|
||||||
|
if (tasks.isEmpty())
|
||||||
|
return false;
|
||||||
|
if (m_isMultiHandler)
|
||||||
|
return true;
|
||||||
|
if (tasks.size() > 1)
|
||||||
|
return false;
|
||||||
|
return canHandle(tasks.first());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ITaskHandler::registerHandler()
|
||||||
|
{
|
||||||
|
g_taskHandlers.append(this);
|
||||||
|
|
||||||
|
m_action->setParent(g_actionParent);
|
||||||
|
QAction *action = m_action;
|
||||||
|
connect(m_action, &QAction::triggered, this, [this] { handle(g_getTasks()); });
|
||||||
|
if (m_actionId.isValid()) {
|
||||||
|
Core::Command *cmd =
|
||||||
|
Core::ActionManager::registerAction(m_action, m_actionId, g_cmdContext, true);
|
||||||
|
action = cmd->action();
|
||||||
|
}
|
||||||
|
g_onCreateAction(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ITaskHandler::deregisterHandler()
|
||||||
|
{
|
||||||
|
g_taskHandlers.removeOne(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Internal {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
class ConfigTaskHandler : public ITaskHandler
|
class ConfigTaskHandler : public ITaskHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ConfigTaskHandler(const Task &pattern, Id page)
|
ConfigTaskHandler(const Task &pattern, Id page)
|
||||||
: m_pattern(pattern)
|
: ITaskHandler(createAction())
|
||||||
|
, m_pattern(pattern)
|
||||||
, m_targetPage(page)
|
, m_targetPage(page)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@@ -45,9 +121,9 @@ private:
|
|||||||
ICore::showOptionsDialog(m_targetPage);
|
ICore::showOptionsDialog(m_targetPage);
|
||||||
}
|
}
|
||||||
|
|
||||||
QAction *createAction(QObject *parent) const override
|
QAction *createAction() const
|
||||||
{
|
{
|
||||||
auto action = new QAction(ICore::msgShowOptionsDialog(), parent);
|
auto action = new QAction(ICore::msgShowOptionsDialog());
|
||||||
action->setToolTip(ICore::msgShowOptionsDialogToolTip());
|
action->setToolTip(ICore::msgShowOptionsDialogToolTip());
|
||||||
return action;
|
return action;
|
||||||
}
|
}
|
||||||
@@ -60,7 +136,7 @@ private:
|
|||||||
class CopyTaskHandler : public ITaskHandler
|
class CopyTaskHandler : public ITaskHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CopyTaskHandler() : ITaskHandler(true) {}
|
CopyTaskHandler() : ITaskHandler(new Action, Core::Constants::COPY, true) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handle(const Tasks &tasks) override
|
void handle(const Tasks &tasks) override
|
||||||
@@ -85,15 +161,12 @@ private:
|
|||||||
}
|
}
|
||||||
setClipboardAndSelection(lines.join('\n'));
|
setClipboardAndSelection(lines.join('\n'));
|
||||||
}
|
}
|
||||||
|
|
||||||
Id actionManagerId() const override { return Id(Core::Constants::COPY); }
|
|
||||||
QAction *createAction(QObject *parent) const override { return new QAction(parent); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class RemoveTaskHandler : public ITaskHandler
|
class RemoveTaskHandler : public ITaskHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RemoveTaskHandler() : ITaskHandler(true) {}
|
RemoveTaskHandler() : ITaskHandler(createAction(), {}, true) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handle(const Tasks &tasks) override
|
void handle(const Tasks &tasks) override
|
||||||
@@ -102,10 +175,10 @@ private:
|
|||||||
TaskHub::removeTask(task);
|
TaskHub::removeTask(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
QAction *createAction(QObject *parent) const override
|
QAction *createAction() const
|
||||||
{
|
{
|
||||||
QAction *removeAction = new QAction(
|
QAction *removeAction = new QAction(
|
||||||
Tr::tr("Remove", "Name of the action triggering the removetaskhandler"), parent);
|
Tr::tr("Remove", "Name of the action triggering the removetaskhandler"));
|
||||||
removeAction->setToolTip(Tr::tr("Remove task from the task list."));
|
removeAction->setToolTip(Tr::tr("Remove task from the task list."));
|
||||||
removeAction->setShortcuts({QKeySequence::Delete, QKeySequence::Backspace});
|
removeAction->setShortcuts({QKeySequence::Delete, QKeySequence::Backspace});
|
||||||
removeAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
|
removeAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
|
||||||
@@ -115,6 +188,10 @@ private:
|
|||||||
|
|
||||||
class ShowInEditorTaskHandler : public ITaskHandler
|
class ShowInEditorTaskHandler : public ITaskHandler
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
ShowInEditorTaskHandler() : ITaskHandler(createAction()) {}
|
||||||
|
|
||||||
|
private:
|
||||||
bool isDefaultHandler() const override { return true; }
|
bool isDefaultHandler() const override { return true; }
|
||||||
|
|
||||||
bool canHandle(const Task &task) const override
|
bool canHandle(const Task &task) const override
|
||||||
@@ -132,9 +209,9 @@ class ShowInEditorTaskHandler : public ITaskHandler
|
|||||||
{task.file, task.movedLine, column}, {}, EditorManager::SwitchSplitIfAlreadyVisible);
|
{task.file, task.movedLine, column}, {}, EditorManager::SwitchSplitIfAlreadyVisible);
|
||||||
}
|
}
|
||||||
|
|
||||||
QAction *createAction(QObject *parent ) const override
|
QAction *createAction() const
|
||||||
{
|
{
|
||||||
QAction *showAction = new QAction(Tr::tr("Show in Editor"), parent);
|
QAction *showAction = new QAction(Tr::tr("Show in Editor"));
|
||||||
showAction->setToolTip(Tr::tr("Show task location in an editor."));
|
showAction->setToolTip(Tr::tr("Show task location in an editor."));
|
||||||
showAction->setShortcut(QKeySequence(Qt::Key_Return));
|
showAction->setShortcut(QKeySequence(Qt::Key_Return));
|
||||||
showAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
|
showAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
|
||||||
@@ -144,6 +221,10 @@ class ShowInEditorTaskHandler : public ITaskHandler
|
|||||||
|
|
||||||
class VcsAnnotateTaskHandler : public ITaskHandler
|
class VcsAnnotateTaskHandler : public ITaskHandler
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
VcsAnnotateTaskHandler() : ITaskHandler(createAction()) {}
|
||||||
|
|
||||||
|
private:
|
||||||
bool canHandle(const Task &task) const override
|
bool canHandle(const Task &task) const override
|
||||||
{
|
{
|
||||||
QFileInfo fi(task.file.toFileInfo());
|
QFileInfo fi(task.file.toFileInfo());
|
||||||
@@ -163,18 +244,21 @@ class VcsAnnotateTaskHandler : public ITaskHandler
|
|||||||
vc->vcsAnnotate(task.file.absoluteFilePath(), task.movedLine);
|
vc->vcsAnnotate(task.file.absoluteFilePath(), task.movedLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
QAction *createAction(QObject *parent) const override
|
QAction *createAction() const
|
||||||
{
|
{
|
||||||
QAction *vcsannotateAction = new QAction(Tr::tr("&Annotate"), parent);
|
QAction *vcsannotateAction = new QAction(Tr::tr("&Annotate"));
|
||||||
vcsannotateAction->setToolTip(Tr::tr("Annotate using version control system."));
|
vcsannotateAction->setToolTip(Tr::tr("Annotate using version control system."));
|
||||||
return vcsannotateAction;
|
return vcsannotateAction;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// FIXME: There should be one handler per LLM, but the ITaskHandler infrastructure is
|
// FIXME: There should be one handler per LLM
|
||||||
// currently static. Alternatively, we could somehow multiplex from here, perhaps via a submenu.
|
|
||||||
class ExplainWithAiHandler : public ITaskHandler
|
class ExplainWithAiHandler : public ITaskHandler
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
ExplainWithAiHandler() : ITaskHandler(createAction()) {}
|
||||||
|
|
||||||
|
private:
|
||||||
bool canHandle(const Task &task) const override
|
bool canHandle(const Task &task) const override
|
||||||
{
|
{
|
||||||
Q_UNUSED(task)
|
Q_UNUSED(task)
|
||||||
@@ -229,9 +313,9 @@ class ExplainWithAiHandler : public ITaskHandler
|
|||||||
process->start();
|
process->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
QAction *createAction(QObject *parent) const override
|
QAction *createAction() const
|
||||||
{
|
{
|
||||||
const auto action = new QAction(Tr::tr("Get help from AI"), parent);
|
const auto action = new QAction(Tr::tr("Get help from AI"));
|
||||||
action->setToolTip(Tr::tr("Ask an AI to help with this issue."));
|
action->setToolTip(Tr::tr("Ask an AI to help with this issue."));
|
||||||
return action;
|
return action;
|
||||||
}
|
}
|
||||||
@@ -239,8 +323,17 @@ class ExplainWithAiHandler : public ITaskHandler
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void setupTaskHandlers()
|
void setupTaskHandlers(
|
||||||
|
QObject *actionParent,
|
||||||
|
const Core::Context &cmdContext,
|
||||||
|
const RegisterHandlerAction &onCreateAction,
|
||||||
|
const GetHandlerTasks &getTasks)
|
||||||
{
|
{
|
||||||
|
g_actionParent = actionParent;
|
||||||
|
g_cmdContext = cmdContext;
|
||||||
|
g_onCreateAction = onCreateAction;
|
||||||
|
g_getTasks = getTasks;
|
||||||
|
|
||||||
static const ConfigTaskHandler
|
static const ConfigTaskHandler
|
||||||
configTaskHandler(Task::compilerMissingTask(), Constants::KITS_SETTINGS_PAGE_ID);
|
configTaskHandler(Task::compilerMissingTask(), Constants::KITS_SETTINGS_PAGE_ID);
|
||||||
static const CopyTaskHandler copyTaskHandler;
|
static const CopyTaskHandler copyTaskHandler;
|
||||||
@@ -248,6 +341,35 @@ void setupTaskHandlers()
|
|||||||
static const ShowInEditorTaskHandler showInEditorTaskHandler;
|
static const ShowInEditorTaskHandler showInEditorTaskHandler;
|
||||||
static const VcsAnnotateTaskHandler vcsAnnotateTaskHandler;
|
static const VcsAnnotateTaskHandler vcsAnnotateTaskHandler;
|
||||||
static const ExplainWithAiHandler explainWithAiHandler;
|
static const ExplainWithAiHandler explainWithAiHandler;
|
||||||
|
|
||||||
|
registerQueuedTaskHandlers();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ProjectExplorer::Internal
|
ITaskHandler *taskHandlerForAction(QAction *action)
|
||||||
|
{
|
||||||
|
return Utils::findOrDefault(g_taskHandlers,
|
||||||
|
[action](ITaskHandler *h) { return h->action() == action; });
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateTaskHandlerActionsState()
|
||||||
|
{
|
||||||
|
const Tasks tasks = g_getTasks();
|
||||||
|
for (ITaskHandler * const h : g_taskHandlers)
|
||||||
|
h->action()->setEnabled(h->canHandle(tasks));
|
||||||
|
}
|
||||||
|
|
||||||
|
ITaskHandler *defaultTaskHandler()
|
||||||
|
{
|
||||||
|
return Utils::findOrDefault(g_taskHandlers,
|
||||||
|
[](ITaskHandler *h) { return h->isDefaultHandler(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
void registerQueuedTaskHandlers()
|
||||||
|
{
|
||||||
|
for (ITaskHandler * const h : std::as_const(g_toRegister))
|
||||||
|
h->registerHandler();
|
||||||
|
g_toRegister.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace ProjectExplorer
|
||||||
|
@@ -9,33 +9,58 @@
|
|||||||
#include <utils/id.h>
|
#include <utils/id.h>
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QPointer>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QAction;
|
class QAction;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
namespace Core { class Context; }
|
||||||
|
|
||||||
namespace ProjectExplorer {
|
namespace ProjectExplorer {
|
||||||
|
namespace Internal { void registerQueuedTaskHandlers(); }
|
||||||
|
|
||||||
class PROJECTEXPLORER_EXPORT ITaskHandler : public QObject
|
class PROJECTEXPLORER_EXPORT ITaskHandler : public QObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit ITaskHandler(bool isMultiHandler = false);
|
explicit ITaskHandler(QAction *action, const Utils::Id &actionId = {},
|
||||||
|
bool isMultiHandler = false);
|
||||||
~ITaskHandler() override;
|
~ITaskHandler() override;
|
||||||
|
|
||||||
virtual bool isDefaultHandler() const { return false; }
|
virtual bool isDefaultHandler() const { return false; }
|
||||||
virtual bool canHandle(const Task &) const { return m_isMultiHandler; }
|
virtual bool canHandle(const Task &) const { return m_isMultiHandler; }
|
||||||
virtual void handle(const Task &); // Non-multi-handlers should implement this.
|
virtual void handle(const Task &task); // Non-multi-handlers should implement this.
|
||||||
virtual void handle(const Tasks &tasks); // Multi-handlers should implement this.
|
virtual void handle(const Tasks &tasks); // Multi-handlers should implement this.
|
||||||
virtual Utils::Id actionManagerId() const { return Utils::Id(); }
|
|
||||||
virtual QAction *createAction(QObject *parent) const = 0;
|
|
||||||
|
|
||||||
bool canHandle(const Tasks &tasks) const;
|
bool canHandle(const Tasks &tasks) const;
|
||||||
|
QAction *action() const { return m_action; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
friend void Internal::registerQueuedTaskHandlers();
|
||||||
|
|
||||||
|
void registerHandler();
|
||||||
|
void deregisterHandler();
|
||||||
|
|
||||||
|
const QPointer<QAction> m_action;
|
||||||
|
const Utils::Id m_actionId;
|
||||||
const bool m_isMultiHandler;
|
const bool m_isMultiHandler;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace Internal { void setupTaskHandlers(); }
|
namespace Internal {
|
||||||
|
using RegisterHandlerAction = std::function<void(QAction *)>;
|
||||||
|
using GetHandlerTasks = std::function<Tasks()>;
|
||||||
|
void setupTaskHandlers(
|
||||||
|
QObject *actionParent,
|
||||||
|
const Core::Context &cmdContext,
|
||||||
|
const RegisterHandlerAction &onCreateAction,
|
||||||
|
const GetHandlerTasks &getTasks);
|
||||||
|
|
||||||
|
ITaskHandler *taskHandlerForAction(QAction *action);
|
||||||
|
ITaskHandler *defaultTaskHandler();
|
||||||
|
void updateTaskHandlerActionsState();
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
} // namespace ProjectExplorer
|
} // namespace ProjectExplorer
|
||||||
|
@@ -11,8 +11,8 @@
|
|||||||
#include "taskhub.h"
|
#include "taskhub.h"
|
||||||
#include "taskmodel.h"
|
#include "taskmodel.h"
|
||||||
|
|
||||||
#include <coreplugin/actionmanager/actionmanager.h>
|
|
||||||
#include <coreplugin/actionmanager/command.h>
|
#include <coreplugin/actionmanager/command.h>
|
||||||
|
#include <coreplugin/coreconstants.h>
|
||||||
#include <coreplugin/editormanager/editormanager.h>
|
#include <coreplugin/editormanager/editormanager.h>
|
||||||
#include <coreplugin/find/itemviewfind.h>
|
#include <coreplugin/find/itemviewfind.h>
|
||||||
#include <coreplugin/icontext.h>
|
#include <coreplugin/icontext.h>
|
||||||
@@ -49,42 +49,6 @@ const char SESSION_FILTER_WARNINGS[] = "TaskWindow.IncludeWarnings";
|
|||||||
|
|
||||||
namespace ProjectExplorer {
|
namespace ProjectExplorer {
|
||||||
|
|
||||||
static QList<ITaskHandler *> g_taskHandlers;
|
|
||||||
|
|
||||||
ITaskHandler::ITaskHandler(bool isMultiHandler) : m_isMultiHandler(isMultiHandler)
|
|
||||||
{
|
|
||||||
g_taskHandlers.append(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
ITaskHandler::~ITaskHandler()
|
|
||||||
{
|
|
||||||
g_taskHandlers.removeOne(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ITaskHandler::handle(const Task &task)
|
|
||||||
{
|
|
||||||
QTC_ASSERT(m_isMultiHandler, return);
|
|
||||||
handle(Tasks{task});
|
|
||||||
}
|
|
||||||
|
|
||||||
void ITaskHandler::handle(const Tasks &tasks)
|
|
||||||
{
|
|
||||||
QTC_ASSERT(canHandle(tasks), return);
|
|
||||||
QTC_ASSERT(!m_isMultiHandler, return);
|
|
||||||
handle(tasks.first());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ITaskHandler::canHandle(const Tasks &tasks) const
|
|
||||||
{
|
|
||||||
if (tasks.isEmpty())
|
|
||||||
return false;
|
|
||||||
if (m_isMultiHandler)
|
|
||||||
return true;
|
|
||||||
if (tasks.size() > 1)
|
|
||||||
return false;
|
|
||||||
return canHandle(tasks.first());
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
class TaskView : public TreeView
|
class TaskView : public TreeView
|
||||||
@@ -131,18 +95,10 @@ private:
|
|||||||
class TaskWindowPrivate
|
class TaskWindowPrivate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ITaskHandler *handler(QAction *action)
|
|
||||||
{
|
|
||||||
ITaskHandler *handler = m_actionToHandlerMap.value(action, nullptr);
|
|
||||||
return g_taskHandlers.contains(handler) ? handler : nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
Internal::TaskModel *m_model;
|
Internal::TaskModel *m_model;
|
||||||
Internal::TaskFilterModel *m_filter;
|
Internal::TaskFilterModel *m_filter;
|
||||||
TaskView m_treeView;
|
TaskView m_treeView;
|
||||||
const Core::Context m_taskWindowContext{Core::Context(Core::Constants::C_PROBLEM_PANE)};
|
const Core::Context m_taskWindowContext{Core::Context(Core::Constants::C_PROBLEM_PANE)};
|
||||||
QHash<QAction *, ITaskHandler *> m_actionToHandlerMap;
|
|
||||||
ITaskHandler *m_defaultHandler = nullptr;
|
|
||||||
QToolButton *m_filterWarningsButton;
|
QToolButton *m_filterWarningsButton;
|
||||||
QToolButton *m_categoriesButton;
|
QToolButton *m_categoriesButton;
|
||||||
QToolButton *m_externalButton = nullptr;
|
QToolButton *m_externalButton = nullptr;
|
||||||
@@ -195,14 +151,7 @@ TaskWindow::TaskWindow() : d(std::make_unique<TaskWindowPrivate>())
|
|||||||
connect(&d->m_treeView, &QAbstractItemView::activated,
|
connect(&d->m_treeView, &QAbstractItemView::activated,
|
||||||
this, &TaskWindow::triggerDefaultHandler);
|
this, &TaskWindow::triggerDefaultHandler);
|
||||||
connect(d->m_treeView.selectionModel(), &QItemSelectionModel::selectionChanged,
|
connect(d->m_treeView.selectionModel(), &QItemSelectionModel::selectionChanged,
|
||||||
this, [this] {
|
this, [] { updateTaskHandlerActionsState(); });
|
||||||
const Tasks tasks = d->m_filter->tasks(d->m_treeView.selectionModel()->selectedIndexes());
|
|
||||||
for (auto it = d->m_actionToHandlerMap.cbegin(); it != d->m_actionToHandlerMap.cend(); ++it) {
|
|
||||||
ITaskHandler * const h = it.value();
|
|
||||||
QTC_ASSERT(g_taskHandlers.contains(h), continue);
|
|
||||||
it.key()->setEnabled(h && h->canHandle(tasks));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
d->m_treeView.setContextMenuPolicy(Qt::ActionsContextMenu);
|
d->m_treeView.setContextMenuPolicy(Qt::ActionsContextMenu);
|
||||||
|
|
||||||
@@ -278,28 +227,15 @@ void TaskWindow::delayedInitialization()
|
|||||||
|
|
||||||
alreadyDone = true;
|
alreadyDone = true;
|
||||||
|
|
||||||
for (ITaskHandler *h : std::as_const(g_taskHandlers)) {
|
const auto registerTaskHandlerAction = [this](QAction *action) {
|
||||||
if (h->isDefaultHandler() && !d->m_defaultHandler)
|
action->setParent(this);
|
||||||
d->m_defaultHandler = h;
|
|
||||||
|
|
||||||
QAction *action = h->createAction(this);
|
|
||||||
action->setEnabled(false);
|
action->setEnabled(false);
|
||||||
QTC_ASSERT(action, continue);
|
|
||||||
d->m_actionToHandlerMap.insert(action, h);
|
|
||||||
connect(action, &QAction::triggered, this, [this, action] {
|
|
||||||
ITaskHandler *h = d->handler(action);
|
|
||||||
if (h)
|
|
||||||
h->handle(d->m_filter->tasks(d->m_treeView.selectionModel()->selectedIndexes()));
|
|
||||||
});
|
|
||||||
|
|
||||||
Id id = h->actionManagerId();
|
|
||||||
if (id.isValid()) {
|
|
||||||
Core::Command *cmd =
|
|
||||||
Core::ActionManager::registerAction(action, id, d->m_taskWindowContext, true);
|
|
||||||
action = cmd->action();
|
|
||||||
}
|
|
||||||
d->m_treeView.addAction(action);
|
d->m_treeView.addAction(action);
|
||||||
}
|
};
|
||||||
|
const auto getTasksForHandler = [this] {
|
||||||
|
return d->m_filter->tasks(d->m_treeView.selectionModel()->selectedIndexes());
|
||||||
|
};
|
||||||
|
setupTaskHandlers(this, d->m_taskWindowContext, registerTaskHandlerAction, getTasksForHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QWidget*> TaskWindow::toolBarWidgets() const
|
QList<QWidget*> TaskWindow::toolBarWidgets() const
|
||||||
@@ -429,7 +365,8 @@ void TaskWindow::openTask(const Task &task)
|
|||||||
|
|
||||||
void TaskWindow::triggerDefaultHandler(const QModelIndex &index)
|
void TaskWindow::triggerDefaultHandler(const QModelIndex &index)
|
||||||
{
|
{
|
||||||
if (!index.isValid() || !d->m_defaultHandler)
|
ITaskHandler * const defaultHandler = defaultTaskHandler();
|
||||||
|
if (!index.isValid() || !defaultHandler)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QModelIndex taskIndex = index;
|
QModelIndex taskIndex = index;
|
||||||
@@ -450,8 +387,8 @@ void TaskWindow::triggerDefaultHandler(const QModelIndex &index)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d->m_defaultHandler->canHandle(task)) {
|
if (defaultHandler->canHandle(task)) {
|
||||||
d->m_defaultHandler->handle(task);
|
defaultHandler->handle(task);
|
||||||
} else {
|
} else {
|
||||||
if (!task.file.exists())
|
if (!task.file.exists())
|
||||||
d->m_model->setFileNotFound(taskIndex, true);
|
d->m_model->setFileNotFound(taskIndex, true);
|
||||||
|
Reference in New Issue
Block a user