1 #include "modifiersetting.hpp"
2 
3 #include <QEvent>
4 #include <QKeyEvent>
5 #include <QLabel>
6 #include <QMouseEvent>
7 #include <QPushButton>
8 #include <QWidget>
9 
10 #include "state.hpp"
11 #include "shortcutmanager.hpp"
12 
13 namespace CSMPrefs
14 {
ModifierSetting(Category * parent,Settings::Manager * values,QMutex * mutex,const std::string & key,const std::string & label)15     ModifierSetting::ModifierSetting(Category* parent, Settings::Manager* values, QMutex* mutex, const std::string& key,
16         const std::string& label)
17         : Setting(parent, values, mutex, key, label)
18         , mButton(nullptr)
19         , mEditorActive(false)
20     {
21     }
22 
makeWidgets(QWidget * parent)23     std::pair<QWidget*, QWidget*> ModifierSetting::makeWidgets(QWidget* parent)
24     {
25         int modifier = 0;
26         State::get().getShortcutManager().getModifier(getKey(), modifier);
27 
28         QString text = QString::fromUtf8(State::get().getShortcutManager().convertToString(modifier).c_str());
29 
30         QLabel* label = new QLabel(QString::fromUtf8(getLabel().c_str()), parent);
31         QPushButton* widget = new QPushButton(text, parent);
32 
33         widget->setCheckable(true);
34         widget->installEventFilter(this);
35 
36         // right clicking on button sets shortcut to RMB, so context menu should not appear
37         widget->setContextMenuPolicy(Qt::PreventContextMenu);
38 
39         mButton = widget;
40 
41         connect(widget, SIGNAL(toggled(bool)), this, SLOT(buttonToggled(bool)));
42 
43         return std::make_pair(label, widget);
44     }
45 
updateWidget()46     void ModifierSetting::updateWidget()
47     {
48         if (mButton)
49         {
50             std::string shortcut = getValues().getString(getKey(), getParent()->getKey());
51 
52             int modifier;
53             State::get().getShortcutManager().convertFromString(shortcut, modifier);
54             State::get().getShortcutManager().setModifier(getKey(), modifier);
55             resetState();
56         }
57     }
58 
eventFilter(QObject * target,QEvent * event)59     bool ModifierSetting::eventFilter(QObject* target, QEvent* event)
60     {
61         if (event->type() == QEvent::KeyPress)
62         {
63             QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
64             if (keyEvent->isAutoRepeat())
65                 return true;
66 
67             int mod = keyEvent->modifiers();
68             int key = keyEvent->key();
69 
70             return handleEvent(target, mod, key);
71         }
72         else if (event->type() == QEvent::MouseButtonPress)
73         {
74             QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
75             int mod = mouseEvent->modifiers();
76             int button = mouseEvent->button();
77 
78             return handleEvent(target, mod, button);
79         }
80         else if (event->type() == QEvent::FocusOut)
81         {
82             resetState();
83         }
84 
85         return false;
86     }
87 
handleEvent(QObject * target,int mod,int value)88     bool ModifierSetting::handleEvent(QObject* target, int mod, int value)
89     {
90         // For potential future exceptions
91         const int Blacklist[] =
92         {
93             0
94         };
95 
96         const size_t BlacklistSize = sizeof(Blacklist) / sizeof(int);
97 
98         if (!mEditorActive)
99         {
100             if (value == Qt::RightButton)
101             {
102                 // Clear modifier
103                 int modifier = 0;
104                 storeValue(modifier);
105 
106                 resetState();
107             }
108 
109             return false;
110         }
111 
112         // Handle blacklist
113         for (size_t i = 0; i < BlacklistSize; ++i)
114         {
115             if (value == Blacklist[i])
116                 return true;
117         }
118 
119 
120         // Update modifier
121         int modifier = value;
122         storeValue(modifier);
123 
124         resetState();
125 
126         return true;
127     }
128 
storeValue(int modifier)129     void ModifierSetting::storeValue(int modifier)
130     {
131         State::get().getShortcutManager().setModifier(getKey(), modifier);
132 
133         // Convert to string and assign
134         std::string value = State::get().getShortcutManager().convertToString(modifier);
135 
136         {
137             QMutexLocker lock(getMutex());
138             getValues().setString(getKey(), getParent()->getKey(), value);
139         }
140 
141         getParent()->getState()->update(*this);
142     }
143 
resetState()144     void ModifierSetting::resetState()
145     {
146         mButton->setChecked(false);
147         mEditorActive = false;
148 
149         // Button text
150         int modifier = 0;
151         State::get().getShortcutManager().getModifier(getKey(), modifier);
152 
153         QString text = QString::fromUtf8(State::get().getShortcutManager().convertToString(modifier).c_str());
154         mButton->setText(text);
155     }
156 
buttonToggled(bool checked)157     void ModifierSetting::buttonToggled(bool checked)
158     {
159         if (checked)
160             mButton->setText("Press keys or click here...");
161 
162         mEditorActive = checked;
163     }
164 }
165