Merge pull request #323 from BigBahss/shortcuts-editor
Shortcuts Editor
This commit is contained in:
commit
b854e5e597
20 changed files with 1259 additions and 32 deletions
|
@ -18,6 +18,7 @@ The **"Breaking Changes"** listed below are changes that have been made in the d
|
|||
- The window sizes and positions of the tileset editor, palette editor, and region map editor are now stored in `porymap.cfg`.
|
||||
- Add ruler tool for measuring metatile distance in events tab (Right-click to turn on/off, left-click to lock in place).
|
||||
- Add delete button to wild pokemon encounters tab.
|
||||
- Add shortcut customization via `Options -> Edit Shortcuts`.
|
||||
|
||||
### Changed
|
||||
- Holding `shift` now toggles "Smart Path" drawing; when the "Smart Paths" checkbox is checked, holding `shift` will temporarily disable it.
|
||||
|
|
BIN
docsrc/manual/images/shortcuts/edit-shortcuts.gif
Normal file
BIN
docsrc/manual/images/shortcuts/edit-shortcuts.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 591 KiB |
|
@ -2,8 +2,16 @@
|
|||
Shortcuts
|
||||
*********
|
||||
|
||||
Porymap has many shortcuts and it can sometimes be hard to keep track of them all.
|
||||
Here is a comprehensive list of the shortcuts provided all in one place for your convenience.
|
||||
Porymap has many keyboard shortcuts set by default, and even more that can be customized yourself. You can view and customize your shortcuts by going to *Options -> Edit Shortcuts*. Shortcut actions are grouped together by the window that they are used in (Main Window, Tileset Editor...). You can set up to 2 shortcuts per action, but you cannot have duplicate shortcuts set within the same window. If you enter a shortcut that is already in use, Porymap will prompt you cancel or overwrite the old shortcut. You can also restore your shortcuts to the defaults.
|
||||
|
||||
.. figure:: images/shortcuts/edit-shortcuts.gif
|
||||
:alt: Edit Shortcuts
|
||||
|
||||
Edit Shortcuts
|
||||
|
||||
Your shortcuts are stored at ``%Appdata%\pret\porymap\porymap.shortcuts.cfg`` on Windows and ``~/Library/Application\ Support/pret/porymap/porymap.shortcuts.cfg`` on macOS).
|
||||
|
||||
For reference, here is a comprehensive list of the default shortcuts set in Porymap.
|
||||
|
||||
Main Window
|
||||
-----------
|
||||
|
|
|
@ -2656,6 +2656,8 @@
|
|||
<addaction name="actionUse_Encounter_Json"/>
|
||||
<addaction name="actionMonitor_Project_Files"/>
|
||||
<addaction name="actionUse_Poryscript"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionEdit_Shortcuts"/>
|
||||
</widget>
|
||||
<addaction name="menuFile"/>
|
||||
<addaction name="menuEdit"/>
|
||||
|
@ -2922,6 +2924,11 @@
|
|||
<string>Export Map Stitch Image...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionEdit_Shortcuts">
|
||||
<property name="text">
|
||||
<string>Edit Shortcuts...</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<customwidgets>
|
||||
|
|
89
forms/shortcutseditor.ui
Normal file
89
forms/shortcutseditor.ui
Normal file
|
@ -0,0 +1,89 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ShortcutsEditor</class>
|
||||
<widget class="QMainWindow" name="ShortcutsEditor">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>700</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Shortcuts Editor</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QScrollArea" name="scrollArea_Shortcuts">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents_Shortcuts">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>794</width>
|
||||
<height>642</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Box</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::RestoreDefaults</set>
|
||||
</property>
|
||||
<property name="centerButtons">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -5,6 +5,8 @@
|
|||
#include <QObject>
|
||||
#include <QByteArrayList>
|
||||
#include <QSize>
|
||||
#include <QKeySequence>
|
||||
#include <QMultiMap>
|
||||
|
||||
enum MapSortOrder {
|
||||
Group = 0,
|
||||
|
@ -192,4 +194,53 @@ private:
|
|||
|
||||
extern ProjectConfig projectConfig;
|
||||
|
||||
class QAction;
|
||||
class Shortcut;
|
||||
|
||||
class ShortcutsConfig : public KeyValueConfigBase
|
||||
{
|
||||
public:
|
||||
ShortcutsConfig() :
|
||||
user_shortcuts({ }),
|
||||
default_shortcuts({ })
|
||||
{ }
|
||||
|
||||
virtual void reset() override { user_shortcuts.clear(); }
|
||||
|
||||
// Call this before applying user shortcuts so that the user can restore defaults.
|
||||
void setDefaultShortcuts(const QObjectList &objects);
|
||||
QList<QKeySequence> defaultShortcuts(const QObject *object) const;
|
||||
|
||||
void setUserShortcuts(const QObjectList &objects);
|
||||
void setUserShortcuts(const QMultiMap<const QObject *, QKeySequence> &objects_keySequences);
|
||||
QList<QKeySequence> userShortcuts(const QObject *object) const;
|
||||
|
||||
protected:
|
||||
virtual QString getConfigFilepath() override;
|
||||
virtual void parseConfigKeyValue(QString key, QString value) override;
|
||||
virtual QMap<QString, QString> getKeyValueMap() override;
|
||||
virtual void onNewConfigFileCreated() override { };
|
||||
virtual void setUnreadKeys() override { };
|
||||
|
||||
private:
|
||||
QMultiMap<QString, QKeySequence> user_shortcuts;
|
||||
QMultiMap<QString, QKeySequence> default_shortcuts;
|
||||
|
||||
enum StoreType {
|
||||
User,
|
||||
Default
|
||||
};
|
||||
|
||||
QString cfgKey(const QObject *object) const;
|
||||
QList<QKeySequence> currentShortcuts(const QObject *object) const;
|
||||
|
||||
void storeShortcutsFromList(StoreType storeType, const QObjectList &objects);
|
||||
void storeShortcuts(
|
||||
StoreType storeType,
|
||||
const QString &cfgKey,
|
||||
const QList<QKeySequence> &keySequences);
|
||||
};
|
||||
|
||||
extern ShortcutsConfig shortcutsConfig;
|
||||
|
||||
#endif // CONFIG_H
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "filterchildrenproxymodel.h"
|
||||
#include "newmappopup.h"
|
||||
#include "newtilesetdialog.h"
|
||||
#include "shortcutseditor.h"
|
||||
|
||||
namespace Ui {
|
||||
class MainWindow;
|
||||
|
@ -129,6 +130,7 @@ private slots:
|
|||
void onNewMapCreated();
|
||||
void onMapCacheCleared();
|
||||
void onMapRulerStatusChanged(const QString &);
|
||||
void applyUserShortcuts();
|
||||
|
||||
void on_action_NewMap_triggered();
|
||||
void on_actionNew_Tileset_triggered();
|
||||
|
@ -148,6 +150,7 @@ private slots:
|
|||
void on_actionUse_Encounter_Json_triggered(bool checked);
|
||||
void on_actionMonitor_Project_Files_triggered(bool checked);
|
||||
void on_actionUse_Poryscript_triggered(bool checked);
|
||||
void on_actionEdit_Shortcuts_triggered();
|
||||
|
||||
void on_mainTabBar_tabBarClicked(int index);
|
||||
|
||||
|
@ -235,6 +238,7 @@ private:
|
|||
QLabel *label_MapRulerStatus;
|
||||
TilesetEditor *tilesetEditor = nullptr;
|
||||
RegionMapEditor *regionMapEditor = nullptr;
|
||||
ShortcutsEditor *shortcutsEditor = nullptr;
|
||||
MapImageExporter *mapImageExporter = nullptr;
|
||||
FilterChildrenProxyModel *mapListProxyModel;
|
||||
NewMapPopup *newmapprompt = nullptr;
|
||||
|
@ -293,11 +297,12 @@ private:
|
|||
|
||||
void initWindow();
|
||||
void initCustomUI();
|
||||
void initExtraShortcuts();
|
||||
void initExtraSignals();
|
||||
void initEditor();
|
||||
void initMiscHeapObjects();
|
||||
void initMapSortOrder();
|
||||
void initShortcuts();
|
||||
void initExtraShortcuts();
|
||||
void setProjectSpecificUIVisibility();
|
||||
void loadUserSettings();
|
||||
void applyMapListFilter(QString filterText);
|
||||
|
@ -309,9 +314,16 @@ private:
|
|||
void closeSupplementaryWindows();
|
||||
void setWindowDisabled(bool);
|
||||
|
||||
void initTilesetEditor();
|
||||
bool initRegionMapEditor();
|
||||
void initShortcutsEditor();
|
||||
void connectSubEditorsToShortcutsEditor();
|
||||
|
||||
bool isProjectOpen();
|
||||
void showExportMapImageWindow(bool stitchMode);
|
||||
void redrawMetatileSelection();
|
||||
|
||||
QObjectList shortcutableObjects() const;
|
||||
};
|
||||
|
||||
enum MapListUserRoles {
|
||||
|
|
52
include/ui/multikeyedit.h
Normal file
52
include/ui/multikeyedit.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
#ifndef MULTIKEYEDIT_H
|
||||
#define MULTIKEYEDIT_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QKeySequenceEdit>
|
||||
|
||||
class QLineEdit;
|
||||
|
||||
|
||||
// A collection of QKeySequenceEdit's laid out horizontally.
|
||||
class MultiKeyEdit : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MultiKeyEdit(QWidget *parent = nullptr, int fieldCount = 2);
|
||||
|
||||
bool eventFilter(QObject *watched, QEvent *event) override;
|
||||
|
||||
int fieldCount() const;
|
||||
void setFieldCount(int count);
|
||||
QList<QKeySequence> keySequences() const;
|
||||
bool removeOne(const QKeySequence &keySequence);
|
||||
bool contains(const QKeySequence &keySequence) const;
|
||||
void setContextMenuPolicy(Qt::ContextMenuPolicy policy);
|
||||
bool isClearButtonEnabled() const;
|
||||
void setClearButtonEnabled(bool enable);
|
||||
|
||||
public slots:
|
||||
void clear();
|
||||
void setKeySequences(const QList<QKeySequence> &keySequences);
|
||||
void addKeySequence(const QKeySequence &keySequence);
|
||||
|
||||
signals:
|
||||
void keySequenceChanged(const QKeySequence &keySequence);
|
||||
void editingFinished();
|
||||
void customContextMenuRequested(const QPoint &pos);
|
||||
|
||||
private:
|
||||
QVector<QKeySequenceEdit *> keySequenceEdit_vec;
|
||||
QList<QKeySequence> keySequence_list; // Used to track changes
|
||||
|
||||
void addNewKeySequenceEdit();
|
||||
void alignKeySequencesLeft();
|
||||
void setFocusToLastNonEmptyKeySequenceEdit();
|
||||
|
||||
private slots:
|
||||
void onEditingFinished();
|
||||
void showDefaultContextMenu(QLineEdit *lineEdit, const QPoint &pos);
|
||||
};
|
||||
|
||||
#endif // MULTIKEYEDIT_H
|
|
@ -47,6 +47,11 @@ public:
|
|||
|
||||
void resize(int width, int height);
|
||||
|
||||
QObjectList shortcutableObjects() const;
|
||||
|
||||
public slots:
|
||||
void applyUserShortcuts();
|
||||
|
||||
private:
|
||||
Ui::RegionMapEditor *ui;
|
||||
Project *project;
|
||||
|
@ -81,6 +86,7 @@ private:
|
|||
RegionMapPixmapItem *region_map_item = nullptr;
|
||||
CityMapPixmapItem *city_map_item = nullptr;
|
||||
|
||||
void initShortcuts();
|
||||
void displayRegionMap();
|
||||
void displayRegionMapImage();
|
||||
void displayRegionMapLayout();
|
||||
|
|
71
include/ui/shortcut.h
Normal file
71
include/ui/shortcut.h
Normal file
|
@ -0,0 +1,71 @@
|
|||
#ifndef SHORTCUT_H
|
||||
#define SHORTCUT_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QKeySequence>
|
||||
#include <QShortcut>
|
||||
|
||||
|
||||
// Alternative to QShortcut that adds support for multiple key sequences.
|
||||
// Use this to allow the shortcut to be editable in ShortcutsEditor.
|
||||
class Shortcut : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DECLARE_PRIVATE(QShortcut)
|
||||
Q_PROPERTY(QKeySequence key READ key WRITE setKey)
|
||||
Q_PROPERTY(QString whatsThis READ whatsThis WRITE setWhatsThis)
|
||||
Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
|
||||
Q_PROPERTY(bool autoRepeat READ autoRepeat WRITE setAutoRepeat)
|
||||
Q_PROPERTY(Qt::ShortcutContext context READ context WRITE setContext)
|
||||
|
||||
public:
|
||||
explicit Shortcut(QWidget *parent);
|
||||
Shortcut(const QKeySequence &key, QWidget *parent,
|
||||
const char *member = nullptr, const char *ambiguousMember = nullptr,
|
||||
Qt::ShortcutContext shortcutContext = Qt::WindowShortcut);
|
||||
Shortcut(const QList<QKeySequence> &keys, QWidget *parent,
|
||||
const char *member = nullptr, const char *ambiguousMember = nullptr,
|
||||
Qt::ShortcutContext shortcutContext = Qt::WindowShortcut);
|
||||
~Shortcut();
|
||||
|
||||
void addKey(const QKeySequence &key);
|
||||
void setKey(const QKeySequence &key);
|
||||
QKeySequence key() const;
|
||||
|
||||
void addKeys(const QList<QKeySequence> &keys);
|
||||
void setKeys(const QList<QKeySequence> &keys);
|
||||
QList<QKeySequence> keys() const;
|
||||
|
||||
void setEnabled(bool enable);
|
||||
bool isEnabled() const;
|
||||
|
||||
void setContext(Qt::ShortcutContext context);
|
||||
Qt::ShortcutContext context() const;
|
||||
|
||||
void setWhatsThis(const QString &text);
|
||||
QString whatsThis() const;
|
||||
|
||||
void setAutoRepeat(bool on);
|
||||
bool autoRepeat() const;
|
||||
|
||||
int id() const;
|
||||
QList<int> ids() const;
|
||||
|
||||
inline QWidget *parentWidget() const
|
||||
{ return static_cast<QWidget *>(QObject::parent()); }
|
||||
|
||||
signals:
|
||||
void activated();
|
||||
void activatedAmbiguously();
|
||||
|
||||
protected:
|
||||
bool event(QEvent *e) override;
|
||||
|
||||
private:
|
||||
const char *sc_member;
|
||||
const char *sc_ambiguousmember;
|
||||
Qt::ShortcutContext sc_context;
|
||||
QVector<QShortcut *> sc_vec;
|
||||
};
|
||||
|
||||
#endif // SHORTCUT_H
|
60
include/ui/shortcutseditor.h
Normal file
60
include/ui/shortcutseditor.h
Normal file
|
@ -0,0 +1,60 @@
|
|||
#ifndef SHORTCUTSEDITOR_H
|
||||
#define SHORTCUTSEDITOR_H
|
||||
|
||||
#include "shortcut.h"
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QDialog>
|
||||
#include <QMap>
|
||||
#include <QHash>
|
||||
#include <QAction>
|
||||
|
||||
class QFormLayout;
|
||||
class MultiKeyEdit;
|
||||
class QAbstractButton;
|
||||
|
||||
|
||||
namespace Ui {
|
||||
class ShortcutsEditor;
|
||||
}
|
||||
|
||||
class ShortcutsEditor : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ShortcutsEditor(QWidget *parent = nullptr);
|
||||
explicit ShortcutsEditor(const QObjectList &shortcutableObjects, QWidget *parent = nullptr);
|
||||
~ShortcutsEditor();
|
||||
|
||||
void setShortcutableObjects(const QObjectList &shortcutableObjects);
|
||||
|
||||
signals:
|
||||
void shortcutsSaved();
|
||||
|
||||
private:
|
||||
Ui::ShortcutsEditor *ui;
|
||||
QWidget *main_container;
|
||||
QMultiMap<QString, const QObject *> labels_objects;
|
||||
QHash<QString, QFormLayout *> contexts_layouts;
|
||||
QHash<MultiKeyEdit *, const QObject *> multiKeyEdits_objects;
|
||||
|
||||
void parseObjectList(const QObjectList &objectList);
|
||||
QString getLabel(const QObject *object) const;
|
||||
bool stringPropertyIsNotEmpty(const QObject *object, const char *name) const;
|
||||
void populateMainContainer();
|
||||
QString getShortcutContext(const QObject *object) const;
|
||||
void addNewContextGroup(const QString &shortcutContext);
|
||||
void addNewMultiKeyEdit(const QObject *object, const QString &shortcutContext);
|
||||
QList<MultiKeyEdit *> siblings(MultiKeyEdit *multiKeyEdit) const;
|
||||
void promptUserOnDuplicateFound(MultiKeyEdit *current, MultiKeyEdit *sender);
|
||||
void removeKeySequence(const QKeySequence &keySequence, MultiKeyEdit *multiKeyEdit);
|
||||
void saveShortcuts();
|
||||
void resetShortcuts();
|
||||
|
||||
private slots:
|
||||
void checkForDuplicates(const QKeySequence &keySequence);
|
||||
void dialogButtonClicked(QAbstractButton *button);
|
||||
};
|
||||
|
||||
#endif // SHORTCUTSEDITOR_H
|
|
@ -42,6 +42,11 @@ public:
|
|||
void updateTilesets(QString primaryTilsetLabel, QString secondaryTilesetLabel);
|
||||
bool selectMetatile(uint16_t metatileId);
|
||||
|
||||
QObjectList shortcutableObjects() const;
|
||||
|
||||
public slots:
|
||||
void applyUserShortcuts();
|
||||
|
||||
private slots:
|
||||
void onHoveredMetatileChanged(uint16_t);
|
||||
void onHoveredMetatileCleared();
|
||||
|
@ -102,6 +107,8 @@ private:
|
|||
void initTileSelector();
|
||||
void initSelectedTileItem();
|
||||
void initMetatileLayersItem();
|
||||
void initShortcuts();
|
||||
void initExtraShortcuts();
|
||||
void restoreWindowState();
|
||||
void initMetatileHistory();
|
||||
void setTilesets(QString primaryTilesetLabel, QString secondaryTilesetLabel);
|
||||
|
@ -112,6 +119,7 @@ private:
|
|||
void refresh();
|
||||
void saveMetatileLabel();
|
||||
void closeEvent(QCloseEvent*);
|
||||
|
||||
Ui::TilesetEditor *ui;
|
||||
History<MetatileHistoryItem*> metatileHistory;
|
||||
TilesetEditorMetatileSelector *metatileSelector = nullptr;
|
||||
|
|
|
@ -71,6 +71,9 @@ SOURCES += src/core/block.cpp \
|
|||
src/ui/newtilesetdialog.cpp \
|
||||
src/ui/flowlayout.cpp \
|
||||
src/ui/mapruler.cpp \
|
||||
src/ui/shortcut.cpp \
|
||||
src/ui/shortcutseditor.cpp \
|
||||
src/ui/multikeyedit.cpp \
|
||||
src/config.cpp \
|
||||
src/editor.cpp \
|
||||
src/main.cpp \
|
||||
|
@ -140,6 +143,9 @@ HEADERS += include/core/block.h \
|
|||
include/ui/overlay.h \
|
||||
include/ui/flowlayout.h \
|
||||
include/ui/mapruler.h \
|
||||
include/ui/shortcut.h \
|
||||
include/ui/shortcutseditor.h \
|
||||
include/ui/multikeyedit.h \
|
||||
include/config.h \
|
||||
include/editor.h \
|
||||
include/mainwindow.h \
|
||||
|
@ -156,7 +162,8 @@ FORMS += forms/mainwindow.ui \
|
|||
forms/newmappopup.ui \
|
||||
forms/aboutporymap.ui \
|
||||
forms/newtilesetdialog.ui \
|
||||
forms/mapimageexporter.ui
|
||||
forms/mapimageexporter.ui \
|
||||
forms/shortcutseditor.ui
|
||||
|
||||
RESOURCES += \
|
||||
resources/images.qrc \
|
||||
|
|
132
src/config.cpp
132
src/config.cpp
|
@ -1,5 +1,6 @@
|
|||
#include "config.h"
|
||||
#include "log.h"
|
||||
#include "shortcut.h"
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFormLayout>
|
||||
|
@ -11,6 +12,8 @@
|
|||
#include <QTextStream>
|
||||
#include <QRegularExpression>
|
||||
#include <QStandardPaths>
|
||||
#include <QAction>
|
||||
#include <QAbstractButton>
|
||||
|
||||
KeyValueConfigBase::~KeyValueConfigBase() {
|
||||
|
||||
|
@ -36,7 +39,7 @@ void KeyValueConfigBase::load() {
|
|||
QTextStream in(&file);
|
||||
in.setCodec("UTF-8");
|
||||
QList<QString> configLines;
|
||||
QRegularExpression re("^(?<key>.+)=(?<value>.*)$");
|
||||
QRegularExpression re("^(?<key>[^=]+)=(?<value>.*)$");
|
||||
while (!in.atEnd()) {
|
||||
QString line = in.readLine().trimmed();
|
||||
int commentIndex = line.indexOf("#");
|
||||
|
@ -414,7 +417,7 @@ ProjectConfig projectConfig;
|
|||
|
||||
QString ProjectConfig::getConfigFilepath() {
|
||||
// porymap config file is in the same directory as porymap itself.
|
||||
return QDir(this->projectDir).filePath("porymap.project.cfg");;
|
||||
return QDir(this->projectDir).filePath("porymap.project.cfg");
|
||||
}
|
||||
|
||||
void ProjectConfig::parseConfigKeyValue(QString key, QString value) {
|
||||
|
@ -703,3 +706,128 @@ void ProjectConfig::setCustomScripts(QList<QString> scripts) {
|
|||
QList<QString> ProjectConfig::getCustomScripts() {
|
||||
return this->customScripts;
|
||||
}
|
||||
|
||||
ShortcutsConfig shortcutsConfig;
|
||||
|
||||
QString ShortcutsConfig::getConfigFilepath() {
|
||||
QString settingsPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
||||
QDir dir(settingsPath);
|
||||
if (!dir.exists())
|
||||
dir.mkpath(settingsPath);
|
||||
|
||||
QString configPath = dir.absoluteFilePath("porymap.shortcuts.cfg");
|
||||
|
||||
return configPath;
|
||||
}
|
||||
|
||||
void ShortcutsConfig::parseConfigKeyValue(QString key, QString value) {
|
||||
QStringList keySequences = value.split(' ');
|
||||
for (auto keySequence : keySequences)
|
||||
user_shortcuts.insert(key, keySequence);
|
||||
}
|
||||
|
||||
QMap<QString, QString> ShortcutsConfig::getKeyValueMap() {
|
||||
QMap<QString, QString> map;
|
||||
for (auto cfg_key : user_shortcuts.uniqueKeys()) {
|
||||
auto keySequences = user_shortcuts.values(cfg_key);
|
||||
QStringList keySequenceStrings;
|
||||
for (auto keySequence : keySequences)
|
||||
keySequenceStrings.append(keySequence.toString());
|
||||
map.insert(cfg_key, keySequenceStrings.join(' '));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
void ShortcutsConfig::setDefaultShortcuts(const QObjectList &objects) {
|
||||
storeShortcutsFromList(StoreType::Default, objects);
|
||||
save();
|
||||
}
|
||||
|
||||
QList<QKeySequence> ShortcutsConfig::defaultShortcuts(const QObject *object) const {
|
||||
return default_shortcuts.values(cfgKey(object));
|
||||
}
|
||||
|
||||
void ShortcutsConfig::setUserShortcuts(const QObjectList &objects) {
|
||||
storeShortcutsFromList(StoreType::User, objects);
|
||||
save();
|
||||
}
|
||||
|
||||
void ShortcutsConfig::setUserShortcuts(const QMultiMap<const QObject *, QKeySequence> &objects_keySequences) {
|
||||
for (auto *object : objects_keySequences.uniqueKeys())
|
||||
if (!object->objectName().isEmpty() && !object->objectName().startsWith("_q_"))
|
||||
storeShortcuts(StoreType::User, cfgKey(object), objects_keySequences.values(object));
|
||||
save();
|
||||
}
|
||||
|
||||
QList<QKeySequence> ShortcutsConfig::userShortcuts(const QObject *object) const {
|
||||
return user_shortcuts.values(cfgKey(object));
|
||||
}
|
||||
|
||||
void ShortcutsConfig::storeShortcutsFromList(StoreType storeType, const QObjectList &objects) {
|
||||
for (const auto *object : objects)
|
||||
if (!object->objectName().isEmpty() && !object->objectName().startsWith("_q_"))
|
||||
storeShortcuts(storeType, cfgKey(object), currentShortcuts(object));
|
||||
}
|
||||
|
||||
void ShortcutsConfig::storeShortcuts(
|
||||
StoreType storeType,
|
||||
const QString &cfgKey,
|
||||
const QList<QKeySequence> &keySequences)
|
||||
{
|
||||
bool storeUser = (storeType == User) || !user_shortcuts.contains(cfgKey);
|
||||
|
||||
if (storeType == Default)
|
||||
default_shortcuts.remove(cfgKey);
|
||||
if (storeUser)
|
||||
user_shortcuts.remove(cfgKey);
|
||||
|
||||
if (keySequences.isEmpty()) {
|
||||
if (storeType == Default)
|
||||
default_shortcuts.insert(cfgKey, QKeySequence());
|
||||
if (storeUser)
|
||||
user_shortcuts.insert(cfgKey, QKeySequence());
|
||||
} else {
|
||||
for (auto keySequence : keySequences) {
|
||||
if (storeType == Default)
|
||||
default_shortcuts.insert(cfgKey, keySequence);
|
||||
if (storeUser)
|
||||
user_shortcuts.insert(cfgKey, keySequence);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Creates a config key from the object's name prepended with the parent
|
||||
* window's object name, and converts camelCase to snake_case. */
|
||||
QString ShortcutsConfig::cfgKey(const QObject *object) const {
|
||||
auto cfg_key = QString();
|
||||
auto *parentWidget = static_cast<QWidget *>(object->parent());
|
||||
if (parentWidget)
|
||||
cfg_key = parentWidget->window()->objectName() + '_';
|
||||
cfg_key += object->objectName();
|
||||
|
||||
QRegularExpression re("[A-Z]");
|
||||
int i = cfg_key.indexOf(re, 1);
|
||||
while (i != -1) {
|
||||
if (cfg_key.at(i - 1) != '_')
|
||||
cfg_key.insert(i++, '_');
|
||||
i = cfg_key.indexOf(re, i + 1);
|
||||
}
|
||||
return cfg_key.toLower();
|
||||
}
|
||||
|
||||
QList<QKeySequence> ShortcutsConfig::currentShortcuts(const QObject *object) const {
|
||||
if (object->inherits("QAction")) {
|
||||
const auto *action = qobject_cast<const QAction *>(object);
|
||||
return action->shortcuts();
|
||||
} else if (object->inherits("Shortcut")) {
|
||||
const auto *shortcut = qobject_cast<const Shortcut *>(object);
|
||||
return shortcut->keys();
|
||||
} else if (object->inherits("QShortcut")) {
|
||||
const auto *qshortcut = qobject_cast<const QShortcut *>(object);
|
||||
return { qshortcut->key() };
|
||||
} else if (object->property("shortcut").isValid()) {
|
||||
return { object->property("shortcut").value<QKeySequence>() };
|
||||
} else {
|
||||
return { };
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,11 +14,11 @@
|
|||
#include "draggablepixmapitem.h"
|
||||
#include "editcommands.h"
|
||||
#include "flowlayout.h"
|
||||
#include "shortcut.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QDirIterator>
|
||||
#include <QStandardItemModel>
|
||||
#include <QShortcut>
|
||||
#include <QSpinBox>
|
||||
#include <QTextEdit>
|
||||
#include <QSpacerItem>
|
||||
|
@ -90,22 +90,84 @@ void MainWindow::initWindow() {
|
|||
porymapConfig.load();
|
||||
this->initCustomUI();
|
||||
this->initExtraSignals();
|
||||
this->initExtraShortcuts();
|
||||
this->initEditor();
|
||||
this->initMiscHeapObjects();
|
||||
this->initMapSortOrder();
|
||||
this->initShortcuts();
|
||||
this->restoreWindowState();
|
||||
|
||||
setWindowDisabled(true);
|
||||
}
|
||||
|
||||
void MainWindow::initShortcuts() {
|
||||
initExtraShortcuts();
|
||||
|
||||
shortcutsConfig.load();
|
||||
shortcutsConfig.setDefaultShortcuts(shortcutableObjects());
|
||||
applyUserShortcuts();
|
||||
}
|
||||
|
||||
void MainWindow::initExtraShortcuts() {
|
||||
new QShortcut(QKeySequence("Ctrl+0"), this, SLOT(resetMapViewScale()));
|
||||
new QShortcut(QKeySequence("Ctrl+G"), ui->checkBox_ToggleGrid, SLOT(toggle()));
|
||||
new QShortcut(QKeySequence("Ctrl+D"), this, SLOT(duplicate()));
|
||||
new QShortcut(QKeySequence::Delete, this, SLOT(on_toolButton_deleteObject_clicked()));
|
||||
new QShortcut(QKeySequence("Backspace"), this, SLOT(on_toolButton_deleteObject_clicked()));
|
||||
ui->actionZoom_In->setShortcuts({QKeySequence("Ctrl++"), QKeySequence("Ctrl+=")});
|
||||
ui->actionZoom_In->setShortcuts({ui->actionZoom_In->shortcut(), QKeySequence("Ctrl+=")});
|
||||
|
||||
auto *shortcutReset_Zoom = new Shortcut(QKeySequence("Ctrl+0"), this, SLOT(resetMapViewScale()));
|
||||
shortcutReset_Zoom->setObjectName("shortcutZoom_Reset");
|
||||
shortcutReset_Zoom->setWhatsThis("Zoom Reset");
|
||||
|
||||
auto *shortcutToggle_Grid = new Shortcut(QKeySequence("Ctrl+G"), ui->checkBox_ToggleGrid, SLOT(toggle()));
|
||||
shortcutToggle_Grid->setObjectName("shortcutToggle_Grid");
|
||||
shortcutToggle_Grid->setWhatsThis("Toggle Grid");
|
||||
|
||||
auto *shortcutDuplicate_Events = new Shortcut(QKeySequence("Ctrl+D"), this, SLOT(duplicate()));
|
||||
shortcutDuplicate_Events->setObjectName("shortcutDuplicate_Events");
|
||||
shortcutDuplicate_Events->setWhatsThis("Duplicate Selected Event(s)");
|
||||
|
||||
auto *shortcutDelete_Object = new Shortcut(
|
||||
{QKeySequence("Del"), QKeySequence("Backspace")}, this, SLOT(on_toolButton_deleteObject_clicked()));
|
||||
shortcutDelete_Object->setObjectName("shortcutDelete_Object");
|
||||
shortcutDelete_Object->setWhatsThis("Delete Selected Event(s)");
|
||||
|
||||
auto *shortcutToggle_Border = new Shortcut(QKeySequence(), ui->checkBox_ToggleBorder, SLOT(toggle()));
|
||||
shortcutToggle_Border->setObjectName("shortcutToggle_Border");
|
||||
shortcutToggle_Border->setWhatsThis("Toggle Border");
|
||||
|
||||
auto *shortcutToggle_Smart_Paths = new Shortcut(QKeySequence(), ui->checkBox_smartPaths, SLOT(toggle()));
|
||||
shortcutToggle_Smart_Paths->setObjectName("shortcutToggle_Smart_Paths");
|
||||
shortcutToggle_Smart_Paths->setWhatsThis("Toggle Smart Paths");
|
||||
|
||||
auto *shortcutExpand_All = new Shortcut(QKeySequence(), this, SLOT(on_toolButton_ExpandAll_clicked()));
|
||||
shortcutExpand_All->setObjectName("shortcutExpand_All");
|
||||
shortcutExpand_All->setWhatsThis("Map List: Expand all folders");
|
||||
|
||||
auto *shortcutCollapse_All = new Shortcut(QKeySequence(), this, SLOT(on_toolButton_CollapseAll_clicked()));
|
||||
shortcutCollapse_All->setObjectName("shortcutCollapse_All");
|
||||
shortcutCollapse_All->setWhatsThis("Map List: Collapse all folders");
|
||||
|
||||
auto *shortcutNew_Event = new Shortcut(QKeySequence(), this, SLOT(on_toolButton_Open_Scripts_clicked()));
|
||||
shortcutNew_Event->setObjectName("shortcut_Open_Scripts");
|
||||
shortcutNew_Event->setWhatsThis("Open Map Scripts");
|
||||
}
|
||||
|
||||
QObjectList MainWindow::shortcutableObjects() const {
|
||||
QObjectList shortcutable_objects;
|
||||
|
||||
for (auto *action : findChildren<QAction *>())
|
||||
if (!action->objectName().isEmpty())
|
||||
shortcutable_objects.append(qobject_cast<QObject *>(action));
|
||||
for (auto *shortcut : findChildren<Shortcut *>())
|
||||
if (!shortcut->objectName().isEmpty())
|
||||
shortcutable_objects.append(qobject_cast<QObject *>(shortcut));
|
||||
|
||||
return shortcutable_objects;
|
||||
}
|
||||
|
||||
void MainWindow::applyUserShortcuts() {
|
||||
for (auto *action : findChildren<QAction *>())
|
||||
if (!action->objectName().isEmpty())
|
||||
action->setShortcuts(shortcutsConfig.userShortcuts(action));
|
||||
for (auto *shortcut : findChildren<Shortcut *>())
|
||||
if (!shortcut->objectName().isEmpty())
|
||||
shortcut->setKeys(shortcutsConfig.userShortcuts(shortcut));
|
||||
}
|
||||
|
||||
void MainWindow::initCustomUI() {
|
||||
|
@ -172,9 +234,11 @@ void MainWindow::initEditor() {
|
|||
this->loadUserSettings();
|
||||
|
||||
undoAction = editor->editGroup.createUndoAction(this, tr("&Undo"));
|
||||
undoAction->setObjectName("action_Undo");
|
||||
undoAction->setShortcut(QKeySequence("Ctrl+Z"));
|
||||
|
||||
redoAction = editor->editGroup.createRedoAction(this, tr("&Redo"));
|
||||
redoAction->setObjectName("action_Redo");
|
||||
redoAction->setShortcuts({QKeySequence("Ctrl+Y"), QKeySequence("Ctrl+Shift+Z")});
|
||||
|
||||
ui->menuEdit->addAction(undoAction);
|
||||
|
@ -185,7 +249,8 @@ void MainWindow::initEditor() {
|
|||
undoView->setAttribute(Qt::WA_QuitOnClose, false);
|
||||
|
||||
// Show the EditHistory dialog with Ctrl+E
|
||||
QAction *showHistory = new QAction("Show Edit History...");
|
||||
QAction *showHistory = new QAction("Show Edit History...", this);
|
||||
showHistory->setObjectName("action_ShowEditHistory");
|
||||
showHistory->setShortcut(QKeySequence("Ctrl+E"));
|
||||
connect(showHistory, &QAction::triggered, [undoView](){ undoView->show(); });
|
||||
|
||||
|
@ -229,7 +294,7 @@ void MainWindow::initMapSortOrder() {
|
|||
mapSortOrderActionGroup->addAction(ui->actionSort_by_Area);
|
||||
mapSortOrderActionGroup->addAction(ui->actionSort_by_Layout);
|
||||
|
||||
connect(ui->toolButton_MapSortOrder, &QToolButton::triggered, this, &MainWindow::mapSortOrder_changed);
|
||||
connect(mapSortOrderActionGroup, &QActionGroup::triggered, this, &MainWindow::mapSortOrder_changed);
|
||||
|
||||
QAction* sortOrder = ui->toolButton_MapSortOrder->menu()->actions()[mapSortOrder];
|
||||
ui->toolButton_MapSortOrder->setIcon(sortOrder->icon());
|
||||
|
@ -1417,6 +1482,48 @@ void MainWindow::on_actionUse_Poryscript_triggered(bool checked)
|
|||
projectConfig.setUsePoryScript(checked);
|
||||
}
|
||||
|
||||
void MainWindow::on_actionEdit_Shortcuts_triggered()
|
||||
{
|
||||
if (!shortcutsEditor)
|
||||
initShortcutsEditor();
|
||||
|
||||
if (shortcutsEditor->isHidden())
|
||||
shortcutsEditor->show();
|
||||
else if (shortcutsEditor->isMinimized())
|
||||
shortcutsEditor->showNormal();
|
||||
else
|
||||
shortcutsEditor->activateWindow();
|
||||
}
|
||||
|
||||
void MainWindow::initShortcutsEditor() {
|
||||
shortcutsEditor = new ShortcutsEditor(this);
|
||||
connect(shortcutsEditor, &ShortcutsEditor::shortcutsSaved,
|
||||
this, &MainWindow::applyUserShortcuts);
|
||||
connect(shortcutsEditor, &QObject::destroyed, [=](QObject *) { shortcutsEditor = nullptr; });
|
||||
|
||||
connectSubEditorsToShortcutsEditor();
|
||||
|
||||
shortcutsEditor->setShortcutableObjects(shortcutableObjects());
|
||||
}
|
||||
|
||||
void MainWindow::connectSubEditorsToShortcutsEditor() {
|
||||
/* Initialize sub-editors so that their children are added to MainWindow's object tree and will
|
||||
* be returned by shortcutableObjects() to be passed to ShortcutsEditor. */
|
||||
if (!tilesetEditor)
|
||||
initTilesetEditor();
|
||||
connect(shortcutsEditor, &ShortcutsEditor::shortcutsSaved,
|
||||
tilesetEditor, &TilesetEditor::applyUserShortcuts);
|
||||
|
||||
// TODO: Remove this check when the region map editor supports pokefirered.
|
||||
if (projectConfig.getBaseGameVersion() != BaseGameVersion::pokefirered) {
|
||||
if (!regionMapEditor)
|
||||
initRegionMapEditor();
|
||||
if (regionMapEditor)
|
||||
connect(shortcutsEditor, &ShortcutsEditor::shortcutsSaved,
|
||||
regionMapEditor, &RegionMapEditor::applyUserShortcuts);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionPencil_triggered()
|
||||
{
|
||||
on_toolButton_Paint_clicked();
|
||||
|
@ -2525,9 +2632,7 @@ void MainWindow::on_checkBox_ToggleBorder_stateChanged(int selected)
|
|||
void MainWindow::on_actionTileset_Editor_triggered()
|
||||
{
|
||||
if (!this->tilesetEditor) {
|
||||
this->tilesetEditor = new TilesetEditor(this->editor->project, this->editor->map, this);
|
||||
connect(this->tilesetEditor, SIGNAL(tilesetsSaved(QString, QString)), this, SLOT(onTilesetsSaved(QString, QString)));
|
||||
connect(this->tilesetEditor, &QObject::destroyed, [=](QObject *) { this->tilesetEditor = nullptr; });
|
||||
initTilesetEditor();
|
||||
}
|
||||
|
||||
if (!this->tilesetEditor->isVisible()) {
|
||||
|
@ -2540,6 +2645,12 @@ void MainWindow::on_actionTileset_Editor_triggered()
|
|||
this->tilesetEditor->selectMetatile(this->editor->metatile_selector_item->getSelectedMetatiles()->at(0));
|
||||
}
|
||||
|
||||
void MainWindow::initTilesetEditor() {
|
||||
this->tilesetEditor = new TilesetEditor(this->editor->project, this->editor->map, this);
|
||||
connect(this->tilesetEditor, SIGNAL(tilesetsSaved(QString, QString)), this, SLOT(onTilesetsSaved(QString, QString)));
|
||||
connect(this->tilesetEditor, &QObject::destroyed, [=](QObject *) { this->tilesetEditor = nullptr; });
|
||||
}
|
||||
|
||||
void MainWindow::on_toolButton_ExpandAll_clicked()
|
||||
{
|
||||
if (ui->mapList) {
|
||||
|
@ -2654,20 +2765,9 @@ void MainWindow::on_horizontalSlider_MetatileZoom_valueChanged(int value) {
|
|||
|
||||
void MainWindow::on_actionRegion_Map_Editor_triggered() {
|
||||
if (!this->regionMapEditor) {
|
||||
this->regionMapEditor = new RegionMapEditor(this, this->editor->project);
|
||||
bool success = this->regionMapEditor->loadRegionMapData()
|
||||
&& this->regionMapEditor->loadCityMaps();
|
||||
if (!success) {
|
||||
delete this->regionMapEditor;
|
||||
this->regionMapEditor = nullptr;
|
||||
QMessageBox msgBox(this);
|
||||
QString errorMsg = QString("There was an error opening the region map data. Please see %1 for full error details.\n\n%3")
|
||||
.arg(getLogPath())
|
||||
.arg(getMostRecentError());
|
||||
msgBox.critical(nullptr, "Error Opening Region Map Editor", errorMsg);
|
||||
if (!initRegionMapEditor()) {
|
||||
return;
|
||||
}
|
||||
connect(this->regionMapEditor, &QObject::destroyed, [=](QObject *) { this->regionMapEditor = nullptr; });
|
||||
}
|
||||
|
||||
if (!this->regionMapEditor->isVisible()) {
|
||||
|
@ -2679,6 +2779,26 @@ void MainWindow::on_actionRegion_Map_Editor_triggered() {
|
|||
}
|
||||
}
|
||||
|
||||
bool MainWindow::initRegionMapEditor() {
|
||||
this->regionMapEditor = new RegionMapEditor(this, this->editor->project);
|
||||
bool success = this->regionMapEditor->loadRegionMapData()
|
||||
&& this->regionMapEditor->loadCityMaps();
|
||||
if (!success) {
|
||||
delete this->regionMapEditor;
|
||||
this->regionMapEditor = nullptr;
|
||||
QMessageBox msgBox(this);
|
||||
QString errorMsg = QString("There was an error opening the region map data. Please see %1 for full error details.\n\n%3")
|
||||
.arg(getLogPath())
|
||||
.arg(getMostRecentError());
|
||||
msgBox.critical(nullptr, "Error Opening Region Map Editor", errorMsg);
|
||||
|
||||
return false;
|
||||
}
|
||||
connect(this->regionMapEditor, &QObject::destroyed, [=](QObject *) { this->regionMapEditor = nullptr; });
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MainWindow::closeSupplementaryWindows() {
|
||||
if (this->tilesetEditor)
|
||||
delete this->tilesetEditor;
|
||||
|
@ -2688,6 +2808,8 @@ void MainWindow::closeSupplementaryWindows() {
|
|||
delete this->mapImageExporter;
|
||||
if (this->newmapprompt)
|
||||
delete this->newmapprompt;
|
||||
if (this->shortcutsEditor)
|
||||
delete this->shortcutsEditor;
|
||||
}
|
||||
|
||||
void MainWindow::closeEvent(QCloseEvent *event) {
|
||||
|
@ -2714,6 +2836,7 @@ void MainWindow::closeEvent(QCloseEvent *event) {
|
|||
);
|
||||
porymapConfig.save();
|
||||
projectConfig.save();
|
||||
shortcutsConfig.save();
|
||||
|
||||
QMainWindow::closeEvent(event);
|
||||
}
|
||||
|
|
185
src/ui/multikeyedit.cpp
Normal file
185
src/ui/multikeyedit.cpp
Normal file
|
@ -0,0 +1,185 @@
|
|||
#include "multikeyedit.h"
|
||||
|
||||
#include <QLineEdit>
|
||||
#include <QHBoxLayout>
|
||||
#include <QtEvents>
|
||||
#include <QMenu>
|
||||
#include <QAction>
|
||||
|
||||
|
||||
MultiKeyEdit::MultiKeyEdit(QWidget *parent, int fieldCount) :
|
||||
QWidget(parent),
|
||||
keySequenceEdit_vec(QVector<QKeySequenceEdit *>()),
|
||||
keySequence_list(QList<QKeySequence>())
|
||||
{
|
||||
setLayout(new QHBoxLayout(this));
|
||||
layout()->setContentsMargins(0, 0, 0, 0);
|
||||
setFieldCount(fieldCount);
|
||||
}
|
||||
|
||||
bool MultiKeyEdit::eventFilter(QObject *watched, QEvent *event) {
|
||||
if (event->type() == QEvent::KeyPress) {
|
||||
auto *watched_kse = qobject_cast<QKeySequenceEdit *>(watched);
|
||||
if (!watched_kse)
|
||||
return false;
|
||||
|
||||
auto *keyEvent = static_cast<QKeyEvent *>(event);
|
||||
if (keyEvent->key() == Qt::Key_Escape) {
|
||||
watched_kse->clearFocus();
|
||||
return true;
|
||||
} else {
|
||||
watched_kse->clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (event->type() == QEvent::ContextMenu) {
|
||||
auto *watched_lineEdit = qobject_cast<QLineEdit *>(watched);
|
||||
if (!watched_lineEdit)
|
||||
return false;
|
||||
|
||||
auto *contextMenuEvent = static_cast<QContextMenuEvent *>(event);
|
||||
if (contextMenuPolicy() == Qt::DefaultContextMenu) {
|
||||
showDefaultContextMenu(watched_lineEdit, contextMenuEvent->pos());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int MultiKeyEdit::fieldCount() const {
|
||||
return keySequenceEdit_vec.count();
|
||||
}
|
||||
|
||||
void MultiKeyEdit::setFieldCount(int count) {
|
||||
if (count < 1)
|
||||
count = 1;
|
||||
|
||||
while (keySequenceEdit_vec.count() < count)
|
||||
addNewKeySequenceEdit();
|
||||
|
||||
while (keySequenceEdit_vec.count() > count)
|
||||
delete keySequenceEdit_vec.takeLast();
|
||||
|
||||
alignKeySequencesLeft();
|
||||
}
|
||||
|
||||
QList<QKeySequence> MultiKeyEdit::keySequences() const {
|
||||
QList<QKeySequence> current_keySequences;
|
||||
for (auto *kse : keySequenceEdit_vec)
|
||||
if (!kse->keySequence().isEmpty())
|
||||
current_keySequences.append(kse->keySequence());
|
||||
return current_keySequences;
|
||||
}
|
||||
|
||||
bool MultiKeyEdit::removeOne(const QKeySequence &keySequence) {
|
||||
for (auto *keySequenceEdit : keySequenceEdit_vec) {
|
||||
if (keySequenceEdit->keySequence() == keySequence) {
|
||||
keySequence_list.removeOne(keySequence);
|
||||
keySequenceEdit->clear();
|
||||
alignKeySequencesLeft();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MultiKeyEdit::contains(const QKeySequence &keySequence) const {
|
||||
for (auto current_keySequence : keySequences())
|
||||
if (current_keySequence == keySequence)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void MultiKeyEdit::setContextMenuPolicy(Qt::ContextMenuPolicy policy) {
|
||||
QWidget::setContextMenuPolicy(policy);
|
||||
auto lineEdit_children = findChildren<QLineEdit *>();
|
||||
for (auto *lineEdit : lineEdit_children)
|
||||
lineEdit->setContextMenuPolicy(policy);
|
||||
}
|
||||
|
||||
bool MultiKeyEdit::isClearButtonEnabled() const {
|
||||
return findChild<QLineEdit *>()->isClearButtonEnabled();
|
||||
}
|
||||
|
||||
void MultiKeyEdit::setClearButtonEnabled(bool enable) {
|
||||
for (auto *lineEdit : findChildren<QLineEdit *>())
|
||||
lineEdit->setClearButtonEnabled(enable);
|
||||
}
|
||||
|
||||
void MultiKeyEdit::clear() {
|
||||
for (auto *keySequenceEdit : keySequenceEdit_vec)
|
||||
keySequenceEdit->clear();
|
||||
keySequence_list.clear();
|
||||
}
|
||||
|
||||
void MultiKeyEdit::setKeySequences(const QList<QKeySequence> &keySequences) {
|
||||
clear();
|
||||
keySequence_list = keySequences;
|
||||
int minCount = qMin(keySequenceEdit_vec.count(), keySequence_list.count());
|
||||
for (int i = 0; i < minCount; ++i)
|
||||
keySequenceEdit_vec[i]->setKeySequence(keySequence_list[i]);
|
||||
}
|
||||
|
||||
void MultiKeyEdit::addKeySequence(const QKeySequence &keySequence) {
|
||||
keySequenceEdit_vec.last()->setKeySequence(keySequence);
|
||||
alignKeySequencesLeft();
|
||||
}
|
||||
|
||||
void MultiKeyEdit::addNewKeySequenceEdit() {
|
||||
auto *keySequenceEdit = new QKeySequenceEdit(this);
|
||||
keySequenceEdit->installEventFilter(this);
|
||||
connect(keySequenceEdit, &QKeySequenceEdit::editingFinished,
|
||||
this, &MultiKeyEdit::onEditingFinished);
|
||||
connect(keySequenceEdit, &QKeySequenceEdit::keySequenceChanged,
|
||||
this, &MultiKeyEdit::keySequenceChanged);
|
||||
|
||||
auto *lineEdit = keySequenceEdit->findChild<QLineEdit *>();
|
||||
lineEdit->setClearButtonEnabled(true);
|
||||
lineEdit->installEventFilter(this);
|
||||
connect(lineEdit, &QLineEdit::customContextMenuRequested,
|
||||
this, &MultiKeyEdit::customContextMenuRequested);
|
||||
|
||||
layout()->addWidget(keySequenceEdit);
|
||||
keySequenceEdit_vec.append(keySequenceEdit);
|
||||
}
|
||||
|
||||
// Shift all key sequences left if there are any empty QKeySequenceEdit's.
|
||||
void MultiKeyEdit::alignKeySequencesLeft() {
|
||||
blockSignals(true);
|
||||
setKeySequences(keySequences());
|
||||
blockSignals(false);
|
||||
}
|
||||
|
||||
void MultiKeyEdit::setFocusToLastNonEmptyKeySequenceEdit() {
|
||||
for (auto it = keySequenceEdit_vec.rbegin(); it != keySequenceEdit_vec.rend(); ++it) {
|
||||
if (!(*it)->keySequence().isEmpty()) {
|
||||
(*it)->setFocus();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MultiKeyEdit::onEditingFinished() {
|
||||
auto *keySequenceEdit = qobject_cast<QKeySequenceEdit *>(sender());
|
||||
if (keySequenceEdit && keySequence_list.contains(keySequenceEdit->keySequence()))
|
||||
removeOne(keySequenceEdit->keySequence());
|
||||
alignKeySequencesLeft();
|
||||
setFocusToLastNonEmptyKeySequenceEdit();
|
||||
|
||||
emit editingFinished();
|
||||
}
|
||||
|
||||
/* QKeySequenceEdit doesn't send or receive context menu events, but it owns QLineEdit that does.
|
||||
* This QLineEdit hijacks those events and so we need to filter/connect to it directly, rather than
|
||||
* the QKeySequenceEdit. I wouldn't be surprised if Qt fixed this in the future, in which case any
|
||||
* context menu related code in this class might need to change. */
|
||||
void MultiKeyEdit::showDefaultContextMenu(QLineEdit *lineEdit, const QPoint &pos) {
|
||||
QMenu menu(this);
|
||||
QAction clearAction("Clear Shortcut", &menu);
|
||||
connect(&clearAction, &QAction::triggered, lineEdit, [this, &lineEdit]() {
|
||||
removeOne(lineEdit->text());
|
||||
});
|
||||
menu.addAction(&clearAction);
|
||||
menu.exec(lineEdit->mapToGlobal(pos));
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
#include "regionmapeditor.h"
|
||||
#include "ui_regionmapeditor.h"
|
||||
#include "imageexport.h"
|
||||
#include "shortcut.h"
|
||||
#include "config.h"
|
||||
#include "log.h"
|
||||
|
||||
|
@ -24,6 +25,7 @@ RegionMapEditor::RegionMapEditor(QWidget *parent, Project *project_) :
|
|||
this->project = project_;
|
||||
this->region_map = new RegionMap;
|
||||
this->ui->action_RegionMap_Resize->setVisible(false);
|
||||
this->initShortcuts();
|
||||
this->restoreWindowState();
|
||||
}
|
||||
|
||||
|
@ -92,6 +94,39 @@ bool RegionMapEditor::loadCityMaps() {
|
|||
return true;
|
||||
}
|
||||
|
||||
void RegionMapEditor::initShortcuts() {
|
||||
auto *shortcut_RM_Options_delete = new Shortcut(
|
||||
{QKeySequence("Del"), QKeySequence("Backspace")}, this, SLOT(on_pushButton_RM_Options_delete_clicked()));
|
||||
shortcut_RM_Options_delete->setObjectName("shortcut_RM_Options_delete");
|
||||
shortcut_RM_Options_delete->setWhatsThis("Map Layout: Delete Square");
|
||||
|
||||
shortcutsConfig.load();
|
||||
shortcutsConfig.setDefaultShortcuts(shortcutableObjects());
|
||||
applyUserShortcuts();
|
||||
}
|
||||
|
||||
QObjectList RegionMapEditor::shortcutableObjects() const {
|
||||
QObjectList shortcutable_objects;
|
||||
|
||||
for (auto *action : findChildren<QAction *>())
|
||||
if (!action->objectName().isEmpty())
|
||||
shortcutable_objects.append(qobject_cast<QObject *>(action));
|
||||
for (auto *shortcut : findChildren<Shortcut *>())
|
||||
if (!shortcut->objectName().isEmpty())
|
||||
shortcutable_objects.append(qobject_cast<QObject *>(shortcut));
|
||||
|
||||
return shortcutable_objects;
|
||||
}
|
||||
|
||||
void RegionMapEditor::applyUserShortcuts() {
|
||||
for (auto *action : findChildren<QAction *>())
|
||||
if (!action->objectName().isEmpty())
|
||||
action->setShortcuts(shortcutsConfig.userShortcuts(action));
|
||||
for (auto *shortcut : findChildren<Shortcut *>())
|
||||
if (!shortcut->objectName().isEmpty())
|
||||
shortcut->setKeys(shortcutsConfig.userShortcuts(shortcut));
|
||||
}
|
||||
|
||||
void RegionMapEditor::displayRegionMap() {
|
||||
displayRegionMapTileSelector();
|
||||
displayCityMapTileSelector();
|
||||
|
|
153
src/ui/shortcut.cpp
Normal file
153
src/ui/shortcut.cpp
Normal file
|
@ -0,0 +1,153 @@
|
|||
#include "shortcut.h"
|
||||
|
||||
#include <QtEvents>
|
||||
#include <QWhatsThis>
|
||||
|
||||
|
||||
Shortcut::Shortcut(QWidget *parent) :
|
||||
QObject(parent),
|
||||
sc_member(nullptr),
|
||||
sc_ambiguousmember(nullptr),
|
||||
sc_context(Qt::WindowShortcut),
|
||||
sc_vec(QVector<QShortcut *>({new QShortcut(parent)}))
|
||||
{ }
|
||||
|
||||
Shortcut::Shortcut(const QKeySequence &key, QWidget *parent,
|
||||
const char *member, const char *ambiguousMember,
|
||||
Qt::ShortcutContext shortcutContext) :
|
||||
QObject(parent),
|
||||
sc_member(member),
|
||||
sc_ambiguousmember(ambiguousMember),
|
||||
sc_context(shortcutContext),
|
||||
sc_vec(QVector<QShortcut *>())
|
||||
{
|
||||
setKey(key);
|
||||
}
|
||||
|
||||
Shortcut::Shortcut(const QList<QKeySequence> &keys, QWidget *parent,
|
||||
const char *member, const char *ambiguousMember,
|
||||
Qt::ShortcutContext shortcutContext) :
|
||||
QObject(parent),
|
||||
sc_member(member),
|
||||
sc_ambiguousmember(ambiguousMember),
|
||||
sc_context(shortcutContext),
|
||||
sc_vec(QVector<QShortcut *>())
|
||||
{
|
||||
setKeys(keys);
|
||||
}
|
||||
|
||||
Shortcut::~Shortcut()
|
||||
{
|
||||
for (auto *sc : sc_vec)
|
||||
delete sc;
|
||||
}
|
||||
|
||||
void Shortcut::addKey(const QKeySequence &key) {
|
||||
sc_vec.append(new QShortcut(key, parentWidget(), sc_member, sc_ambiguousmember, sc_context));
|
||||
}
|
||||
|
||||
void Shortcut::setKey(const QKeySequence &key) {
|
||||
if (sc_vec.isEmpty()) {
|
||||
addKey(key);
|
||||
} else {
|
||||
while (sc_vec.count() != 1)
|
||||
delete sc_vec.takeLast();
|
||||
sc_vec.first()->setKey(key);
|
||||
}
|
||||
}
|
||||
|
||||
QKeySequence Shortcut::key() const {
|
||||
return sc_vec.first()->key();
|
||||
}
|
||||
|
||||
void Shortcut::addKeys(const QList<QKeySequence> &keys) {
|
||||
for (auto key : keys)
|
||||
addKey(key);
|
||||
}
|
||||
|
||||
void Shortcut::setKeys(const QList<QKeySequence> &keys) {
|
||||
if (keys.isEmpty())
|
||||
return;
|
||||
|
||||
while (sc_vec.count() < keys.count())
|
||||
addKey(QKeySequence());
|
||||
|
||||
while (sc_vec.count() > keys.count())
|
||||
delete sc_vec.takeLast();
|
||||
|
||||
for (int i = 0; i < keys.count(); ++i)
|
||||
sc_vec[i]->setKey(keys[i]);
|
||||
}
|
||||
|
||||
QList<QKeySequence> Shortcut::keys() const {
|
||||
QList<QKeySequence> ks_list = QList<QKeySequence>();
|
||||
for (auto *sc : sc_vec)
|
||||
ks_list.append(sc->key());
|
||||
return ks_list;
|
||||
}
|
||||
|
||||
void Shortcut::setEnabled(bool enable) {
|
||||
for (auto *sc : sc_vec)
|
||||
sc->setEnabled(enable);
|
||||
}
|
||||
|
||||
bool Shortcut::isEnabled() const {
|
||||
return sc_vec.first()->isEnabled();
|
||||
}
|
||||
|
||||
void Shortcut::setContext(Qt::ShortcutContext context) {
|
||||
sc_context = context;
|
||||
for (auto *sc : sc_vec)
|
||||
sc->setContext(context);
|
||||
}
|
||||
|
||||
Qt::ShortcutContext Shortcut::context() const {
|
||||
return sc_context;
|
||||
}
|
||||
|
||||
void Shortcut::setWhatsThis(const QString &text) {
|
||||
for (auto *sc : sc_vec)
|
||||
sc->setWhatsThis(text);
|
||||
}
|
||||
|
||||
QString Shortcut::whatsThis() const {
|
||||
return sc_vec.first()->whatsThis();
|
||||
}
|
||||
|
||||
void Shortcut::setAutoRepeat(bool on) {
|
||||
for (auto *sc : sc_vec)
|
||||
sc->setAutoRepeat(on);
|
||||
}
|
||||
|
||||
bool Shortcut::autoRepeat() const {
|
||||
return sc_vec.first()->autoRepeat();
|
||||
}
|
||||
|
||||
int Shortcut::id() const {
|
||||
return sc_vec.first()->id();
|
||||
}
|
||||
|
||||
QList<int> Shortcut::ids() const {
|
||||
QList<int> id_list;
|
||||
for (auto *sc : sc_vec)
|
||||
id_list.append(sc->id());
|
||||
return id_list;
|
||||
}
|
||||
|
||||
bool Shortcut::event(QEvent *e) {
|
||||
if (isEnabled() && e->type() == QEvent::Shortcut) {
|
||||
auto se = static_cast<QShortcutEvent *>(e);
|
||||
if (ids().contains(se->shortcutId()) && keys().contains(se->key())) {
|
||||
if (QWhatsThis::inWhatsThisMode()) {
|
||||
QWhatsThis::showText(QCursor::pos(), whatsThis());
|
||||
} else {
|
||||
if (se->isAmbiguous())
|
||||
emit activatedAmbiguously();
|
||||
else
|
||||
emit activated();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
188
src/ui/shortcutseditor.cpp
Normal file
188
src/ui/shortcutseditor.cpp
Normal file
|
@ -0,0 +1,188 @@
|
|||
#include "shortcutseditor.h"
|
||||
#include "ui_shortcutseditor.h"
|
||||
#include "config.h"
|
||||
#include "multikeyedit.h"
|
||||
#include "log.h"
|
||||
|
||||
#include <QGroupBox>
|
||||
#include <QFormLayout>
|
||||
#include <QAbstractButton>
|
||||
#include <QtEvents>
|
||||
#include <QMessageBox>
|
||||
#include <QRegularExpression>
|
||||
#include <QLabel>
|
||||
|
||||
|
||||
ShortcutsEditor::ShortcutsEditor(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
ui(new Ui::ShortcutsEditor),
|
||||
main_container(nullptr)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
main_container = ui->scrollAreaWidgetContents_Shortcuts;
|
||||
auto *main_layout = new QVBoxLayout(main_container);
|
||||
main_layout->setSpacing(12);
|
||||
connect(ui->buttonBox, &QDialogButtonBox::clicked,
|
||||
this, &ShortcutsEditor::dialogButtonClicked);
|
||||
}
|
||||
|
||||
ShortcutsEditor::ShortcutsEditor(const QObjectList &shortcutableObjects, QWidget *parent) :
|
||||
ShortcutsEditor(parent)
|
||||
{
|
||||
setShortcutableObjects(shortcutableObjects);
|
||||
}
|
||||
|
||||
ShortcutsEditor::~ShortcutsEditor()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void ShortcutsEditor::setShortcutableObjects(const QObjectList &shortcutableObjects) {
|
||||
parseObjectList(shortcutableObjects);
|
||||
populateMainContainer();
|
||||
}
|
||||
|
||||
void ShortcutsEditor::saveShortcuts() {
|
||||
QMultiMap<const QObject *, QKeySequence> objects_keySequences;
|
||||
for (auto it = multiKeyEdits_objects.cbegin(); it != multiKeyEdits_objects.cend(); ++it) {
|
||||
if (it.key()->keySequences().isEmpty())
|
||||
objects_keySequences.insert(it.value(), QKeySequence());
|
||||
for (auto keySequence : it.key()->keySequences())
|
||||
objects_keySequences.insert(it.value(), keySequence);
|
||||
}
|
||||
|
||||
shortcutsConfig.setUserShortcuts(objects_keySequences);
|
||||
emit shortcutsSaved();
|
||||
}
|
||||
|
||||
// Restores default shortcuts but doesn't save until Apply or OK is clicked.
|
||||
void ShortcutsEditor::resetShortcuts() {
|
||||
for (auto it = multiKeyEdits_objects.begin(); it != multiKeyEdits_objects.end(); ++it) {
|
||||
it.key()->blockSignals(true);
|
||||
const auto defaults = shortcutsConfig.defaultShortcuts(it.value());
|
||||
it.key()->setKeySequences(defaults);
|
||||
it.key()->blockSignals(false);
|
||||
}
|
||||
}
|
||||
|
||||
void ShortcutsEditor::parseObjectList(const QObjectList &objectList) {
|
||||
for (auto *object : objectList) {
|
||||
const auto label = getLabel(object);
|
||||
if (!label.isEmpty() && !object->objectName().isEmpty() && !object->objectName().startsWith("_q_"))
|
||||
labels_objects.insert(label, object);
|
||||
}
|
||||
}
|
||||
|
||||
QString ShortcutsEditor::getLabel(const QObject *object) const {
|
||||
if (stringPropertyIsNotEmpty(object, "text"))
|
||||
return object->property("text").toString().remove('&');
|
||||
else if (stringPropertyIsNotEmpty(object, "whatsThis"))
|
||||
return object->property("whatsThis").toString().remove('&');
|
||||
else
|
||||
return QString();
|
||||
}
|
||||
|
||||
bool ShortcutsEditor::stringPropertyIsNotEmpty(const QObject *object, const char *name) const {
|
||||
return object->property(name).isValid() && !object->property(name).toString().isEmpty();
|
||||
}
|
||||
|
||||
void ShortcutsEditor::populateMainContainer() {
|
||||
for (auto object : labels_objects) {
|
||||
const auto shortcutContext = getShortcutContext(object);
|
||||
if (!contexts_layouts.contains(shortcutContext))
|
||||
addNewContextGroup(shortcutContext);
|
||||
|
||||
addNewMultiKeyEdit(object, shortcutContext);
|
||||
}
|
||||
}
|
||||
|
||||
// The context for which the object's shortcut is active (Displayed in group box title).
|
||||
// Uses the parent window's objectName and adds spaces between words.
|
||||
QString ShortcutsEditor::getShortcutContext(const QObject *object) const {
|
||||
auto objectParentWidget = static_cast<QWidget *>(object->parent());
|
||||
auto context = objectParentWidget->window()->objectName();
|
||||
QRegularExpression re("[A-Z]");
|
||||
int i = context.indexOf(re, 1);
|
||||
while (i != -1) {
|
||||
if (context.at(i - 1) != ' ')
|
||||
context.insert(i++, ' ');
|
||||
i = context.indexOf(re, i + 1);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
// Seperate shortcuts into context groups for duplicate checking.
|
||||
void ShortcutsEditor::addNewContextGroup(const QString &shortcutContext) {
|
||||
auto *groupBox = new QGroupBox(shortcutContext, main_container);
|
||||
main_container->layout()->addWidget(groupBox);
|
||||
auto *formLayout = new QFormLayout(groupBox);
|
||||
contexts_layouts.insert(shortcutContext, formLayout);
|
||||
}
|
||||
|
||||
void ShortcutsEditor::addNewMultiKeyEdit(const QObject *object, const QString &shortcutContext) {
|
||||
auto *container = contexts_layouts.value(shortcutContext)->parentWidget();
|
||||
auto *multiKeyEdit = new MultiKeyEdit(container);
|
||||
multiKeyEdit->setKeySequences(shortcutsConfig.userShortcuts(object));
|
||||
connect(multiKeyEdit, &MultiKeyEdit::keySequenceChanged,
|
||||
this, &ShortcutsEditor::checkForDuplicates);
|
||||
contexts_layouts.value(shortcutContext)->addRow(labels_objects.key(object), multiKeyEdit);
|
||||
multiKeyEdits_objects.insert(multiKeyEdit, object);
|
||||
}
|
||||
|
||||
void ShortcutsEditor::checkForDuplicates(const QKeySequence &keySequence) {
|
||||
if (keySequence.isEmpty())
|
||||
return;
|
||||
|
||||
auto *sender_multiKeyEdit = qobject_cast<MultiKeyEdit *>(sender());
|
||||
if (!sender_multiKeyEdit)
|
||||
return;
|
||||
|
||||
for (auto *sibling_multiKeyEdit : siblings(sender_multiKeyEdit))
|
||||
if (sibling_multiKeyEdit->contains(keySequence))
|
||||
promptUserOnDuplicateFound(sender_multiKeyEdit, sibling_multiKeyEdit);
|
||||
}
|
||||
|
||||
QList<MultiKeyEdit *> ShortcutsEditor::siblings(MultiKeyEdit *multiKeyEdit) const {
|
||||
auto list = multiKeyEdit->parent()->findChildren<MultiKeyEdit *>(QString(), Qt::FindDirectChildrenOnly);
|
||||
list.removeOne(multiKeyEdit);
|
||||
return list;
|
||||
}
|
||||
|
||||
void ShortcutsEditor::promptUserOnDuplicateFound(MultiKeyEdit *sender, MultiKeyEdit *sibling) {
|
||||
const auto duplicateKeySequence = sender->keySequences().last();
|
||||
const auto siblingLabel = getLabel(multiKeyEdits_objects.value(sibling));
|
||||
const auto message = QString(
|
||||
"Shortcut '%1' is already used by '%2', would you like to replace it?")
|
||||
.arg(duplicateKeySequence.toString()).arg(siblingLabel);
|
||||
|
||||
const auto result = QMessageBox::question(
|
||||
this, "porymap", message, QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
|
||||
|
||||
if (result == QMessageBox::Yes)
|
||||
removeKeySequence(duplicateKeySequence, sibling);
|
||||
else
|
||||
removeKeySequence(duplicateKeySequence, sender);
|
||||
|
||||
activateWindow();
|
||||
}
|
||||
|
||||
void ShortcutsEditor::removeKeySequence(const QKeySequence &keySequence, MultiKeyEdit *multiKeyEdit) {
|
||||
multiKeyEdit->blockSignals(true);
|
||||
multiKeyEdit->removeOne(keySequence);
|
||||
multiKeyEdit->blockSignals(false);
|
||||
}
|
||||
|
||||
void ShortcutsEditor::dialogButtonClicked(QAbstractButton *button) {
|
||||
auto buttonRole = ui->buttonBox->buttonRole(button);
|
||||
if (buttonRole == QDialogButtonBox::AcceptRole) {
|
||||
saveShortcuts();
|
||||
close();
|
||||
} else if (buttonRole == QDialogButtonBox::ApplyRole) {
|
||||
saveShortcuts();
|
||||
} else if (buttonRole == QDialogButtonBox::RejectRole) {
|
||||
close();
|
||||
} else if (buttonRole == QDialogButtonBox::ResetRole) {
|
||||
resetShortcuts();
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@
|
|||
#include "paletteutil.h"
|
||||
#include "imageexport.h"
|
||||
#include "config.h"
|
||||
#include "shortcut.h"
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QDialogButtonBox>
|
||||
|
@ -86,7 +87,6 @@ void TilesetEditor::setTilesets(QString primaryTilesetLabel, QString secondaryTi
|
|||
|
||||
void TilesetEditor::initUi() {
|
||||
ui->setupUi(this);
|
||||
new QShortcut(QKeySequence("Ctrl+Shift+Z"), this, SLOT(on_actionRedo_triggered()));
|
||||
this->tileXFlip = ui->checkBox_xFlip->isChecked();
|
||||
this->tileYFlip = ui->checkBox_yFlip->isChecked();
|
||||
this->paletteId = ui->spinBox_paletteSelector->value();
|
||||
|
@ -102,6 +102,7 @@ void TilesetEditor::initUi() {
|
|||
this->initMetatileLayersItem();
|
||||
this->initTileSelector();
|
||||
this->initSelectedTileItem();
|
||||
this->initShortcuts();
|
||||
this->metatileSelector->select(0);
|
||||
this->restoreWindowState();
|
||||
}
|
||||
|
@ -209,6 +210,48 @@ void TilesetEditor::initSelectedTileItem() {
|
|||
this->ui->graphicsView_selectedTile->setFixedSize(this->selectedTilePixmapItem->pixmap().width() + 2, this->selectedTilePixmapItem->pixmap().height() + 2);
|
||||
}
|
||||
|
||||
void TilesetEditor::initShortcuts() {
|
||||
initExtraShortcuts();
|
||||
|
||||
shortcutsConfig.load();
|
||||
shortcutsConfig.setDefaultShortcuts(shortcutableObjects());
|
||||
applyUserShortcuts();
|
||||
}
|
||||
|
||||
void TilesetEditor::initExtraShortcuts() {
|
||||
ui->actionRedo->setShortcuts({ui->actionRedo->shortcut(), QKeySequence("Ctrl+Shift+Z")});
|
||||
|
||||
auto *shortcut_xFlip = new Shortcut(QKeySequence(), ui->checkBox_xFlip, SLOT(toggle()));
|
||||
shortcut_xFlip->setObjectName("shortcut_xFlip");
|
||||
shortcut_xFlip->setWhatsThis("X Flip");
|
||||
|
||||
auto *shortcut_yFlip = new Shortcut(QKeySequence(), ui->checkBox_yFlip, SLOT(toggle()));
|
||||
shortcut_yFlip->setObjectName("shortcut_yFlip");
|
||||
shortcut_yFlip->setWhatsThis("Y Flip");
|
||||
}
|
||||
|
||||
QObjectList TilesetEditor::shortcutableObjects() const {
|
||||
QObjectList shortcutable_objects;
|
||||
|
||||
for (auto *action : findChildren<QAction *>())
|
||||
if (!action->objectName().isEmpty())
|
||||
shortcutable_objects.append(qobject_cast<QObject *>(action));
|
||||
for (auto *shortcut : findChildren<Shortcut *>())
|
||||
if (!shortcut->objectName().isEmpty())
|
||||
shortcutable_objects.append(qobject_cast<QObject *>(shortcut));
|
||||
|
||||
return shortcutable_objects;
|
||||
}
|
||||
|
||||
void TilesetEditor::applyUserShortcuts() {
|
||||
for (auto *action : findChildren<QAction *>())
|
||||
if (!action->objectName().isEmpty())
|
||||
action->setShortcuts(shortcutsConfig.userShortcuts(action));
|
||||
for (auto *shortcut : findChildren<Shortcut *>())
|
||||
if (!shortcut->objectName().isEmpty())
|
||||
shortcut->setKeys(shortcutsConfig.userShortcuts(shortcut));
|
||||
}
|
||||
|
||||
void TilesetEditor::restoreWindowState() {
|
||||
logInfo("Restoring tileset editor geometry from previous session.");
|
||||
QMap<QString, QByteArray> geometry = porymapConfig.getTilesetEditorGeometry();
|
||||
|
|
Loading…
Reference in a new issue