mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-14 05:07:10 +02:00
Section for shortcuts editing.
This commit is contained in:
parent
c82fbefcfc
commit
0585e72c35
7 changed files with 572 additions and 4 deletions
|
@ -1474,6 +1474,8 @@ PRIVATE
|
|||
settings/settings_privacy_security.h
|
||||
settings/settings_scale_preview.cpp
|
||||
settings/settings_scale_preview.h
|
||||
settings/settings_shortcuts.cpp
|
||||
settings/settings_shortcuts.h
|
||||
settings/settings_type.h
|
||||
settings/settings_websites.cpp
|
||||
settings/settings_websites.h
|
||||
|
|
|
@ -642,6 +642,43 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_settings_chat_quick_action_react" = "Send reaction with double click";
|
||||
"lng_settings_chat_corner_reaction" = "Reaction button on messages";
|
||||
|
||||
"lng_settings_shortcuts" = "Keyboard shortcuts";
|
||||
"lng_shortcuts_reset" = "Reset to default";
|
||||
"lng_shortcuts_close" = "Close the window";
|
||||
"lng_shortcuts_lock" = "Lock the application";
|
||||
"lng_shortcuts_minimize" = "Minimize the window";
|
||||
"lng_shortcuts_quit" = "Quit the application";
|
||||
"lng_shortcuts_media_play" = "Play the media";
|
||||
"lng_shortcuts_media_pause" = "Pause the media";
|
||||
"lng_shortcuts_media_play_pause" = "Toggle media playback";
|
||||
"lng_shortcuts_media_stop" = "Stop media playback";
|
||||
"lng_shortcuts_media_previous" = "Previous track";
|
||||
"lng_shortcuts_media_next" = "Next track";
|
||||
"lng_shortcuts_search" = "Search messages";
|
||||
"lng_shortcuts_chat_previous" = "Previous chat";
|
||||
"lng_shortcuts_chat_next" = "Next chat";
|
||||
"lng_shortcuts_chat_first" = "First chat";
|
||||
"lng_shortcuts_chat_last" = "Last chat";
|
||||
"lng_shortcuts_chat_self" = "Saved Messages";
|
||||
"lng_shortcuts_chat_pinned_n" = "Pinned chat #{index}";
|
||||
"lng_shortcuts_show_account_n" = "Account #{index}";
|
||||
"lng_shortcuts_show_all_chats" = "All Chats folder";
|
||||
"lng_shortcuts_show_folder_n" = "Folder #{index}";
|
||||
"lng_shortcuts_show_folder_last" = "Last folder";
|
||||
"lng_shortcuts_folder_next" = "Next folder";
|
||||
"lng_shortcuts_folder_previous" = "Previous folder";
|
||||
"lng_shortcuts_scheduled" = "Scheduled messages";
|
||||
"lng_shortcuts_archive" = "Archived chats";
|
||||
"lng_shortcuts_contacts" = "Contacts list";
|
||||
"lng_shortcuts_just_send" = "Just send";
|
||||
"lng_shortcuts_silent_send" = "Silent send";
|
||||
"lng_shortcuts_schedule" = "Schedule";
|
||||
"lng_shortcuts_read_chat" = "Mark chat as read";
|
||||
"lng_shortcuts_archive_chat" = "Archive chat";
|
||||
"lng_shortcuts_media_fullscreen" = "Toggle video fullscreen";
|
||||
"lng_shortcuts_show_chat_menu" = "Show chat menu";
|
||||
"lng_shortcuts_recording" = "Recording...";
|
||||
|
||||
"lng_settings_chat_reactions_title" = "Quick Reaction";
|
||||
"lng_settings_chat_reactions_subtitle" = "Choose your favorite reaction";
|
||||
"lng_settings_chat_message_reply_from" = "Bob Harris";
|
||||
|
|
|
@ -28,6 +28,7 @@ namespace {
|
|||
constexpr auto kCountLimit = 256; // How many shortcuts can be in json file.
|
||||
|
||||
rpl::event_stream<not_null<Request*>> RequestsStream;
|
||||
bool Paused/* = false*/;
|
||||
|
||||
const auto AutoRepeatCommands = base::flat_set<Command>{
|
||||
Command::MediaPrevious,
|
||||
|
@ -175,6 +176,9 @@ public:
|
|||
|
||||
[[nodiscard]] const QStringList &errors() const;
|
||||
|
||||
[[nodiscard]] base::flat_map<QKeySequence, Command> keysDefaults() const;
|
||||
[[nodiscard]] base::flat_map<QKeySequence, Command> keysCurrents() const;
|
||||
|
||||
private:
|
||||
void fillDefaults();
|
||||
void writeDefaultFile();
|
||||
|
@ -189,6 +193,8 @@ private:
|
|||
base::flat_map<QKeySequence, base::unique_qptr<QAction>> _shortcuts;
|
||||
base::flat_multi_map<not_null<QObject*>, Command> _commandByObject;
|
||||
|
||||
base::flat_map<QKeySequence, Command> _defaults;
|
||||
|
||||
base::flat_set<QAction*> _mediaShortcuts;
|
||||
base::flat_set<QAction*> _supportShortcuts;
|
||||
|
||||
|
@ -278,6 +284,21 @@ const QStringList &Manager::errors() const {
|
|||
return _errors;
|
||||
}
|
||||
|
||||
base::flat_map<QKeySequence, Command> Manager::keysDefaults() const {
|
||||
return _defaults;
|
||||
}
|
||||
|
||||
base::flat_map<QKeySequence, Command> Manager::keysCurrents() const {
|
||||
auto result = base::flat_map<QKeySequence, Command>();
|
||||
for (const auto &[keys, command] : _shortcuts) {
|
||||
const auto i = _commandByObject.findFirst(command);
|
||||
if (i != _commandByObject.end()) {
|
||||
result.emplace(keys, i->second);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<Command> Manager::lookup(not_null<QObject*> object) const {
|
||||
auto result = std::vector<Command>();
|
||||
auto i = _commandByObject.findFirst(object);
|
||||
|
@ -441,6 +462,8 @@ void Manager::fillDefaults() {
|
|||
set(u"ctrl+r"_q, Command::ReadChat);
|
||||
|
||||
set(u"ctrl+\\"_q, Command::ShowChatMenu);
|
||||
|
||||
_defaults = keysCurrents();
|
||||
}
|
||||
|
||||
void Manager::writeDefaultFile() {
|
||||
|
@ -598,7 +621,9 @@ bool Launch(Command command) {
|
|||
}
|
||||
|
||||
bool Launch(std::vector<Command> commands) {
|
||||
if (auto handler = RequestHandler(std::move(commands))) {
|
||||
if (Paused) {
|
||||
return false;
|
||||
} else if (auto handler = RequestHandler(std::move(commands))) {
|
||||
return handler();
|
||||
}
|
||||
return false;
|
||||
|
@ -630,6 +655,55 @@ void ToggleSupportShortcuts(bool toggled) {
|
|||
Data.toggleSupport(toggled);
|
||||
}
|
||||
|
||||
void Pause() {
|
||||
Paused = true;
|
||||
}
|
||||
|
||||
void Unpause() {
|
||||
Paused = false;
|
||||
}
|
||||
|
||||
base::flat_map<QKeySequence, Command> KeysDefaults() {
|
||||
return Data.keysDefaults();
|
||||
}
|
||||
|
||||
base::flat_map<QKeySequence, Command> KeysCurrents() {
|
||||
return Data.keysCurrents();
|
||||
}
|
||||
|
||||
bool AllowWithoutModifiers(int key) {
|
||||
const auto service = {
|
||||
Qt::Key_Escape,
|
||||
Qt::Key_Tab,
|
||||
Qt::Key_Backtab,
|
||||
Qt::Key_Backspace,
|
||||
Qt::Key_Return,
|
||||
Qt::Key_Enter,
|
||||
Qt::Key_Insert,
|
||||
Qt::Key_Delete,
|
||||
Qt::Key_Pause,
|
||||
Qt::Key_Print,
|
||||
Qt::Key_SysReq,
|
||||
Qt::Key_Clear,
|
||||
Qt::Key_Home,
|
||||
Qt::Key_End,
|
||||
Qt::Key_Left,
|
||||
Qt::Key_Up,
|
||||
Qt::Key_Right,
|
||||
Qt::Key_Down,
|
||||
Qt::Key_PageUp,
|
||||
Qt::Key_PageDown,
|
||||
Qt::Key_Shift,
|
||||
Qt::Key_Control,
|
||||
Qt::Key_Meta,
|
||||
Qt::Key_Alt,
|
||||
Qt::Key_CapsLock,
|
||||
Qt::Key_NumLock,
|
||||
Qt::Key_ScrollLock,
|
||||
};
|
||||
return (key >= 0x80) && !ranges::contains(service, key);
|
||||
}
|
||||
|
||||
void Finish() {
|
||||
Data.clear();
|
||||
}
|
||||
|
|
|
@ -139,4 +139,11 @@ void ToggleMediaShortcuts(bool toggled);
|
|||
// have some conflicts with default input shortcuts, like Ctrl+Delete.
|
||||
void ToggleSupportShortcuts(bool toggled);
|
||||
|
||||
void Pause();
|
||||
void Unpause();
|
||||
|
||||
[[nodiscard]] base::flat_map<QKeySequence, Command> KeysDefaults();
|
||||
[[nodiscard]] base::flat_map<QKeySequence, Command> KeysCurrents();
|
||||
[[nodiscard]] bool AllowWithoutModifiers(int key);
|
||||
|
||||
} // namespace Shortcuts
|
||||
|
|
|
@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "settings/settings_advanced.h"
|
||||
#include "settings/settings_privacy_security.h"
|
||||
#include "settings/settings_experimental.h"
|
||||
#include "settings/settings_shortcuts.h"
|
||||
#include "boxes/abstract_box.h"
|
||||
#include "boxes/peers/edit_peer_color_box.h"
|
||||
#include "boxes/connection_box.h"
|
||||
|
@ -833,7 +834,8 @@ void SetupStickersEmoji(
|
|||
|
||||
void SetupMessages(
|
||||
not_null<Window::SessionController*> controller,
|
||||
not_null<Ui::VerticalLayout*> container) {
|
||||
not_null<Ui::VerticalLayout*> container,
|
||||
Fn<void(Type)> showOther) {
|
||||
Ui::AddDivider(container);
|
||||
Ui::AddSkip(container);
|
||||
|
||||
|
@ -1003,7 +1005,16 @@ void SetupMessages(
|
|||
Core::App().saveSettingsDelayed();
|
||||
}, inner->lifetime());
|
||||
|
||||
Ui::AddSkip(inner, st::settingsCheckboxesSkip);
|
||||
AddButtonWithIcon(
|
||||
inner,
|
||||
tr::lng_settings_shortcuts(),
|
||||
st::settingsButton,
|
||||
{ &st::menuIconBotCommands }
|
||||
)->addClickHandler([=] {
|
||||
showOther(Shortcuts::Id());
|
||||
});
|
||||
|
||||
Ui::AddSkip(inner);
|
||||
}
|
||||
|
||||
void SetupArchive(
|
||||
|
@ -1793,7 +1804,7 @@ void Chat::setupContent(not_null<Window::SessionController*> controller) {
|
|||
SetupCloudThemes(controller, content);
|
||||
SetupChatBackground(controller, content);
|
||||
SetupStickersEmoji(controller, content);
|
||||
SetupMessages(controller, content);
|
||||
SetupMessages(controller, content, showOtherMethod());
|
||||
Ui::AddDivider(content);
|
||||
SetupSensitiveContent(controller, content, std::move(updateOnTick));
|
||||
SetupArchive(controller, content);
|
||||
|
|
406
Telegram/SourceFiles/settings/settings_shortcuts.cpp
Normal file
406
Telegram/SourceFiles/settings/settings_shortcuts.cpp
Normal file
|
@ -0,0 +1,406 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "settings/settings_shortcuts.h"
|
||||
|
||||
#include "base/event_filter.h"
|
||||
#include "core/application.h"
|
||||
#include "core/shortcuts.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "ui/text/text_utilities.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/wrap/slide_wrap.h"
|
||||
#include "ui/wrap/vertical_layout.h"
|
||||
#include "ui/vertical_list.h"
|
||||
#include "styles/style_settings.h"
|
||||
|
||||
namespace Settings {
|
||||
namespace {
|
||||
|
||||
namespace S = ::Shortcuts;
|
||||
|
||||
struct Labeled {
|
||||
S::Command command = {};
|
||||
rpl::producer<QString> label;
|
||||
};
|
||||
|
||||
[[nodiscard]] std::vector<Labeled> Entries() {
|
||||
using C = S::Command;
|
||||
const auto pinned = [](int index) {
|
||||
return tr::lng_shortcuts_chat_pinned_n(
|
||||
lt_index,
|
||||
rpl::single(QString::number(index)));
|
||||
};
|
||||
const auto account = [](int index) {
|
||||
return tr::lng_shortcuts_show_account_n(
|
||||
lt_index,
|
||||
rpl::single(QString::number(index)));
|
||||
};
|
||||
const auto folder = [](int index) {
|
||||
return tr::lng_shortcuts_show_folder_n(
|
||||
lt_index,
|
||||
rpl::single(QString::number(index)));
|
||||
};
|
||||
const auto separator = Labeled{ C(), nullptr };
|
||||
return {
|
||||
{ C::Close, tr::lng_shortcuts_close() },
|
||||
{ C::Lock, tr::lng_shortcuts_lock() },
|
||||
{ C::Minimize, tr::lng_shortcuts_minimize() },
|
||||
{ C::Quit, tr::lng_shortcuts_quit() },
|
||||
separator,
|
||||
{ C::Search, tr::lng_shortcuts_search() },
|
||||
separator,
|
||||
{ C::ChatPrevious, tr::lng_shortcuts_chat_previous() },
|
||||
{ C::ChatNext, tr::lng_shortcuts_chat_next() },
|
||||
{ C::ChatFirst, tr::lng_shortcuts_chat_first() },
|
||||
{ C::ChatLast, tr::lng_shortcuts_chat_last() },
|
||||
{ C::ChatSelf, tr::lng_shortcuts_chat_self() },
|
||||
separator,
|
||||
{ C::ChatPinned1, pinned(1) },
|
||||
{ C::ChatPinned2, pinned(2) },
|
||||
{ C::ChatPinned3, pinned(3) },
|
||||
{ C::ChatPinned4, pinned(4) },
|
||||
{ C::ChatPinned5, pinned(5) },
|
||||
{ C::ChatPinned6, pinned(6) },
|
||||
{ C::ChatPinned7, pinned(7) },
|
||||
{ C::ChatPinned8, pinned(8) },
|
||||
separator,
|
||||
{ C::ShowAccount1, account(1) },
|
||||
{ C::ShowAccount2, account(2) },
|
||||
{ C::ShowAccount3, account(3) },
|
||||
{ C::ShowAccount4, account(4) },
|
||||
{ C::ShowAccount5, account(5) },
|
||||
{ C::ShowAccount6, account(6) },
|
||||
separator,
|
||||
{ C::ShowAllChats, tr::lng_shortcuts_show_all_chats() },
|
||||
{ C::ShowFolder1, folder(1) },
|
||||
{ C::ShowFolder2, folder(2) },
|
||||
{ C::ShowFolder3, folder(3) },
|
||||
{ C::ShowFolder4, folder(4) },
|
||||
{ C::ShowFolder5, folder(5) },
|
||||
{ C::ShowFolder6, folder(6) },
|
||||
{ C::ShowFolderLast, tr::lng_shortcuts_show_folder_last() },
|
||||
{ C::FolderNext, tr::lng_shortcuts_folder_next() },
|
||||
{ C::FolderPrevious, tr::lng_shortcuts_folder_previous() },
|
||||
{ C::ShowArchive, tr::lng_shortcuts_archive() },
|
||||
{ C::ShowContacts, tr::lng_shortcuts_contacts() },
|
||||
separator,
|
||||
{ C::ReadChat, tr::lng_shortcuts_read_chat() },
|
||||
{ C::ArchiveChat, tr::lng_shortcuts_archive_chat() },
|
||||
{ C::ShowScheduled, tr::lng_shortcuts_scheduled() },
|
||||
{ C::ShowChatMenu, tr::lng_shortcuts_show_chat_menu() },
|
||||
separator,
|
||||
{ C::JustSendMessage, tr::lng_shortcuts_just_send() },
|
||||
{ C::SendSilentMessage, tr::lng_shortcuts_silent_send() },
|
||||
{ C::ScheduleMessage, tr::lng_shortcuts_schedule() },
|
||||
separator,
|
||||
{ C::MediaViewerFullscreen, tr::lng_shortcuts_media_fullscreen() },
|
||||
separator,
|
||||
{ C::MediaPlay, tr::lng_shortcuts_media_play() },
|
||||
{ C::MediaPause, tr::lng_shortcuts_media_pause() },
|
||||
{ C::MediaPlayPause, tr::lng_shortcuts_media_play_pause() },
|
||||
{ C::MediaStop, tr::lng_shortcuts_media_stop() },
|
||||
{ C::MediaPrevious, tr::lng_shortcuts_media_previous() },
|
||||
{ C::MediaNext, tr::lng_shortcuts_media_next() },
|
||||
};
|
||||
}
|
||||
|
||||
[[nodiscard]] Fn<void()> SetupShortcutsContent(
|
||||
not_null<Window::SessionController*> controller,
|
||||
not_null<Ui::VerticalLayout*> content) {
|
||||
const auto &defaults = S::KeysDefaults();
|
||||
const auto ¤ts = S::KeysCurrents();
|
||||
|
||||
struct Button {
|
||||
S::Command command;
|
||||
std::unique_ptr<Ui::SettingsButton> widget;
|
||||
rpl::variable<QKeySequence> key;
|
||||
rpl::variable<bool> removed;
|
||||
};
|
||||
struct Entry {
|
||||
S::Command command;
|
||||
rpl::producer<QString> label;
|
||||
std::vector<QKeySequence> original;
|
||||
std::vector<QKeySequence> now;
|
||||
Ui::VerticalLayout *wrap = nullptr;
|
||||
std::vector<std::unique_ptr<Button>> buttons;
|
||||
};
|
||||
struct State {
|
||||
std::vector<Entry> entries;
|
||||
rpl::variable<bool> modified;
|
||||
rpl::variable<Button*> recording;
|
||||
rpl::variable<QKeySequence> lastKey;
|
||||
};
|
||||
const auto state = content->lifetime().make_state<State>();
|
||||
const auto labeled = Entries();
|
||||
auto &entries = state->entries = ranges::views::all(
|
||||
labeled
|
||||
) | ranges::views::transform([](Labeled labeled) {
|
||||
return Entry{ labeled.command, std::move(labeled.label) };
|
||||
}) | ranges::to_vector;
|
||||
|
||||
for (const auto &[keys, command] : defaults) {
|
||||
const auto i = ranges::find(entries, command, &Entry::command);
|
||||
if (i != end(entries)) {
|
||||
i->original.push_back(keys);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &[keys, command] : currents) {
|
||||
const auto i = ranges::find(entries, command, &Entry::command);
|
||||
if (i != end(entries)) {
|
||||
i->now.push_back(keys);
|
||||
}
|
||||
}
|
||||
|
||||
const auto checkModified = [=] {
|
||||
for (const auto &entry : state->entries) {
|
||||
auto original = entry.original;
|
||||
auto now = entry.now;
|
||||
ranges::sort(original);
|
||||
ranges::sort(now);
|
||||
if (original != now) {
|
||||
state->modified = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
state->modified = false;
|
||||
};
|
||||
checkModified();
|
||||
|
||||
const auto fill = [=](Entry &entry) {
|
||||
auto index = 0;
|
||||
if (entry.original.empty()) {
|
||||
entry.original.push_back(QKeySequence());
|
||||
}
|
||||
if (entry.now.empty()) {
|
||||
entry.now.push_back(QKeySequence());
|
||||
}
|
||||
for (const auto &now : entry.now) {
|
||||
if (index < entry.buttons.size()) {
|
||||
entry.buttons[index]->key = now;
|
||||
} else {
|
||||
auto button = std::make_unique<Button>(Button{
|
||||
.command = entry.command,
|
||||
.key = now,
|
||||
});
|
||||
const auto raw = button.get();
|
||||
const auto widget = entry.wrap->add(
|
||||
object_ptr<Ui::SettingsButton>(
|
||||
entry.wrap,
|
||||
rpl::duplicate(entry.label),
|
||||
st::settingsButtonNoIcon));
|
||||
const auto keys = Ui::CreateChild<Ui::FlatLabel>(
|
||||
widget,
|
||||
st::settingsButtonNoIcon.rightLabel);
|
||||
keys->show();
|
||||
rpl::combine(
|
||||
widget->widthValue(),
|
||||
rpl::duplicate(entry.label),
|
||||
button->key.value(),
|
||||
state->recording.value(),
|
||||
button->removed.value()
|
||||
) | rpl::start_with_next([=](
|
||||
int width,
|
||||
const QString &button,
|
||||
const QKeySequence &key,
|
||||
Button *recording,
|
||||
bool removed) {
|
||||
const auto &st = st::settingsButtonNoIcon;
|
||||
const auto available = width
|
||||
- st.padding.left()
|
||||
- st.padding.right()
|
||||
- st.style.font->width(button)
|
||||
- st::settingsButtonRightSkip;
|
||||
keys->setMarkedText((recording == raw)
|
||||
? Ui::Text::Italic(
|
||||
tr::lng_shortcuts_recording(tr::now))
|
||||
: key.isEmpty()
|
||||
? TextWithEntities()
|
||||
: removed
|
||||
? Ui::Text::Wrapped(
|
||||
TextWithEntities{ key.toString() },
|
||||
EntityType::StrikeOut)
|
||||
: TextWithEntities{ key.toString() });
|
||||
keys->setTextColorOverride(removed
|
||||
? st::attentionButtonFg->c
|
||||
: (recording == raw)
|
||||
? st::boxTextFgGood->c
|
||||
: std::optional<QColor>());
|
||||
keys->resizeToNaturalWidth(available);
|
||||
keys->moveToRight(
|
||||
st::settingsButtonRightSkip,
|
||||
st.padding.top());
|
||||
}, keys->lifetime());
|
||||
keys->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
|
||||
widget->setClickedCallback([=] {
|
||||
S::Pause();
|
||||
state->recording = raw;
|
||||
});
|
||||
button->widget.reset(widget);
|
||||
entry.buttons.push_back(std::move(button));
|
||||
}
|
||||
++index;
|
||||
}
|
||||
while (entry.wrap->count() > index) {
|
||||
entry.buttons.pop_back();
|
||||
}
|
||||
};
|
||||
|
||||
const auto stopRecording = [=](std::optional<QKeySequence> result = {}) {
|
||||
const auto button = state->recording.current();
|
||||
if (!button) {
|
||||
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<Button>::get);
|
||||
if (i != end(entry.buttons)) {
|
||||
const auto index = i - begin(entry.buttons);
|
||||
if (now.isEmpty()) {
|
||||
entry.now.erase(begin(entry.now) + index);
|
||||
} else {
|
||||
const auto i = ranges::find(entry.now, now);
|
||||
if (i == end(entry.now)) {
|
||||
entry.now[index] = now;
|
||||
} else if (i != begin(entry.now) + index) {
|
||||
std::swap(entry.now[index], *i);
|
||||
entry.now.erase(i);
|
||||
}
|
||||
}
|
||||
fill(entry);
|
||||
checkModified();
|
||||
} else if (now != was) {
|
||||
const auto i = now.isEmpty()
|
||||
? end(entry.now)
|
||||
: ranges::find(entry.now, now);
|
||||
if (i != end(entry.now)) {
|
||||
entry.buttons[i - begin(entry.now)]->removed = true;
|
||||
}
|
||||
const auto j = was.isEmpty()
|
||||
? end(entry.now)
|
||||
: ranges::find(entry.now, was);
|
||||
if (j != end(entry.now)) {
|
||||
entry.buttons[j - begin(entry.now)]->removed = false;
|
||||
was = QKeySequence();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
InvokeQueued(content, [=] {
|
||||
InvokeQueued(content, [=] {
|
||||
// Let all the shortcut events propagate first.
|
||||
S::Unpause();
|
||||
});
|
||||
});
|
||||
};
|
||||
base::install_event_filter(content, qApp, [=](not_null<QEvent*> e) {
|
||||
const auto type = e->type();
|
||||
if (type == QEvent::ShortcutOverride && state->recording.current()) {
|
||||
const auto key = static_cast<QKeyEvent*>(e.get());
|
||||
const auto m = key->modifiers();
|
||||
const auto k = key->key();
|
||||
const auto clear = !m
|
||||
&& (k == Qt::Key_Backspace || k == Qt::Key_Delete);
|
||||
if (k == Qt::Key_Control
|
||||
|| k == Qt::Key_Shift
|
||||
|| k == Qt::Key_Alt
|
||||
|| k == Qt::Key_Meta) {
|
||||
return base::EventFilterResult::Cancel;
|
||||
} else if (!m && !clear && !S::AllowWithoutModifiers(k)) {
|
||||
stopRecording();
|
||||
return base::EventFilterResult::Cancel;
|
||||
}
|
||||
stopRecording(clear ? QKeySequence() : QKeySequence(k | m));
|
||||
return base::EventFilterResult::Cancel;
|
||||
} else if (type == QEvent::KeyPress) {
|
||||
if (static_cast<QKeyEvent*>(e.get())->key() == Qt::Key_Escape) {
|
||||
stopRecording();
|
||||
return base::EventFilterResult::Cancel;
|
||||
}
|
||||
}
|
||||
return base::EventFilterResult::Continue;
|
||||
});
|
||||
|
||||
const auto modifiedWrap = content->add(
|
||||
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
|
||||
content,
|
||||
object_ptr<Ui::VerticalLayout>(content)));
|
||||
const auto modifiedInner = modifiedWrap->entity();
|
||||
AddDivider(modifiedInner);
|
||||
AddSkip(modifiedInner);
|
||||
const auto reset = modifiedInner->add(object_ptr<Ui::SettingsButton>(
|
||||
modifiedInner,
|
||||
tr::lng_shortcuts_reset(),
|
||||
st::settingsButtonNoIcon));
|
||||
reset->setClickedCallback([=] {
|
||||
stopRecording();
|
||||
for (auto &entry : state->entries) {
|
||||
if (entry.now != entry.original) {
|
||||
entry.now = entry.original;
|
||||
fill(entry);
|
||||
}
|
||||
}
|
||||
checkModified();
|
||||
});
|
||||
AddSkip(modifiedInner);
|
||||
AddDivider(modifiedInner);
|
||||
modifiedWrap->toggleOn(state->modified.value());
|
||||
|
||||
AddSkip(content);
|
||||
for (auto &entry : entries) {
|
||||
if (!entry.label) {
|
||||
AddSkip(content);
|
||||
AddDivider(content);
|
||||
AddSkip(content);
|
||||
continue;
|
||||
}
|
||||
entry.wrap = content->add(object_ptr<Ui::VerticalLayout>(content));
|
||||
fill(entry);
|
||||
}
|
||||
|
||||
return [=] {
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Shortcuts::Shortcuts(
|
||||
QWidget *parent,
|
||||
not_null<Window::SessionController*> controller)
|
||||
: Section(parent) {
|
||||
setupContent(controller);
|
||||
}
|
||||
|
||||
Shortcuts::~Shortcuts() {
|
||||
if (!Core::Quitting()) {
|
||||
_save();
|
||||
}
|
||||
}
|
||||
|
||||
rpl::producer<QString> Shortcuts::title() {
|
||||
return tr::lng_settings_shortcuts();
|
||||
}
|
||||
|
||||
void Shortcuts::setupContent(
|
||||
not_null<Window::SessionController*> controller) {
|
||||
const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
|
||||
|
||||
_save = SetupShortcutsContent(controller, content);
|
||||
|
||||
Ui::ResizeFitChild(this, content);
|
||||
}
|
||||
|
||||
} // namespace Settings
|
31
Telegram/SourceFiles/settings/settings_shortcuts.h
Normal file
31
Telegram/SourceFiles/settings/settings_shortcuts.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "settings/settings_common_session.h"
|
||||
|
||||
namespace Settings {
|
||||
|
||||
class Shortcuts : public Section<Shortcuts> {
|
||||
public:
|
||||
Shortcuts(
|
||||
QWidget *parent,
|
||||
not_null<Window::SessionController*> controller);
|
||||
~Shortcuts();
|
||||
|
||||
[[nodiscard]] rpl::producer<QString> title() override;
|
||||
|
||||
private:
|
||||
void setupContent(not_null<Window::SessionController*> controller);
|
||||
|
||||
Fn<void()> _save;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Settings
|
||||
|
Loading…
Add table
Reference in a new issue