diff --git a/Telegram/SourceFiles/core/shortcuts.cpp b/Telegram/SourceFiles/core/shortcuts.cpp index 687db4d257..63f8957e72 100644 --- a/Telegram/SourceFiles/core/shortcuts.cpp +++ b/Telegram/SourceFiles/core/shortcuts.cpp @@ -179,19 +179,30 @@ public: [[nodiscard]] base::flat_map keysDefaults() const; [[nodiscard]] base::flat_map keysCurrents() const; + void change( + QKeySequence was, + QKeySequence now, + Command command, + std::optional restore); + private: void fillDefaults(); void writeDefaultFile(); bool readCustomFile(); void set(const QString &keys, Command command, bool replace = false); + void set(const QKeySequence &result, Command command, bool replace); void remove(const QString &keys); + void remove(const QKeySequence &keys); void unregister(base::unique_qptr shortcut); + void pruneListened(); + QStringList _errors; base::flat_map> _shortcuts; base::flat_multi_map, Command> _commandByObject; + std::vector> _listened; base::flat_map _defaults; @@ -299,6 +310,23 @@ base::flat_map Manager::keysCurrents() const { return result; } +void Manager::change( + QKeySequence was, + QKeySequence now, + Command command, + std::optional restore) { + if (!was.isEmpty()) { + remove(was); + } + if (!now.isEmpty()) { + set(now, command, true); + } + if (restore) { + Assert(!was.isEmpty()); + set(was, *restore, true); + } +} + std::vector Manager::lookup(not_null object) const { auto result = std::vector(); auto i = _commandByObject.findFirst(object); @@ -322,11 +350,23 @@ void Manager::toggleSupport(bool toggled) { } void Manager::listen(not_null widget) { + pruneListened(); + _listened.push_back(widget.get()); for (const auto &[keys, shortcut] : _shortcuts) { widget->addAction(shortcut.get()); } } +void Manager::pruneListened() { + for (auto i = begin(_listened); i != end(_listened);) { + if (i->data()) { + ++i; + } else { + i = _listened.erase(i); + } + } +} + bool Manager::readCustomFile() { // read custom shortcuts from file if it exists or write an empty custom shortcuts file QFile file(CustomFilePath()); @@ -527,8 +567,15 @@ void Manager::set(const QString &keys, Command command, bool replace) { _errors.push_back(u"Could not derive key sequence '%1'!"_q.arg(keys)); return; } + set(result, command, replace); +} + +void Manager::set( + const QKeySequence &keys, + Command command, + bool replace) { auto shortcut = base::make_unique_q(); - shortcut->setShortcut(result); + shortcut->setShortcut(keys); shortcut->setShortcutContext(Qt::ApplicationShortcut); if (!AutoRepeatCommands.contains(command)) { shortcut->setAutoRepeat(false); @@ -539,20 +586,26 @@ void Manager::set(const QString &keys, Command command, bool replace) { shortcut->setEnabled(false); } auto object = shortcut.get(); - auto i = _shortcuts.find(result); + auto i = _shortcuts.find(keys); if (i == end(_shortcuts)) { - i = _shortcuts.emplace(result, std::move(shortcut)).first; + i = _shortcuts.emplace(keys, std::move(shortcut)).first; } else if (replace) { unregister(std::exchange(i->second, std::move(shortcut))); } else { object = i->second.get(); } _commandByObject.emplace(object, command); - if (!shortcut && isMediaShortcut) { - _mediaShortcuts.emplace(i->second.get()); - } - if (!shortcut && isSupportShortcut) { - _supportShortcuts.emplace(i->second.get()); + if (!shortcut) { // Added the new one. + if (isMediaShortcut) { + _mediaShortcuts.emplace(i->second.get()); + } + if (isSupportShortcut) { + _supportShortcuts.emplace(i->second.get()); + } + pruneListened(); + for (const auto &widget : _listened) { + widget->addAction(i->second.get()); + } } } @@ -566,7 +619,11 @@ void Manager::remove(const QString &keys) { _errors.push_back(u"Could not derive key sequence '%1'!"_q.arg(keys)); return; } - const auto i = _shortcuts.find(result); + remove(result); +} + +void Manager::remove(const QKeySequence &keys) { + const auto i = _shortcuts.find(keys); if (i != end(_shortcuts)) { unregister(std::move(i->second)); _shortcuts.erase(i); @@ -671,6 +728,14 @@ base::flat_map KeysCurrents() { return Data.keysCurrents(); } +void Change( + QKeySequence was, + QKeySequence now, + Command command, + std::optional restore) { + Data.change(was, now, command, restore); +} + bool AllowWithoutModifiers(int key) { const auto service = { Qt::Key_Escape, diff --git a/Telegram/SourceFiles/core/shortcuts.h b/Telegram/SourceFiles/core/shortcuts.h index 53da6e0b4f..eaad212497 100644 --- a/Telegram/SourceFiles/core/shortcuts.h +++ b/Telegram/SourceFiles/core/shortcuts.h @@ -144,6 +144,13 @@ void Unpause(); [[nodiscard]] base::flat_map KeysDefaults(); [[nodiscard]] base::flat_map KeysCurrents(); + +void Change( + QKeySequence was, + QKeySequence now, + Command command, + std::optional restore = {}); + [[nodiscard]] bool AllowWithoutModifiers(int key); } // namespace Shortcuts diff --git a/Telegram/SourceFiles/settings/settings_shortcuts.cpp b/Telegram/SourceFiles/settings/settings_shortcuts.cpp index f895cfbb06..754d110998 100644 --- a/Telegram/SourceFiles/settings/settings_shortcuts.cpp +++ b/Telegram/SourceFiles/settings/settings_shortcuts.cpp @@ -227,10 +227,10 @@ struct Labeled { TextWithEntities{ key.toString() }, EntityType::StrikeOut) : TextWithEntities{ key.toString() }); - keys->setTextColorOverride(removed - ? st::attentionButtonFg->c - : (recording == raw) + keys->setTextColorOverride((recording == raw) ? st::boxTextFgGood->c + : removed + ? st::attentionButtonFg->c : std::optional()); keys->resizeToNaturalWidth(available); keys->moveToRight( @@ -259,56 +259,71 @@ struct Labeled { return; } state->recording = nullptr; - if (result) { - auto was = button->key.current(); - const auto now = *result; - for (auto &entry : state->entries) { - const auto i = ranges::find( - entry.buttons, - button, - &std::unique_ptr