keyboard shortcuts widget now checks for duplicate shortcuts everytime shortcut is changed and offers solutions, fixes #1605

This commit is contained in:
Martin Rotter 2025-01-31 11:10:56 +01:00
parent 08388cb9b9
commit 68060c7dcd
5 changed files with 123 additions and 15 deletions

View File

@ -0,0 +1,46 @@
# Use this as RSS Guard post-processing script.
#
# Example command line usage:
# curl 'PATH_TO_SOME_YOUTUBE_CHANNEL_RSS_FEED' | python 'youtube-limit-length.py'
import sys
import xml.etree.ElementTree as ET
import requests
import json
import isodate
sys.stdin.reconfigure(encoding="utf-8")
input_data = sys.stdin.read()
api_key = "YOUR_API_KEY_HERE"
min_required_length = 90 # In seconds.
youtube_query = (
"https://www.googleapis.com/youtube/v3/videos?part=contentDetails&id=VIDEO-ID&key="
+ api_key
)
ns = {
"atom": "http://www.w3.org/2005/Atom",
"yt": "http://www.youtube.com/xml/schemas/2015",
}
tree = ET.fromstring(input_data)
entries = tree.findall("atom:entry", ns)
for entry in entries:
video_id = entry.find("yt:videoId", ns).text
youtube_query_specific = youtube_query.replace("VIDEO-ID", video_id)
api_response = requests.get(youtube_query_specific).text
response_json = json.loads(api_response)
try:
length_encoded = str(response_json["items"][0]["contentDetails"]["duration"])
except:
continue
length = isodate.parse_duration(length_encoded)
if length.seconds < min_required_length:
tree.remove(entry)
sys.stdout.buffer.write(ET.tostring(tree, encoding='utf-8', method='xml'))

View File

