You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
216 lines
5.9 KiB
C++
216 lines
5.9 KiB
C++
#include "shortcutsetting.hpp"
|
|
|
|
#include <QEvent>
|
|
#include <QKeyEvent>
|
|
#include <QLabel>
|
|
#include <QMouseEvent>
|
|
#include <QPushButton>
|
|
#include <QWidget>
|
|
#include <QString>
|
|
|
|
#include "state.hpp"
|
|
#include "shortcutmanager.hpp"
|
|
|
|
namespace CSMPrefs
|
|
{
|
|
const int ShortcutSetting::MaxKeys;
|
|
|
|
ShortcutSetting::ShortcutSetting(Category* parent, Settings::Manager* values, QMutex* mutex, const std::string& key,
|
|
const std::string& label)
|
|
: Setting(parent, values, mutex, key, label)
|
|
, mButton(0)
|
|
, mEditorActive(false)
|
|
, mEditorPos(0)
|
|
{
|
|
for (int i = 0; i < MaxKeys; ++i)
|
|
{
|
|
mEditorKeys[i] = 0;
|
|
}
|
|
}
|
|
|
|
std::pair<QWidget*, QWidget*> ShortcutSetting::makeWidgets(QWidget* parent)
|
|
{
|
|
QKeySequence sequence;
|
|
State::get().getShortcutManager().getSequence(getKey(), sequence);
|
|
|
|
QString text = QString::fromUtf8(State::get().getShortcutManager().convertToString(sequence).c_str());
|
|
|
|
QLabel* label = new QLabel(QString::fromUtf8(getLabel().c_str()), parent);
|
|
QPushButton* widget = new QPushButton(text, parent);
|
|
|
|
widget->setCheckable(true);
|
|
widget->installEventFilter(this);
|
|
|
|
// right clicking on button sets shortcut to RMB, so context menu should not appear
|
|
widget->setContextMenuPolicy(Qt::PreventContextMenu);
|
|
|
|
mButton = widget;
|
|
|
|
connect(widget, SIGNAL(toggled(bool)), this, SLOT(buttonToggled(bool)));
|
|
|
|
return std::make_pair(label, widget);
|
|
}
|
|
|
|
void ShortcutSetting::updateWidget()
|
|
{
|
|
if (mButton)
|
|
{
|
|
std::string shortcut = getValues().getString(getKey(), getParent()->getKey());
|
|
|
|
QKeySequence sequence;
|
|
State::get().getShortcutManager().convertFromString(shortcut, sequence);
|
|
State::get().getShortcutManager().setSequence(getKey(), sequence);
|
|
resetState();
|
|
}
|
|
}
|
|
|
|
bool ShortcutSetting::eventFilter(QObject* target, QEvent* event)
|
|
{
|
|
if (event->type() == QEvent::KeyPress)
|
|
{
|
|
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
|
|
if (keyEvent->isAutoRepeat())
|
|
return true;
|
|
|
|
int mod = keyEvent->modifiers();
|
|
int key = keyEvent->key();
|
|
|
|
return handleEvent(target, mod, key, true);
|
|
}
|
|
else if (event->type() == QEvent::KeyRelease)
|
|
{
|
|
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
|
|
if (keyEvent->isAutoRepeat())
|
|
return true;
|
|
|
|
int mod = keyEvent->modifiers();
|
|
int key = keyEvent->key();
|
|
|
|
return handleEvent(target, mod, key, false);
|
|
}
|
|
else if (event->type() == QEvent::MouseButtonPress)
|
|
{
|
|
QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
|
|
int mod = mouseEvent->modifiers();
|
|
int key = mouseEvent->button();
|
|
|
|
return handleEvent(target, mod, key, true);
|
|
}
|
|
else if (event->type() == QEvent::MouseButtonRelease)
|
|
{
|
|
QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
|
|
int mod = mouseEvent->modifiers();
|
|
int key = mouseEvent->button();
|
|
|
|
return handleEvent(target, mod, key, false);
|
|
}
|
|
else if (event->type() == QEvent::FocusOut)
|
|
{
|
|
resetState();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool ShortcutSetting::handleEvent(QObject* target, int mod, int value, bool active)
|
|
{
|
|
// Modifiers are handled differently
|
|
const int Blacklist[] =
|
|
{
|
|
Qt::Key_Shift,
|
|
Qt::Key_Control,
|
|
Qt::Key_Meta,
|
|
Qt::Key_Alt,
|
|
Qt::Key_AltGr
|
|
};
|
|
|
|
const size_t BlacklistSize = sizeof(Blacklist) / sizeof(int);
|
|
|
|
if (!mEditorActive)
|
|
{
|
|
if (value == Qt::RightButton && !active)
|
|
{
|
|
// Clear sequence
|
|
QKeySequence sequence = QKeySequence(0, 0, 0, 0);
|
|
storeValue(sequence);
|
|
|
|
resetState();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// Handle blacklist
|
|
for (size_t i = 0; i < BlacklistSize; ++i)
|
|
{
|
|
if (value == Blacklist[i])
|
|
return true;
|
|
}
|
|
|
|
if (!active || mEditorPos >= MaxKeys)
|
|
{
|
|
// Update key
|
|
QKeySequence sequence = QKeySequence(mEditorKeys[0], mEditorKeys[1], mEditorKeys[2], mEditorKeys[3]);
|
|
storeValue(sequence);
|
|
|
|
resetState();
|
|
}
|
|
else
|
|
{
|
|
if (mEditorPos == 0)
|
|
{
|
|
mEditorKeys[0] = mod | value;
|
|
}
|
|
else
|
|
{
|
|
mEditorKeys[mEditorPos] = value;
|
|
}
|
|
|
|
mEditorPos += 1;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void ShortcutSetting::storeValue(const QKeySequence& sequence)
|
|
{
|
|
State::get().getShortcutManager().setSequence(getKey(), sequence);
|
|
|
|
// Convert to string and assign
|
|
std::string value = State::get().getShortcutManager().convertToString(sequence);
|
|
|
|
{
|
|
QMutexLocker lock(getMutex());
|
|
getValues().setString(getKey(), getParent()->getKey(), value);
|
|
}
|
|
|
|
getParent()->getState()->update(*this);
|
|
}
|
|
|
|
void ShortcutSetting::resetState()
|
|
{
|
|
mButton->setChecked(false);
|
|
mEditorActive = false;
|
|
mEditorPos = 0;
|
|
for (int i = 0; i < MaxKeys; ++i)
|
|
{
|
|
mEditorKeys[i] = 0;
|
|
}
|
|
|
|
// Button text
|
|
QKeySequence sequence;
|
|
State::get().getShortcutManager().getSequence(getKey(), sequence);
|
|
|
|
QString text = QString::fromUtf8(State::get().getShortcutManager().convertToString(sequence).c_str());
|
|
mButton->setText(text);
|
|
}
|
|
|
|
void ShortcutSetting::buttonToggled(bool checked)
|
|
{
|
|
if (checked)
|
|
mButton->setText("Press keys or click here...");
|
|
|
|
mEditorActive = checked;
|
|
}
|
|
}
|