1/*
2 This file is part of the KDE libraries
3 SPDX-FileCopyrightText: 1999, 2000 Kurt Granroth <granroth@kde.org>
4
5 SPDX-License-Identifier: LGPL-2.0-only
6*/
7
8#ifndef KSTANDARDACTION_PRIVATE_H
9#define KSTANDARDACTION_PRIVATE_H
10
11#include <QAction>
12#include <QApplication>
13
14#include <KLazyLocalizedString>
15#include <KLocalizedString>
16#include <KStandardShortcut>
17
18#include <string>
19
20namespace KStandardAction
21{
22
23// Helper class for storing raw data in static tables which can be used for QString instance
24// creation at runtime without copying/converting to new memalloc'ed memory, as well as avoiding
25// that way storing the strings directly as QStrings resulting in non-constexpr init code on
26// library loading
27struct RawStringData {
28 template<std::size_t StringSize>
29 constexpr inline RawStringData(const char16_t (&_data)[StringSize])
30 : data(_data)
31 , size(std::char_traits<char16_t>::length(s: _data))
32 {
33 }
34 constexpr inline RawStringData(std::nullptr_t)
35 {
36 }
37 constexpr inline RawStringData() = default;
38
39 inline QString toString() const
40 {
41 if (!data) {
42 return QString();
43 }
44
45 return Qt::Literals::StringLiterals::operator""_s(str: data, size);
46 }
47
48private:
49 const char16_t *const data = nullptr;
50 const std::size_t size = 0;
51};
52
53struct KStandardActionInfo {
54 StandardAction id;
55 KStandardShortcut::StandardShortcut idAccel;
56 const RawStringData psName;
57 const KLazyLocalizedString psLabel;
58 const KLazyLocalizedString psToolTip;
59 const RawStringData psIconName;
60};
61// clang-format off
62static const KStandardActionInfo g_rgActionInfo[] = {
63 { .id: New, .idAccel: KStandardShortcut::New, .psName: u"file_new", .psLabel: kli18n(text: "&New"), .psToolTip: kli18n(text: "Create new document"), .psIconName: u"document-new" },
64 { .id: Open, .idAccel: KStandardShortcut::Open, .psName: u"file_open", .psLabel: kli18n(text: "&Open…"), .psToolTip: kli18n(text: "Open an existing document"), .psIconName: u"document-open" },
65 { .id: OpenRecent, .idAccel: KStandardShortcut::AccelNone, .psName: u"file_open_recent", .psLabel: kli18n(text: "Open &Recent"), .psToolTip: kli18n(text: "Open a document which was recently opened"), .psIconName: u"document-open-recent" },
66 { .id: Save, .idAccel: KStandardShortcut::Save, .psName: u"file_save", .psLabel: kli18n(text: "&Save"), .psToolTip: kli18n(text: "Save document"), .psIconName: u"document-save" },
67 { .id: SaveAs, .idAccel: KStandardShortcut::SaveAs, .psName: u"file_save_as", .psLabel: kli18n(text: "Save &As…"), .psToolTip: kli18n(text: "Save document under a new name"), .psIconName: u"document-save-as" },
68 { .id: Revert, .idAccel: KStandardShortcut::Revert, .psName: u"file_revert", .psLabel: kli18n(text: "Re&vert"), .psToolTip: kli18n(text: "Revert unsaved changes made to document"), .psIconName: u"document-revert" },
69 { .id: Close, .idAccel: KStandardShortcut::Close, .psName: u"file_close", .psLabel: kli18n(text: "&Close"), .psToolTip: kli18n(text: "Close document"), .psIconName: u"document-close" },
70 { .id: Print, .idAccel: KStandardShortcut::Print, .psName: u"file_print", .psLabel: kli18n(text: "&Print…"), .psToolTip: kli18n(text: "Print document"), .psIconName: u"document-print" },
71 { .id: PrintPreview, .idAccel: KStandardShortcut::PrintPreview, .psName: u"file_print_preview", .psLabel: kli18n(text: "Print Previe&w"), .psToolTip: kli18n(text: "Show a print preview of document"), .psIconName: u"document-print-preview" },
72 { .id: Mail, .idAccel: KStandardShortcut::Mail, .psName: u"file_mail", .psLabel: kli18n(text: "&Mail…"), .psToolTip: kli18n(text: "Send document by mail"), .psIconName: u"mail-send" },
73 { .id: Quit, .idAccel: KStandardShortcut::Quit, .psName: u"file_quit", .psLabel: kli18n(text: "&Quit"), .psToolTip: kli18n(text: "Quit application"), .psIconName: u"application-exit" },
74
75 { .id: Undo, .idAccel: KStandardShortcut::Undo, .psName: u"edit_undo", .psLabel: kli18n(text: "&Undo"), .psToolTip: kli18n(text: "Undo last action"), .psIconName: u"edit-undo" },
76 { .id: Redo, .idAccel: KStandardShortcut::Redo, .psName: u"edit_redo", .psLabel: kli18n(text: "Re&do"), .psToolTip: kli18n(text: "Redo last undone action"), .psIconName: u"edit-redo" },
77 { .id: Cut, .idAccel: KStandardShortcut::Cut, .psName: u"edit_cut", .psLabel: kli18n(text: "Cu&t"), .psToolTip: kli18n(text: "Cut selection to clipboard"), .psIconName: u"edit-cut" },
78 { .id: Copy, .idAccel: KStandardShortcut::Copy, .psName: u"edit_copy", .psLabel: kli18n(text: "&Copy"), .psToolTip: kli18n(text: "Copy selection to clipboard"), .psIconName: u"edit-copy" },
79 { .id: Paste, .idAccel: KStandardShortcut::Paste, .psName: u"edit_paste", .psLabel: kli18n(text: "&Paste"), .psToolTip: kli18n(text: "Paste clipboard content"), .psIconName: u"edit-paste" },
80 { .id: Clear, .idAccel: KStandardShortcut::Clear, .psName: u"edit_clear", .psLabel: kli18n(text: "C&lear"), .psToolTip: {}, .psIconName: u"edit-clear" },
81 { .id: SelectAll, .idAccel: KStandardShortcut::SelectAll, .psName: u"edit_select_all", .psLabel: kli18n(text: "Select &All"), .psToolTip: {}, .psIconName: u"edit-select-all" },
82 { .id: Deselect, .idAccel: KStandardShortcut::Deselect, .psName: u"edit_deselect", .psLabel: kli18n(text: "Dese&lect"), .psToolTip: {}, .psIconName: u"edit-select-none" },
83 { .id: Find, .idAccel: KStandardShortcut::Find, .psName: u"edit_find", .psLabel: kli18n(text: "&Find…"), .psToolTip: {}, .psIconName: u"edit-find" },
84 { .id: FindNext, .idAccel: KStandardShortcut::FindNext, .psName: u"edit_find_next", .psLabel: kli18n(text: "Find &Next"), .psToolTip: {}, .psIconName: u"go-down-search" },
85 { .id: FindPrev, .idAccel: KStandardShortcut::FindPrev, .psName: u"edit_find_prev", .psLabel: kli18n(text: "Find Pre&vious"), .psToolTip: {}, .psIconName: u"go-up-search" },
86 { .id: Replace, .idAccel: KStandardShortcut::Replace, .psName: u"edit_replace", .psLabel: kli18n(text: "&Replace…"), .psToolTip: {}, .psIconName: u"edit-find-replace" },
87
88 { .id: ActualSize, .idAccel: KStandardShortcut::ActualSize, .psName: u"view_actual_size", .psLabel: kli18n(text: "Zoom to &Actual Size"), .psToolTip: kli18n(text: "View document at its actual size"), .psIconName: u"zoom-original" },
89 { .id: FitToPage, .idAccel: KStandardShortcut::FitToPage, .psName: u"view_fit_to_page", .psLabel: kli18n(text: "&Fit to Page"), .psToolTip: kli18n(text: "Zoom to fit page in window"), .psIconName: u"zoom-fit-page" },
90 { .id: FitToWidth, .idAccel: KStandardShortcut::FitToWidth, .psName: u"view_fit_to_width", .psLabel: kli18n(text: "Fit to Page &Width"), .psToolTip: kli18n(text: "Zoom to fit page width in window"), .psIconName: u"zoom-fit-width" },
91 { .id: FitToHeight, .idAccel: KStandardShortcut::FitToHeight, .psName: u"view_fit_to_height", .psLabel: kli18n(text: "Fit to Page &Height"), .psToolTip: kli18n(text: "Zoom to fit page height in window"), .psIconName: u"zoom-fit-height" },
92 { .id: ZoomIn, .idAccel: KStandardShortcut::ZoomIn, .psName: u"view_zoom_in", .psLabel: kli18n(text: "Zoom &In"), .psToolTip: {}, .psIconName: u"zoom-in" },
93 { .id: ZoomOut, .idAccel: KStandardShortcut::ZoomOut, .psName: u"view_zoom_out", .psLabel: kli18n(text: "Zoom &Out"), .psToolTip: {}, .psIconName: u"zoom-out" },
94 { .id: Zoom, .idAccel: KStandardShortcut::Zoom, .psName: u"view_zoom", .psLabel: kli18n(text: "&Zoom…"), .psToolTip: kli18n(text: "Select zoom level"), .psIconName: u"zoom" },
95 { .id: Redisplay, .idAccel: KStandardShortcut::Reload, .psName: u"view_redisplay", .psLabel: kli18n(text: "&Refresh"), .psToolTip: kli18n(text: "Refresh document"), .psIconName: u"view-refresh" },
96
97 { .id: Up, .idAccel: KStandardShortcut::Up, .psName: u"go_up", .psLabel: kli18n(text: "&Up"), .psToolTip: kli18n(text: "Go up"), .psIconName: u"go-up" },
98 // The following three have special i18n() needs for sLabel
99 { .id: Back, .idAccel: KStandardShortcut::Back, .psName: u"go_back", .psLabel: {}, .psToolTip: {}, .psIconName: u"go-previous" },
100 { .id: Forward, .idAccel: KStandardShortcut::Forward, .psName: u"go_forward", .psLabel: {}, .psToolTip: {}, .psIconName: u"go-next" },
101 { .id: Home, .idAccel: KStandardShortcut::Home, .psName: u"go_home", .psLabel: {}, .psToolTip: {}, .psIconName: u"go-home" },
102 { .id: Prior, .idAccel: KStandardShortcut::Prior, .psName: u"go_previous", .psLabel: kli18n(text: "&Previous Page"), .psToolTip: kli18n(text: "Go to previous page"), .psIconName: u"go-previous-view-page" },
103 { .id: Next, .idAccel: KStandardShortcut::Next, .psName: u"go_next", .psLabel: kli18n(text: "&Next Page"), .psToolTip: kli18n(text: "Go to next page"), .psIconName: u"go-next-view-page" },
104 { .id: Goto, .idAccel: KStandardShortcut::Goto, .psName: u"go_goto", .psLabel: kli18n(text: "&Go To…"), .psToolTip: {}, .psIconName: {} },
105 { .id: GotoPage, .idAccel: KStandardShortcut::GotoPage, .psName: u"go_goto_page", .psLabel: kli18n(text: "&Go to Page…"), .psToolTip: {}, .psIconName: u"go-jump" },
106 { .id: GotoLine, .idAccel: KStandardShortcut::GotoLine, .psName: u"go_goto_line", .psLabel: kli18n(text: "&Go to Line…"), .psToolTip: {}, .psIconName: {} },
107 { .id: FirstPage, .idAccel: KStandardShortcut::Begin, .psName: u"go_first", .psLabel: kli18n(text: "&First Page"), .psToolTip: kli18n(text: "Go to first page"), .psIconName: u"go-first-view-page" },
108 { .id: LastPage, .idAccel: KStandardShortcut::End, .psName: u"go_last", .psLabel: kli18n(text: "&Last Page"), .psToolTip: kli18n(text: "Go to last page"), .psIconName: u"go-last-view-page" },
109 { .id: DocumentBack, .idAccel: KStandardShortcut::DocumentBack, .psName: u"go_document_back", .psLabel: kli18n(text: "&Back"), .psToolTip: kli18n(text: "Go back in document"), .psIconName: u"go-previous" },
110 { .id: DocumentForward, .idAccel: KStandardShortcut::DocumentForward, .psName: u"go_document_forward", .psLabel: kli18n(text: "&Forward"), .psToolTip: kli18n(text: "Go forward in document"), .psIconName: u"go-next" },
111
112 { .id: AddBookmark, .idAccel: KStandardShortcut::AddBookmark, .psName: u"bookmark_add", .psLabel: kli18n(text: "&Add Bookmark"), .psToolTip: {}, .psIconName: u"bookmark-new" },
113 { .id: EditBookmarks, .idAccel: KStandardShortcut::EditBookmarks, .psName: u"bookmark_edit", .psLabel: kli18n(text: "&Edit Bookmarks…"), .psToolTip: {}, .psIconName: u"bookmarks-organize" },
114
115 { .id: Spelling, .idAccel: KStandardShortcut::Spelling, .psName: u"tools_spelling", .psLabel: kli18n(text: "&Spelling…"), .psToolTip: kli18n(text: "Check spelling in document"), .psIconName: u"tools-check-spelling" },
116
117 { .id: ShowMenubar, .idAccel: KStandardShortcut::ShowMenubar, .psName: u"options_show_menubar", .psLabel: kli18n(text: "Show &Menubar"), .psToolTip: kli18n(text: "Show or hide menubar"), .psIconName: u"show-menu" },
118 { .id: ShowToolbar, .idAccel: KStandardShortcut::ShowToolbar, .psName: u"options_show_toolbar", .psLabel: kli18n(text: "Show &Toolbar"), .psToolTip: kli18n(text: "Show or hide toolbar"), .psIconName: {} },
119 { .id: ShowStatusbar, .idAccel: KStandardShortcut::ShowStatusbar, .psName: u"options_show_statusbar", .psLabel: kli18n(text: "Show St&atusbar"), .psToolTip: kli18n(text: "Show or hide statusbar"), .psIconName: {} },
120 { .id: FullScreen, .idAccel: KStandardShortcut::FullScreen, .psName: u"fullscreen", .psLabel: kli18n(text: "F&ull Screen Mode"), .psToolTip: {}, .psIconName: u"view-fullscreen" },
121 { .id: KeyBindings, .idAccel: KStandardShortcut::KeyBindings, .psName: u"options_configure_keybinding", .psLabel: kli18n(text: "Configure Keyboard S&hortcuts…"), .psToolTip: {}, .psIconName: u"configure-shortcuts" },
122 { .id: Preferences, .idAccel: KStandardShortcut::Preferences, .psName: u"options_configure", .psLabel: kli18n(text: "&Configure %1…"), .psToolTip: {}, .psIconName: u"configure" },
123 { .id: ConfigureToolbars, .idAccel: KStandardShortcut::ConfigureToolbars, .psName: u"options_configure_toolbars", .psLabel: kli18n(text: "Configure Tool&bars…"), .psToolTip: {}, .psIconName: u"configure-toolbars" },
124 { .id: ConfigureNotifications, .idAccel: KStandardShortcut::ConfigureNotifications, .psName: u"options_configure_notifications", .psLabel: kli18n(text: "Configure &Notifications…"), .psToolTip: {}, .psIconName: u"preferences-desktop-notification" },
125
126 // the idea here is that Contents is used in menus, and Help in dialogs, so both share the same
127 // shortcut
128 { .id: HelpContents, .idAccel: KStandardShortcut::Help, .psName: u"help_contents", .psLabel: kli18n(text: "%1 &Handbook"), .psToolTip: {}, .psIconName: u"help-contents" },
129 { .id: WhatsThis, .idAccel: KStandardShortcut::WhatsThis, .psName: u"help_whats_this", .psLabel: kli18n(text: "What's &This?"), .psToolTip: {}, .psIconName: u"help-contextual" },
130 { .id: ReportBug, .idAccel: KStandardShortcut::ReportBug, .psName: u"help_report_bug", .psLabel: kli18n(text: "&Report Bug…"), .psToolTip: {}, .psIconName: u"tools-report-bug" },
131 { .id: SwitchApplicationLanguage, .idAccel: KStandardShortcut::SwitchApplicationLanguage, .psName: u"switch_application_language", .psLabel: kli18n(text: "Configure &Language…"), .psToolTip: {}, .psIconName: u"preferences-desktop-locale" },
132 { .id: AboutApp, .idAccel: KStandardShortcut::AccelNone, .psName: u"help_about_app", .psLabel: kli18n(text: "&About %1"), .psToolTip: {}, .psIconName: nullptr },
133 { .id: AboutKDE, .idAccel: KStandardShortcut::AccelNone, .psName: u"help_about_kde", .psLabel: kli18n(text: "About &KDE"), .psToolTip: {}, .psIconName: u"kde" },
134 { .id: DeleteFile, .idAccel: KStandardShortcut::DeleteFile, .psName: u"deletefile", .psLabel: kli18n(text: "&Delete"), .psToolTip: {}, .psIconName: u"edit-delete" },
135 { .id: RenameFile, .idAccel: KStandardShortcut::RenameFile, .psName: u"renamefile", .psLabel: kli18n(text: "&Rename…"), .psToolTip: {}, .psIconName: u"edit-rename" },
136 { .id: MoveToTrash, .idAccel: KStandardShortcut::MoveToTrash, .psName: u"movetotrash", .psLabel: kli18n(text: "&Move to Trash"), .psToolTip: {}, .psIconName: u"trash-empty" },
137 { .id: Donate, .idAccel: KStandardShortcut::Donate, .psName: u"help_donate", .psLabel: kli18n(text: "&Donate"), .psToolTip: {}, .psIconName: u"help-donate"},
138 { .id: HamburgerMenu, .idAccel: KStandardShortcut::OpenMainMenu, .psName: u"hamburger_menu", .psLabel: kli18n(text: "Open &Menu"), .psToolTip: {}, .psIconName: u"application-menu" },
139 { .id: ActionNone, .idAccel: KStandardShortcut::AccelNone, .psName: nullptr, .psLabel: {}, .psToolTip: {}, .psIconName: nullptr }
140};
141// clang-format on
142
143inline const KStandardActionInfo *infoPtr(StandardAction id)
144{
145 for (uint i = 0; g_rgActionInfo[i].id != ActionNone; i++) {
146 if (g_rgActionInfo[i].id == id) {
147 return &g_rgActionInfo[i];
148 }
149 }
150
151 return nullptr;
152}
153
154static inline QStringList internal_stdNames()
155{
156 QStringList result;
157
158 for (uint i = 0; g_rgActionInfo[i].id != ActionNone; i++)
159 if (!g_rgActionInfo[i].psLabel.isEmpty()) {
160 if (QByteArray(g_rgActionInfo[i].psLabel.untranslatedText()).contains(bv: "%1"))
161 // Prevents KLocalizedString::toString() from complaining about unsubstituted placeholder.
162 {
163 result.append(t: g_rgActionInfo[i].psLabel.subs(a: QString()).toString());
164 } else {
165 result.append(t: g_rgActionInfo[i].psLabel.toString());
166 }
167 }
168
169 return result;
170}
171
172class AutomaticAction : public QAction
173{
174 Q_OBJECT
175
176public:
177 AutomaticAction(const QIcon &icon, const QString &text, KStandardShortcut::StandardShortcut standardShortcut, const char *slot, QObject *parent);
178public Q_SLOTS:
179 inline void cut()
180 {
181 invokeEditSlot(slot: "cut");
182 }
183 inline void copy()
184 {
185 invokeEditSlot(slot: "copy");
186 }
187 inline void paste()
188 {
189 invokeEditSlot(slot: "paste");
190 }
191 inline void clear()
192 {
193 invokeEditSlot(slot: "clear");
194 }
195 inline void selectAll()
196 {
197 invokeEditSlot(slot: "selectAll");
198 }
199
200 void invokeEditSlot(const char *slot)
201 {
202 if (qApp->focusWidget()) {
203 QMetaObject::invokeMethod(qApp->focusWidget(), member: slot);
204 }
205 }
206};
207
208}
209
210#endif
211

source code of kconfigwidgets/src/kstandardaction_p.h