@ -4,6 +4,7 @@
#include "definitions/definitions.h"
#include "dynamic-shortcuts/shortcutcatcher.h"
#include "gui/messagebox.h"
#include <QAction>
#include <QGridLayout>
@ -25,15 +26,15 @@ bool DynamicShortcutsWidget::areShortcutsUnique() const {
QList<QKeySequence> all_shortcuts;
// Obtain all shortcuts.
for (const ActionBinding& binding : m_actionBindings) {
const QKeySequence new_shortcut = binding.second->shortcut();
for (ShortcutCatcher* catcher : m_actionBindings) {
const QKeySequence new_shortcut = catcher->shortcut();
if (!new_shortcut.isEmpty() && all_shortcuts.contains(new_shortcut)) {
// Problem, two identical non-empty shortcuts found.
return false;
}
else {
all_shortcuts.append(binding.second->shortcut());
all_shortcuts.append(catcher->shortcut());
}
}
@ -41,8 +42,8 @@ bool DynamicShortcutsWidget::areShortcutsUnique() const {
}
void DynamicShortcutsWidget::updateShortcuts() {
for (const ActionBinding& binding : std::as_const(m_actionBindings)) {
binding.first->setShortcut(binding.second->shortcut());
for (ShortcutCatcher* catcher : std::as_const(m_actionBindings)) {
catcher->action()->setShortcut(catcher->shortcut());
}
}
@ -58,15 +59,14 @@ void DynamicShortcutsWidget::populate(QList<QAction*> actions) {
// Create shortcut catcher for this action and set default shortcut.
auto* catcher = new ShortcutCatcher(this);
catcher->setAction(action);
catcher->setDefaultShortcut(action->shortcut());
// Store information for re-initialization of shortcuts
// of actions when widget gets "confirmed".
QPair<QAction*, ShortcutCatcher*> new_binding;
if (!action->shortcut().isEmpty()) {
m_assignedShortcuts.insert(action->shortcut(), catcher);
}
new_binding.first = action;
new_binding.second = catcher;
m_actionBindings << new_binding;
m_actionBindings.append(catcher);
// Add new catcher to our control.
auto* action_label = new QLabel(this);
@ -89,15 +89,63 @@ void DynamicShortcutsWidget::populate(QList<QAction*> actions) {
action_icon->setPixmap(action->icon().pixmap(ICON_SIZE_SETTINGS, ICON_SIZE_SETTINGS));
action_icon->setToolTip(action->toolTip());
m_layout->addWidget(action_icon, row_id, 0);
m_layout->addWidget(action_label, row_id, 1);
m_layout->addWidget(catcher, row_id, 2);
row_id++;
connect(catcher, &ShortcutCatcher::shortcutChanged, this, &DynamicShortcutsWidget::setupChanged);
connect(catcher, &ShortcutCatcher::shortcutChanged, this, &DynamicShortcutsWidget::onShortcutChanged);
}
// Make sure that "spacer" is added.
m_layout->setRowStretch(row_id, 1);
m_layout->setColumnStretch(1, 1);
}
void DynamicShortcutsWidget::onShortcutChanged(const QKeySequence& sequence) {
ShortcutCatcher* catcher = qobject_cast<ShortcutCatcher*>(sender());
QKeySequence assigned_sequence = m_assignedShortcuts.key(catcher);
qDebugNN << catcher->action()->text();
// We remove currently assigned sequence to this catcher.
m_assignedShortcuts.remove(assigned_sequence);
if (!sequence.isEmpty()) {
// Now we check if any other catcher has assigned the same sequence.
ShortcutCatcher* conflicting_catcher = m_assignedShortcuts.value(sequence);
if (conflicting_catcher != nullptr) {
// We found conflicting catcher.
catcher->blockSignals(true);
QMessageBox::StandardButton decision =
MsgBox::show(this,
QMessageBox::Icon::Critical,
tr("Duplicate shortcut"),
tr("There is another action which has the same shortcut assigned."),
tr("Do you want to keep the new shortcut assignment and clear the previous shortcut?"),
conflicting_catcher->action()->text().remove(QSL("&")),
QMessageBox::StandardButton::Yes | QMessageBox::StandardButton::No,
QMessageBox::StandardButton::Yes);
catcher->blockSignals(false);
if (decision == QMessageBox::StandardButton::Yes) {
// We keep the new shortcut and reset old conflicting action.
m_assignedShortcuts.insert(sequence, catcher);
conflicting_catcher->clearShortcut();
}
else {
// We discard new shortcut.
catcher->clearShortcut();
}
}
else {
m_assignedShortcuts.insert(sequence, catcher);
}
}
emit setupChanged();
}

View File

@ -8,8 +8,6 @@
class QGridLayout;
class ShortcutCatcher;
typedef QPair<QAction*, ShortcutCatcher*> ActionBinding;
class DynamicShortcutsWidget : public QWidget {
Q_OBJECT
@ -33,12 +31,16 @@ class DynamicShortcutsWidget : public QWidget {
// assigned to actions before calling this method.
void populate(QList<QAction*> actions);
private slots:
void onShortcutChanged(const QKeySequence& sequence);
signals:
void setupChanged();
private:
QGridLayout* m_layout;
QList<ActionBinding> m_actionBindings;
QList<ShortcutCatcher*> m_actionBindings;
QHash<QKeySequence, ShortcutCatcher*> m_assignedShortcuts;
};
#endif // DYNAMICSHORTCUTSOVERVIEW_H

View File

@ -65,3 +65,11 @@ void ShortcutCatcher::resetShortcut() {
void ShortcutCatcher::clearShortcut() {
setShortcut(QKeySequence());
}
QAction* ShortcutCatcher::action() const {
return m_action;
}
void ShortcutCatcher::setAction(QAction* act) {
m_action = act;
}

View File

@ -19,6 +19,9 @@ class ShortcutCatcher : public QWidget {
void setDefaultShortcut(const QKeySequence& key);
void setShortcut(const QKeySequence& key);
QAction* action() const;
void setAction(QAction* act);
public slots:
void resetShortcut();
void clearShortcut();
@ -27,6 +30,7 @@ class ShortcutCatcher : public QWidget {
void shortcutChanged(const QKeySequence& seguence);
private:
QAction* m_action;
PlainToolButton* m_btnReset;
PlainToolButton* m_btnClear;
QKeySequenceEdit* m_shortcutBox;