1 // For license of this file, see <project-root-folder>/LICENSE.md.
2 
3 #include "dynamic-shortcuts/dynamicshortcutswidget.h"
4 
5 #include "definitions/definitions.h"
6 #include "dynamic-shortcuts/shortcutcatcher.h"
7 #include "gui/reusable/squeezelabel.h"
8 
9 #include <QAction>
10 #include <QGridLayout>
11 #include <QLabel>
12 
DynamicShortcutsWidget(QWidget * parent)13 DynamicShortcutsWidget::DynamicShortcutsWidget(QWidget* parent) : QWidget(parent) {
14   // Create layout for this control and set is as active.
15   m_layout = new QGridLayout(this);
16   m_layout->setContentsMargins({});
17 
18   setLayout(m_layout);
19 }
20 
~DynamicShortcutsWidget()21 DynamicShortcutsWidget::~DynamicShortcutsWidget() {
22   delete m_layout;
23 }
24 
areShortcutsUnique() const25 bool DynamicShortcutsWidget::areShortcutsUnique() const {
26   QList<QKeySequence> all_shortcuts;
27 
28   // Obtain all shortcuts.
29   for (const ActionBinding& binding : m_actionBindings) {
30     const QKeySequence new_shortcut = binding.second->shortcut();
31 
32     if (!new_shortcut.isEmpty() && all_shortcuts.contains(new_shortcut)) {
33       // Problem, two identical non-empty shortcuts found.
34       return false;
35     }
36     else {
37       all_shortcuts.append(binding.second->shortcut());
38     }
39   }
40 
41   return true;
42 }
43 
updateShortcuts()44 void DynamicShortcutsWidget::updateShortcuts() {
45   for (const ActionBinding& binding : qAsConst(m_actionBindings)) {
46     binding.first->setShortcut(binding.second->shortcut());
47   }
48 }
49 
populate(QList<QAction * > actions)50 void DynamicShortcutsWidget::populate(QList<QAction*> actions) {
51   m_actionBindings.clear();
52   std::sort(actions.begin(), actions.end(), [](QAction* lhs, QAction* rhs) {
53     return QString::localeAwareCompare(lhs->text().replace(QL1S("&"), QString()), rhs->text().replace(QL1S("&"), QString())) < 0;
54   });
55   int row_id = 0;
56 
57   for (QAction* action : actions) {
58     // Create shortcut catcher for this action and set default shortcut.
59     auto* catcher = new ShortcutCatcher(this);
60 
61     catcher->setDefaultShortcut(action->shortcut());
62 
63     // Store information for re-initialization of shortcuts
64     // of actions when widget gets "confirmed".
65     QPair<QAction*, ShortcutCatcher*> new_binding;
66 
67     new_binding.first = action;
68     new_binding.second = catcher;
69     m_actionBindings << new_binding;
70 
71     // Add new catcher to our control.
72     auto* action_label = new QLabel(this);
73     auto act_text = action->text().remove(QSL("&"));
74     auto act_toolt = action->toolTip();
75 
76     if (act_text == act_toolt) {
77       action_label->setText(act_text);
78     }
79     else {
80       action_label->setText(QSL("%1 (%2)").arg(act_text, act_toolt));
81     }
82 
83     action_label->setToolTip(action->toolTip());
84     action_label->setWordWrap(true);
85 
86     //action_label->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
87 
88     auto* action_icon = new QLabel(this);
89 
90     action_icon->setPixmap(action->icon().pixmap(ICON_SIZE_SETTINGS, ICON_SIZE_SETTINGS));
91     action_icon->setToolTip(action->toolTip());
92     m_layout->addWidget(action_icon, row_id, 0);
93     m_layout->addWidget(action_label, row_id, 1);
94     m_layout->addWidget(catcher, row_id, 2);
95 
96     row_id++;
97     connect(catcher, &ShortcutCatcher::shortcutChanged, this, &DynamicShortcutsWidget::setupChanged);
98   }
99 
100   // Make sure that "spacer" is added.
101   m_layout->setRowStretch(row_id, 1);
102   m_layout->setColumnStretch(1, 1);
103 }
104