git repos / SagoImageBrowser

blame: src/shortcutmanager.cpp

normal view · raw

14cf904f Poul Sander 2026-06-22 18:18 1
/*
14cf904f Poul Sander 2026-06-22 18:18 2
MIT License
14cf904f Poul Sander 2026-06-22 18:18 3
14cf904f Poul Sander 2026-06-22 18:18 4
Copyright (c) 2026 Poul Sander
14cf904f Poul Sander 2026-06-22 18:18 5
14cf904f Poul Sander 2026-06-22 18:18 6
Permission is hereby granted, free of charge, to any person obtaining a copy
14cf904f Poul Sander 2026-06-22 18:18 7
of this software and associated documentation files (the "Software"), to deal
14cf904f Poul Sander 2026-06-22 18:18 8
in the Software without restriction, including without limitation the rights
14cf904f Poul Sander 2026-06-22 18:18 9
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14cf904f Poul Sander 2026-06-22 18:18 10
copies of the Software, and to permit persons to whom the Software is
14cf904f Poul Sander 2026-06-22 18:18 11
furnished to do so, subject to the following conditions:
14cf904f Poul Sander 2026-06-22 18:18 12
14cf904f Poul Sander 2026-06-22 18:18 13
The above copyright notice and this permission notice shall be included in all
14cf904f Poul Sander 2026-06-22 18:18 14
copies or substantial portions of the Software.
14cf904f Poul Sander 2026-06-22 18:18 15
14cf904f Poul Sander 2026-06-22 18:18 16
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14cf904f Poul Sander 2026-06-22 18:18 17
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14cf904f Poul Sander 2026-06-22 18:18 18
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14cf904f Poul Sander 2026-06-22 18:18 19
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
14cf904f Poul Sander 2026-06-22 18:18 20
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
14cf904f Poul Sander 2026-06-22 18:18 21
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
14cf904f Poul Sander 2026-06-22 18:18 22
SOFTWARE.
14cf904f Poul Sander 2026-06-22 18:18 23
14cf904f Poul Sander 2026-06-22 18:18 24
*/
14cf904f Poul Sander 2026-06-22 18:18 25
83f0e0bc Poul Sander 2026-05-30 17:59 26
#include "shortcutmanager.h"
83f0e0bc Poul Sander 2026-05-30 17:59 27
83f0e0bc Poul Sander 2026-05-30 17:59 28
#include <QKeyEvent>
83f0e0bc Poul Sander 2026-05-30 17:59 29
#include <QSettings>
d4402664 Poul Sander 2026-06-07 18:04 30
#include <QCoreApplication>
83f0e0bc Poul Sander 2026-05-30 17:59 31
83f0e0bc Poul Sander 2026-05-30 17:59 32
namespace {
83f0e0bc Poul Sander 2026-05-30 17:59 33
83f0e0bc Poul Sander 2026-05-30 17:59 34
struct ActionInfo {
83f0e0bc Poul Sander 2026-05-30 17:59 35
    const char *name;        // settings key
83f0e0bc Poul Sander 2026-05-30 17:59 36
    const char *description; // human-readable for help overlay / prefs table
83f0e0bc Poul Sander 2026-05-30 17:59 37
    QKeySequence defaultKey;
83f0e0bc Poul Sander 2026-05-30 17:59 38
    ShortcutManager::Category category;
83f0e0bc Poul Sander 2026-05-30 17:59 39
};
83f0e0bc Poul Sander 2026-05-30 17:59 40
83f0e0bc Poul Sander 2026-05-30 17:59 41
// Order must match ShortcutManager::Action enum
83f0e0bc Poul Sander 2026-05-30 17:59 42
static const ActionInfo kDefaults[ShortcutManager::ActionCount] = {
c89c2e86 Poul Sander 2026-06-20 22:29 43
    {"ToggleHelp",      QT_TRANSLATE_NOOP("ShortcutManager", "Show/hide keyboard shortcuts"), QKeySequence(Qt::Key_F1),       ShortcutManager::CatNotConfigurable},
c89c2e86 Poul Sander 2026-06-20 22:29 44
    {"CloseViewer",     QT_TRANSLATE_NOOP("ShortcutManager", "Close viewer"),                 QKeySequence(Qt::Key_Escape),   ShortcutManager::CatImageViewer},
c89c2e86 Poul Sander 2026-06-20 22:29 45
    {"CloseViewerAlt",  QT_TRANSLATE_NOOP("ShortcutManager", "Close viewer (alt)"),           QKeySequence(Qt::Key_Return),   ShortcutManager::CatImageViewer},
c89c2e86 Poul Sander 2026-06-20 22:29 46
    {"NextImage",       QT_TRANSLATE_NOOP("ShortcutManager", "Next image"),                   QKeySequence(Qt::Key_PageDown), ShortcutManager::CatImageViewer},
c89c2e86 Poul Sander 2026-06-20 22:29 47
    {"PrevImage",       QT_TRANSLATE_NOOP("ShortcutManager", "Previous image"),               QKeySequence(Qt::Key_PageUp),   ShortcutManager::CatImageViewer},
c89c2e86 Poul Sander 2026-06-20 22:29 48
    {"PanLeft",         QT_TRANSLATE_NOOP("ShortcutManager", "Pan left"),                     QKeySequence(Qt::Key_Left),     ShortcutManager::CatImageViewer},
c89c2e86 Poul Sander 2026-06-20 22:29 49
    {"PanRight",        QT_TRANSLATE_NOOP("ShortcutManager", "Pan right"),                    QKeySequence(Qt::Key_Right),    ShortcutManager::CatImageViewer},
c89c2e86 Poul Sander 2026-06-20 22:29 50
    {"PanUp",           QT_TRANSLATE_NOOP("ShortcutManager", "Pan up"),                       QKeySequence(Qt::Key_Up),       ShortcutManager::CatImageViewer},
c89c2e86 Poul Sander 2026-06-20 22:29 51
    {"PanDown",         QT_TRANSLATE_NOOP("ShortcutManager", "Pan down"),                     QKeySequence(Qt::Key_Down),     ShortcutManager::CatImageViewer},
c89c2e86 Poul Sander 2026-06-20 22:29 52
    {"ZoomOriginal",    QT_TRANSLATE_NOOP("ShortcutManager", "Zoom to original size"),        QKeySequence(Qt::Key_Slash),    ShortcutManager::CatImageViewer},
c89c2e86 Poul Sander 2026-06-20 22:29 53
    {"ZoomFit",         QT_TRANSLATE_NOOP("ShortcutManager", "Zoom to fit screen"),           QKeySequence(Qt::Key_Asterisk), ShortcutManager::CatImageViewer},
c89c2e86 Poul Sander 2026-06-20 22:29 54
    {"ZoomIn",          QT_TRANSLATE_NOOP("ShortcutManager", "Zoom in"),                      QKeySequence(Qt::Key_Plus),     ShortcutManager::CatImageViewer},
c89c2e86 Poul Sander 2026-06-20 22:29 55
    {"ZoomOut",         QT_TRANSLATE_NOOP("ShortcutManager", "Zoom out"),                     QKeySequence(Qt::Key_Minus),    ShortcutManager::CatImageViewer},
c89c2e86 Poul Sander 2026-06-20 22:29 56
    {"ToggleExif",      QT_TRANSLATE_NOOP("ShortcutManager", "Toggle EXIF info"),             QKeySequence(Qt::Key_I),        ShortcutManager::CatImageViewer},
c89c2e86 Poul Sander 2026-06-20 22:29 57
    {"EditCaption",     QT_TRANSLATE_NOOP("ShortcutManager", "Edit caption"),                 QKeySequence(Qt::Key_E),        ShortcutManager::CatImageViewer},
c89c2e86 Poul Sander 2026-06-20 22:29 58
    {"ToggleFullscreen",QT_TRANSLATE_NOOP("ShortcutManager", "Toggle fullscreen"),            QKeySequence(Qt::Key_F11),      ShortcutManager::CatImageViewer},
c89c2e86 Poul Sander 2026-06-20 22:29 59
    {"ActivateEntry",   QT_TRANSLATE_NOOP("ShortcutManager", "Open folder / image"),          QKeySequence(Qt::Key_Return),   ShortcutManager::CatBrowser},
c89c2e86 Poul Sander 2026-06-20 22:29 60
    {"PrevFolder",      QT_TRANSLATE_NOOP("ShortcutManager", "Previous folder"),              QKeySequence(Qt::ALT | Qt::Key_Left),  ShortcutManager::CatBrowser},
c89c2e86 Poul Sander 2026-06-20 22:29 61
    {"NextFolder",      QT_TRANSLATE_NOOP("ShortcutManager", "Next folder"),                  QKeySequence(Qt::ALT | Qt::Key_Right), ShortcutManager::CatBrowser},
c89c2e86 Poul Sander 2026-06-20 22:29 62
    {"MoveToTrash",     QT_TRANSLATE_NOOP("ShortcutManager", "Move image to trash"),          QKeySequence(Qt::Key_Delete),   ShortcutManager::CatBrowser},
83f0e0bc Poul Sander 2026-05-30 17:59 63
};
83f0e0bc Poul Sander 2026-05-30 17:59 64
83f0e0bc Poul Sander 2026-05-30 17:59 65
} // namespace
83f0e0bc Poul Sander 2026-05-30 17:59 66
83f0e0bc Poul Sander 2026-05-30 17:59 67
ShortcutManager::ShortcutManager()
83f0e0bc Poul Sander 2026-05-30 17:59 68
{
83f0e0bc Poul Sander 2026-05-30 17:59 69
    resetToDefaults();
83f0e0bc Poul Sander 2026-05-30 17:59 70
}
83f0e0bc Poul Sander 2026-05-30 17:59 71
83f0e0bc Poul Sander 2026-05-30 17:59 72
ShortcutManager &ShortcutManager::instance()
83f0e0bc Poul Sander 2026-05-30 17:59 73
{
83f0e0bc Poul Sander 2026-05-30 17:59 74
    static ShortcutManager mgr;
83f0e0bc Poul Sander 2026-05-30 17:59 75
    return mgr;
83f0e0bc Poul Sander 2026-05-30 17:59 76
}
83f0e0bc Poul Sander 2026-05-30 17:59 77
83f0e0bc Poul Sander 2026-05-30 17:59 78
QKeySequence ShortcutManager::shortcut(Action action) const
83f0e0bc Poul Sander 2026-05-30 17:59 79
{
83f0e0bc Poul Sander 2026-05-30 17:59 80
    if (action < 0 || action >= ActionCount)
83f0e0bc Poul Sander 2026-05-30 17:59 81
        return {};
83f0e0bc Poul Sander 2026-05-30 17:59 82
    return m_bindings[action].key;
83f0e0bc Poul Sander 2026-05-30 17:59 83
}
83f0e0bc Poul Sander 2026-05-30 17:59 84
83f0e0bc Poul Sander 2026-05-30 17:59 85
QString ShortcutManager::displayKey(Action action) const
83f0e0bc Poul Sander 2026-05-30 17:59 86
{
83f0e0bc Poul Sander 2026-05-30 17:59 87
    if (action < 0 || action >= ActionCount)
83f0e0bc Poul Sander 2026-05-30 17:59 88
        return {};
83f0e0bc Poul Sander 2026-05-30 17:59 89
    return m_bindings[action].key.toString(QKeySequence::NativeText);
83f0e0bc Poul Sander 2026-05-30 17:59 90
}
83f0e0bc Poul Sander 2026-05-30 17:59 91
83f0e0bc Poul Sander 2026-05-30 17:59 92
QString ShortcutManager::description(Action action) const
83f0e0bc Poul Sander 2026-05-30 17:59 93
{
83f0e0bc Poul Sander 2026-05-30 17:59 94
    return actionDescription(action);
83f0e0bc Poul Sander 2026-05-30 17:59 95
}
83f0e0bc Poul Sander 2026-05-30 17:59 96
83f0e0bc Poul Sander 2026-05-30 17:59 97
void ShortcutManager::setShortcut(Action action, const QKeySequence &seq)
83f0e0bc Poul Sander 2026-05-30 17:59 98
{
83f0e0bc Poul Sander 2026-05-30 17:59 99
    if (action >= 0 && action < ActionCount)
83f0e0bc Poul Sander 2026-05-30 17:59 100
        m_bindings[action].key = seq;
83f0e0bc Poul Sander 2026-05-30 17:59 101
}
83f0e0bc Poul Sander 2026-05-30 17:59 102
83f0e0bc Poul Sander 2026-05-30 17:59 103
void ShortcutManager::resetToDefaults()
83f0e0bc Poul Sander 2026-05-30 17:59 104
{
83f0e0bc Poul Sander 2026-05-30 17:59 105
    for (int i = 0; i < ActionCount; ++i)
83f0e0bc Poul Sander 2026-05-30 17:59 106
        m_bindings[i].key = kDefaults[i].defaultKey;
83f0e0bc Poul Sander 2026-05-30 17:59 107
}
83f0e0bc Poul Sander 2026-05-30 17:59 108
83f0e0bc Poul Sander 2026-05-30 17:59 109
void ShortcutManager::load(QSettings &settings)
83f0e0bc Poul Sander 2026-05-30 17:59 110
{
83f0e0bc Poul Sander 2026-05-30 17:59 111
    settings.beginGroup("shortcuts");
83f0e0bc Poul Sander 2026-05-30 17:59 112
    for (int i = 0; i < ActionCount; ++i) {
83f0e0bc Poul Sander 2026-05-30 17:59 113
        if (kDefaults[i].category == CatNotConfigurable) {
83f0e0bc Poul Sander 2026-05-30 17:59 114
            m_bindings[i].key = kDefaults[i].defaultKey;
83f0e0bc Poul Sander 2026-05-30 17:59 115
            continue;
83f0e0bc Poul Sander 2026-05-30 17:59 116
        }
83f0e0bc Poul Sander 2026-05-30 17:59 117
        const QString key = QString::fromLatin1(kDefaults[i].name);
83f0e0bc Poul Sander 2026-05-30 17:59 118
        if (settings.contains(key))
83f0e0bc Poul Sander 2026-05-30 17:59 119
            m_bindings[i].key = QKeySequence(settings.value(key).toString());
83f0e0bc Poul Sander 2026-05-30 17:59 120
        else
83f0e0bc Poul Sander 2026-05-30 17:59 121
            m_bindings[i].key = kDefaults[i].defaultKey;
83f0e0bc Poul Sander 2026-05-30 17:59 122
    }
83f0e0bc Poul Sander 2026-05-30 17:59 123
    settings.endGroup();
83f0e0bc Poul Sander 2026-05-30 17:59 124
}
83f0e0bc Poul Sander 2026-05-30 17:59 125
83f0e0bc Poul Sander 2026-05-30 17:59 126
void ShortcutManager::save(QSettings &settings) const
83f0e0bc Poul Sander 2026-05-30 17:59 127
{
83f0e0bc Poul Sander 2026-05-30 17:59 128
    settings.beginGroup("shortcuts");
83f0e0bc Poul Sander 2026-05-30 17:59 129
    for (int i = 0; i < ActionCount; ++i) {
83f0e0bc Poul Sander 2026-05-30 17:59 130
        if (kDefaults[i].category == CatNotConfigurable)
83f0e0bc Poul Sander 2026-05-30 17:59 131
            continue;
83f0e0bc Poul Sander 2026-05-30 17:59 132
        const QString key = QString::fromLatin1(kDefaults[i].name);
83f0e0bc Poul Sander 2026-05-30 17:59 133
        if (m_bindings[i].key == kDefaults[i].defaultKey)
83f0e0bc Poul Sander 2026-05-30 17:59 134
            settings.remove(key); // only store non-defaults
83f0e0bc Poul Sander 2026-05-30 17:59 135
        else
83f0e0bc Poul Sander 2026-05-30 17:59 136
            settings.setValue(key, m_bindings[i].key.toString());
83f0e0bc Poul Sander 2026-05-30 17:59 137
    }
83f0e0bc Poul Sander 2026-05-30 17:59 138
    settings.endGroup();
83f0e0bc Poul Sander 2026-05-30 17:59 139
}
83f0e0bc Poul Sander 2026-05-30 17:59 140
83f0e0bc Poul Sander 2026-05-30 17:59 141
QKeySequence ShortcutManager::defaultShortcut(Action action)
83f0e0bc Poul Sander 2026-05-30 17:59 142
{
83f0e0bc Poul Sander 2026-05-30 17:59 143
    if (action < 0 || action >= ActionCount)
83f0e0bc Poul Sander 2026-05-30 17:59 144
        return {};
83f0e0bc Poul Sander 2026-05-30 17:59 145
    return kDefaults[action].defaultKey;
83f0e0bc Poul Sander 2026-05-30 17:59 146
}
83f0e0bc Poul Sander 2026-05-30 17:59 147
83f0e0bc Poul Sander 2026-05-30 17:59 148
QString ShortcutManager::actionName(Action action)
83f0e0bc Poul Sander 2026-05-30 17:59 149
{
83f0e0bc Poul Sander 2026-05-30 17:59 150
    if (action < 0 || action >= ActionCount)
83f0e0bc Poul Sander 2026-05-30 17:59 151
        return {};
83f0e0bc Poul Sander 2026-05-30 17:59 152
    return QString::fromLatin1(kDefaults[action].name);
83f0e0bc Poul Sander 2026-05-30 17:59 153
}
83f0e0bc Poul Sander 2026-05-30 17:59 154
83f0e0bc Poul Sander 2026-05-30 17:59 155
QString ShortcutManager::actionDescription(Action action)
83f0e0bc Poul Sander 2026-05-30 17:59 156
{
83f0e0bc Poul Sander 2026-05-30 17:59 157
    if (action < 0 || action >= ActionCount)
83f0e0bc Poul Sander 2026-05-30 17:59 158
        return {};
4c41f5ff Poul Sander 2026-05-31 00:01 159
    return QCoreApplication::translate("ShortcutManager", kDefaults[action].description);
83f0e0bc Poul Sander 2026-05-30 17:59 160
}
83f0e0bc Poul Sander 2026-05-30 17:59 161
83f0e0bc Poul Sander 2026-05-30 17:59 162
ShortcutManager::Category ShortcutManager::actionCategory(Action action)
83f0e0bc Poul Sander 2026-05-30 17:59 163
{
83f0e0bc Poul Sander 2026-05-30 17:59 164
    if (action < 0 || action >= ActionCount)
83f0e0bc Poul Sander 2026-05-30 17:59 165
        return CatNotConfigurable;
83f0e0bc Poul Sander 2026-05-30 17:59 166
    return kDefaults[action].category;
83f0e0bc Poul Sander 2026-05-30 17:59 167
}
83f0e0bc Poul Sander 2026-05-30 17:59 168
83f0e0bc Poul Sander 2026-05-30 17:59 169
bool ShortcutManager::matches(const QKeyEvent *event, Action action) const
83f0e0bc Poul Sander 2026-05-30 17:59 170
{
83f0e0bc Poul Sander 2026-05-30 17:59 171
    if (action < 0 || action >= ActionCount)
83f0e0bc Poul Sander 2026-05-30 17:59 172
        return false;
83f0e0bc Poul Sander 2026-05-30 17:59 173
    const QKeySequence &seq = m_bindings[action].key;
83f0e0bc Poul Sander 2026-05-30 17:59 174
    if (seq.isEmpty())
83f0e0bc Poul Sander 2026-05-30 17:59 175
        return false;
83f0e0bc Poul Sander 2026-05-30 17:59 176
    // Compare the first key in the sequence against the event's key + modifiers.
83f0e0bc Poul Sander 2026-05-30 17:59 177
    int eventKey = event->key();
83f0e0bc Poul Sander 2026-05-30 17:59 178
    Qt::KeyboardModifiers mods = event->modifiers() & ~Qt::KeypadModifier;
83f0e0bc Poul Sander 2026-05-30 17:59 179
    if (mods != Qt::NoModifier)
83f0e0bc Poul Sander 2026-05-30 17:59 180
        eventKey |= mods;
83f0e0bc Poul Sander 2026-05-30 17:59 181
    return seq[0] == QKeyCombination::fromCombined(eventKey);
83f0e0bc Poul Sander 2026-05-30 17:59 182
}
1970-01-01 00:00 183