mirror of
				https://github.com/TES3MP/openmw-tes3mp.git
				synced 2025-10-31 18:56:43 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			215 lines
		
	
	
	
		
			5.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			215 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;
 | |
|     }
 | |
| }
 |