1 /**************************************************************************
2 * Otter Browser: Web browser controlled by the user, not vice-versa.
3 * Copyright (C) 2013 - 2018 Michal Dutkiewicz aka Emdek <michal@emdek.pl>
4 * Copyright (C) 2014 - 2015 Piotr Wójcik <chocimier@tlen.pl>
5 * Copyright (C) 2015 Jan Bajer aka bajasoft <jbajer@gmail.com>
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 **************************************************************************/
21
22 #include "ActionsManager.h"
23 #include "JsonSettings.h"
24 #include "SessionsManager.h"
25 #include "ThemesManager.h"
26
27 #include <QtCore/QJsonArray>
28 #include <QtCore/QJsonObject>
29 #include <QtCore/QMetaEnum>
30 #include <QtCore/QTextStream>
31 #include <QtGui/QKeySequence>
32
33 namespace Otter
34 {
35
operator ==(const KeyboardProfile::Action & other) const36 bool KeyboardProfile::Action::operator ==(const KeyboardProfile::Action &other) const
37 {
38 return (shortcuts == other.shortcuts && parameters == other.parameters && action == other.action);
39 }
40
KeyboardProfile(const QString & identifier,LoadMode mode)41 KeyboardProfile::KeyboardProfile(const QString &identifier, LoadMode mode) : Addon(),
42 m_identifier(identifier),
43 m_isModified(false)
44 {
45 if (identifier.isEmpty())
46 {
47 return;
48 }
49
50 const JsonSettings settings(SessionsManager::getReadableDataPath(QLatin1String("keyboard/") + identifier + QLatin1String(".json")));
51 const QStringList comments(settings.getComment().split(QLatin1Char('\n')));
52
53 for (int i = 0; i < comments.count(); ++i)
54 {
55 const QString key(comments.at(i).section(QLatin1Char(':'), 0, 0).trimmed());
56 const QString value(comments.at(i).section(QLatin1Char(':'), 1).trimmed());
57
58 if (key == QLatin1String("Title"))
59 {
60 m_title = value;
61 }
62 else if (key == QLatin1String("Description"))
63 {
64 m_description = value;
65 }
66 else if (key == QLatin1String("Author"))
67 {
68 m_author = value;
69 }
70 else if (key == QLatin1String("Version"))
71 {
72 m_version = value;
73 }
74 }
75
76 if (mode == MetaDataOnlyMode)
77 {
78 return;
79 }
80
81 const QJsonArray contextsArray(settings.array());
82 const bool areSingleKeyShortcutsAllowed((mode == FullMode) ? true : SettingsManager::getOption(SettingsManager::Browser_EnableSingleKeyShortcutsOption).toBool());
83
84 for (int i = 0; i < contextsArray.count(); ++i)
85 {
86 const QJsonArray actionsArray(contextsArray.at(i).toObject().value(QLatin1String("actions")).toArray());
87 QVector<Action> definitions;
88 definitions.reserve(actionsArray.count());
89
90 for (int j = 0; j < actionsArray.count(); ++j)
91 {
92 const QJsonObject actionObject(actionsArray.at(j).toObject());
93 const int action(ActionsManager::getActionIdentifier(actionObject.value(QLatin1String("action")).toString()));
94
95 if (action < 0)
96 {
97 continue;
98 }
99
100 const QJsonArray shortcutsArray(actionObject.value(QLatin1String("shortcuts")).toArray());
101 QVector<QKeySequence> shortcuts;
102 shortcuts.reserve(shortcutsArray.count());
103
104 for (int k = 0; k < shortcutsArray.count(); ++k)
105 {
106 const QKeySequence shortcut(shortcutsArray.at(k).toString());
107
108 if (shortcut.isEmpty() || (!areSingleKeyShortcutsAllowed && !ActionsManager::isShortcutAllowed(shortcut, ActionsManager::DisallowSingleKeyShortcutCheck, false)))
109 {
110 continue;
111 }
112
113 shortcuts.append(shortcut);
114 }
115
116 if (shortcuts.isEmpty())
117 {
118 continue;
119 }
120
121 KeyboardProfile::Action definition;
122 definition.shortcuts = shortcuts;
123 definition.parameters = actionObject.value(QLatin1String("parameters")).toVariant().toMap();
124 definition.action = action;
125
126 definitions.append(definition);
127 }
128
129 m_definitions[ActionsManager::GenericContext] = definitions;
130 }
131 }
132
setTitle(const QString & title)133 void KeyboardProfile::setTitle(const QString &title)
134 {
135 if (title != m_title)
136 {
137 m_title = title;
138 m_isModified = true;
139 }
140 }
141
setDescription(const QString & description)142 void KeyboardProfile::setDescription(const QString &description)
143 {
144 if (description != m_description)
145 {
146 m_description = description;
147 m_isModified = true;
148 }
149 }
150
setAuthor(const QString & author)151 void KeyboardProfile::setAuthor(const QString &author)
152 {
153 if (author != m_author)
154 {
155 m_author = author;
156 m_isModified = true;
157 }
158 }
159
setVersion(const QString & version)160 void KeyboardProfile::setVersion(const QString &version)
161 {
162 if (version != m_version)
163 {
164 m_version = version;
165 m_isModified = true;
166 }
167 }
168
setDefinitions(const QHash<int,QVector<KeyboardProfile::Action>> & definitions)169 void KeyboardProfile::setDefinitions(const QHash<int, QVector<KeyboardProfile::Action> > &definitions)
170 {
171 if (definitions != m_definitions)
172 {
173 m_definitions = definitions;
174 m_isModified = true;
175 }
176 }
177
setModified(bool isModified)178 void KeyboardProfile::setModified(bool isModified)
179 {
180 m_isModified = isModified;
181 }
182
getName() const183 QString KeyboardProfile::getName() const
184 {
185 return m_identifier;
186 }
187
getTitle() const188 QString KeyboardProfile::getTitle() const
189 {
190 return (m_title.isEmpty() ? QCoreApplication::translate("Otter::KeyboardProfile", "(Untitled)") : m_title);
191 }
192
getDescription() const193 QString KeyboardProfile::getDescription() const
194 {
195 return m_description;
196 }
197
getAuthor() const198 QString KeyboardProfile::getAuthor() const
199 {
200 return m_author;
201 }
202
getVersion() const203 QString KeyboardProfile::getVersion() const
204 {
205 return m_version;
206 }
207
getDefinitions() const208 QHash<int, QVector<KeyboardProfile::Action> > KeyboardProfile::getDefinitions() const
209 {
210 return m_definitions;
211 }
212
isModified() const213 bool KeyboardProfile::isModified() const
214 {
215 return m_isModified;
216 }
217
save()218 bool KeyboardProfile::save()
219 {
220 JsonSettings settings(SessionsManager::getWritableDataPath(QLatin1String("keyboard/") + m_identifier + QLatin1String(".json")));
221 QString comment;
222 QTextStream stream(&comment);
223 stream.setCodec("UTF-8");
224 stream << QLatin1String("Title: ") << (m_title.isEmpty() ? QT_TR_NOOP("(Untitled)") : m_title) << QLatin1Char('\n');
225 stream << QLatin1String("Description: ") << m_description << QLatin1Char('\n');
226 stream << QLatin1String("Type: keyboard-profile\n");
227 stream << QLatin1String("Author: ") << m_author << QLatin1Char('\n');
228 stream << QLatin1String("Version: ") << m_version;
229
230 settings.setComment(comment);
231
232 QJsonArray contextsArray;
233 QHash<int, QVector<KeyboardProfile::Action> >::const_iterator contextsIterator;
234
235 for (contextsIterator = m_definitions.begin(); contextsIterator != m_definitions.end(); ++contextsIterator)
236 {
237 QJsonArray actionsArray;
238
239 for (int i = 0; i < contextsIterator.value().count(); ++i)
240 {
241 const KeyboardProfile::Action &action(contextsIterator.value().at(i));
242 QJsonArray shortcutsArray;
243
244 for (int j = 0; j < action.shortcuts.count(); ++j)
245 {
246 shortcutsArray.append(action.shortcuts.at(j).toString());
247 }
248
249 QJsonObject actionObject{{QLatin1String("action"), ActionsManager::getActionName(action.action)}, {QLatin1String("shortcuts"), shortcutsArray}};
250
251 if (!action.parameters.isEmpty())
252 {
253 actionObject.insert(QLatin1String("parameters"), QJsonObject::fromVariantMap(action.parameters));
254 }
255
256 actionsArray.append(actionObject);
257 }
258
259 contextsArray.append(QJsonObject({{QLatin1String("context"), QLatin1String("Generic")}, {QLatin1String("actions"), actionsArray}}));
260 }
261
262 settings.setArray(contextsArray);
263
264 const bool result(settings.save());
265
266 if (result)
267 {
268 m_isModified = false;
269 }
270
271 return result;
272 }
273
274 ActionsManager* ActionsManager::m_instance(nullptr);
275 QMap<int, QVector<QKeySequence> > ActionsManager::m_shortcuts;
276 QMultiMap<int, QPair<QVariantMap, QVector<QKeySequence> > > ActionsManager::m_extraShortcuts;
277 QVector<QKeySequence> ActionsManager::m_disallowedShortcuts;
278 QVector<ActionsManager::ActionDefinition> ActionsManager::m_definitions;
279 int ActionsManager::m_actionIdentifierEnumerator(0);
280
ActionsManager(QObject * parent)281 ActionsManager::ActionsManager(QObject *parent) : QObject(parent),
282 m_reloadTimer(0)
283 {
284 m_definitions.reserve(ActionsManager::OtherAction);
285
286 registerAction(RunMacroAction, QT_TRANSLATE_NOOP("actions", "Run Macro"), QT_TRANSLATE_NOOP("actions", "Run Arbitrary List of Actions"), {}, ActionDefinition::ApplicationScope, ActionDefinition::RequiresParameters);
287 registerAction(SetOptionAction, QT_TRANSLATE_NOOP("actions", "Set Option"), QT_TRANSLATE_NOOP("actions", "Set, Reset or Toggle Option"), {}, ActionDefinition::ApplicationScope, ActionDefinition::RequiresParameters);
288 registerAction(NewTabAction, QT_TRANSLATE_NOOP("actions", "New Tab"), {}, ThemesManager::createIcon(QLatin1String("tab-new")), ActionDefinition::MainWindowScope);
289 registerAction(NewTabPrivateAction, QT_TRANSLATE_NOOP("actions", "New Private Tab"), {}, ThemesManager::createIcon(QLatin1String("tab-new-private")), ActionDefinition::MainWindowScope);
290 registerAction(NewWindowAction, QT_TRANSLATE_NOOP("actions", "New Window"), {}, ThemesManager::createIcon(QLatin1String("window-new")), ActionDefinition::ApplicationScope);
291 registerAction(NewWindowPrivateAction, QT_TRANSLATE_NOOP("actions", "New Private Window"), {}, ThemesManager::createIcon(QLatin1String("window-new-private")), ActionDefinition::ApplicationScope);
292 registerAction(OpenAction, QT_TRANSLATE_NOOP("actions", "Open…"), {}, ThemesManager::createIcon(QLatin1String("document-open")), ActionDefinition::MainWindowScope);
293 registerAction(SaveAction, QT_TRANSLATE_NOOP("actions", "Save…"), {}, ThemesManager::createIcon(QLatin1String("document-save")), ActionDefinition::WindowScope);
294 registerAction(CloneTabAction, QT_TRANSLATE_NOOP("actions", "Clone Tab"), {}, {}, ActionDefinition::WindowScope);
295 registerAction(PeekTabAction, QT_TRANSLATE_NOOP("actions", "Peek Tab"), {}, {}, ActionDefinition::MainWindowScope);
296 registerAction(PinTabAction, QT_TRANSLATE_NOOP("actions", "Pin Tab"), {}, {}, ActionDefinition::WindowScope);
297 registerAction(DetachTabAction, QT_TRANSLATE_NOOP("actions", "Detach Tab"), {}, {}, ActionDefinition::WindowScope);
298 registerAction(MaximizeTabAction, QT_TRANSLATE_NOOP("actions", "Maximize"), QT_TRANSLATE_NOOP("actions", "Maximize Tab"), {}, ActionDefinition::WindowScope);
299 registerAction(MinimizeTabAction, QT_TRANSLATE_NOOP("actions", "Minimize"), QT_TRANSLATE_NOOP("actions", "Minimize Tab"), {}, ActionDefinition::WindowScope);
300 registerAction(RestoreTabAction, QT_TRANSLATE_NOOP("actions", "Restore"), QT_TRANSLATE_NOOP("actions", "Restore Tab"), {}, ActionDefinition::WindowScope);
301 registerAction(AlwaysOnTopTabAction, QT_TRANSLATE_NOOP("actions", "Stay on Top"), {}, {}, ActionDefinition::WindowScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsCheckableFlag));
302 registerAction(ClearTabHistoryAction, QT_TRANSLATE_NOOP("actions", "Clear Tab History"), QT_TRANSLATE_NOOP("actions", "Remove Local Tab History"), {}, ActionDefinition::WindowScope, ActionDefinition::NoFlags, ActionsManager::ActionDefinition::NavigationCategory);
303 registerAction(PurgeTabHistoryAction, QT_TRANSLATE_NOOP("actions", "Purge Tab History"), QT_TRANSLATE_NOOP("actions", "Remove Local and Global Tab History"), {}, ActionDefinition::WindowScope, ActionDefinition::IsDeprecatedFlag, ActionsManager::ActionDefinition::NavigationCategory);
304 registerAction(MuteTabMediaAction, QT_TRANSLATE_NOOP("actions", "Mute Tab Media"), {}, ThemesManager::createIcon(QLatin1String("audio-volume-muted")), ActionDefinition::WindowScope);
305 registerAction(SuspendTabAction, QT_TRANSLATE_NOOP("actions", "Suspend Tab"), {}, {}, ActionDefinition::WindowScope, ActionDefinition::NoFlags);
306 registerAction(CloseTabAction, QT_TRANSLATE_NOOP("actions", "Close Tab"), {}, ThemesManager::createIcon(QLatin1String("tab-close")), ActionDefinition::WindowScope);
307 registerAction(CloseOtherTabsAction, QT_TRANSLATE_NOOP("actions", "Close Other Tabs"), {}, ThemesManager::createIcon(QLatin1String("tab-close-other")), ActionDefinition::MainWindowScope);
308 registerAction(ClosePrivateTabsAction, QT_TRANSLATE_NOOP("actions", "Close All Private Tabs"), QT_TRANSLATE_NOOP("actions", "Close All Private Tabs in Current Window"), {}, ActionDefinition::MainWindowScope, ActionDefinition::NoFlags);
309 registerAction(ClosePrivateTabsPanicAction, QT_TRANSLATE_NOOP("actions", "Close Private Tabs and Windows"), {}, {}, ActionDefinition::ApplicationScope);
310 registerAction(ReopenTabAction, QT_TRANSLATE_NOOP("actions", "Reopen Previously Closed Tab"), {}, {}, ActionDefinition::MainWindowScope, ActionDefinition::NoFlags);
311 registerAction(MaximizeAllAction, QT_TRANSLATE_NOOP("actions", "Maximize All"), {}, {}, ActionDefinition::MainWindowScope);
312 registerAction(MinimizeAllAction, QT_TRANSLATE_NOOP("actions", "Minimize All"), {}, {}, ActionDefinition::MainWindowScope);
313 registerAction(RestoreAllAction, QT_TRANSLATE_NOOP("actions", "Restore All"), {}, {}, ActionDefinition::MainWindowScope);
314 registerAction(CascadeAllAction, QT_TRANSLATE_NOOP("actions", "Cascade"), {}, {}, ActionDefinition::MainWindowScope);
315 registerAction(TileAllAction, QT_TRANSLATE_NOOP("actions", "Tile"), {}, {}, ActionDefinition::MainWindowScope);
316 registerAction(CloseWindowAction, QT_TRANSLATE_NOOP("actions", "Close Window"), {}, {}, ActionDefinition::MainWindowScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsImmutableFlag));
317 registerAction(ReopenWindowAction, QT_TRANSLATE_NOOP("actions", "Reopen Previously Closed Window"), {}, {}, ActionDefinition::ApplicationScope, ActionDefinition::NoFlags);
318 registerAction(SessionsAction, QT_TRANSLATE_NOOP("actions", "Manage Sessions…"), {}, {}, ActionDefinition::ApplicationScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsImmutableFlag));
319 registerAction(SaveSessionAction, QT_TRANSLATE_NOOP("actions", "Save Current Session…"), {}, {}, ActionDefinition::ApplicationScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsImmutableFlag));
320 registerAction(OpenUrlAction, QT_TRANSLATE_NOOP("actions", "Open URL"), {}, {}, ActionDefinition::MainWindowScope, ActionDefinition::RequiresParameters);
321 registerAction(OpenLinkAction, QT_TRANSLATE_NOOP("actions", "Open"), {}, ThemesManager::createIcon(QLatin1String("document-open")), ActionDefinition::WindowScope, ActionDefinition::IsEnabledFlag, ActionDefinition::LinkCategory);
322 registerAction(OpenLinkInCurrentTabAction, QT_TRANSLATE_NOOP("actions", "Open in This Tab"), {}, {}, ActionDefinition::WindowScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsDeprecatedFlag), ActionDefinition::LinkCategory);
323 registerAction(OpenLinkInNewTabAction, QT_TRANSLATE_NOOP("actions", "Open in New Tab"), {}, {}, ActionDefinition::WindowScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsDeprecatedFlag), ActionDefinition::LinkCategory);
324 registerAction(OpenLinkInNewTabBackgroundAction, QT_TRANSLATE_NOOP("actions", "Open in New Background Tab"), {}, {}, ActionDefinition::WindowScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsDeprecatedFlag), ActionDefinition::LinkCategory);
325 registerAction(OpenLinkInNewWindowAction, QT_TRANSLATE_NOOP("actions", "Open in New Window"), {}, {}, ActionDefinition::WindowScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsDeprecatedFlag), ActionDefinition::LinkCategory);
326 registerAction(OpenLinkInNewWindowBackgroundAction, QT_TRANSLATE_NOOP("actions", "Open in New Background Window"), {}, {}, ActionDefinition::WindowScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsDeprecatedFlag), ActionDefinition::LinkCategory);
327 registerAction(OpenLinkInNewPrivateTabAction, QT_TRANSLATE_NOOP("actions", "Open in New Private Tab"), {}, {}, ActionDefinition::WindowScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsDeprecatedFlag), ActionDefinition::LinkCategory);
328 registerAction(OpenLinkInNewPrivateTabBackgroundAction, QT_TRANSLATE_NOOP("actions", "Open in New Private Background Tab"), {}, {}, ActionDefinition::WindowScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsDeprecatedFlag), ActionDefinition::LinkCategory);
329 registerAction(OpenLinkInNewPrivateWindowAction, QT_TRANSLATE_NOOP("actions", "Open in New Private Window"), {}, {}, ActionDefinition::WindowScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsDeprecatedFlag), ActionDefinition::LinkCategory);
330 registerAction(OpenLinkInNewPrivateWindowBackgroundAction, QT_TRANSLATE_NOOP("actions", "Open in New Private Background Window"), {}, {}, ActionDefinition::WindowScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsDeprecatedFlag), ActionDefinition::LinkCategory);
331 registerAction(CopyLinkToClipboardAction, QT_TRANSLATE_NOOP("actions", "Copy Link to Clipboard"), {}, {}, ActionDefinition::WindowScope, ActionDefinition::IsEnabledFlag, ActionDefinition::LinkCategory);
332 registerAction(BookmarkLinkAction, QT_TRANSLATE_NOOP("actions", "Bookmark Link…"), {}, ThemesManager::createIcon(QLatin1String("bookmark-new")), ActionDefinition::WindowScope, ActionDefinition::IsEnabledFlag, ActionDefinition::LinkCategory);
333 registerAction(SaveLinkToDiskAction, QT_TRANSLATE_NOOP("actions", "Save Link Target As…"), {}, {}, ActionDefinition::WindowScope, ActionDefinition::IsEnabledFlag, ActionDefinition::LinkCategory);
334 registerAction(SaveLinkToDownloadsAction, QT_TRANSLATE_NOOP("actions", "Save to Downloads"), {}, {}, ActionDefinition::WindowScope, ActionDefinition::IsEnabledFlag, ActionDefinition::LinkCategory);
335 registerAction(OpenSelectionAsLinkAction, QT_TRANSLATE_NOOP("actions", "Go to This Address"), {}, {}, ActionDefinition::WindowScope);
336 registerAction(OpenFrameAction, QT_TRANSLATE_NOOP("actions", "Open"), QT_TRANSLATE_NOOP("actions", "Open Frame"), {}, ActionDefinition::WindowScope, ActionDefinition::IsEnabledFlag, ActionDefinition::FrameCategory);
337 registerAction(OpenFrameInCurrentTabAction, QT_TRANSLATE_NOOP("actions", "Open"), QT_TRANSLATE_NOOP("actions", "Open Frame in This Tab"), {}, ActionDefinition::WindowScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsDeprecatedFlag), ActionDefinition::FrameCategory);
338 registerAction(OpenFrameInNewTabAction, QT_TRANSLATE_NOOP("actions", "Open in New Tab"), QT_TRANSLATE_NOOP("actions", "Open Frame in New Tab"), {}, ActionDefinition::WindowScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsDeprecatedFlag), ActionDefinition::FrameCategory);
339 registerAction(OpenFrameInNewTabBackgroundAction, QT_TRANSLATE_NOOP("actions", "Open in New Background Tab"), QT_TRANSLATE_NOOP("actions", "Open Frame in New Background Tab"), {}, ActionDefinition::WindowScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsDeprecatedFlag), ActionDefinition::FrameCategory);
340 registerAction(CopyFrameLinkToClipboardAction, QT_TRANSLATE_NOOP("actions", "Copy Frame Link to Clipboard"), {}, {}, ActionDefinition::WindowScope, ActionDefinition::IsEnabledFlag, ActionDefinition::FrameCategory);
341 registerAction(ReloadFrameAction, QT_TRANSLATE_NOOP("actions", "Reload"), QT_TRANSLATE_NOOP("actions", "Reload Frame"), {}, ActionDefinition::WindowScope, ActionDefinition::IsEnabledFlag, ActionDefinition::FrameCategory);
342 registerAction(ViewFrameSourceAction, QT_TRANSLATE_NOOP("actions", "View Frame Source"), {}, {}, ActionDefinition::WindowScope, ActionDefinition::IsEnabledFlag, ActionDefinition::FrameCategory);
343 registerAction(OpenImageAction, QT_TRANSLATE_NOOP("actions", "Open Image"), {}, {}, ActionDefinition::WindowScope, ActionDefinition::IsEnabledFlag, ActionDefinition::ImageCategory);
344 registerAction(OpenImageInNewTabAction, QT_TRANSLATE_NOOP("actions", "Open Image In New Tab"), {}, {}, ActionDefinition::WindowScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsDeprecatedFlag), ActionDefinition::ImageCategory);
345 registerAction(OpenImageInNewTabBackgroundAction, QT_TRANSLATE_NOOP("actions", "Open Image in New Background Tab"), {}, {}, ActionDefinition::WindowScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsDeprecatedFlag), ActionDefinition::ImageCategory);
346 registerAction(SaveImageToDiskAction, QT_TRANSLATE_NOOP("actions", "Save Image…"), {}, {}, ActionDefinition::WindowScope, ActionDefinition::IsEnabledFlag, ActionDefinition::ImageCategory);
347 registerAction(CopyImageToClipboardAction, QT_TRANSLATE_NOOP("actions", "Copy Image to Clipboard"), {}, {}, ActionDefinition::WindowScope, ActionDefinition::IsEnabledFlag, ActionDefinition::ImageCategory);
348 registerAction(CopyImageUrlToClipboardAction, QT_TRANSLATE_NOOP("actions", "Copy Image Link to Clipboard"), {}, {}, ActionDefinition::WindowScope, ActionDefinition::IsEnabledFlag, ActionDefinition::ImageCategory);
349 registerAction(ReloadImageAction, QT_TRANSLATE_NOOP("actions", "Reload Image"), {}, {}, ActionDefinition::WindowScope, ActionDefinition::IsEnabledFlag, ActionDefinition::ImageCategory);
350 registerAction(ImagePropertiesAction, QT_TRANSLATE_NOOP("actions", "Image Properties…"), {}, {}, ActionDefinition::WindowScope, ActionDefinition::IsEnabledFlag, ActionDefinition::ImageCategory);
351 registerAction(SaveMediaToDiskAction, QT_TRANSLATE_NOOP("actions", "Save Media…"), {}, {}, ActionDefinition::WindowScope, ActionDefinition::IsEnabledFlag, ActionDefinition::MediaCategory);
352 registerAction(CopyMediaUrlToClipboardAction, QT_TRANSLATE_NOOP("actions", "Copy Media Link to Clipboard"), {}, {}, ActionDefinition::WindowScope, ActionDefinition::IsEnabledFlag, ActionDefinition::MediaCategory);
353 registerAction(MediaControlsAction, QT_TRANSLATE_NOOP("actions", "Show Controls"), QT_TRANSLATE_NOOP("actions", "Show Media Controls"), {}, ActionDefinition::WindowScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsCheckableFlag), ActionDefinition::MediaCategory);
354 registerAction(MediaLoopAction, QT_TRANSLATE_NOOP("actions", "Looping"), QT_TRANSLATE_NOOP("actions", "Playback Looping"), {}, ActionDefinition::WindowScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsCheckableFlag), ActionDefinition::MediaCategory);
355 registerAction(MediaPlayPauseAction, QT_TRANSLATE_NOOP("actions", "Play"), QT_TRANSLATE_NOOP("actions", "Play Media"), ThemesManager::createIcon(QLatin1String("media-playback-start")), ActionDefinition::WindowScope, ActionDefinition::IsEnabledFlag, ActionDefinition::MediaCategory);
356 registerAction(MediaMuteAction, QT_TRANSLATE_NOOP("actions", "Mute"), QT_TRANSLATE_NOOP("actions", "Mute Media"), ThemesManager::createIcon(QLatin1String("audio-volume-muted")), ActionDefinition::WindowScope, ActionDefinition::IsEnabledFlag, ActionDefinition::MediaCategory);
357 registerAction(MediaPlaybackRateAction, QT_TRANSLATE_NOOP("actions", "Playback Rate"), {}, {}, ActionDefinition::WindowScope, ActionDefinition::IsCheckableFlag, ActionDefinition::MediaCategory);
358 registerAction(FillPasswordAction, QT_TRANSLATE_NOOP("actions", "Log In"), {}, ThemesManager::createIcon(QLatin1String("fill-password")), ActionDefinition::WindowScope, ActionDefinition::NoFlags, ActionDefinition::PageCategory);
359 registerAction(GoAction, QT_TRANSLATE_NOOP("actions", "Go"), QT_TRANSLATE_NOOP("actions", "Go to URL"), ThemesManager::createIcon(QLatin1String("go-jump-locationbar")), ActionDefinition::MainWindowScope);
360 registerAction(GoBackAction, QT_TRANSLATE_NOOP("actions", "Back"), QT_TRANSLATE_NOOP("actions", "Go Back"), ThemesManager::createIcon(QLatin1String("go-previous")), ActionDefinition::WindowScope, ActionDefinition::IsEnabledFlag, ActionDefinition::NavigationCategory);
361 registerAction(GoForwardAction, QT_TRANSLATE_NOOP("actions", "Forward"), QT_TRANSLATE_NOOP("actions", "Go Forward"), ThemesManager::createIcon(QLatin1String("go-next")), ActionDefinition::WindowScope, ActionDefinition::IsEnabledFlag, ActionDefinition::NavigationCategory);
362 registerAction(GoToHistoryIndexAction, QT_TRANSLATE_NOOP("actions", "Go to History Entry"), {}, {}, ActionDefinition::WindowScope, ActionDefinition::RequiresParameters, ActionDefinition::NavigationCategory);
363 registerAction(GoToPageAction, QT_TRANSLATE_NOOP("actions", "Go to Page or Search"), {}, {}, ActionDefinition::MainWindowScope);
364 registerAction(GoToHomePageAction, QT_TRANSLATE_NOOP("actions", "Go to Home Page"), {}, ThemesManager::createIcon(QLatin1String("go-home")), ActionDefinition::MainWindowScope);
365 registerAction(GoToParentDirectoryAction, QT_TRANSLATE_NOOP("actions", "Go to Parent Directory"), {}, {}, ActionDefinition::WindowScope);
366 registerAction(RewindAction, QT_TRANSLATE_NOOP("actions", "Rewind"), QT_TRANSLATE_NOOP("actions", "Rewind History"), ThemesManager::createIcon(QLatin1String("go-first")), ActionDefinition::WindowScope, ActionDefinition::IsEnabledFlag, ActionDefinition::NavigationCategory);
367 registerAction(FastForwardAction, QT_TRANSLATE_NOOP("actions", "Fast Forward"), {}, ThemesManager::createIcon(QLatin1String("go-last")), ActionDefinition::WindowScope, ActionDefinition::IsEnabledFlag, ActionDefinition::NavigationCategory);
368 registerAction(RemoveHistoryIndexAction, QT_TRANSLATE_NOOP("actions", "Remove History Entry"), {}, {}, ActionDefinition::WindowScope, ActionDefinition::RequiresParameters, ActionDefinition::NavigationCategory);
369 registerAction(StopAction, QT_TRANSLATE_NOOP("actions", "Stop"), {}, ThemesManager::createIcon(QLatin1String("process-stop")), ActionDefinition::WindowScope, ActionDefinition::IsEnabledFlag, ActionDefinition::NavigationCategory);
370 registerAction(StopScheduledReloadAction, QT_TRANSLATE_NOOP("actions", "Stop Scheduled Page Reload"), {}, {}, ActionDefinition::WindowScope);
371 registerAction(StopAllAction, QT_TRANSLATE_NOOP("actions", "Stop All Pages"), {}, ThemesManager::createIcon(QLatin1String("process-stop")), ActionDefinition::MainWindowScope);
372 registerAction(ReloadAction, QT_TRANSLATE_NOOP("actions", "Reload"), {}, ThemesManager::createIcon(QLatin1String("view-refresh")), ActionDefinition::WindowScope, ActionDefinition::IsEnabledFlag, ActionDefinition::NavigationCategory);
373 registerAction(ReloadOrStopAction, QT_TRANSLATE_NOOP("actions", "Reload"), QT_TRANSLATE_NOOP("actions", "Reload or Stop"), ThemesManager::createIcon(QLatin1String("view-refresh")), ActionDefinition::WindowScope, ActionDefinition::IsEnabledFlag, ActionDefinition::NavigationCategory);
374 registerAction(ReloadAndBypassCacheAction, QT_TRANSLATE_NOOP("actions", "Reload and Bypass Cache"), {}, {}, ActionDefinition::WindowScope);
375 registerAction(ReloadAllAction, QT_TRANSLATE_NOOP("actions", "Reload All Tabs"), {}, ThemesManager::createIcon(QLatin1String("view-refresh")), ActionDefinition::MainWindowScope);
376 registerAction(ScheduleReloadAction, QT_TRANSLATE_NOOP("actions", "Schedule Page Reload"), {}, {}, ActionDefinition::WindowScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsCheckableFlag));
377 registerAction(ContextMenuAction, QT_TRANSLATE_NOOP("actions", "Show Context Menu"), {}, {}, ActionDefinition::WindowScope);
378 registerAction(UndoAction, QT_TRANSLATE_NOOP("actions", "Undo"), {}, ThemesManager::createIcon(QLatin1String("edit-undo")), ActionDefinition::EditorScope, ActionDefinition::IsEnabledFlag, ActionDefinition::EditingCategory);
379 registerAction(RedoAction, QT_TRANSLATE_NOOP("actions", "Redo"), {}, ThemesManager::createIcon(QLatin1String("edit-redo")), ActionDefinition::EditorScope, ActionDefinition::IsEnabledFlag, ActionDefinition::EditingCategory);
380 registerAction(CutAction, QT_TRANSLATE_NOOP("actions", "Cut"), {}, ThemesManager::createIcon(QLatin1String("edit-cut")), ActionDefinition::EditorScope, ActionDefinition::IsEnabledFlag, ActionDefinition::EditingCategory);
381 registerAction(CopyAction, QT_TRANSLATE_NOOP("actions", "Copy"), {}, ThemesManager::createIcon(QLatin1String("edit-copy")), ActionDefinition::EditorScope, ActionDefinition::IsEnabledFlag, ActionDefinition::EditingCategory);
382 registerAction(CopyPlainTextAction, QT_TRANSLATE_NOOP("actions", "Copy as Plain Text"), {}, {}, ActionDefinition::WindowScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsDeprecatedFlag), ActionDefinition::EditingCategory);
383 registerAction(CopyAddressAction, QT_TRANSLATE_NOOP("actions", "Copy Address"), {}, {}, ActionDefinition::WindowScope);
384 registerAction(CopyToNoteAction, QT_TRANSLATE_NOOP("actions", "Copy to Note"), {}, {}, ActionDefinition::EditorScope, ActionDefinition::IsEnabledFlag, ActionDefinition::EditingCategory);
385 registerAction(PasteAction, QT_TRANSLATE_NOOP("actions", "Paste"), {}, ThemesManager::createIcon(QLatin1String("edit-paste")), ActionDefinition::EditorScope, ActionDefinition::IsEnabledFlag, ActionDefinition::EditingCategory);
386 registerAction(PasteAndGoAction, QT_TRANSLATE_NOOP("actions", "Paste and Go"), {}, {}, ActionDefinition::WindowScope);
387 registerAction(DeleteAction, QT_TRANSLATE_NOOP("actions", "Delete"), {}, ThemesManager::createIcon(QLatin1String("edit-delete")), ActionDefinition::EditorScope, ActionDefinition::IsEnabledFlag, ActionDefinition::EditingCategory);
388 registerAction(SelectAllAction, QT_TRANSLATE_NOOP("actions", "Select All"), {}, ThemesManager::createIcon(QLatin1String("edit-select-all")), ActionDefinition::EditorScope, ActionDefinition::IsEnabledFlag, ActionDefinition::EditingCategory);
389 registerAction(UnselectAction, QT_TRANSLATE_NOOP("actions", "Deselect"), {}, {}, ActionDefinition::EditorScope, ActionDefinition::IsEnabledFlag, ActionDefinition::EditingCategory);
390 registerAction(ClearAllAction, QT_TRANSLATE_NOOP("actions", "Clear All"), {}, {}, ActionDefinition::EditorScope, ActionDefinition::IsEnabledFlag, ActionDefinition::EditingCategory);
391 registerAction(CheckSpellingAction, QT_TRANSLATE_NOOP("actions", "Check Spelling"), {}, {}, ActionDefinition::EditorScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsCheckableFlag), ActionDefinition::EditingCategory);
392 registerAction(FindAction, QT_TRANSLATE_NOOP("actions", "Find…"), {}, ThemesManager::createIcon(QLatin1String("edit-find")), ActionDefinition::WindowScope);
393 registerAction(FindNextAction, QT_TRANSLATE_NOOP("actions", "Find Next"), {}, ThemesManager::createIcon(QLatin1String("go-down")), ActionDefinition::WindowScope);
394 registerAction(FindPreviousAction, QT_TRANSLATE_NOOP("actions", "Find Previous"), {}, ThemesManager::createIcon(QLatin1String("go-up")), ActionDefinition::WindowScope);
395 registerAction(QuickFindAction, QT_TRANSLATE_NOOP("actions", "Quick Find"), {}, {}, ActionDefinition::WindowScope);
396 registerAction(SearchAction, QT_TRANSLATE_NOOP("actions", "Search"), {}, ThemesManager::createIcon(QLatin1String("edit-find")), ActionDefinition::WindowScope, ActionDefinition::IsEnabledFlag, ActionDefinition::EditingCategory);
397 registerAction(CreateSearchAction, QT_TRANSLATE_NOOP("actions", "Create Search…"), {}, {}, ActionDefinition::WindowScope, ActionDefinition::IsEnabledFlag, ActionDefinition::EditingCategory);
398 registerAction(ZoomInAction, QT_TRANSLATE_NOOP("actions", "Zoom In"), {}, ThemesManager::createIcon(QLatin1String("zoom-in")), ActionDefinition::WindowScope);
399 registerAction(ZoomOutAction, QT_TRANSLATE_NOOP("actions", "Zoom Out"), {}, ThemesManager::createIcon(QLatin1String("zoom-out")), ActionDefinition::WindowScope);
400 registerAction(ZoomOriginalAction, QT_TRANSLATE_NOOP("actions", "Zoom Original"), {}, ThemesManager::createIcon(QLatin1String("zoom-original")), ActionDefinition::WindowScope);
401 registerAction(ScrollToStartAction, QT_TRANSLATE_NOOP("actions", "Go to Start of the Page"), {}, {}, ActionDefinition::WindowScope);
402 registerAction(ScrollToEndAction, QT_TRANSLATE_NOOP("actions", "Go to the End of the Page"), {}, {}, ActionDefinition::WindowScope);
403 registerAction(ScrollPageUpAction, QT_TRANSLATE_NOOP("actions", "Page Up"), {}, {}, ActionDefinition::WindowScope);
404 registerAction(ScrollPageDownAction, QT_TRANSLATE_NOOP("actions", "Page Down"), {}, {}, ActionDefinition::WindowScope);
405 registerAction(ScrollPageLeftAction, QT_TRANSLATE_NOOP("actions", "Page Left"), {}, {}, ActionDefinition::WindowScope);
406 registerAction(ScrollPageRightAction, QT_TRANSLATE_NOOP("actions", "Page Right"), {}, {}, ActionDefinition::WindowScope);
407 registerAction(StartDragScrollAction, QT_TRANSLATE_NOOP("actions", "Enter Drag Scroll Mode"), {}, {}, ActionDefinition::WindowScope);
408 registerAction(StartMoveScrollAction, QT_TRANSLATE_NOOP("actions", "Enter Move Scroll Mode"), {}, {}, ActionDefinition::WindowScope);
409 registerAction(EndScrollAction, QT_TRANSLATE_NOOP("actions", "Exit Scroll Mode"), {}, {}, ActionDefinition::WindowScope);
410 registerAction(PrintAction, QT_TRANSLATE_NOOP("actions", "Print…"), {}, ThemesManager::createIcon(QLatin1String("document-print")), ActionDefinition::WindowScope);
411 registerAction(PrintPreviewAction, QT_TRANSLATE_NOOP("actions", "Print Preview"), {}, ThemesManager::createIcon(QLatin1String("document-print-preview")), ActionDefinition::WindowScope);
412 registerAction(TakeScreenshotAction, QT_TRANSLATE_NOOP("actions", "Take Screenshot"), {}, {}, ActionDefinition::WindowScope, ActionDefinition::NoFlags);
413 registerAction(ActivateAddressFieldAction, QT_TRANSLATE_NOOP("actions", "Activate Address Field"), {}, {}, ActionDefinition::MainWindowScope);
414 registerAction(ActivateSearchFieldAction, QT_TRANSLATE_NOOP("actions", "Activate Search Field"), {}, {}, ActionDefinition::MainWindowScope);
415 registerAction(ActivateContentAction, QT_TRANSLATE_NOOP("actions", "Activate Content"), {}, {}, ActionDefinition::WindowScope);
416 registerAction(ActivatePreviouslyUsedTabAction, QT_TRANSLATE_NOOP("actions", "Go to Previously Used Tab"), {}, {}, ActionDefinition::MainWindowScope);
417 registerAction(ActivateLeastRecentlyUsedTabAction, QT_TRANSLATE_NOOP("actions", "Go to Least Recently Used Tab"), {}, {}, ActionDefinition::MainWindowScope);
418 registerAction(ActivateTabAction, QT_TRANSLATE_NOOP("actions", "Activate Tab"), {}, {}, ActionDefinition::MainWindowScope, ActionDefinition::RequiresParameters);
419 registerAction(ActivateTabOnLeftAction, QT_TRANSLATE_NOOP("actions", "Go to Tab on Left"), {}, {}, ActionDefinition::MainWindowScope);
420 registerAction(ActivateTabOnRightAction, QT_TRANSLATE_NOOP("actions", "Go to Tab on Right"), {}, {}, ActionDefinition::MainWindowScope);
421 registerAction(ActivateWindowAction, QT_TRANSLATE_NOOP("actions", "Activate Window"), {}, {}, ActionDefinition::ApplicationScope, ActionDefinition::RequiresParameters);
422 registerAction(BookmarksAction, QT_TRANSLATE_NOOP("actions", "Manage Bookmarks"), {}, ThemesManager::createIcon(QLatin1String("bookmarks-organize")), ActionDefinition::MainWindowScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsImmutableFlag));
423 registerAction(BookmarkPageAction, QT_TRANSLATE_NOOP("actions", "Bookmark Page…"), {}, ThemesManager::createIcon(QLatin1String("bookmark-new")), ActionDefinition::WindowScope, ActionDefinition::IsEnabledFlag, ActionDefinition::PageCategory);
424 registerAction(BookmarkAllOpenPagesAction, QT_TRANSLATE_NOOP("actions", "Bookmark All Open Pages"), {}, {}, ActionDefinition::MainWindowScope);
425 registerAction(OpenBookmarkAction, QT_TRANSLATE_NOOP("actions", "Open Bookmark"), {}, {}, ActionDefinition::MainWindowScope, ActionDefinition::RequiresParameters);
426 registerAction(QuickBookmarkAccessAction, QT_TRANSLATE_NOOP("actions", "Quick Bookmark Access"), {}, {}, ActionDefinition::MainWindowScope);
427 registerAction(CookiesAction, QT_TRANSLATE_NOOP("actions", "Cookies"), {}, ThemesManager::createIcon(QLatin1String("cookies")), ActionDefinition::MainWindowScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsImmutableFlag));
428 registerAction(LoadPluginsAction, QT_TRANSLATE_NOOP("actions", "Load All Plugins on the Page"), {}, ThemesManager::createIcon(QLatin1String("preferences-plugin")), ActionDefinition::WindowScope, ActionDefinition::NoFlags);
429 registerAction(EnableJavaScriptAction, QT_TRANSLATE_NOOP("actions", "Enable JavaScript"), {}, {}, ActionDefinition::WindowScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsCheckableFlag), ActionDefinition::PageCategory);
430 registerAction(EnableReferrerAction, QT_TRANSLATE_NOOP("actions", "Enable Referrer"), {}, {}, ActionDefinition::WindowScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsCheckableFlag), ActionDefinition::PageCategory);
431 registerAction(ViewSourceAction, QT_TRANSLATE_NOOP("actions", "View Source"), {}, {}, ActionDefinition::WindowScope, ActionDefinition::NoFlags, ActionDefinition::NavigationCategory);
432 registerAction(InspectPageAction, QT_TRANSLATE_NOOP("actions", "Inspect Page"), {}, {}, ActionDefinition::WindowScope, ActionDefinition::IsCheckableFlag);
433 registerAction(InspectElementAction, QT_TRANSLATE_NOOP("actions", "Inspect Element…"), {}, {}, ActionDefinition::WindowScope, ActionDefinition::NoFlags);
434 registerAction(WorkOfflineAction, QT_TRANSLATE_NOOP("actions", "Work Offline"), {}, {}, ActionDefinition::ApplicationScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsCheckableFlag));
435 registerAction(FullScreenAction, QT_TRANSLATE_NOOP("actions", "Full Screen"), {}, ThemesManager::createIcon(QLatin1String("view-fullscreen")), ActionDefinition::MainWindowScope);
436 registerAction(ShowTabSwitcherAction, QT_TRANSLATE_NOOP("actions", "Show Tab Switcher"), {}, {}, ActionDefinition::MainWindowScope);
437 registerAction(ShowToolBarAction, QT_TRANSLATE_NOOP("actions", "Show Toolbar"), {}, {}, ActionDefinition::MainWindowScope, (ActionDefinition::IsCheckableFlag | ActionDefinition::RequiresParameters));
438 registerAction(ShowMenuBarAction, QT_TRANSLATE_NOOP("actions", "Show Menubar"), {}, {}, ActionDefinition::MainWindowScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsDeprecatedFlag | ActionDefinition::IsCheckableFlag));
439 registerAction(ShowTabBarAction, QT_TRANSLATE_NOOP("actions", "Show Tabbar"), {}, {}, ActionDefinition::MainWindowScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsDeprecatedFlag | ActionDefinition::IsCheckableFlag));
440 registerAction(ShowSidebarAction, QT_TRANSLATE_NOOP("actions", "Show Sidebar"), {}, ThemesManager::createIcon(QLatin1String("sidebar-show")), ActionDefinition::MainWindowScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsDeprecatedFlag | ActionDefinition::IsCheckableFlag));
441 registerAction(ShowErrorConsoleAction, QT_TRANSLATE_NOOP("actions", "Show Error Console"), {}, {}, ActionDefinition::MainWindowScope, (ActionDefinition::IsDeprecatedFlag | ActionDefinition::IsCheckableFlag));
442 registerAction(LockToolBarsAction, QT_TRANSLATE_NOOP("actions", "Lock Toolbars"), {}, {}, ActionDefinition::ApplicationScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsCheckableFlag));
443 registerAction(ResetToolBarsAction, QT_TRANSLATE_NOOP("actions", "Reset to Defaults…"), QT_TRANSLATE_NOOP("actions", "Reset Toolbars to Defaults…"), {}, ActionDefinition::ApplicationScope);
444 registerAction(ShowPanelAction, QT_TRANSLATE_NOOP("actions", "Show Panel"), QT_TRANSLATE_NOOP("actions", "Show Specified Panel in Sidebar"), {}, ActionDefinition::MainWindowScope);
445 registerAction(OpenPanelAction, QT_TRANSLATE_NOOP("actions", "Open Panel as Tab"), QT_TRANSLATE_NOOP("actions", "Open Curent Sidebar Panel as Tab"), ThemesManager::createIcon(QLatin1String("arrow-right")), ActionDefinition::MainWindowScope);
446 registerAction(ContentBlockingAction, QT_TRANSLATE_NOOP("actions", "Content Blocking…"), {}, ThemesManager::createIcon(QLatin1String("content-blocking")), ActionDefinition::MainWindowScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsImmutableFlag));
447 registerAction(HistoryAction, QT_TRANSLATE_NOOP("actions", "View History"), {}, ThemesManager::createIcon(QLatin1String("view-history")), ActionDefinition::MainWindowScope);
448 registerAction(ClearHistoryAction, QT_TRANSLATE_NOOP("actions", "Clear History…"), {}, ThemesManager::createIcon(QLatin1String("edit-clear-history")), ActionDefinition::MainWindowScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsImmutableFlag));
449 registerAction(AddonsAction, QT_TRANSLATE_NOOP("actions", "Addons"), {}, ThemesManager::createIcon(QLatin1String("preferences-plugin")), ActionDefinition::MainWindowScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsImmutableFlag));
450 registerAction(NotesAction, QT_TRANSLATE_NOOP("actions", "Notes"), {}, ThemesManager::createIcon(QLatin1String("notes")), ActionDefinition::MainWindowScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsImmutableFlag));
451 registerAction(PasswordsAction, QT_TRANSLATE_NOOP("actions", "Passwords"), {}, ThemesManager::createIcon(QLatin1String("dialog-password")), ActionDefinition::MainWindowScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsImmutableFlag));
452 registerAction(TransfersAction, QT_TRANSLATE_NOOP("actions", "Downloads"), {}, ThemesManager::createIcon(QLatin1String("transfers")), ActionDefinition::MainWindowScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsImmutableFlag));
453 registerAction(PreferencesAction, QT_TRANSLATE_NOOP("actions", "Preferences…"), {}, {}, ActionDefinition::MainWindowScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsImmutableFlag));
454 registerAction(WebsitePreferencesAction, QT_TRANSLATE_NOOP("actions", "Website Preferences…"), {}, {}, ActionDefinition::WindowScope, ActionDefinition::IsEnabledFlag, ActionDefinition::PageCategory);
455 registerAction(QuickPreferencesAction, QT_TRANSLATE_NOOP("actions", "Quick Preferences"), {}, {}, ActionDefinition::WindowScope);
456 registerAction(ResetQuickPreferencesAction, QT_TRANSLATE_NOOP("actions", "Reset Options"), {}, {}, ActionDefinition::WindowScope, ActionDefinition::NoFlags);
457 registerAction(WebsiteInformationAction, QT_TRANSLATE_NOOP("actions", "Website Information…"), {}, {}, ActionDefinition::WindowScope);
458 registerAction(WebsiteCertificateInformationAction, QT_TRANSLATE_NOOP("actions", "Website Certificate Information…"), {}, {}, ActionDefinition::WindowScope);
459 registerAction(SwitchApplicationLanguageAction, QT_TRANSLATE_NOOP("actions", "Switch Application Language…"), {}, ThemesManager::createIcon(QLatin1String("preferences-desktop-locale")), ActionDefinition::ApplicationScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsImmutableFlag));
460 registerAction(CheckForUpdatesAction, QT_TRANSLATE_NOOP("actions", "Check for Updates…"), {}, {}, ActionDefinition::ApplicationScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsImmutableFlag));
461 registerAction(DiagnosticReportAction, QT_TRANSLATE_NOOP("actions", "Diagnostic Report…"), {}, {}, ActionDefinition::ApplicationScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsImmutableFlag));
462 registerAction(AboutApplicationAction, QT_TRANSLATE_NOOP("actions", "About Otter…"), {}, ThemesManager::createIcon(QLatin1String("otter-browser"), false), ActionDefinition::ApplicationScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsImmutableFlag));
463 registerAction(AboutQtAction, QT_TRANSLATE_NOOP("actions", "About Qt…"), {}, ThemesManager::createIcon(QLatin1String("qt")), ActionDefinition::ApplicationScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsImmutableFlag));
464 registerAction(ExitAction, QT_TRANSLATE_NOOP("actions", "Exit"), {}, ThemesManager::createIcon(QLatin1String("application-exit")), ActionDefinition::ApplicationScope, (ActionDefinition::IsEnabledFlag | ActionDefinition::IsImmutableFlag));
465
466 connect(SettingsManager::getInstance(), &SettingsManager::optionChanged, this, &ActionsManager::handleOptionChanged);
467 }
468
createInstance()469 void ActionsManager::createInstance()
470 {
471 if (!m_instance)
472 {
473 m_instance = new ActionsManager(QCoreApplication::instance());
474 m_actionIdentifierEnumerator = ActionsManager::staticMetaObject.indexOfEnumerator(QLatin1String("ActionIdentifier").data());
475
476 loadProfiles();
477 }
478 }
479
timerEvent(QTimerEvent * event)480 void ActionsManager::timerEvent(QTimerEvent *event)
481 {
482 if (event->timerId() == m_reloadTimer)
483 {
484 killTimer(m_reloadTimer);
485
486 m_reloadTimer = 0;
487
488 loadProfiles();
489 }
490 }
491
loadProfiles()492 void ActionsManager::loadProfiles()
493 {
494 m_shortcuts.clear();
495 m_extraShortcuts.clear();
496
497 QVector<QKeySequence> allShortcuts;
498 const QStringList profiles(SettingsManager::getOption(SettingsManager::Browser_KeyboardShortcutsProfilesOrderOption).toStringList());
499
500 for (int i = 0; i < profiles.count(); ++i)
501 {
502 const QHash<int, QVector<KeyboardProfile::Action> > definitions(KeyboardProfile(profiles.at(i)).getDefinitions());
503 QHash<int, QVector<KeyboardProfile::Action> >::const_iterator iterator;
504
505 for (iterator = definitions.constBegin(); iterator != definitions.constEnd(); ++iterator)
506 {
507 for (int j = 0; j < iterator.value().count(); ++j)
508 {
509 const KeyboardProfile::Action definition(iterator.value().at(j));
510 QVector<QKeySequence> shortcuts;
511
512 if (definition.parameters.isEmpty() && m_shortcuts.contains(definition.action))
513 {
514 shortcuts = m_shortcuts[definition.action];
515 }
516 else if (!definition.parameters.isEmpty() && m_extraShortcuts.contains(definition.action))
517 {
518 const QList<QPair<QVariantMap, QVector<QKeySequence> > > extraDefinitions(m_extraShortcuts.values(definition.action));
519
520 for (int k = 0; k < extraDefinitions.count(); ++k)
521 {
522 if (extraDefinitions.at(k).first == definition.parameters)
523 {
524 shortcuts = extraDefinitions.at(k).second;
525
526 break;
527 }
528 }
529 }
530
531 for (int k = 0; k < definition.shortcuts.count(); ++k)
532 {
533 const QKeySequence shortcut(definition.shortcuts.at(k));
534
535 if (!allShortcuts.contains(shortcut))
536 {
537 shortcuts.append(shortcut);
538 allShortcuts.append(shortcut);
539 }
540 }
541
542 if (!shortcuts.isEmpty())
543 {
544 if (definition.parameters.isEmpty())
545 {
546 m_shortcuts[definition.action] = shortcuts;
547 }
548 else
549 {
550 m_extraShortcuts.insert(definition.action, {definition.parameters, shortcuts});
551 }
552 }
553 }
554 }
555 }
556
557 emit m_instance->shortcutsChanged();
558 }
559
registerAction(int identifier,const QString & text,const QString & description,const QIcon & icon,ActionDefinition::ActionScope scope,ActionDefinition::ActionFlags flags,ActionDefinition::ActionCategory category)560 void ActionsManager::registerAction(int identifier, const QString &text, const QString &description, const QIcon &icon, ActionDefinition::ActionScope scope, ActionDefinition::ActionFlags flags, ActionDefinition::ActionCategory category)
561 {
562 ActionsManager::ActionDefinition action;
563 action.description = description;
564 action.defaultState.text = text;
565 action.defaultState.icon = icon;
566 action.defaultState.isEnabled = flags.testFlag(ActionDefinition::IsEnabledFlag);
567 action.identifier = identifier;
568 action.flags = flags;
569 action.category = category;
570 action.scope = scope;
571
572 m_definitions.append(action);
573 }
574
handleOptionChanged(int identifier)575 void ActionsManager::handleOptionChanged(int identifier)
576 {
577 switch (identifier)
578 {
579 case SettingsManager::Browser_EnableSingleKeyShortcutsOption:
580 case SettingsManager::Browser_KeyboardShortcutsProfilesOrderOption:
581 if (m_reloadTimer == 0)
582 {
583 m_reloadTimer = startTimer(250);
584 }
585
586 break;
587 default:
588 break;
589 }
590 }
591
getInstance()592 ActionsManager* ActionsManager::getInstance()
593 {
594 return m_instance;
595 }
596
createReport()597 QString ActionsManager::createReport()
598 {
599 QString report;
600 QTextStream stream(&report);
601 stream.setFieldAlignment(QTextStream::AlignLeft);
602 stream << QLatin1String("Keyboard Shortcuts:\n");
603
604 for (int i = 0; i < m_definitions.count(); ++i)
605 {
606 if (m_shortcuts.contains(i))
607 {
608 const QVector<QKeySequence> shortcuts(m_shortcuts[i]);
609
610 stream << QLatin1Char('\t');
611 stream.setFieldWidth(30);
612 stream << getActionName(i);
613 stream.setFieldWidth(20);
614
615 for (int j = 0; j < shortcuts.count(); ++j)
616 {
617 stream << shortcuts.at(j).toString(QKeySequence::PortableText);
618 }
619
620 stream.setFieldWidth(0);
621 stream << QLatin1Char('\n');
622 }
623
624 if (m_extraShortcuts.contains(i))
625 {
626 const QList<QPair<QVariantMap, QVector<QKeySequence> > > definitions(m_extraShortcuts.values(i));
627
628 if (!m_shortcuts.contains(i))
629 {
630 stream << QLatin1Char('\t');
631 stream.setFieldWidth(30);
632 stream << getActionName(i);
633 stream.setFieldWidth(0);
634 stream << QLatin1Char('\n');
635 }
636
637 for (int j = 0; j < definitions.count(); ++j)
638 {
639 const QVector<QKeySequence> shortcuts(definitions.at(j).second);
640
641 stream << QLatin1Char('\t');
642 stream.setFieldWidth(30);
643 stream << QLatin1Char(' ') + QJsonDocument(QJsonObject::fromVariantMap(definitions.at(j).first)).toJson(QJsonDocument::Compact);
644 stream.setFieldWidth(20);
645
646 for (int k = 0; k < shortcuts.count(); ++k)
647 {
648 stream << shortcuts.at(k).toString(QKeySequence::PortableText);
649 }
650
651 stream.setFieldWidth(0);
652 stream << QLatin1Char('\n');
653 }
654 }
655 }
656
657 stream << QLatin1Char('\n');
658
659 return report;
660 }
661
getActionName(int identifier)662 QString ActionsManager::getActionName(int identifier)
663 {
664 QString name(ActionsManager::staticMetaObject.enumerator(m_actionIdentifierEnumerator).valueToKey(identifier));
665
666 if (!name.isEmpty())
667 {
668 name.chop(6);
669
670 return name;
671 }
672
673 return {};
674 }
675
getActionShortcut(int identifier,const QVariantMap & parameters)676 QKeySequence ActionsManager::getActionShortcut(int identifier, const QVariantMap ¶meters)
677 {
678 if (parameters.isEmpty() && m_shortcuts.contains(identifier))
679 {
680 return m_shortcuts[identifier].first();
681 }
682
683 if (!parameters.isEmpty() && m_extraShortcuts.contains(identifier))
684 {
685 const QList<QPair<QVariantMap, QVector<QKeySequence> > > definitions(m_extraShortcuts.values(identifier));
686
687 for (int i = 0; i < definitions.count(); ++i)
688 {
689 if (definitions.at(i).first == parameters)
690 {
691 return definitions.at(i).second.first();
692 }
693 }
694 }
695
696 return QKeySequence();
697 }
698
getActionDefinitions()699 QVector<ActionsManager::ActionDefinition> ActionsManager::getActionDefinitions()
700 {
701 return m_definitions;
702 }
703
getShortcutDefinitions()704 QVector<KeyboardProfile::Action> ActionsManager::getShortcutDefinitions()
705 {
706 QVector<KeyboardProfile::Action> definitions;
707 definitions.reserve(m_shortcuts.count() + m_extraShortcuts.count());
708
709 QMap<int, QVector<QKeySequence> >::iterator shortcutsIterator;
710
711 for (shortcutsIterator = m_shortcuts.begin(); shortcutsIterator != m_shortcuts.end(); ++shortcutsIterator)
712 {
713 KeyboardProfile::Action definition;
714 definition.shortcuts = shortcutsIterator.value();
715 definition.action = shortcutsIterator.key();
716
717 definitions.append(definition);
718 }
719
720 QMultiMap<int, QPair<QVariantMap, QVector<QKeySequence> > >::iterator extraShortcutsIterator;
721
722 for (extraShortcutsIterator = m_extraShortcuts.begin(); extraShortcutsIterator != m_extraShortcuts.end(); ++extraShortcutsIterator)
723 {
724 KeyboardProfile::Action definition;
725 definition.parameters = extraShortcutsIterator.value().first;
726 definition.shortcuts = extraShortcutsIterator.value().second;
727 definition.action = extraShortcutsIterator.key();
728
729 definitions.append(definition);
730 }
731
732 return definitions;
733 }
734
getActionDefinition(int identifier)735 ActionsManager::ActionDefinition ActionsManager::getActionDefinition(int identifier)
736 {
737 if (identifier < 0 || identifier >= m_definitions.count())
738 {
739 return ActionsManager::ActionDefinition();
740 }
741
742 return m_definitions[identifier];
743 }
744
getActionIdentifier(const QString & name)745 int ActionsManager::getActionIdentifier(const QString &name)
746 {
747 if (!name.endsWith(QLatin1String("Action")))
748 {
749 return ActionsManager::staticMetaObject.enumerator(m_actionIdentifierEnumerator).keyToValue((name + QLatin1String("Action")).toLatin1());
750 }
751
752 return ActionsManager::staticMetaObject.enumerator(m_actionIdentifierEnumerator).keyToValue(name.toLatin1());
753 }
754
isShortcutAllowed(const QKeySequence & shortcut,ShortcutCheck check,bool areSingleKeyShortcutsAllowed)755 bool ActionsManager::isShortcutAllowed(const QKeySequence &shortcut, ShortcutCheck check, bool areSingleKeyShortcutsAllowed)
756 {
757 if (shortcut.isEmpty())
758 {
759 return false;
760 }
761
762 if ((check == AllChecks || check == DisallowSingleKeyShortcutCheck) && (!areSingleKeyShortcutsAllowed && (shortcut[0] == Qt::Key_Plus || !shortcut.toString(QKeySequence::PortableText).contains(QLatin1Char('+'))) && shortcut[0] != Qt::Key_Delete && !(shortcut[0] >= Qt::Key_F1 && shortcut[0] <= Qt::Key_F35)))
763 {
764 return false;
765 }
766
767 if (check == AllChecks || check == DisallowStandardShortcutCheck)
768 {
769 if (m_disallowedShortcuts.isEmpty())
770 {
771 m_disallowedShortcuts = {QKeySequence(QKeySequence::Copy), QKeySequence(QKeySequence::Cut), QKeySequence(QKeySequence::Delete), QKeySequence(QKeySequence::Paste), QKeySequence(QKeySequence::Redo), QKeySequence(QKeySequence::SelectAll), QKeySequence(QKeySequence::Undo)};
772 }
773
774 if (m_disallowedShortcuts.contains(shortcut))
775 {
776 return false;
777 }
778 }
779
780 return true;
781 }
782
783 }
784