Taskwindow: Allow for Keyboard shortcuts in actions

Allow to trigger TaskHandler actions by keyboard shortcut. Simplify
the code while doing so.

As a side effect the default handler is now listed in the context menu,
which makes it more discoverable.

Change-Id: I41183e5a5ef77be57360f29f289e327cadfaa7d1
Reviewed-by: Daniel Teske <daniel.teske@digia.com>
Reviewed-by: Eike Ziller <eike.ziller@digia.com>
This commit is contained in:
Tobias Hunger
2012-10-05 14:35:34 +02:00
committed by Eike Ziller
parent a28f48366c
commit 432de3a198
3 changed files with 69 additions and 71 deletions

View File

@@ -32,6 +32,8 @@
#include "projectexplorer_export.h" #include "projectexplorer_export.h"
#include <coreplugin/id.h>
#include <QObject> #include <QObject>
#include <QString> #include <QString>
@@ -52,6 +54,7 @@ public:
virtual bool isDefaultHandler() const { return false; } virtual bool isDefaultHandler() const { return false; }
virtual bool canHandle(const Task &) const = 0; virtual bool canHandle(const Task &) const = 0;
virtual void handle(const Task &) = 0; virtual void handle(const Task &) = 0;
virtual Core::Id actionManagerId() const { return Core::Id(); }
virtual QAction *createAction(QObject *parent) const = 0; virtual QAction *createAction(QObject *parent) const = 0;
}; };

View File

