mirror of
https://github.com/Murmele/Gittyup.git
synced 2024-09-11 10:45:39 +03:00
Merge pull request #28 from exactly-one-kas/hotkey-manager
Adds support for customizable hotkeys
This commit is contained in:
commit
e8bbac9609
BIN
rsrc/hotkeys.png
Normal file
BIN
rsrc/hotkeys.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.0 KiB |
118
rsrc/hotkeys.svg
Normal file
118
rsrc/hotkeys.svg
Normal file
@ -0,0 +1,118 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
id="svg980"
|
||||
height="64"
|
||||
width="64"
|
||||
version="1.1">
|
||||
<metadata
|
||||
id="metadata986">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs984" />
|
||||
<rect
|
||||
id="rect970"
|
||||
fill="darkgray"
|
||||
ry="6"
|
||||
rx="6"
|
||||
height="60"
|
||||
width="60"
|
||||
y="3"
|
||||
x="3" />
|
||||
<rect
|
||||
style="fill:#bf8040;fill-opacity:1;stroke:#604020;stroke-opacity:1"
|
||||
id="rect972"
|
||||
stroke="darkslategray"
|
||||
stroke-width="1"
|
||||
fill="slategray"
|
||||
ry="6"
|
||||
rx="6"
|
||||
height="60"
|
||||
width="60"
|
||||
y="1"
|
||||
x="1" />
|
||||
<g
|
||||
transform="translate(-1,0.5)"
|
||||
id="g2324">
|
||||
<rect
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
|
||||
id="rect2123"
|
||||
width="46"
|
||||
height="33"
|
||||
x="9"
|
||||
y="14" />
|
||||
<g
|
||||
style="fill:#000000"
|
||||
id="g2347">
|
||||
<rect
|
||||
y="38"
|
||||
x="17"
|
||||
height="5"
|
||||
width="30"
|
||||
id="rect2125"
|
||||
style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.94868332;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
|
||||
<rect
|
||||
y="28"
|
||||
x="19.5"
|
||||
height="5"
|
||||
width="5"
|
||||
id="rect2298"
|
||||
style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
|
||||
<rect
|
||||
style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
|
||||
id="rect4184"
|
||||
width="5"
|
||||
height="5"
|
||||
x="29.5"
|
||||
y="28" />
|
||||
<rect
|
||||
y="28"
|
||||
x="39.5"
|
||||
height="5"
|
||||
width="5"
|
||||
id="rect4186"
|
||||
style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
|
||||
<rect
|
||||
style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
|
||||
id="rect4190"
|
||||
width="5"
|
||||
height="5"
|
||||
x="14.5"
|
||||
y="18" />
|
||||
<rect
|
||||
y="18"
|
||||
x="24.5"
|
||||
height="5"
|
||||
width="5"
|
||||
id="rect4192"
|
||||
style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
|
||||
<rect
|
||||
style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
|
||||
id="rect4194"
|
||||
width="5"
|
||||
height="5"
|
||||
x="34.5"
|
||||
y="18" />
|
||||
<rect
|
||||
y="18"
|
||||
x="44.5"
|
||||
height="5"
|
||||
width="5"
|
||||
id="rect4196"
|
||||
style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.3 KiB |
BIN
rsrc/hotkeys@2x.png
Normal file
BIN
rsrc/hotkeys@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
@ -30,6 +30,8 @@
|
||||
<file>github.png</file>
|
||||
<file>github_dark.png</file>
|
||||
<file>gitlab.png</file>
|
||||
<file>hotkeys.png</file>
|
||||
<file>hotkeys@2x.png</file>
|
||||
<file>lfs.png</file>
|
||||
<file>lfs@2x.png</file>
|
||||
<file>logo-type.png</file>
|
||||
|
@ -117,10 +117,15 @@ void Settings::endGroup()
|
||||
}
|
||||
|
||||
QVariant Settings::value(const QString &key) const
|
||||
{
|
||||
return value(key, defaultValue(key));
|
||||
}
|
||||
|
||||
QVariant Settings::value(const QString &key, const QVariant &defaultValue) const
|
||||
{
|
||||
QSettings settings;
|
||||
settings.beginGroup(group());
|
||||
QVariant result = settings.value(key, defaultValue(key));
|
||||
QVariant result = settings.value(key, defaultValue);
|
||||
settings.endGroup();
|
||||
return result;
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ public:
|
||||
void endGroup();
|
||||
|
||||
QVariant value(const QString &key) const;
|
||||
QVariant value(const QString &key, const QVariant &defaultValue) const;
|
||||
QVariant defaultValue(const QString &key) const;
|
||||
void setValue(const QString &key, const QVariant &value, bool refresh = false);
|
||||
|
||||
|
@ -13,6 +13,7 @@ add_library(dialogs
|
||||
DiffPanel.cpp
|
||||
ExternalToolsDialog.cpp
|
||||
ExternalToolsModel.cpp
|
||||
HotkeysPanel.cpp
|
||||
IconLabel.cpp
|
||||
MergeDialog.cpp
|
||||
NewBranchDialog.cpp
|
||||
|
562
src/dialogs/HotkeysPanel.cpp
Normal file
562
src/dialogs/HotkeysPanel.cpp
Normal file
@ -0,0 +1,562 @@
|
||||
//
|
||||
// Copyright (c) 2021, Gittyup
|
||||
//
|
||||
// This software is licensed under the MIT License. The LICENSE.md file
|
||||
// describes the conditions under which this software may be distributed.
|
||||
//
|
||||
// Author: Kas (https://github.com/exactly-one-kas)
|
||||
//
|
||||
|
||||
#include "HotkeysPanel.h"
|
||||
#include "ui/HotkeyManager.h"
|
||||
#include <QAbstractItemModel>
|
||||
#include <QDialog>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QHeaderView>
|
||||
#include <QKeySequence>
|
||||
#include <QKeySequenceEdit>
|
||||
#include <QLabel>
|
||||
#include <QMap>
|
||||
#include <QModelIndex>
|
||||
#include <QRegularExpression>
|
||||
#include <QString>
|
||||
#include <QVBoxLayout>
|
||||
#include <QVector>
|
||||
|
||||
namespace
|
||||
{
|
||||
class HotkeyGroupData;
|
||||
class HotkeyKeyData;
|
||||
|
||||
class HotkeyData : public QObject
|
||||
{
|
||||
public:
|
||||
enum class ObjectType
|
||||
{
|
||||
Key,
|
||||
Group
|
||||
};
|
||||
|
||||
HotkeyData(QObject *parent, HotkeyGroupData *group, const QString &label)
|
||||
: QObject(parent), mGroup(group), mLabel(label)
|
||||
{
|
||||
}
|
||||
|
||||
QString label() const
|
||||
{
|
||||
return mLabel;
|
||||
}
|
||||
|
||||
QString fullLabel() const;
|
||||
|
||||
HotkeyGroupData *group() const
|
||||
{
|
||||
return mGroup;
|
||||
}
|
||||
|
||||
virtual ObjectType type() const = 0;
|
||||
virtual void findConflicts(
|
||||
const QKeySequence &keys,
|
||||
QStringList &conflicts,
|
||||
Hotkey target
|
||||
) const = 0;
|
||||
|
||||
private:
|
||||
HotkeyGroupData *mGroup;
|
||||
QString mLabel;
|
||||
};
|
||||
|
||||
class HotkeyGroupData : public HotkeyData
|
||||
{
|
||||
public:
|
||||
HotkeyGroupData(
|
||||
QObject *parent,
|
||||
const QString &label,
|
||||
HotkeyGroupData *group = nullptr
|
||||
) : HotkeyData(parent, group, label)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ObjectType type() const override
|
||||
{
|
||||
return ObjectType::Group;
|
||||
}
|
||||
|
||||
virtual void findConflicts(
|
||||
const QKeySequence &keys,
|
||||
QStringList &conflicts,
|
||||
Hotkey target
|
||||
) const override
|
||||
{
|
||||
for (auto child: mChildren) {
|
||||
child->findConflicts(keys, conflicts, target);
|
||||
}
|
||||
}
|
||||
|
||||
QVector<HotkeyData*> childrenData() const
|
||||
{
|
||||
return mChildren;
|
||||
}
|
||||
|
||||
void addChildData(HotkeyData *data)
|
||||
{
|
||||
mChildren.append(data);
|
||||
}
|
||||
|
||||
private:
|
||||
QVector<HotkeyData*> mChildren;
|
||||
};
|
||||
|
||||
class HotkeyKeyData : public HotkeyData
|
||||
{
|
||||
public:
|
||||
HotkeyKeyData(HotkeyGroupData *group, const QString &label, Hotkey hotkey, HotkeyManager *manager)
|
||||
: HotkeyData(group, group, label), mHotkey(hotkey), mManager(manager)
|
||||
{
|
||||
mKeys = hotkey.currentKeys(manager);
|
||||
}
|
||||
|
||||
virtual ObjectType type() const override
|
||||
{
|
||||
return ObjectType::Key;
|
||||
}
|
||||
|
||||
virtual void findConflicts(
|
||||
const QKeySequence &keys,
|
||||
QStringList &conflicts,
|
||||
Hotkey target
|
||||
) const override
|
||||
{
|
||||
if (mHotkey != target && !mKeys.isEmpty()) {
|
||||
auto leftMatch = mKeys.matches(keys);
|
||||
auto rightMatch = keys.matches(mKeys);
|
||||
|
||||
if (
|
||||
leftMatch == QKeySequence::ExactMatch
|
||||
|
||||
// Recognize conflicts of partial matches on key sequences
|
||||
// We have to do it this way since NoMatch also gets returned
|
||||
// if one sequence is shorter than the other
|
||||
|| (leftMatch == QKeySequence::PartialMatch && rightMatch == QKeySequence::NoMatch)
|
||||
|| (leftMatch == QKeySequence::NoMatch && rightMatch == QKeySequence::PartialMatch)
|
||||
) {
|
||||
conflicts.push_back(fullLabel());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QKeySequence keys() const
|
||||
{
|
||||
return mKeys;
|
||||
}
|
||||
|
||||
void setKeys(QKeySequence keys)
|
||||
{
|
||||
mHotkey.setKeys(keys, mManager);
|
||||
mKeys = keys;
|
||||
}
|
||||
|
||||
Hotkey hotkey() const
|
||||
{
|
||||
return mHotkey;
|
||||
}
|
||||
|
||||
private:
|
||||
Hotkey mHotkey;
|
||||
HotkeyManager *mManager;
|
||||
QKeySequence mKeys;
|
||||
};
|
||||
|
||||
QString HotkeyData::fullLabel() const
|
||||
{
|
||||
QString res = label();
|
||||
|
||||
if (
|
||||
mGroup
|
||||
&& mGroup->mGroup // Don't use the root's label
|
||||
) {
|
||||
res = mGroup->fullLabel() + " -> " + res;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
class HotkeyModel : public QAbstractItemModel
|
||||
{
|
||||
public:
|
||||
enum class ColumnIndex : int
|
||||
{
|
||||
Min = 0,
|
||||
Label = 0,
|
||||
Keys = 1,
|
||||
Max = 1
|
||||
};
|
||||
|
||||
HotkeyModel(QObject *parent, HotkeyGroupData *root): QAbstractItemModel(parent), mRoot(root)
|
||||
{
|
||||
}
|
||||
|
||||
virtual int columnCount(const QModelIndex &parent) const override
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override
|
||||
{
|
||||
if (!parent.isValid())
|
||||
return mRoot->childrenData().length();
|
||||
|
||||
HotkeyData *data = (HotkeyData*)parent.internalPointer();
|
||||
if(data->type() != HotkeyData::ObjectType::Group)
|
||||
return 0;
|
||||
|
||||
return ((HotkeyGroupData*)data)->childrenData().length();
|
||||
}
|
||||
|
||||
virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override
|
||||
{
|
||||
if (row < 0 || column < (int)ColumnIndex::Min || column > (int)ColumnIndex::Max)
|
||||
return QModelIndex();
|
||||
|
||||
HotkeyGroupData *group = nullptr;
|
||||
if (parent.isValid()) {
|
||||
HotkeyData *data = (HotkeyData*)parent.internalPointer();
|
||||
if(data->type() == HotkeyData::ObjectType::Group)
|
||||
group = (HotkeyGroupData*)data;
|
||||
|
||||
} else {
|
||||
group = mRoot;
|
||||
}
|
||||
|
||||
if(!group || row >= group->childrenData().length())
|
||||
return QModelIndex();
|
||||
|
||||
return createIndex(row, column, group->childrenData()[row]);
|
||||
}
|
||||
|
||||
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override
|
||||
{
|
||||
if (
|
||||
!index.isValid()
|
||||
|| index.column() < (int)ColumnIndex::Min
|
||||
|| index.column() > (int)ColumnIndex::Max
|
||||
)
|
||||
return QVariant();
|
||||
|
||||
HotkeyData *data = (HotkeyData*)index.internalPointer();
|
||||
|
||||
switch ((ColumnIndex)index.column()) {
|
||||
case ColumnIndex::Label:
|
||||
if (role == Qt::DisplayRole)
|
||||
return QVariant(data->label());
|
||||
else
|
||||
return QVariant();
|
||||
|
||||
case ColumnIndex::Keys:
|
||||
if(data->type() != HotkeyData::ObjectType::Key)
|
||||
return QVariant();
|
||||
else if(role == Qt::DisplayRole)
|
||||
return QVariant(((HotkeyKeyData*)data)->keys().toString(QKeySequence::NativeText));
|
||||
else if(role == Qt::UserRole)
|
||||
return QVariant::fromValue(((HotkeyKeyData*)data)->keys());
|
||||
else if(role == Qt::UserRole + 1)
|
||||
return QVariant::fromValue(((HotkeyKeyData*)data)->hotkey());
|
||||
else
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override
|
||||
{
|
||||
if (!index.isValid() || index.column() != (int)ColumnIndex::Keys || role != Qt::UserRole)
|
||||
return false;
|
||||
|
||||
HotkeyData *data = (HotkeyData*)index.internalPointer();
|
||||
if (data->type() != HotkeyData::ObjectType::Key)
|
||||
return false;
|
||||
|
||||
((HotkeyKeyData*)data)->setKeys(value.value<QKeySequence>());
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual QModelIndex parent(const QModelIndex &index) const override
|
||||
{
|
||||
if (
|
||||
!index.isValid()
|
||||
|| index.column() < (int)ColumnIndex::Min
|
||||
|| index.column() > (int)ColumnIndex::Max
|
||||
)
|
||||
return QModelIndex();
|
||||
|
||||
HotkeyData *data = (HotkeyData*)index.internalPointer();
|
||||
HotkeyGroupData *parent = data->group();
|
||||
|
||||
int parentRow = 0;
|
||||
if (parent && parent->group())
|
||||
parentRow = parent->group()->childrenData().indexOf(parent);
|
||||
|
||||
if(!parent)
|
||||
return QModelIndex();
|
||||
else
|
||||
return createIndex(parentRow, 0, parent);
|
||||
}
|
||||
|
||||
virtual Qt::ItemFlags flags(const QModelIndex &index) const override
|
||||
{
|
||||
if (
|
||||
!index.isValid()
|
||||
|| index.column() < (int)ColumnIndex::Min
|
||||
|| index.column() > (int)ColumnIndex::Max
|
||||
)
|
||||
return Qt::ItemFlag::NoItemFlags;
|
||||
|
||||
Qt::ItemFlags res = Qt::ItemFlag::ItemIsEnabled;
|
||||
|
||||
if (((HotkeyData*)index.internalPointer())->type() == HotkeyData::ObjectType::Key)
|
||||
res |= Qt::ItemFlag::ItemIsSelectable | Qt::ItemFlag::ItemNeverHasChildren;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override
|
||||
{
|
||||
if (
|
||||
orientation != Qt::Orientation::Horizontal
|
||||
|| section < (int)ColumnIndex::Min
|
||||
|| section > (int)ColumnIndex::Max
|
||||
|| role != Qt::DisplayRole
|
||||
)
|
||||
return QVariant();
|
||||
|
||||
switch ((ColumnIndex)section) {
|
||||
case ColumnIndex::Label:
|
||||
return QVariant(tr("Action"));
|
||||
|
||||
case ColumnIndex::Keys:
|
||||
return QVariant(tr("Keys"));
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void findConflicts(
|
||||
const QKeySequence &keys,
|
||||
QStringList &conflicts,
|
||||
Hotkey target
|
||||
) const
|
||||
{
|
||||
mRoot->findConflicts(keys, conflicts, target);
|
||||
}
|
||||
|
||||
private:
|
||||
HotkeyGroupData *mRoot;
|
||||
};
|
||||
|
||||
class SimpleKeyEdit : public QKeySequenceEdit
|
||||
{
|
||||
public:
|
||||
SimpleKeyEdit(QWidget *parent): QKeySequenceEdit(parent)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void keyPressEvent(QKeyEvent *e) override
|
||||
{
|
||||
if (e->modifiers() == Qt::KeyboardModifier::NoModifier || e->modifiers() == Qt::KeyboardModifier::KeypadModifier)
|
||||
{
|
||||
switch (e->key()) {
|
||||
case Qt::Key_Backspace:
|
||||
case Qt::Key_Delete:
|
||||
setKeySequence(QKeySequence());
|
||||
|
||||
case Qt::Key_Enter:
|
||||
case Qt::Key_Return:
|
||||
case Qt::Key_Escape:
|
||||
case Qt::Key_Tab:
|
||||
e->ignore();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
QKeySequenceEdit::keyPressEvent(e);
|
||||
}
|
||||
};
|
||||
|
||||
class KeybindDialog : public QDialog
|
||||
{
|
||||
public:
|
||||
KeybindDialog(
|
||||
QWidget *parent,
|
||||
HotkeyModel *hotkeys,
|
||||
Hotkey hotkey
|
||||
): QDialog(parent)
|
||||
{
|
||||
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||
|
||||
auto conflicts = new QLabel(this);
|
||||
|
||||
mKeys = new SimpleKeyEdit(this);
|
||||
connect(
|
||||
mKeys,
|
||||
&SimpleKeyEdit::keySequenceChanged,
|
||||
[conflicts, hotkey, hotkeys](const QKeySequence &keys) {
|
||||
if (keys.isEmpty()) {
|
||||
conflicts->setText("");
|
||||
return;
|
||||
}
|
||||
|
||||
auto conflictLabels = QStringList();
|
||||
hotkeys->findConflicts(keys, conflictLabels, hotkey);
|
||||
|
||||
if (conflictLabels.isEmpty()) {
|
||||
conflicts->setText("");
|
||||
} else {
|
||||
conflicts->setText(
|
||||
tr("The selected key is the same for the following actions:\n%1")
|
||||
.arg(" - " + conflictLabels.join("\n - "))
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
layout->addWidget(new QLabel(tr("Please press the desired hotkey"), this));
|
||||
layout->addWidget(mKeys);
|
||||
layout->addWidget(conflicts);
|
||||
|
||||
QDialogButtonBox *buttons = new QDialogButtonBox(this);
|
||||
buttons->addButton(QDialogButtonBox::Ok);
|
||||
buttons->addButton(QDialogButtonBox::Cancel);
|
||||
connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
||||
connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
|
||||
layout->addWidget(buttons);
|
||||
|
||||
mKeys->setFocus();
|
||||
}
|
||||
|
||||
QKeySequence keys() const
|
||||
{
|
||||
return mKeys->keySequence();
|
||||
}
|
||||
|
||||
void setKeys(const QKeySequence &keys)
|
||||
{
|
||||
mKeys->setKeySequence(keys);
|
||||
}
|
||||
|
||||
private:
|
||||
SimpleKeyEdit *mKeys;
|
||||
};
|
||||
}
|
||||
|
||||
HotkeysPanel::HotkeysPanel(QWidget *parent) : QTreeView(parent)
|
||||
{
|
||||
static QRegularExpression slashRegex("/+");
|
||||
|
||||
HotkeyManager *manager = HotkeyManager::instance();
|
||||
|
||||
QMap<QString, HotkeyGroupData*> groups;
|
||||
HotkeyGroupData *root = new HotkeyGroupData(this, "<Root>");
|
||||
|
||||
// Build hotkey hierarchy
|
||||
for (Hotkey hotkey: manager->knownHotkeys()) {
|
||||
QString label = hotkey.label().replace(slashRegex, "/");
|
||||
int lastSep = label.lastIndexOf('/');
|
||||
|
||||
HotkeyGroupData *group;
|
||||
|
||||
// Look for existing group along hierarchy
|
||||
int pos = lastSep;
|
||||
while (pos >= 0) {
|
||||
group = groups.value(label.left(pos));
|
||||
if (group)
|
||||
break;
|
||||
|
||||
pos = label.lastIndexOf('/', pos - 1);
|
||||
}
|
||||
|
||||
// Use root if no matching group has been found
|
||||
if (!group) {
|
||||
Q_ASSERT(pos < 0);
|
||||
group = root;
|
||||
pos = 0;
|
||||
}
|
||||
|
||||
// Build and insert missing groups
|
||||
while (pos < lastSep && pos >= 0) {
|
||||
pos = label.indexOf('/', pos + 1);
|
||||
QString path = label.left(pos);
|
||||
|
||||
int subPos = path.lastIndexOf('/');
|
||||
|
||||
group = new HotkeyGroupData(group, tr(path.mid(subPos + 1).toUtf8()), group);
|
||||
group->group()->addChildData(group);
|
||||
|
||||
Q_ASSERT(!groups.contains(path));
|
||||
groups.insert(path, group);
|
||||
}
|
||||
|
||||
// Add hotkey to group
|
||||
group->addChildData(new HotkeyKeyData(group, tr(label.mid(lastSep + 1).toUtf8()), hotkey, manager));
|
||||
}
|
||||
|
||||
setModel(new HotkeyModel(this, root));
|
||||
setUniformRowHeights(true);
|
||||
setAllColumnsShowFocus(true);
|
||||
setEditTriggers(EditTrigger::DoubleClicked | EditTrigger::EditKeyPressed);
|
||||
expandAll();
|
||||
|
||||
header()->setSectionsMovable(false);
|
||||
header()->setSectionResizeMode(0, QHeaderView::ResizeMode::ResizeToContents);
|
||||
header()->setSectionResizeMode(1, QHeaderView::ResizeMode::Stretch);
|
||||
}
|
||||
|
||||
bool HotkeysPanel::edit(const QModelIndex &index, QAbstractItemView::EditTrigger trigger, QEvent *event)
|
||||
{
|
||||
if (!index.isValid() || !(trigger & editTriggers()))
|
||||
return false;
|
||||
|
||||
QModelIndex keyIndex = index.siblingAtColumn((int)HotkeyModel::ColumnIndex::Keys);
|
||||
QVariant data = keyIndex.data(Qt::UserRole);
|
||||
|
||||
if(!data.isValid())
|
||||
return false;
|
||||
|
||||
KeybindDialog *dialog = new KeybindDialog(
|
||||
this,
|
||||
(HotkeyModel*) model(),
|
||||
keyIndex.data(Qt::UserRole + 1).value<Hotkey>()
|
||||
);
|
||||
|
||||
dialog->setKeys(data.value<QKeySequence>());
|
||||
|
||||
QPersistentModelIndex idx(keyIndex);
|
||||
connect(dialog, &QDialog::accepted, [this, idx, dialog]() {
|
||||
model()->setData(idx, QVariant::fromValue(dialog->keys()), Qt::UserRole);
|
||||
});
|
||||
|
||||
dialog->setModal(true);
|
||||
dialog->setAttribute(Qt::WA_DeleteOnClose);
|
||||
dialog->show();
|
||||
return true;
|
||||
}
|
||||
|
||||
QSize HotkeysPanel::sizeHint() const
|
||||
{
|
||||
return QSize(600, 320);
|
||||
}
|
||||
|
||||
void HotkeysPanel::keyPressEvent(QKeyEvent *e)
|
||||
{
|
||||
if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) {
|
||||
QModelIndexList indexes = selectedIndexes();
|
||||
if (!indexes.isEmpty())
|
||||
edit(indexes.first(), EditTrigger::EditKeyPressed, e);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
QTreeView::keyPressEvent(e);
|
||||
}
|
30
src/dialogs/HotkeysPanel.h
Normal file
30
src/dialogs/HotkeysPanel.h
Normal file
@ -0,0 +1,30 @@
|
||||
//
|
||||
// Copyright (c) 2021, Gittyup
|
||||
//
|
||||
// This software is licensed under the MIT License. The LICENSE.md file
|
||||
// describes the conditions under which this software may be distributed.
|
||||
//
|
||||
// Author: Kas (https://github.com/exactly-one-kas)
|
||||
//
|
||||
|
||||
#include <QKeyEvent>
|
||||
#include <QTreeView>
|
||||
|
||||
class HotkeysPanel : public QTreeView
|
||||
{
|
||||
public:
|
||||
enum Column
|
||||
{
|
||||
Name,
|
||||
Kind,
|
||||
Description
|
||||
};
|
||||
|
||||
HotkeysPanel(QWidget *parent = nullptr);
|
||||
|
||||
virtual QSize sizeHint() const override;
|
||||
|
||||
protected:
|
||||
virtual bool edit(const QModelIndex &index, QAbstractItemView::EditTrigger trigger, QEvent *event) override;
|
||||
virtual void keyPressEvent(QKeyEvent *e) override;
|
||||
};
|
@ -11,6 +11,7 @@
|
||||
#include "AboutDialog.h"
|
||||
#include "DiffPanel.h"
|
||||
#include "ExternalToolsDialog.h"
|
||||
#include "HotkeysPanel.h"
|
||||
#include "PluginsPanel.h"
|
||||
#include "app/Application.h"
|
||||
#include "app/CustomTheme.h"
|
||||
@ -880,6 +881,14 @@ SettingsDialog::SettingsDialog(Index index, QWidget *parent)
|
||||
|
||||
stack->addWidget(new MiscPanel(this));
|
||||
|
||||
// Add hotkeys panel.
|
||||
QAction *hotkeys = toolbar->addAction(QIcon(":/hotkeys.png"), tr("Hotkeys"));
|
||||
hotkeys->setData(Hotkeys);
|
||||
hotkeys->setActionGroup(actions);
|
||||
hotkeys->setCheckable(true);
|
||||
|
||||
stack->addWidget(new HotkeysPanel(this));
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
// Add terminal panel.
|
||||
QAction *terminal = toolbar->addAction(QIcon(":/terminal.png"), tr("Terminal"));
|
||||
|
@ -27,6 +27,7 @@ public:
|
||||
Update,
|
||||
Plugins,
|
||||
Misc,
|
||||
Hotkeys,
|
||||
Terminal
|
||||
};
|
||||
|
||||
|
@ -27,6 +27,7 @@ add_library(ui
|
||||
Footer.cpp
|
||||
History.cpp
|
||||
IgnoreDialog.cpp
|
||||
HotkeyManager.cpp
|
||||
IndexCompleter.cpp
|
||||
Location.cpp
|
||||
MainWindow.cpp
|
||||
|
208
src/ui/HotkeyManager.cpp
Normal file
208
src/ui/HotkeyManager.cpp
Normal file
@ -0,0 +1,208 @@
|
||||
//
|
||||
// Copyright (c) 2021, Gittyup
|
||||
//
|
||||
// This software is licensed under the MIT License. The LICENSE.md file
|
||||
// describes the conditions under which this software may be distributed.
|
||||
//
|
||||
// Author: Kas (https://github.com/exactly-one-kas)
|
||||
//
|
||||
|
||||
#include "HotkeyManager.h"
|
||||
|
||||
struct HotkeyManagerHandle
|
||||
{
|
||||
const char *defaultKeys;
|
||||
QKeySequence::StandardKey standardKey;
|
||||
const char *configPath;
|
||||
const char *label;
|
||||
int index;
|
||||
HotkeyManagerHandle *next;
|
||||
};
|
||||
|
||||
static HotkeyManagerHandle *hotkeyRegistry;
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
static bool consumed;
|
||||
#endif
|
||||
|
||||
HotkeyHandle::HotkeyHandle(QMetaObject::Connection &&changeSignalConnection): changeSignalConnection(std::move(changeSignalConnection))
|
||||
{
|
||||
}
|
||||
|
||||
HotkeyHandle::~HotkeyHandle()
|
||||
{
|
||||
disconnect(changeSignalConnection);
|
||||
}
|
||||
|
||||
HotkeyHandle *Hotkey::use(std::function<void(const QKeySequence&)> changeHandler, HotkeyManager *manager) const
|
||||
{
|
||||
if (!manager)
|
||||
manager = HotkeyManager::instance();
|
||||
|
||||
QMetaObject::Connection connection = QObject::connect(manager, &HotkeyManager::changed, [this, changeHandler, manager](const HotkeyManagerHandle *handle) {
|
||||
if (handle == mHandle)
|
||||
changeHandler(manager->keys(mHandle));
|
||||
});
|
||||
|
||||
changeHandler(manager->keys(mHandle));
|
||||
|
||||
return new HotkeyHandle(std::move(connection));
|
||||
}
|
||||
|
||||
HotkeyHandle *Hotkey::use(QAction *action, HotkeyManager *manager) const
|
||||
{
|
||||
HotkeyHandle *res = use(
|
||||
[action](const QKeySequence &keys) {
|
||||
action->setShortcut(keys);
|
||||
},
|
||||
manager
|
||||
);
|
||||
|
||||
res->setParent(action);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
HotkeyHandle *Hotkey::use(QShortcut *shortcut, HotkeyManager *manager) const
|
||||
{
|
||||
HotkeyHandle *res = use(
|
||||
[shortcut](const QKeySequence &keys) {
|
||||
shortcut->setKey(keys);
|
||||
},
|
||||
manager
|
||||
);
|
||||
|
||||
res->setParent(shortcut);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
QString Hotkey::label() const
|
||||
{
|
||||
return mHandle->label;
|
||||
}
|
||||
|
||||
QKeySequence Hotkey::currentKeys(const HotkeyManager *manager) const
|
||||
{
|
||||
if (!manager)
|
||||
manager = HotkeyManager::instance();
|
||||
|
||||
return manager->keys(mHandle);
|
||||
}
|
||||
|
||||
QString Hotkey::defaultKeys() const
|
||||
{
|
||||
return QObject::tr(mHandle->defaultKeys);
|
||||
}
|
||||
|
||||
void Hotkey::setKeys(const QKeySequence &keys, HotkeyManager *manager)
|
||||
{
|
||||
if (!manager)
|
||||
manager = HotkeyManager::instance();
|
||||
|
||||
manager->setKeys(mHandle, keys);
|
||||
}
|
||||
|
||||
Hotkey::Hotkey(const HotkeyManagerHandle *handle): mHandle(handle)
|
||||
{
|
||||
}
|
||||
|
||||
HotkeyManager *HotkeyManager::instance()
|
||||
{
|
||||
static HotkeyManager *instance = nullptr;
|
||||
if (!instance)
|
||||
instance = new HotkeyManager();
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
Hotkey HotkeyManager::registerHotkey(const char *defaultKeys, QKeySequence::StandardKey standardKey, const char *configPath, const char *label)
|
||||
{
|
||||
#ifndef QT_NO_DEBUG
|
||||
Q_ASSERT_X(!consumed, "HotkeyManager::registerHotkey()", "Registering a hotkey after creating a hotkey manager");
|
||||
#endif
|
||||
|
||||
HotkeyManagerHandle *info = new HotkeyManagerHandle();
|
||||
info->defaultKeys = defaultKeys;
|
||||
info->standardKey = standardKey;
|
||||
info->configPath = configPath;
|
||||
info->label = label;
|
||||
info->next = hotkeyRegistry;
|
||||
|
||||
if (hotkeyRegistry)
|
||||
info->index = hotkeyRegistry->index + 1;
|
||||
else
|
||||
info->index = 0;
|
||||
|
||||
hotkeyRegistry = info;
|
||||
|
||||
return Hotkey(info);
|
||||
}
|
||||
|
||||
Hotkey HotkeyManager::registerHotkey(const char *defaultKeys, const char *configPath, const char *label)
|
||||
{
|
||||
if (!defaultKeys)
|
||||
defaultKeys = "";
|
||||
|
||||
return registerHotkey(defaultKeys, QKeySequence::StandardKey::UnknownKey, configPath, label);
|
||||
}
|
||||
|
||||
Hotkey HotkeyManager::registerHotkey(QKeySequence::StandardKey standardKey, const char *configPath, const char *label)
|
||||
{
|
||||
return registerHotkey(nullptr, standardKey, configPath, label);
|
||||
}
|
||||
|
||||
static QKeySequence getKeys(const QString &setting, HotkeyManagerHandle *handle)
|
||||
{
|
||||
if (!setting.isEmpty())
|
||||
return QKeySequence(setting, QKeySequence::SequenceFormat::PortableText);
|
||||
else if (!handle->defaultKeys)
|
||||
return QKeySequence(handle->standardKey);
|
||||
else
|
||||
return QKeySequence(handle->defaultKeys);
|
||||
}
|
||||
|
||||
HotkeyManager::HotkeyManager(Settings *settings):
|
||||
mSettings(settings),
|
||||
mHandles(hotkeyRegistry->index + 1),
|
||||
mKeys(hotkeyRegistry->index + 1)
|
||||
{
|
||||
#ifndef QT_NO_DEBUG
|
||||
consumed = true;
|
||||
#endif
|
||||
|
||||
if (!mSettings)
|
||||
mSettings = Settings::instance();
|
||||
|
||||
mSettings->beginGroup("hotkeys");
|
||||
|
||||
for (HotkeyManagerHandle *i = hotkeyRegistry; i; i = i->next) {
|
||||
mHandles[i->index] = i;
|
||||
mKeys[i->index] = getKeys(mSettings->value(i->configPath, "").toString(), i);
|
||||
}
|
||||
|
||||
mSettings->endGroup();
|
||||
}
|
||||
|
||||
QVector<Hotkey> HotkeyManager::knownHotkeys() const
|
||||
{
|
||||
QVector<Hotkey> res(mHandles.size());
|
||||
|
||||
for (HotkeyManagerHandle *i: mHandles)
|
||||
res[i->index] = Hotkey(i);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
QKeySequence HotkeyManager::keys(const HotkeyManagerHandle *handle) const
|
||||
{
|
||||
return mKeys[handle->index];
|
||||
}
|
||||
|
||||
void HotkeyManager::setKeys(const HotkeyManagerHandle *handle, const QKeySequence &keys)
|
||||
{
|
||||
mKeys[handle->index] = keys;
|
||||
mSettings->setValue("hotkeys/" + QString(handle->configPath), keys.toString());
|
||||
|
||||
emit changed(handle);
|
||||
}
|
104
src/ui/HotkeyManager.h
Normal file
104
src/ui/HotkeyManager.h
Normal file
@ -0,0 +1,104 @@
|
||||
//
|
||||
// Copyright (c) 2021, Gittyup
|
||||
//
|
||||
// This software is licensed under the MIT License. The LICENSE.md file
|
||||
// describes the conditions under which this software may be distributed.
|
||||
//
|
||||
// Author: Kas (https://github.com/exactly-one-kas)
|
||||
//
|
||||
|
||||
#ifndef HOTKEYMANAGER_H
|
||||
#define HOTKEYMANAGER_H
|
||||
|
||||
#include "conf/Settings.h"
|
||||
#include <functional>
|
||||
#include <QAction>
|
||||
#include <QObject>
|
||||
#include <QKeySequence>
|
||||
#include <QShortcut>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
|
||||
class HotkeyManager;
|
||||
struct HotkeyManagerHandle;
|
||||
|
||||
class HotkeyHandle : public QObject
|
||||
{
|
||||
public:
|
||||
HotkeyHandle(QMetaObject::Connection &&changeSignalConnection);
|
||||
~HotkeyHandle();
|
||||
|
||||
private:
|
||||
QMetaObject::Connection changeSignalConnection;
|
||||
};
|
||||
|
||||
class Hotkey
|
||||
{
|
||||
friend class HotkeyManager;
|
||||
|
||||
public:
|
||||
inline Hotkey(): mHandle(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
HotkeyHandle *use(std::function<void(const QKeySequence&)> changeHandler, HotkeyManager *manager = nullptr) const;
|
||||
HotkeyHandle *use(QAction *action, HotkeyManager *manager = nullptr) const;
|
||||
HotkeyHandle *use(QShortcut *shortcut, HotkeyManager *manager = nullptr) const;
|
||||
|
||||
QString label() const;
|
||||
QKeySequence currentKeys(const HotkeyManager *manager = nullptr) const;
|
||||
QString defaultKeys() const;
|
||||
void setKeys(const QKeySequence &keys, HotkeyManager *manager = nullptr);
|
||||
|
||||
inline bool isValid() const
|
||||
{
|
||||
return mHandle != nullptr;
|
||||
}
|
||||
|
||||
inline bool operator ==(const Hotkey &op) const
|
||||
{
|
||||
return mHandle == op.mHandle;
|
||||
}
|
||||
|
||||
inline bool operator !=(const Hotkey &op) const
|
||||
{
|
||||
return mHandle != op.mHandle;
|
||||
}
|
||||
|
||||
private:
|
||||
const HotkeyManagerHandle *mHandle;
|
||||
|
||||
Hotkey(const HotkeyManagerHandle *handle);
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(Hotkey)
|
||||
|
||||
class HotkeyManager : public QObject
|
||||
{
|
||||
friend class Hotkey;
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static Hotkey registerHotkey(const char *defaultKeys, const char *configPath, const char *label);
|
||||
static Hotkey registerHotkey(QKeySequence::StandardKey defaultKeys, const char *configPath, const char *label);
|
||||
static HotkeyManager *instance();
|
||||
|
||||
HotkeyManager(Settings *settings = nullptr);
|
||||
QVector<Hotkey> knownHotkeys() const;
|
||||
|
||||
signals:
|
||||
void changed(const HotkeyManagerHandle *handle);
|
||||
|
||||
private:
|
||||
static Hotkey registerHotkey(const char *defaultKeys, QKeySequence::StandardKey standardKey, const char *configPath, const char *label);
|
||||
|
||||
Settings *mSettings;
|
||||
QVector<HotkeyManagerHandle*> mHandles;
|
||||
QVector<QKeySequence> mKeys;
|
||||
|
||||
QKeySequence keys(const HotkeyManagerHandle *handle) const;
|
||||
void setKeys(const HotkeyManagerHandle *handle, const QKeySequence &keys);
|
||||
};
|
||||
|
||||
#endif
|
@ -13,6 +13,7 @@
|
||||
#include "EditorWindow.h"
|
||||
#include "FindWidget.h"
|
||||
#include "History.h"
|
||||
#include "HotkeyManager.h"
|
||||
#include "MainWindow.h"
|
||||
#include "RepoView.h"
|
||||
#include "TabWidget.h"
|
||||
@ -66,6 +67,350 @@ void openCloneDialog(CloneDialog::Kind kind)
|
||||
|
||||
bool MenuBar::sDebugMenuVisible = false;
|
||||
|
||||
static Hotkey newFileHotkey = HotkeyManager::registerHotkey(
|
||||
QKeySequence::New,
|
||||
"file/new",
|
||||
"File/New File"
|
||||
);
|
||||
|
||||
static Hotkey newWinHotkey = HotkeyManager::registerHotkey(
|
||||
"Ctrl+Meta+N",
|
||||
"file/newWindow",
|
||||
"File/New Window"
|
||||
);
|
||||
|
||||
static Hotkey cloneHotkey = HotkeyManager::registerHotkey(
|
||||
"Ctrl+Shift+N",
|
||||
"file/clone",
|
||||
"File/Clone Repository"
|
||||
);
|
||||
|
||||
static Hotkey initHotkey = HotkeyManager::registerHotkey(
|
||||
"Ctrl+Alt+N",
|
||||
"file/init",
|
||||
"File/Initialize New Repository"
|
||||
);
|
||||
|
||||
static Hotkey openHotkey = HotkeyManager::registerHotkey(
|
||||
QKeySequence::Open,
|
||||
"file/open",
|
||||
"File/Open Repository"
|
||||
);
|
||||
|
||||
static Hotkey closeHotkey = HotkeyManager::registerHotkey(
|
||||
QKeySequence::Close,
|
||||
"file/close",
|
||||
"File/Close"
|
||||
);
|
||||
|
||||
static Hotkey saveHotkey = HotkeyManager::registerHotkey(
|
||||
QKeySequence::Save,
|
||||
"file/save",
|
||||
"File/Save"
|
||||
);
|
||||
|
||||
#ifndef Q_OS_MAC
|
||||
static Hotkey quitHotkey = HotkeyManager::registerHotkey(
|
||||
QKeySequence::Quit,
|
||||
"file/quit",
|
||||
"File/Exit"
|
||||
);
|
||||
#endif
|
||||
|
||||
static Hotkey undoHotkey = HotkeyManager::registerHotkey(
|
||||
QKeySequence::Undo,
|
||||
"edit/undo",
|
||||
"Edit/Undo"
|
||||
);
|
||||
|
||||
static Hotkey redoHotkey = HotkeyManager::registerHotkey(
|
||||
QKeySequence::Redo,
|
||||
"edit/redo",
|
||||
"Edit/Redo"
|
||||
);
|
||||
|
||||
static Hotkey cutHotkey = HotkeyManager::registerHotkey(
|
||||
QKeySequence::Cut,
|
||||
"edit/cut",
|
||||
"Edit/Cut"
|
||||
);
|
||||
|
||||
static Hotkey copyHotkey = HotkeyManager::registerHotkey(
|
||||
QKeySequence::Copy,
|
||||
"edit/copy",
|
||||
"Edit/Copy"
|
||||
);
|
||||
|
||||
static Hotkey pasteHotkey = HotkeyManager::registerHotkey(
|
||||
QKeySequence::Paste,
|
||||
"edit/paste",
|
||||
"Edit/Paste"
|
||||
);
|
||||
|
||||
static Hotkey selectAllHotkey = HotkeyManager::registerHotkey(
|
||||
QKeySequence::SelectAll,
|
||||
"edit/selectAll",
|
||||
"Edit/Select All"
|
||||
);
|
||||
|
||||
static Hotkey findHotkey = HotkeyManager::registerHotkey(
|
||||
QKeySequence::Find,
|
||||
"edit/find",
|
||||
"Edit/Find"
|
||||
);
|
||||
|
||||
static Hotkey findNextHotkey = HotkeyManager::registerHotkey(
|
||||
QKeySequence::FindNext,
|
||||
"edit/findNext",
|
||||
"Edit/Find Next"
|
||||
);
|
||||
|
||||
static Hotkey findPreviousHotkey = HotkeyManager::registerHotkey(
|
||||
QKeySequence::FindPrevious,
|
||||
"edit/findPrevious",
|
||||
"Edit/Find Previous"
|
||||
);
|
||||
|
||||
static Hotkey findSelectionHotkey = HotkeyManager::registerHotkey(
|
||||
"Ctrl+E",
|
||||
"edit/findSelection",
|
||||
"Edit/Use Selection for Find"
|
||||
);
|
||||
|
||||
static Hotkey refreshHotkey = HotkeyManager::registerHotkey(
|
||||
QKeySequence::Refresh,
|
||||
"view/refresh",
|
||||
"View/Refresh"
|
||||
);
|
||||
|
||||
static Hotkey toggleLogHotkey = HotkeyManager::registerHotkey(
|
||||
nullptr,
|
||||
"view/toggleLog",
|
||||
"View/Toggle Log"
|
||||
);
|
||||
|
||||
static Hotkey toggleMaximizeHotkey = HotkeyManager::registerHotkey(
|
||||
"Ctrl+M",
|
||||
"view/toggleMaximize",
|
||||
"View/Toggle Maximize"
|
||||
);
|
||||
|
||||
static Hotkey toggleViewHotkey = HotkeyManager::registerHotkey(
|
||||
nullptr,
|
||||
"view/toggleView",
|
||||
"View/Toggle Tree View"
|
||||
);
|
||||
|
||||
static Hotkey configureRepositoryHotkey = HotkeyManager::registerHotkey(
|
||||
nullptr,
|
||||
"repository/configure",
|
||||
"Repository/Configure Repository"
|
||||
);
|
||||
|
||||
static Hotkey stageAllHotkey = HotkeyManager::registerHotkey(
|
||||
"Ctrl++",
|
||||
"repository/stageAll",
|
||||
"Repository/Stage All"
|
||||
);
|
||||
|
||||
static Hotkey unstageAllHotkey = HotkeyManager::registerHotkey(
|
||||
"Ctrl+-",
|
||||
"repository/unstageAll",
|
||||
"Repository/Unstage All"
|
||||
);
|
||||
|
||||
static Hotkey commitHotkey = HotkeyManager::registerHotkey(
|
||||
"Ctrl+Shift+C",
|
||||
"repository/commit",
|
||||
"Repository/Commit"
|
||||
);
|
||||
|
||||
static Hotkey amendCommitHotkey = HotkeyManager::registerHotkey(
|
||||
"Ctrl+Shift+A",
|
||||
"repository/amendCommit",
|
||||
"Repository/Amend Commit"
|
||||
);
|
||||
|
||||
static Hotkey lfsUnlockHotkey = HotkeyManager::registerHotkey(
|
||||
nullptr,
|
||||
"repository/lfs/unlock",
|
||||
"Repository/Remove all LFS locks"
|
||||
);
|
||||
|
||||
static Hotkey lfsInitializeHotkey = HotkeyManager::registerHotkey(
|
||||
nullptr,
|
||||
"repository/lfs/initialize",
|
||||
"Repository/Initialize LFS"
|
||||
);
|
||||
|
||||
static Hotkey configureRemotesHotkey = HotkeyManager::registerHotkey(
|
||||
nullptr,
|
||||
"remote/configure",
|
||||
"Remote/Configure"
|
||||
);
|
||||
|
||||
static Hotkey fetchHotkey = HotkeyManager::registerHotkey(
|
||||
"Ctrl+Shift+Alt+F",
|
||||
"remote/fetch",
|
||||
"Remote/Fetch"
|
||||
);
|
||||
|
||||
static Hotkey fetchAllHotkey = HotkeyManager::registerHotkey(
|
||||
"Ctrl+Shift+Alt+A",
|
||||
"remote/fetchAll",
|
||||
"Remote/Fetch All"
|
||||
);
|
||||
|
||||
static Hotkey fetchFromHotkey = HotkeyManager::registerHotkey(
|
||||
"Ctrl+Shift+F",
|
||||
"remote/fetchFrom",
|
||||
"Remote/Fetch From"
|
||||
);
|
||||
|
||||
static Hotkey pullHotkey = HotkeyManager::registerHotkey(
|
||||
"Ctrl+Shift+Alt+L",
|
||||
"remote/pull",
|
||||
"Remote/Pull"
|
||||
);
|
||||
|
||||
static Hotkey pullFromHotkey = HotkeyManager::registerHotkey(
|
||||
"Ctrl+Shift+L",
|
||||
"remote/pullFrom",
|
||||
"Remote/Pull From"
|
||||
);
|
||||
|
||||
static Hotkey pushHotkey = HotkeyManager::registerHotkey(
|
||||
"Ctrl+Shift+Alt+P",
|
||||
"remote/push",
|
||||
"Remote/Push"
|
||||
);
|
||||
|
||||
static Hotkey pushToHotkey = HotkeyManager::registerHotkey(
|
||||
"Ctrl+Shift+P",
|
||||
"remote/pushTo",
|
||||
"Remote/Push To"
|
||||
);
|
||||
|
||||
static Hotkey configureBranchesHotkey = HotkeyManager::registerHotkey(
|
||||
nullptr,
|
||||
"branch/configure",
|
||||
"Branch/Configure"
|
||||
);
|
||||
|
||||
static Hotkey newBranchHotkey = HotkeyManager::registerHotkey(
|
||||
nullptr,
|
||||
"branch/new",
|
||||
"Branch/New"
|
||||
);
|
||||
|
||||
static Hotkey checkoutCurrentHotkey = HotkeyManager::registerHotkey(
|
||||
"Ctrl+Shift+Alt+H",
|
||||
"branch/checkoutCurrent",
|
||||
"Branch/Checkout Current"
|
||||
);
|
||||
|
||||
static Hotkey checkoutHotkey = HotkeyManager::registerHotkey(
|
||||
"Ctrl+Shift+H",
|
||||
"branch/checkout",
|
||||
"Branch/Checkout"
|
||||
);
|
||||
|
||||
static Hotkey mergeHotkey = HotkeyManager::registerHotkey(
|
||||
"Ctrl+Shift+M",
|
||||
"branch/merge",
|
||||
"Branch/Merge"
|
||||
);
|
||||
|
||||
static Hotkey rebaseHotkey = HotkeyManager::registerHotkey(
|
||||
"Ctrl+Shift+R",
|
||||
"branch/rebase",
|
||||
"Branch/Rebase"
|
||||
);
|
||||
|
||||
static Hotkey abortHotkey = HotkeyManager::registerHotkey(
|
||||
"Ctrl+Shift+A",
|
||||
"branch/abort",
|
||||
"Branch/Abort Merge"
|
||||
);
|
||||
|
||||
static Hotkey configureSubmodulesHotkey = HotkeyManager::registerHotkey(
|
||||
nullptr,
|
||||
"branch/configure",
|
||||
"Branch/Configure"
|
||||
);
|
||||
|
||||
static Hotkey updateSubmodulesHotkey = HotkeyManager::registerHotkey(
|
||||
"Ctrl+Shift+Alt+U",
|
||||
"branch/update",
|
||||
"Branch/Update All"
|
||||
);
|
||||
|
||||
static Hotkey initSubmodulesHotkey = HotkeyManager::registerHotkey(
|
||||
"Ctrl+Shift+U",
|
||||
"branch/init",
|
||||
"Branch/Update"
|
||||
);
|
||||
|
||||
static Hotkey showStashesHotkey = HotkeyManager::registerHotkey(
|
||||
nullptr,
|
||||
"stash/show",
|
||||
"Stash/Show Stashes"
|
||||
);
|
||||
|
||||
static Hotkey stashHotkey = HotkeyManager::registerHotkey(
|
||||
"Ctrl+Shift+T",
|
||||
"stash/stash",
|
||||
"Stash/Stash"
|
||||
);
|
||||
|
||||
static Hotkey stashPopHotkey = HotkeyManager::registerHotkey(
|
||||
"Ctrl+Shift+Alt+T",
|
||||
"stash/pop",
|
||||
"Stash/Pop"
|
||||
);
|
||||
|
||||
static Hotkey prevHotkey = HotkeyManager::registerHotkey(
|
||||
QKeySequence::Back,
|
||||
"history/prev",
|
||||
"History/Back"
|
||||
);
|
||||
|
||||
static Hotkey nextHotkey = HotkeyManager::registerHotkey(
|
||||
QKeySequence::Forward,
|
||||
"history/next",
|
||||
"History/Forward"
|
||||
);
|
||||
|
||||
static Hotkey prevTabHotkey = HotkeyManager::registerHotkey(
|
||||
QKeySequence::PreviousChild,
|
||||
"window/prevTab",
|
||||
"Window/Show Previous Tab"
|
||||
);
|
||||
|
||||
static Hotkey nextTabHotkey = HotkeyManager::registerHotkey(
|
||||
QKeySequence::NextChild,
|
||||
"window/nextTab",
|
||||
"Window/Show Next Tab"
|
||||
);
|
||||
|
||||
static Hotkey chooserHotkey = HotkeyManager::registerHotkey(
|
||||
"Ctrl+Shift+O",
|
||||
"window/chooser",
|
||||
"Window/Show Repository Chooser"
|
||||
);
|
||||
|
||||
static Hotkey preferencesHotkey = HotkeyManager::registerHotkey(
|
||||
nullptr,
|
||||
"tools/preferences",
|
||||
"Tools/Options"
|
||||
);
|
||||
|
||||
static Hotkey squashHotkey = HotkeyManager::registerHotkey(
|
||||
"Ctrl+Shift+Q",
|
||||
"tools/preferences",
|
||||
"Tools/Options"
|
||||
);
|
||||
|
||||
MenuBar::MenuBar(QWidget *parent)
|
||||
: QMenuBar(parent)
|
||||
{
|
||||
@ -73,7 +418,7 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
QMenu *file = addMenu(tr("File"));
|
||||
|
||||
QAction *newFile = file->addAction(tr("New File"));
|
||||
newFile->setShortcut(QKeySequence::New);
|
||||
newFileHotkey.use(newFile);
|
||||
connect(newFile, &QAction::triggered, [] {
|
||||
if (MainWindow *window = MainWindow::activeWindow()) {
|
||||
if (RepoView *view = window->currentView()) {
|
||||
@ -87,19 +432,19 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
});
|
||||
|
||||
QAction *newWin = file->addAction(tr("New Window"));
|
||||
newWin->setShortcut(tr("Ctrl+Meta+N"));
|
||||
newWinHotkey.use(newWin);
|
||||
connect(newWin, &QAction::triggered, [] {
|
||||
MainWindow::open();
|
||||
});
|
||||
|
||||
QAction *clone = file->addAction(tr("Clone Repository..."));
|
||||
clone->setShortcut(tr("Ctrl+Shift+N"));
|
||||
cloneHotkey.use(clone);
|
||||
connect(clone, &QAction::triggered, [] {
|
||||
openCloneDialog(CloneDialog::Clone);
|
||||
});
|
||||
|
||||
QAction *init = file->addAction(tr("Initialize New Repository..."));
|
||||
init->setShortcut(tr("Ctrl+Alt+N"));
|
||||
initHotkey.use(init);
|
||||
connect(init, &QAction::triggered, [] {
|
||||
openCloneDialog(CloneDialog::Init);
|
||||
});
|
||||
@ -107,7 +452,7 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
file->addSeparator();
|
||||
|
||||
QAction *open = file->addAction(tr("Open Repository..."));
|
||||
open->setShortcut(QKeySequence::Open);
|
||||
openHotkey.use(open);
|
||||
connect(open, &QAction::triggered, [] {
|
||||
// FIXME: Filter out non-git dirs.
|
||||
Settings *settings = Settings::instance();
|
||||
@ -134,7 +479,7 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
file->addSeparator();
|
||||
|
||||
mClose = file->addAction(tr("Close"));
|
||||
mClose->setShortcut(QKeySequence::Close);
|
||||
closeHotkey.use(mClose);
|
||||
connect(mClose, &QAction::triggered, [] {
|
||||
QWidget *window = QApplication::activeWindow();
|
||||
if (!window)
|
||||
@ -151,7 +496,7 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
});
|
||||
|
||||
mSave = file->addAction(tr("Save"));
|
||||
mSave->setShortcut(QKeySequence::Save);
|
||||
saveHotkey.use(mSave);
|
||||
mSave->setEnabled(false);
|
||||
connect(mSave, &QAction::triggered, [this] {
|
||||
static_cast<EditorWindow *>(window())->widget()->save();
|
||||
@ -162,7 +507,7 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
#ifndef Q_OS_MAC
|
||||
QAction *quit = file->addAction(tr("Exit"));
|
||||
quit->setMenuRole(QAction::QuitRole);
|
||||
quit->setShortcut(QKeySequence::Quit);
|
||||
quitHotkey.use(quit);
|
||||
connect(quit, &QAction::triggered, &QApplication::closeAllWindows);
|
||||
#endif
|
||||
|
||||
@ -170,7 +515,7 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
QMenu *edit = addMenu(tr("Edit"));
|
||||
|
||||
mUndo = edit->addAction(tr("Undo"));
|
||||
mUndo->setShortcut(QKeySequence::Undo);
|
||||
undoHotkey.use(mUndo);
|
||||
connect(mUndo, &QAction::triggered, [] {
|
||||
QWidget *widget = QApplication::focusWidget();
|
||||
if (TextEditor *editor = qobject_cast<TextEditor *>(widget)) {
|
||||
@ -183,7 +528,7 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
});
|
||||
|
||||
mRedo = edit->addAction(tr("Redo"));
|
||||
mRedo->setShortcut(QKeySequence::Redo);
|
||||
redoHotkey.use(mRedo);
|
||||
connect(mRedo, &QAction::triggered, [this] {
|
||||
QWidget *widget = QApplication::focusWidget();
|
||||
if (TextEditor *editor = qobject_cast<TextEditor *>(widget)) {
|
||||
@ -198,7 +543,7 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
edit->addSeparator();
|
||||
|
||||
mCut = edit->addAction(tr("Cut"));
|
||||
mCut->setShortcut(QKeySequence::Cut);
|
||||
cutHotkey.use(mCut);
|
||||
connect(mCut, &QAction::triggered, [] {
|
||||
QWidget *widget = QApplication::focusWidget();
|
||||
if (TextEditor *editor = qobject_cast<TextEditor *>(widget)) {
|
||||
@ -211,7 +556,7 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
});
|
||||
|
||||
mCopy = edit->addAction(tr("Copy"));
|
||||
mCopy->setShortcut(QKeySequence::Copy);
|
||||
copyHotkey.use(mCopy);
|
||||
connect(mCopy, &QAction::triggered, [] {
|
||||
QWidget *widget = QApplication::focusWidget();
|
||||
if (TextEditor *editor = qobject_cast<TextEditor *>(widget)) {
|
||||
@ -226,7 +571,7 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
});
|
||||
|
||||
mPaste = edit->addAction(tr("Paste"));
|
||||
mPaste->setShortcut(QKeySequence::Paste);
|
||||
pasteHotkey.use(mPaste);
|
||||
connect(mPaste, &QAction::triggered, [] {
|
||||
QWidget *widget = QApplication::focusWidget();
|
||||
if (TextEditor *editor = qobject_cast<TextEditor *>(widget)) {
|
||||
@ -239,7 +584,7 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
});
|
||||
|
||||
mSelectAll = edit->addAction(tr("Select All"));
|
||||
mSelectAll->setShortcut(QKeySequence::SelectAll);
|
||||
selectAllHotkey.use(mSelectAll);
|
||||
connect(mSelectAll, &QAction::triggered, [] {
|
||||
QWidget *widget = QApplication::focusWidget();
|
||||
if (TextEditor *editor = qobject_cast<TextEditor *>(widget)) {
|
||||
@ -255,7 +600,7 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
|
||||
mFind = edit->addAction(tr("Find..."));
|
||||
mFind->setObjectName("Find");
|
||||
mFind->setShortcut(QKeySequence::Find);
|
||||
findHotkey.use(mFind);
|
||||
connect(mFind, &QAction::triggered, [] {
|
||||
QWidget *widget = QApplication::activeWindow();
|
||||
if (MainWindow *window = qobject_cast<MainWindow *>(widget)) {
|
||||
@ -266,7 +611,7 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
});
|
||||
|
||||
mFindNext = edit->addAction(tr("Find Next"));
|
||||
mFindNext->setShortcut(QKeySequence::FindNext);
|
||||
findNextHotkey.use(mFindNext);
|
||||
connect(mFindNext, &QAction::triggered, [] {
|
||||
QWidget *widget = QApplication::activeWindow();
|
||||
if (MainWindow *window = qobject_cast<MainWindow *>(widget)) {
|
||||
@ -277,7 +622,7 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
});
|
||||
|
||||
mFindPrevious = edit->addAction(tr("Find Previous"));
|
||||
mFindPrevious->setShortcut(QKeySequence::FindPrevious);
|
||||
findPreviousHotkey.use(mFindPrevious);
|
||||
connect(mFindPrevious, &QAction::triggered, [] {
|
||||
QWidget *widget = QApplication::activeWindow();
|
||||
if (MainWindow *window = qobject_cast<MainWindow *>(widget)) {
|
||||
@ -288,7 +633,7 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
});
|
||||
|
||||
mFindSelection = edit->addAction(tr("Use Selection for Find"));
|
||||
mFindSelection->setShortcut(tr("Ctrl+E"));
|
||||
findSelectionHotkey.use(mFindSelection);
|
||||
connect(mFindSelection, &QAction::triggered, [this] {
|
||||
QWidget *widget = QApplication::focusWidget();
|
||||
if (TextEditor *editor = qobject_cast<TextEditor *>(widget)) {
|
||||
@ -307,7 +652,7 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
QMenu *viewMenu = addMenu(tr("View"));
|
||||
|
||||
mRefresh = viewMenu->addAction(tr("Refresh"));
|
||||
mRefresh->setShortcut(QKeySequence::Refresh);
|
||||
refreshHotkey.use(mRefresh);
|
||||
connect(mRefresh, &QAction::triggered, [this] {
|
||||
view()->refresh();
|
||||
});
|
||||
@ -315,6 +660,7 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
viewMenu->addSeparator();
|
||||
|
||||
mToggleLog = viewMenu->addAction(tr("Show Log"));
|
||||
toggleLogHotkey.use(mToggleLog);
|
||||
connect(mToggleLog, &QAction::triggered, [this] {
|
||||
RepoView *view = this->view();
|
||||
view->setLogVisible(!view->isLogVisible());
|
||||
@ -322,6 +668,7 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
|
||||
mToggleMaximize = new StateAction(tr("Normal"), tr("Maximize"), viewMenu);
|
||||
viewMenu->addAction(mToggleMaximize);
|
||||
toggleMaximizeHotkey.use(mToggleMaximize);
|
||||
mToggleMaximize->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_M));
|
||||
connect(mToggleMaximize, &QAction::triggered, [this] {
|
||||
bool maximize = mToggleMaximize->isActive();
|
||||
@ -336,6 +683,7 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
});
|
||||
|
||||
mToggleView = viewMenu->addAction(tr("Show Tree View"));
|
||||
toggleViewHotkey.use(mToggleView);
|
||||
connect(mToggleView, &QAction::triggered, [this] {
|
||||
RepoView *view = this->view();
|
||||
bool diff = (view->viewMode() == RepoView::DoubleTree);
|
||||
@ -346,7 +694,7 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
QMenu *repository = addMenu(tr("Repository"));
|
||||
|
||||
mConfigureRepository = repository->addAction(tr("Configure Repository..."));
|
||||
mConfigureRepository->setMenuRole(QAction::NoRole);
|
||||
configureRepositoryHotkey.use(mConfigureRepository);
|
||||
connect(mConfigureRepository, &QAction::triggered, [this] {
|
||||
view()->configureSettings();
|
||||
});
|
||||
@ -354,13 +702,13 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
repository->addSeparator();
|
||||
|
||||
mStageAll = repository->addAction(tr("Stage All"));
|
||||
mStageAll->setShortcut(tr("Ctrl++"));
|
||||
stageAllHotkey.use(mStageAll);
|
||||
connect(mStageAll, &QAction::triggered, [this] {
|
||||
view()->stage();
|
||||
});
|
||||
|
||||
mUnstageAll = repository->addAction(tr("Unstage All"));
|
||||
mUnstageAll->setShortcut(tr("Ctrl+-"));
|
||||
unstageAllHotkey.use(mUnstageAll);
|
||||
connect(mUnstageAll, &QAction::triggered, [this] {
|
||||
view()->unstage();
|
||||
});
|
||||
@ -368,13 +716,13 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
repository->addSeparator();
|
||||
|
||||
mCommit = repository->addAction(tr("Commit"));
|
||||
mCommit->setShortcut(tr("Ctrl+Shift+C"));
|
||||
commitHotkey.use(mCommit);
|
||||
connect(mCommit, &QAction::triggered, [this] {
|
||||
view()->commit();
|
||||
});
|
||||
|
||||
mAmendCommit = repository->addAction(tr("Amend Commit"));
|
||||
mAmendCommit->setShortcut(tr("Ctrl+Shift+A"));
|
||||
amendCommitHotkey.use(mAmendCommit);
|
||||
connect(mAmendCommit, &QAction::triggered, [this] {
|
||||
view()->amendCommit();
|
||||
});
|
||||
@ -383,6 +731,7 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
|
||||
QMenu *lfs = repository->addMenu(tr("Git LFS"));
|
||||
mLfsUnlock = lfs->addAction(tr("Remove all locks"));
|
||||
lfsUnlockHotkey.use(mLfsUnlock);
|
||||
connect(mLfsUnlock, &QAction::triggered, [this] {
|
||||
view()->lfsSetLocked(view()->repo().lfsLocks().values(), false);
|
||||
});
|
||||
@ -390,6 +739,7 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
lfs->addSeparator();
|
||||
|
||||
mLfsInitialize = lfs->addAction(tr("Initialize"));
|
||||
lfsInitializeHotkey.use(mLfsInitialize);
|
||||
connect(mLfsInitialize, &QAction::triggered, [this] {
|
||||
view()->lfsInitialize();
|
||||
});
|
||||
@ -399,6 +749,7 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
|
||||
mConfigureRemotes = remote->addAction(tr("Configure Remotes..."));
|
||||
mConfigureRemotes->setMenuRole(QAction::NoRole);
|
||||
configureRemotesHotkey.use(mConfigureRemotes);
|
||||
connect(mConfigureRemotes, &QAction::triggered, [this] {
|
||||
view()->configureSettings(ConfigDialog::Remotes);
|
||||
});
|
||||
@ -406,19 +757,19 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
remote->addSeparator();
|
||||
|
||||
mFetch = remote->addAction(tr("Fetch"));
|
||||
mFetch->setShortcut(tr("Ctrl+Shift+Alt+F"));
|
||||
fetchHotkey.use(mFetch);
|
||||
connect(mFetch, &QAction::triggered, [this] {
|
||||
view()->fetch();
|
||||
});
|
||||
|
||||
mFetchAll = remote->addAction(tr("Fetch All"));
|
||||
mFetchAll->setShortcut(tr("Ctrl+Shift+Alt+A"));
|
||||
fetchAllHotkey.use(mFetchAll);
|
||||
connect(mFetchAll, &QAction::triggered, [this] {
|
||||
view()->fetchAll();
|
||||
});
|
||||
|
||||
mFetchFrom = remote->addAction(tr("Fetch From..."));
|
||||
mFetchFrom->setShortcut(tr("Ctrl+Shift+F"));
|
||||
fetchFromHotkey.use(mFetchFrom);
|
||||
connect(mFetchFrom, &QAction::triggered, [this] {
|
||||
RemoteDialog *dialog = new RemoteDialog(RemoteDialog::Fetch, view());
|
||||
dialog->open();
|
||||
@ -427,13 +778,13 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
remote->addSeparator();
|
||||
|
||||
mPull = remote->addAction(tr("Pull"));
|
||||
mPull->setShortcut(tr("Ctrl+Shift+Alt+L"));
|
||||
pullHotkey.use(mPull);
|
||||
connect(mPull, &QAction::triggered, [this] {
|
||||
view()->pull();
|
||||
});
|
||||
|
||||
mPullFrom = remote->addAction(tr("Pull From..."));
|
||||
mPullFrom->setShortcut(tr("Ctrl+Shift+L"));
|
||||
pullFromHotkey.use(mPullFrom);
|
||||
connect(mPullFrom, &QAction::triggered, [this] {
|
||||
RemoteDialog *dialog = new RemoteDialog(RemoteDialog::Pull, view());
|
||||
dialog->open();
|
||||
@ -442,13 +793,13 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
remote->addSeparator();
|
||||
|
||||
mPush = remote->addAction(tr("Push"));
|
||||
mPush->setShortcut(tr("Ctrl+Shift+Alt+P"));
|
||||
pushHotkey.use(mPush);
|
||||
connect(mPush, &QAction::triggered, [this] {
|
||||
view()->push();
|
||||
});
|
||||
|
||||
mPushTo = remote->addAction(tr("Push To..."));
|
||||
mPushTo->setShortcut(tr("Ctrl+Shift+P"));
|
||||
pushToHotkey.use(mPushTo);
|
||||
connect(mPushTo, &QAction::triggered, [this] {
|
||||
RemoteDialog *dialog = new RemoteDialog(RemoteDialog::Push, view());
|
||||
dialog->open();
|
||||
@ -459,11 +810,13 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
|
||||
mConfigureBranches = branch->addAction(tr("Configure Branches..."));
|
||||
mConfigureBranches->setMenuRole(QAction::NoRole);
|
||||
configureBranchesHotkey.use(mConfigureBranches);
|
||||
connect(mConfigureBranches, &QAction::triggered, [this] {
|
||||
view()->configureSettings(ConfigDialog::Branches);
|
||||
});
|
||||
|
||||
mNewBranch = branch->addAction(tr("New Branch..."));
|
||||
newBranchHotkey.use(mNewBranch);
|
||||
connect(mNewBranch, &QAction::triggered, [this] {
|
||||
view()->promptToCreateBranch();
|
||||
});
|
||||
@ -471,7 +824,7 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
branch->addSeparator();
|
||||
|
||||
mCheckoutCurrent = branch->addAction(tr("Checkout Current"));
|
||||
mCheckoutCurrent->setShortcut(tr("Ctrl+Shift+Alt+H"));
|
||||
checkoutCurrentHotkey.use(mCheckoutCurrent);
|
||||
connect(mCheckoutCurrent, &QAction::triggered, [this] {
|
||||
RepoView *view = this->view();
|
||||
git::Reference ref = view->reference();
|
||||
@ -482,7 +835,7 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
});
|
||||
|
||||
mCheckout = branch->addAction(tr("Checkout..."));
|
||||
mCheckout->setShortcut(tr("Ctrl+Shift+H"));
|
||||
checkoutHotkey.use(mCheckout);
|
||||
connect(mCheckout, &QAction::triggered, [this] {
|
||||
view()->promptToCheckout();
|
||||
});
|
||||
@ -490,7 +843,7 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
branch->addSeparator();
|
||||
|
||||
mMerge = branch->addAction(tr("Merge..."));
|
||||
mMerge->setShortcut(tr("Ctrl+Shift+M"));
|
||||
mergeHotkey.use(mMerge);
|
||||
connect(mMerge, &QAction::triggered, [this] {
|
||||
RepoView *view = this->view();
|
||||
MergeDialog *dialog =
|
||||
@ -503,7 +856,7 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
});
|
||||
|
||||
mRebase = branch->addAction(tr("Rebase..."));
|
||||
mRebase->setShortcut(tr("Ctrl+Shift+R"));
|
||||
rebaseHotkey.use(mRebase);
|
||||
connect(mRebase, &QAction::triggered, [this] {
|
||||
RepoView *view = this->view();
|
||||
MergeDialog *dialog =
|
||||
@ -516,7 +869,7 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
});
|
||||
|
||||
mSquash = branch->addAction(tr("Squash..."));
|
||||
mSquash->setShortcut(tr("Ctrl+Shift+Q"));
|
||||
squashHotkey.use(mSquash);
|
||||
connect(mSquash, &QAction::triggered, [this] {
|
||||
RepoView *view = this->view();
|
||||
MergeDialog *dialog =
|
||||
@ -531,7 +884,7 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
branch->addSeparator();
|
||||
|
||||
mAbort = branch->addAction(tr("Abort Merge"));
|
||||
mAbort->setShortcut(tr("Ctrl+Shift+A"));
|
||||
abortHotkey.use(mAbort);
|
||||
connect(mAbort, &QAction::triggered, [this] {
|
||||
view()->mergeAbort();
|
||||
});
|
||||
@ -541,6 +894,7 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
|
||||
mConfigureSubmodules = submodule->addAction(tr("Configure Submodules..."));
|
||||
mConfigureSubmodules->setMenuRole(QAction::NoRole);
|
||||
configureSubmodulesHotkey.use(mConfigureSubmodules);
|
||||
connect(mConfigureSubmodules, &QAction::triggered, [this] {
|
||||
view()->configureSettings(ConfigDialog::Submodules);
|
||||
});
|
||||
@ -548,13 +902,13 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
submodule->addSeparator();
|
||||
|
||||
mUpdateSubmodules = submodule->addAction(tr("Update All"));
|
||||
mUpdateSubmodules->setShortcut(tr("Ctrl+Shift+Alt+U"));
|
||||
updateSubmodulesHotkey.use(mUpdateSubmodules);
|
||||
connect(mUpdateSubmodules, &QAction::triggered, [this] {
|
||||
view()->updateSubmodules();
|
||||
});
|
||||
|
||||
mInitSubmodules = submodule->addAction(tr("Update..."));
|
||||
mInitSubmodules->setShortcut(tr("Ctrl+Shift+U"));
|
||||
initSubmodulesHotkey.use(mInitSubmodules);
|
||||
connect(mInitSubmodules, &QAction::triggered, [this] {
|
||||
RepoView *view = this->view();
|
||||
git::Repository repo = view->repo();
|
||||
@ -591,6 +945,7 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
QMenu *stash = addMenu(tr("Stash"));
|
||||
|
||||
mShowStashes = stash->addAction(tr("Show Stashes"));
|
||||
showStashesHotkey.use(mShowStashes);
|
||||
connect(mShowStashes, &QAction::triggered, [this] {
|
||||
RepoView *view = this->view();
|
||||
view->selectReference(view->repo().stashRef());
|
||||
@ -599,13 +954,13 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
stash->addSeparator();
|
||||
|
||||
mStash = stash->addAction(tr("Stash..."));
|
||||
mStash->setShortcut(tr("Ctrl+Shift+T"));
|
||||
stashHotkey.use(mStash);
|
||||
connect(mStash, &QAction::triggered, [this] {
|
||||
view()->promptToStash();
|
||||
});
|
||||
|
||||
mStashPop = stash->addAction(tr("Pop Stash"));
|
||||
mStashPop->setShortcut(tr("Ctrl+Shift+Alt+T"));
|
||||
stashPopHotkey.use(mStashPop);
|
||||
connect(mStashPop, &QAction::triggered, [this] {
|
||||
view()->popStash();
|
||||
});
|
||||
@ -614,14 +969,14 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
QMenu *historyMenu = addMenu(tr("History"));
|
||||
|
||||
mPrev = historyMenu->addAction(tr("Back"));
|
||||
mPrev->setShortcut(QKeySequence::Back);
|
||||
prevHotkey.use(mPrev);
|
||||
mPrev->setEnabled(false);
|
||||
connect(mPrev, &QAction::triggered, [this] {
|
||||
view()->history()->prev();
|
||||
});
|
||||
|
||||
mNext = historyMenu->addAction(tr("Forward"));
|
||||
mNext->setShortcut(QKeySequence::Forward);
|
||||
nextHotkey.use(mNext);
|
||||
mNext->setEnabled(false);
|
||||
connect(mNext, &QAction::triggered, [this] {
|
||||
view()->history()->next();
|
||||
@ -630,7 +985,7 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
// Window
|
||||
QMenu *windowMenu = addMenu(tr("Window"));
|
||||
mPrevTab = windowMenu->addAction(tr("Show Previous Tab"));
|
||||
mPrevTab->setShortcut(QKeySequence::PreviousChild);
|
||||
prevTabHotkey.use(mPrevTab);
|
||||
connect(mPrevTab, &QAction::triggered, [this] {
|
||||
MainWindow *win = static_cast<MainWindow *>(window());
|
||||
TabWidget *tabs = win->tabWidget();
|
||||
@ -639,7 +994,7 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
});
|
||||
|
||||
mNextTab = windowMenu->addAction(tr("Show Next Tab"));
|
||||
mNextTab->setShortcut(QKeySequence::NextChild);
|
||||
nextTabHotkey.use(mNextTab);
|
||||
connect(mNextTab, &QAction::triggered, [this] {
|
||||
MainWindow *win = static_cast<MainWindow *>(window());
|
||||
TabWidget *tabs = win->tabWidget();
|
||||
@ -650,13 +1005,13 @@ MenuBar::MenuBar(QWidget *parent)
|
||||
windowMenu->addSeparator();
|
||||
|
||||
QAction *chooser = windowMenu->addAction(tr("Show Repository Chooser..."));
|
||||
chooser->setShortcut(tr("Ctrl+Shift+O"));
|
||||
chooserHotkey.use(chooser);
|
||||
connect(chooser, &QAction::triggered, &StartDialog::openSharedInstance);
|
||||
|
||||
// Tools
|
||||
QMenu *tools = addMenu(tr("Tools"));
|
||||
QAction *preferences = tools->addAction(tr("Options..."));
|
||||
preferences->setMenuRole(QAction::PreferencesRole);
|
||||
preferencesHotkey.use(preferences);
|
||||
connect(preferences, &QAction::triggered, [] {
|
||||
SettingsDialog::openSharedInstance();
|
||||
});
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "dialogs/PullRequestDialog.h"
|
||||
#include "git/Branch.h"
|
||||
#include "git/Commit.h"
|
||||
#include "ui/HotkeyManager.h"
|
||||
#include <QAction>
|
||||
#include <QButtonGroup>
|
||||
#include <QHBoxLayout>
|
||||
@ -801,6 +802,18 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
static Hotkey terminalHotkey = HotkeyManager::registerHotkey(
|
||||
nullptr,
|
||||
"tools/terminal",
|
||||
"Tools/Open Terminal"
|
||||
);
|
||||
|
||||
static Hotkey fileManagerHotkey = HotkeyManager::registerHotkey(
|
||||
nullptr,
|
||||
"tools/fileManager",
|
||||
"Tools/Open File Manager"
|
||||
);
|
||||
|
||||
} // anon. namespace
|
||||
|
||||
ToolBar::ToolBar(MainWindow *parent)
|
||||
@ -948,7 +961,13 @@ ToolBar::ToolBar(MainWindow *parent)
|
||||
connect(mTerminalButton, &Button::clicked, [this] {
|
||||
currentView()->openTerminal();
|
||||
});
|
||||
|
||||
|
||||
QShortcut *shortcut = new QShortcut(this);
|
||||
terminalHotkey.use(shortcut);
|
||||
connect(shortcut, &QShortcut::activated, mTerminalButton, &Button::click);
|
||||
|
||||
addWidget(new Spacer(4, this));
|
||||
|
||||
mFileManagerButton = new FileManagerButton(this);
|
||||
mFileManagerButton->setToolTip(tr("Open file manager"));
|
||||
addWidget(mFileManagerButton);
|
||||
@ -956,6 +975,10 @@ ToolBar::ToolBar(MainWindow *parent)
|
||||
currentView()->openFileManager();
|
||||
});
|
||||
|
||||
shortcut = new QShortcut(this);
|
||||
fileManagerHotkey.use(shortcut);
|
||||
connect(shortcut, &QShortcut::activated, mFileManagerButton, &Button::click);
|
||||
|
||||
addWidget(new Spacer(4, this));
|
||||
|
||||
mConfigButton = new SettingsButton(this);
|
||||
|
Loading…
Reference in New Issue
Block a user