Commit 384437e9 authored by Eike Ziller's avatar Eike Ziller

Refactor CommandMappings to be a widget instead of options page

The IOptionsPage parts in it were trivial, and we need more flexibility
for the shortcut settings options pages.

Change-Id: I93ddaf060ac88ef339da9f542719f2d695660ac0
Reviewed-by: default avatarhjk <hjk@theqtcompany.com>
parent 2b66e48b
......@@ -58,15 +58,9 @@ class CommandMappingsPrivate
{
public:
CommandMappingsPrivate(CommandMappings *parent)
: q(parent), m_widget(0)
{}
void setupWidget()
: q(parent)
{
QTC_CHECK(m_widget == 0);
m_widget = new QWidget;
groupBox = new QGroupBox(m_widget);
groupBox = new QGroupBox(parent);
groupBox->setTitle(CommandMappings::tr("Command Mappings"));
filterEdit = new FancyLineEdit(groupBox);
......@@ -89,12 +83,12 @@ public:
importButton = new QPushButton(CommandMappings::tr("Import..."), groupBox);
exportButton = new QPushButton(CommandMappings::tr("Export..."), groupBox);
targetEditGroup = new QGroupBox(CommandMappings::tr("Target Identifier"), m_widget);
targetEditGroup = new QGroupBox(CommandMappings::tr("Target Identifier"), parent);
targetEditGroup->setEnabled(false);
targetEdit = new FancyLineEdit(targetEditGroup);
targetEdit->setAutoHideButton(FancyLineEdit::Right, true);
targetEdit->setPlaceholderText(QString());
targetEdit->installEventFilter(q);
targetEdit->setFiltering(true);
targetEdit->setValidationFunction([this](FancyLineEdit *, QString *) {
return !q->hasConflicts();
......@@ -121,8 +115,10 @@ public:
vboxLayout1->addWidget(commandList);
vboxLayout1->addLayout(hboxLayout1);
targetLabel = new QLabel(CommandMappings::tr("Target:"));
QHBoxLayout *hboxLayout2 = new QHBoxLayout();
hboxLayout2->addWidget(new QLabel(CommandMappings::tr("Target:"), targetEditGroup));
hboxLayout2->addWidget(targetLabel);
hboxLayout2->addWidget(targetEdit);
hboxLayout2->addWidget(resetButton);
......@@ -130,39 +126,34 @@ public:
vboxLayout2->addLayout(hboxLayout2);
vboxLayout2->addWidget(infoLabel);
QVBoxLayout *vboxLayout = new QVBoxLayout(m_widget);
QVBoxLayout *vboxLayout = new QVBoxLayout(parent);
vboxLayout->addWidget(groupBox);
vboxLayout->addWidget(targetEditGroup);
q->connect(targetEdit, SIGNAL(buttonClicked(Utils::FancyLineEdit::Side)),
SLOT(removeTargetIdentifier()));
q->connect(resetButton, SIGNAL(clicked()),
SLOT(resetTargetIdentifier()));
q->connect(exportButton, SIGNAL(clicked()),
SLOT(exportAction()));
q->connect(importButton, SIGNAL(clicked()),
SLOT(importAction()));
q->connect(defaultButton, SIGNAL(clicked()),
SLOT(defaultAction()));
q->initialize();
q->connect(targetEdit, &FancyLineEdit::buttonClicked,
q, &CommandMappings::removeTargetIdentifier);
q->connect(resetButton, &QPushButton::clicked,
q, &CommandMappings::resetTargetIdentifier);
q->connect(exportButton, &QPushButton::clicked,
q, &CommandMappings::exportAction);
q->connect(importButton, &QPushButton::clicked,
q, &CommandMappings::importAction);
q->connect(defaultButton, &QPushButton::clicked,
q, &CommandMappings::defaultAction);
commandList->sortByColumn(0, Qt::AscendingOrder);
q->connect(filterEdit, SIGNAL(textChanged(QString)),
SLOT(filterChanged(QString)));
q->connect(commandList, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
SLOT(commandChanged(QTreeWidgetItem*)));
q->connect(targetEdit, SIGNAL(textChanged(QString)),
SLOT(targetIdentifierChanged()));
q->connect(filterEdit, &FancyLineEdit::textChanged,
q, &CommandMappings::filterChanged);
q->connect(commandList, &QTreeWidget::currentItemChanged,
q, &CommandMappings::commandChanged);
q->connect(targetEdit, &FancyLineEdit::textChanged,
q, &CommandMappings::targetIdentifierChanged);
new HeaderViewStretcher(commandList->header(), 1);
q->commandChanged(0);
}
CommandMappings *q;
QPointer<QWidget> m_widget;
QGroupBox *groupBox;
FancyLineEdit *filterEdit;
......@@ -171,14 +162,15 @@ public:
QPushButton *importButton;
QPushButton *exportButton;
QGroupBox *targetEditGroup;
QLabel *targetLabel;
FancyLineEdit *targetEdit;
QPushButton *resetButton;
};
} // namespace Internal
CommandMappings::CommandMappings(QObject *parent)
: IOptionsPage(parent), d(new Internal::CommandMappingsPrivate(this))
CommandMappings::CommandMappings(QWidget *parent)
: QWidget(parent), d(new Internal::CommandMappingsPrivate(this))
{
}
......@@ -187,13 +179,6 @@ CommandMappings::~CommandMappings()
delete d;
}
QWidget *CommandMappings::widget()
{
if (!d->m_widget)
d->setupWidget();
return d->m_widget;
}
void CommandMappings::setImportExportEnabled(bool enabled)
{
d->importButton->setVisible(enabled);
......@@ -217,7 +202,7 @@ void CommandMappings::setPageTitle(const QString &s)
void CommandMappings::setTargetLabelText(const QString &s)
{
d->targetEdit->setText(s);
d->targetLabel->setText(s);
}
void CommandMappings::setTargetEditTitle(const QString &s)
......@@ -230,11 +215,6 @@ void CommandMappings::setTargetHeader(const QString &s)
d->commandList->setHeaderLabels(QStringList() << tr("Command") << tr("Label") << s);
}
void CommandMappings::finish()
{
delete d->m_widget;
}
void CommandMappings::commandChanged(QTreeWidgetItem *current)
{
if (!current || !current->data(0, Qt::UserRole).isValid()) {
......
......@@ -31,7 +31,9 @@
#ifndef COMMANDMAPPINGS_H
#define COMMANDMAPPINGS_H
#include <coreplugin/dialogs/ioptionspage.h>
#include <coreplugin/core_global.h>
#include <QWidget>
QT_BEGIN_NAMESPACE
class QLineEdit;
......@@ -45,31 +47,32 @@ namespace Core {
namespace Internal { class CommandMappingsPrivate; }
class CORE_EXPORT CommandMappings : public IOptionsPage
class CORE_EXPORT CommandMappings : public QWidget
{
Q_OBJECT
public:
CommandMappings(QObject *parent = 0);
CommandMappings(QWidget *parent = 0);
~CommandMappings();
virtual bool hasConflicts() const;
protected slots:
void commandChanged(QTreeWidgetItem *current);
void filterChanged(const QString &f);
virtual void importAction() {}
virtual void exportAction() {}
virtual void defaultAction() = 0;
protected:
// IOptionsPage
QWidget *widget();
virtual void apply() {}
virtual void finish();
virtual void removeTargetIdentifier() = 0;
virtual void resetTargetIdentifier() = 0;
virtual void targetIdentifierChanged() = 0;
virtual void defaultAction() = 0;
virtual void exportAction() {}
virtual void importAction() {}
virtual void initialize() = 0;
void filterChanged(const QString &f);
bool filter(const QString &filterString, QTreeWidgetItem *item);
virtual void commandChanged(QTreeWidgetItem *current);
// access to m_page
void setImportExportEnabled(bool enabled);
QTreeWidget *commandList() const;
......
......@@ -39,6 +39,7 @@
#include <coreplugin/actionmanager/commandsfile.h>
#include <utils/fancylineedit.h>
#include <utils/qtcassert.h>
#include <QKeyEvent>
#include <QFileDialog>
......@@ -49,14 +50,54 @@
Q_DECLARE_METATYPE(Core::Internal::ShortcutItem*)
static int translateModifiers(Qt::KeyboardModifiers state,
const QString &text)
{
int result = 0;
// The shift modifier only counts when it is not used to type a symbol
// that is only reachable using the shift key anyway
if ((state & Qt::ShiftModifier) && (text.size() == 0
|| !text.at(0).isPrint()
|| text.at(0).isLetterOrNumber()
|| text.at(0).isSpace()))
result |= Qt::SHIFT;
if (state & Qt::ControlModifier)
result |= Qt::CTRL;
if (state & Qt::MetaModifier)
result |= Qt::META;
if (state & Qt::AltModifier)
result |= Qt::ALT;
return result;
}
namespace Core {
namespace Internal {
ShortcutSettings::ShortcutSettings(QObject *parent)
: CommandMappings(parent), m_initialized(false)
ShortcutSettingsWidget::ShortcutSettingsWidget(QWidget *parent)
: CommandMappings(parent)
{
setPageTitle(tr("Keyboard Shortcuts"));
setTargetLabelText(tr("Key sequence:"));
setTargetEditTitle(tr("Shortcut"));
setTargetHeader(tr("Shortcut"));
targetEdit()->setPlaceholderText(tr("Type to set shortcut"));
m_keyNum = m_key[0] = m_key[1] = m_key[2] = m_key[3] = 0;
connect(ActionManager::instance(), &ActionManager::commandListChanged,
this, &ShortcutSettingsWidget::initialize);
targetEdit()->installEventFilter(this);
initialize();
}
ShortcutSettingsWidget::~ShortcutSettingsWidget()
{
connect(ActionManager::instance(), SIGNAL(commandListChanged()), this, SLOT(initialize()));
qDeleteAll(m_scitems);
}
ShortcutSettings::ShortcutSettings(QObject *parent)
: IOptionsPage(parent)
{
setId(Constants::SETTINGS_ID_SHORTCUTS);
setDisplayName(tr("Keyboard"));
setCategory(Constants::SETTINGS_CATEGORY_CORE);
......@@ -66,40 +107,29 @@ ShortcutSettings::ShortcutSettings(QObject *parent)
QWidget *ShortcutSettings::widget()
{
m_initialized = true;
m_keyNum = m_key[0] = m_key[1] = m_key[2] = m_key[3] = 0;
QWidget *w = CommandMappings::widget();
const QString pageTitle = tr("Keyboard Shortcuts");
const QString targetLabelText = tr("Key sequence:");
const QString editTitle = tr("Shortcut");
setPageTitle(pageTitle);
setTargetLabelText(targetLabelText);
setTargetEditTitle(editTitle);
setTargetHeader(editTitle);
targetEdit()->setPlaceholderText(tr("Type to set shortcut"));
return w;
if (!m_widget)
m_widget = new ShortcutSettingsWidget();
return m_widget;
}
void ShortcutSettings::apply()
void ShortcutSettingsWidget::apply()
{
foreach (ShortcutItem *item, m_scitems)
item->m_cmd->setKeySequence(item->m_key);
}
void ShortcutSettings::finish()
void ShortcutSettings::apply()
{
qDeleteAll(m_scitems);
m_scitems.clear();
QTC_ASSERT(m_widget, return);
m_widget->apply();
}
CommandMappings::finish();
m_initialized = false;
void ShortcutSettings::finish()
{
delete m_widget;
}
bool ShortcutSettings::eventFilter(QObject *o, QEvent *e)
bool ShortcutSettingsWidget::eventFilter(QObject *o, QEvent *e)
{
Q_UNUSED(o)
......@@ -123,7 +153,7 @@ bool ShortcutSettings::eventFilter(QObject *o, QEvent *e)
return false;
}
void ShortcutSettings::commandChanged(QTreeWidgetItem *current)
void ShortcutSettingsWidget::commandChanged(QTreeWidgetItem *current)
{
CommandMappings::commandChanged(current);
if (!current || !current->data(0, Qt::UserRole).isValid())
......@@ -133,7 +163,7 @@ void ShortcutSettings::commandChanged(QTreeWidgetItem *current)
markCollisions(scitem);
}
void ShortcutSettings::targetIdentifierChanged()
void ShortcutSettingsWidget::targetIdentifierChanged()
{
QTreeWidgetItem *current = commandList()->currentItem();
if (current && current->data(0, Qt::UserRole).isValid()) {
......@@ -148,7 +178,7 @@ void ShortcutSettings::targetIdentifierChanged()
}
}
bool ShortcutSettings::hasConflicts() const
bool ShortcutSettingsWidget::hasConflicts() const
{
QTreeWidgetItem *current = commandList()->currentItem();
if (!current || !current->data(0, Qt::UserRole).isValid())
......@@ -185,7 +215,7 @@ bool ShortcutSettings::hasConflicts() const
return false;
}
void ShortcutSettings::setKeySequence(const QKeySequence &key)
void ShortcutSettingsWidget::setKeySequence(const QKeySequence &key)
{
m_key[0] = m_key[1] = m_key[2] = m_key[3] = 0;
m_keyNum = key.count();
......@@ -195,7 +225,7 @@ void ShortcutSettings::setKeySequence(const QKeySequence &key)
targetEdit()->setText(key.toString(QKeySequence::NativeText));
}
void ShortcutSettings::resetTargetIdentifier()
void ShortcutSettingsWidget::resetTargetIdentifier()
{
QTreeWidgetItem *current = commandList()->currentItem();
if (current && current->data(0, Qt::UserRole).isValid()) {
......@@ -206,7 +236,7 @@ void ShortcutSettings::resetTargetIdentifier()
}
}
void ShortcutSettings::removeTargetIdentifier()
void ShortcutSettingsWidget::removeTargetIdentifier()
{
m_keyNum = m_key[0] = m_key[1] = m_key[2] = m_key[3] = 0;
targetEdit()->clear();
......@@ -215,9 +245,9 @@ void ShortcutSettings::removeTargetIdentifier()
markCollisions(item);
}
void ShortcutSettings::importAction()
void ShortcutSettingsWidget::importAction()
{
QString fileName = QFileDialog::getOpenFileName(widget(), tr("Import Keyboard Mapping Scheme"),
QString fileName = QFileDialog::getOpenFileName(ICore::dialogParent(), tr("Import Keyboard Mapping Scheme"),
ICore::resourcePath() + QLatin1String("/schemes/"),
tr("Keyboard Mapping Scheme (*.kms)"));
if (!fileName.isEmpty()) {
......@@ -245,7 +275,7 @@ void ShortcutSettings::importAction()
}
}
void ShortcutSettings::defaultAction()
void ShortcutSettingsWidget::defaultAction()
{
foreach (ShortcutItem *item, m_scitems) {
item->m_key = item->m_cmd->defaultKeySequence();
......@@ -259,7 +289,7 @@ void ShortcutSettings::defaultAction()
markCollisions(item);
}
void ShortcutSettings::exportAction()
void ShortcutSettingsWidget::exportAction()
{
QString fileName = DocumentManager::getSaveFileNameWithExtension(
tr("Export Keyboard Mapping Scheme"),
......@@ -271,7 +301,7 @@ void ShortcutSettings::exportAction()
}
}
void ShortcutSettings::clear()
void ShortcutSettingsWidget::clear()
{
QTreeWidget *tree = commandList();
for (int i = tree->topLevelItemCount()-1; i >= 0 ; --i) {
......@@ -281,10 +311,8 @@ void ShortcutSettings::clear()
m_scitems.clear();
}
void ShortcutSettings::initialize()
void ShortcutSettingsWidget::initialize()
{
if (!m_initialized)
return;
clear();
QMap<QString, QTreeWidgetItem *> sections;
......@@ -329,7 +357,7 @@ void ShortcutSettings::initialize()
filterChanged(filterText());
}
void ShortcutSettings::handleKeyEvent(QKeyEvent *e)
void ShortcutSettingsWidget::handleKeyEvent(QKeyEvent *e)
{
int nextKey = e->key();
if ( m_keyNum > 3 ||
......@@ -362,27 +390,7 @@ void ShortcutSettings::handleKeyEvent(QKeyEvent *e)
e->accept();
}
int ShortcutSettings::translateModifiers(Qt::KeyboardModifiers state,
const QString &text)
{
int result = 0;
// The shift modifier only counts when it is not used to type a symbol
// that is only reachable using the shift key anyway
if ((state & Qt::ShiftModifier) && (text.size() == 0
|| !text.at(0).isPrint()
|| text.at(0).isLetterOrNumber()
|| text.at(0).isSpace()))
result |= Qt::SHIFT;
if (state & Qt::ControlModifier)
result |= Qt::CTRL;
if (state & Qt::MetaModifier)
result |= Qt::META;
if (state & Qt::AltModifier)
result |= Qt::ALT;
return result;
}
void ShortcutSettings::markCollisions(ShortcutItem *item)
void ShortcutSettingsWidget::markCollisions(ShortcutItem *item)
{
bool hasCollision = false;
if (!item->m_key.isEmpty()) {
......
......@@ -32,8 +32,10 @@
#define SHORTCUTSETTINGS_H
#include <coreplugin/actionmanager/commandmappings.h>
#include <coreplugin/dialogs/ioptionspage.h>
#include <QKeySequence>
#include <QPointer>
QT_BEGIN_NAMESPACE
class QKeyEvent;
......@@ -55,45 +57,52 @@ struct ShortcutItem
QTreeWidgetItem *m_item;
};
class ShortcutSettings : public CommandMappings
class ShortcutSettingsWidget : public CommandMappings
{
Q_OBJECT
public:
ShortcutSettings(QObject *parent = 0);
ShortcutSettingsWidget(QWidget *parent = 0);
~ShortcutSettingsWidget() override;
QWidget *widget();
void apply();
void finish();
protected:
bool eventFilter(QObject *o, QEvent *e);
private slots:
void commandChanged(QTreeWidgetItem *current);
void targetIdentifierChanged();
void resetTargetIdentifier();
void removeTargetIdentifier();
void importAction();
void exportAction();
void defaultAction();
void initialize();
bool eventFilter(QObject *o, QEvent *e) override;
private:
void setKeySequence(const QKeySequence &key);
void clear();
void commandChanged(QTreeWidgetItem *current) override;
void targetIdentifierChanged() override;
void resetTargetIdentifier() override;
void removeTargetIdentifier() override;
void importAction() override;
void exportAction() override;
void defaultAction() override;
bool hasConflicts() const override;
private:
void initialize();
void handleKeyEvent(QKeyEvent *e);
int translateModifiers(Qt::KeyboardModifiers state, const QString &text);
void markCollisions(ShortcutItem *);
bool hasConflicts() const;
void setKeySequence(const QKeySequence &key);
void clear();
QList<ShortcutItem *> m_scitems;
int m_key[4], m_keyNum;
};
class ShortcutSettings : public IOptionsPage
{
Q_OBJECT
bool m_initialized;
public:
ShortcutSettings(QObject *parent = 0);
QWidget *widget() override;
void apply() override;
void finish() override;
private:
QPointer<ShortcutSettingsWidget> m_widget;
};
} // namespace Internal
......
......@@ -539,7 +539,41 @@ void FakeVimOptionPage::updateVimRcWidgets()
enum { CommandRole = Qt::UserRole };
class FakeVimExCommandsPage : public CommandMappings
class FakeVimExCommandsWidget : public CommandMappings
{
Q_OBJECT
public:
FakeVimExCommandsWidget(FakeVimPluginPrivate *q, QWidget *parent = 0)
: CommandMappings(parent), m_q(q)
{
setPageTitle(Tr::tr("Ex Command Mapping"));
setTargetHeader(Tr::tr("Ex Trigger Expression"));
setTargetLabelText(Tr::tr("Regular expression:"));
setTargetEditTitle(Tr::tr("Ex Command"));
targetEdit()->setPlaceholderText(QString());
setImportExportEnabled(false);
initialize();
}
protected:
void targetIdentifierChanged() override;
void resetTargetIdentifier() override;
void removeTargetIdentifier() override;
void defaultAction() override;
void commandChanged(QTreeWidgetItem *current) override;
private:
void initialize();
ExCommandMap &exCommandMap();
ExCommandMap &defaultExCommandMap();
FakeVimPluginPrivate *m_q;
};
class FakeVimExCommandsPage : public IOptionsPage
{
Q_OBJECT
......@@ -554,34 +588,28 @@ public:
setCategoryIcon(_(SETTINGS_CATEGORY_FAKEVIM_ICON));
}
QWidget *widget();
void initialize();
ExCommandMap &exCommandMap();
ExCommandMap &defaultExCommandMap();