@@ -68,7 +68,6 @@ public:
TaskView(QWidget *parent = 0); TaskView(QWidget *parent = 0);
~TaskView(); ~TaskView();
void resizeEvent(QResizeEvent *e); void resizeEvent(QResizeEvent *e);
void keyPressEvent(QKeyEvent *e);
}; };
class TaskWindowContext : public Core::IContext class TaskWindowContext : public Core::IContext
@@ -189,16 +188,6 @@ void TaskView::resizeEvent(QResizeEvent *e)
static_cast<TaskDelegate *>(itemDelegate())->emitSizeHintChanged(selectionModel()->currentIndex()); static_cast<TaskDelegate *>(itemDelegate())->emitSizeHintChanged(selectionModel()->currentIndex());
} }
void TaskView::keyPressEvent(QKeyEvent *e)
{
if (!e->modifiers() && e->key() == Qt::Key_Return) {
emit activated(currentIndex());
e->accept();
return;
}
QListView::keyPressEvent(e);
}
///// /////
// TaskWindow // TaskWindow
///// /////
@@ -211,13 +200,13 @@ public:
Internal::TaskView *m_listview; Internal::TaskView *m_listview;
Internal::TaskWindowContext *m_taskWindowContext; Internal::TaskWindowContext *m_taskWindowContext;
QMenu *m_contextMenu; QMenu *m_contextMenu;
QModelIndex m_contextMenuIndex;
ITaskHandler *m_defaultHandler; ITaskHandler *m_defaultHandler;
QToolButton *m_filterWarningsButton; QToolButton *m_filterWarningsButton;
QToolButton *m_categoriesButton; QToolButton *m_categoriesButton;
QMenu *m_categoriesMenu; QMenu *m_categoriesMenu;
TaskHub *m_taskHub; TaskHub *m_taskHub;
int m_badgeCount; int m_badgeCount;
QList<QAction *> m_actions;
}; };
static QToolButton *createFilterButton(QIcon icon, const QString &toolTip, static QToolButton *createFilterButton(QIcon icon, const QString &toolTip,
@@ -261,17 +250,14 @@ TaskWindow::TaskWindow(TaskHub *taskhub) : d(new TaskWindowPrivate)
connect(d->m_listview->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), connect(d->m_listview->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
tld, SLOT(currentChanged(QModelIndex,QModelIndex))); tld, SLOT(currentChanged(QModelIndex,QModelIndex)));
connect(d->m_listview->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
this, SLOT(currentChanged(QModelIndex)));
connect(d->m_listview, SIGNAL(activated(QModelIndex)), connect(d->m_listview, SIGNAL(activated(QModelIndex)),
this, SLOT(triggerDefaultHandler(QModelIndex))); this, SLOT(triggerDefaultHandler(QModelIndex)));
d->m_contextMenu = new QMenu(d->m_listview); d->m_contextMenu = new QMenu(d->m_listview);
connect(d->m_contextMenu, SIGNAL(triggered(QAction*)),
this, SLOT(contextMenuEntryTriggered(QAction*)));
d->m_listview->setContextMenuPolicy(Qt::CustomContextMenu); d->m_listview->setContextMenuPolicy(Qt::ActionsContextMenu);
connect(d->m_listview, SIGNAL(customContextMenuRequested(QPoint)),
this, SLOT(showContextMenu(QPoint)));
d->m_filterWarningsButton = createFilterButton(d->m_model->taskTypeIcon(Task::Warning), d->m_filterWarningsButton = createFilterButton(d->m_model->taskTypeIcon(Task::Warning),
tr("Show Warnings"), tr("Show Warnings"),
@@ -315,7 +301,6 @@ TaskWindow::TaskWindow(TaskHub *taskhub) : d(new TaskWindowPrivate)
TaskWindow::~TaskWindow() TaskWindow::~TaskWindow()
{ {
Core::ICore::removeContextObject(d->m_taskWindowContext); Core::ICore::removeContextObject(d->m_taskWindowContext);
cleanContextMenu();
delete d->m_filterWarningsButton; delete d->m_filterWarningsButton;
delete d->m_listview; delete d->m_listview;
delete d->m_filter; delete d->m_filter;
@@ -323,6 +308,43 @@ TaskWindow::~TaskWindow()
delete d; delete d;
} }
static ITaskHandler *handler(QAction *action)
{
return qobject_cast<ITaskHandler *>(action->data().value<QObject *>());
}
void TaskWindow::delayedInitialization()
{
static bool alreadyDone = false;
if (alreadyDone)
return;
alreadyDone = true;
QList<ITaskHandler *> handlers = ExtensionSystem::PluginManager::getObjects<ITaskHandler>();
foreach (ITaskHandler *h, handlers) {
if (h->isDefaultHandler() && !d->m_defaultHandler)
d->m_defaultHandler = h;
QAction *action = h->createAction(this);
QTC_ASSERT(action, continue);
action->setData(qVariantFromValue(qobject_cast<QObject*>(h)));
connect(action, SIGNAL(triggered()), this, SLOT(actionTriggered()));
d->m_actions << action;
Core::Id id = h->actionManagerId();
if (id.isValid()) {
Core::Command *cmd = Core::ActionManager::instance()
->registerAction(action, id, d->m_taskWindowContext->context(), true);
action = cmd->action();
}
d->m_listview->addAction(action);
}
// Disable everything for now:
currentChanged(QModelIndex());
}
QList<QWidget*> TaskWindow::toolBarWidgets() const QList<QWidget*> TaskWindow::toolBarWidgets() const
{ {
return QList<QWidget*>() << d->m_filterWarningsButton << d->m_categoriesButton; return QList<QWidget*>() << d->m_filterWarningsButton << d->m_categoriesButton;
@@ -382,8 +404,19 @@ void TaskWindow::setCategoryVisibility(const Core::Id &categoryId, bool visible)
setBadgeNumber(d->m_badgeCount); setBadgeNumber(d->m_badgeCount);
} }
void TaskWindow::visibilityChanged(bool /* b */) void TaskWindow::currentChanged(const QModelIndex &index)
{ {
const Task task = index.isValid() ? d->m_filter->task(index) : Task();
foreach (QAction *action, d->m_actions) {
ITaskHandler *h = handler(action);
action->setEnabled((task.isNull() || !h) ? false : h->canHandle(task));
}
}
void TaskWindow::visibilityChanged(bool visible)
{
if (visible)
delayedInitialization();
} }
void TaskWindow::addCategory(const Core::Id &categoryId, const QString &displayName, bool visible) void TaskWindow::addCategory(const Core::Id &categoryId, const QString &displayName, bool visible)
@@ -470,20 +503,9 @@ void TaskWindow::openTask(unsigned int id)
void TaskWindow::triggerDefaultHandler(const QModelIndex &index) void TaskWindow::triggerDefaultHandler(const QModelIndex &index)
{ {
if (!index.isValid()) if (!index.isValid() || !d->m_defaultHandler)
return; return;
// Find a default handler to use:
if (!d->m_defaultHandler) {
QList<ITaskHandler *> handlers = ExtensionSystem::PluginManager::getObjects<ITaskHandler>();
foreach(ITaskHandler *handler, handlers) {
if (handler->isDefaultHandler()) {
d->m_defaultHandler = handler;
break;
}
}
}
Q_ASSERT(d->m_defaultHandler);
Task task(d->m_filter->task(index)); Task task(d->m_filter->task(index));
if (task.isNull()) if (task.isNull())
return; return;
@@ -496,49 +518,21 @@ void TaskWindow::triggerDefaultHandler(const QModelIndex &index)
} }
} }
void TaskWindow::showContextMenu(const QPoint &position) void TaskWindow::actionTriggered()
{ {
QModelIndex index = d->m_listview->indexAt(position); QAction *action = qobject_cast<QAction *>(sender());
if (!index.isValid()) if (!action || !action->isEnabled())
return;
ITaskHandler *h = handler(action);
if (!h)
return; return;
d->m_contextMenuIndex = index;
cleanContextMenu();
QModelIndex index = d->m_listview->selectionModel()->currentIndex();
Task task = d->m_filter->task(index); Task task = d->m_filter->task(index);
if (task.isNull()) if (task.isNull())
return; return;
QList<ITaskHandler *> handlers = ExtensionSystem::PluginManager::getObjects<ITaskHandler>(); h->handle(task);
foreach(ITaskHandler *handler, handlers) {
if (handler == d->m_defaultHandler)
continue;
QAction * action = handler->createAction(d->m_contextMenu);
action->setEnabled(handler->canHandle(task));
action->setData(qVariantFromValue(qobject_cast<QObject*>(handler)));
d->m_contextMenu->addAction(action);
}
d->m_contextMenu->popup(d->m_listview->mapToGlobal(position));
}
void TaskWindow::contextMenuEntryTriggered(QAction *action)
{
if (action->isEnabled()) {
Task task = d->m_filter->task(d->m_contextMenuIndex);
if (task.isNull())
return;
ITaskHandler *handler = qobject_cast<ITaskHandler*>(action->data().value<QObject*>());
if (!handler)
return;
handler->handle(task);
}
}
void TaskWindow::cleanContextMenu()
{
QList<QAction *> actions = d->m_contextMenu->actions();
qDeleteAll(actions);
d->m_contextMenu->clear();
} }
void TaskWindow::setShowWarnings(bool show) void TaskWindow::setShowWarnings(bool show)

View File

@@ -55,6 +55,8 @@ public:
TaskWindow(ProjectExplorer::TaskHub *taskHub); TaskWindow(ProjectExplorer::TaskHub *taskHub);
virtual ~TaskWindow(); virtual ~TaskWindow();
void delayedInitialization();
int taskCount(const Core::Id &category = Core::Id()) const; int taskCount(const Core::Id &category = Core::Id()) const;
int warningTaskCount(const Core::Id &category = Core::Id()) const; int warningTaskCount(const Core::Id &category = Core::Id()) const;
int errorTaskCount(const Core::Id &category = Core::Id()) const; int errorTaskCount(const Core::Id &category = Core::Id()) const;
@@ -92,16 +94,15 @@ private slots:
void openTask(unsigned int id); void openTask(unsigned int id);
void clearTasks(const Core::Id &categoryId); void clearTasks(const Core::Id &categoryId);
void setCategoryVisibility(const Core::Id &categoryId, bool visible); void setCategoryVisibility(const Core::Id &categoryId, bool visible);
void currentChanged(const QModelIndex &index);
void triggerDefaultHandler(const QModelIndex &index); void triggerDefaultHandler(const QModelIndex &index);
void showContextMenu(const QPoint &position); void actionTriggered();
void contextMenuEntryTriggered(QAction *);
void setShowWarnings(bool); void setShowWarnings(bool);
void updateCategoriesMenu(); void updateCategoriesMenu();
void filterCategoryTriggered(QAction *action); void filterCategoryTriggered(QAction *action);
private: private:
void cleanContextMenu();
int sizeHintForColumn(int column) const; int sizeHintForColumn(int column) const;
TaskWindowPrivate *d; TaskWindowPrivate *d;