Qt: Initial hotkey implementation
This commit is contained in:
parent
0590f0935c
commit
40e1b7af23
|
@ -12,6 +12,10 @@ add_executable(duckstation-qt
|
||||||
gamelistsettingswidget.ui
|
gamelistsettingswidget.ui
|
||||||
gamelistwidget.cpp
|
gamelistwidget.cpp
|
||||||
gamelistwidget.h
|
gamelistwidget.h
|
||||||
|
hotkeysettingswidget.cpp
|
||||||
|
hotkeysettingswidget.h
|
||||||
|
inputbindingwidgets.cpp
|
||||||
|
inputbindingwidgets.h
|
||||||
main.cpp
|
main.cpp
|
||||||
mainwindow.cpp
|
mainwindow.cpp
|
||||||
mainwindow.h
|
mainwindow.h
|
||||||
|
|
|
@ -37,6 +37,8 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="consolesettingswidget.cpp" />
|
<ClCompile Include="consolesettingswidget.cpp" />
|
||||||
<ClCompile Include="gpusettingswidget.cpp" />
|
<ClCompile Include="gpusettingswidget.cpp" />
|
||||||
|
<ClCompile Include="hotkeysettingswidget.cpp" />
|
||||||
|
<ClCompile Include="inputbindingwidgets.cpp" />
|
||||||
<ClCompile Include="qtdisplaywindow.cpp" />
|
<ClCompile Include="qtdisplaywindow.cpp" />
|
||||||
<ClCompile Include="gamelistsettingswidget.cpp" />
|
<ClCompile Include="gamelistsettingswidget.cpp" />
|
||||||
<ClCompile Include="gamelistwidget.cpp" />
|
<ClCompile Include="gamelistwidget.cpp" />
|
||||||
|
@ -53,6 +55,8 @@
|
||||||
<QtMoc Include="portsettingswidget.h" />
|
<QtMoc Include="portsettingswidget.h" />
|
||||||
<QtMoc Include="qtdisplaywindow.h" />
|
<QtMoc Include="qtdisplaywindow.h" />
|
||||||
<QtMoc Include="gpusettingswidget.h" />
|
<QtMoc Include="gpusettingswidget.h" />
|
||||||
|
<QtMoc Include="hotkeysettingswidget.h" />
|
||||||
|
<QtMoc Include="inputbindingwidgets.h" />
|
||||||
<ClInclude Include="settingwidgetbinder.h" />
|
<ClInclude Include="settingwidgetbinder.h" />
|
||||||
<QtMoc Include="consolesettingswidget.h" />
|
<QtMoc Include="consolesettingswidget.h" />
|
||||||
<QtMoc Include="gamelistsettingswidget.h" />
|
<QtMoc Include="gamelistsettingswidget.h" />
|
||||||
|
@ -105,6 +109,8 @@
|
||||||
<ClCompile Include="$(IntDir)moc_gamelistsettingswidget.cpp" />
|
<ClCompile Include="$(IntDir)moc_gamelistsettingswidget.cpp" />
|
||||||
<ClCompile Include="$(IntDir)moc_gamelistwidget.cpp" />
|
<ClCompile Include="$(IntDir)moc_gamelistwidget.cpp" />
|
||||||
<ClCompile Include="$(IntDir)moc_gpusettingswidget.cpp" />
|
<ClCompile Include="$(IntDir)moc_gpusettingswidget.cpp" />
|
||||||
|
<ClCompile Include="$(IntDir)moc_hotkeysettingswidget.cpp" />
|
||||||
|
<ClCompile Include="$(IntDir)moc_inputbindingwidgets.cpp" />
|
||||||
<ClCompile Include="$(IntDir)moc_mainwindow.cpp" />
|
<ClCompile Include="$(IntDir)moc_mainwindow.cpp" />
|
||||||
<ClCompile Include="$(IntDir)moc_opengldisplaywindow.cpp" />
|
<ClCompile Include="$(IntDir)moc_opengldisplaywindow.cpp" />
|
||||||
<ClCompile Include="$(IntDir)moc_portsettingswidget.cpp" />
|
<ClCompile Include="$(IntDir)moc_portsettingswidget.cpp" />
|
||||||
|
|
|
@ -25,11 +25,15 @@
|
||||||
<ClCompile Include="$(IntDir)moc_qtdisplaywindow.cpp" />
|
<ClCompile Include="$(IntDir)moc_qtdisplaywindow.cpp" />
|
||||||
<ClCompile Include="gpusettingswidget.cpp" />
|
<ClCompile Include="gpusettingswidget.cpp" />
|
||||||
<ClCompile Include="$(IntDir)moc_gpusettingswidget.cpp" />
|
<ClCompile Include="$(IntDir)moc_gpusettingswidget.cpp" />
|
||||||
|
<ClCompile Include="inputbindingwidgets.cpp" />
|
||||||
|
<ClCompile Include="hotkeysettingswidget.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="qtsettingsinterface.h" />
|
<ClInclude Include="qtsettingsinterface.h" />
|
||||||
<ClInclude Include="qtutils.h" />
|
<ClInclude Include="qtutils.h" />
|
||||||
<ClInclude Include="settingwidgetbinder.h" />
|
<ClInclude Include="settingwidgetbinder.h" />
|
||||||
|
<ClInclude Include="inputbindingwidgets.h" />
|
||||||
|
<ClInclude Include="hotkeysettingswidget.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Filter Include="resources">
|
<Filter Include="resources">
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
#include "hotkeysettingswidget.h"
|
||||||
|
#include "core/controller.h"
|
||||||
|
#include "core/settings.h"
|
||||||
|
#include "inputbindingwidgets.h"
|
||||||
|
#include "qthostinterface.h"
|
||||||
|
#include "qtutils.h"
|
||||||
|
#include <QtCore/QTimer>
|
||||||
|
#include <QtGui/QKeyEvent>
|
||||||
|
#include <QtWidgets/QGridLayout>
|
||||||
|
#include <QtWidgets/QLabel>
|
||||||
|
|
||||||
|
HotkeySettingsWidget::HotkeySettingsWidget(QtHostInterface* host_interface, QWidget* parent /* = nullptr */)
|
||||||
|
: QWidget(parent), m_host_interface(host_interface)
|
||||||
|
{
|
||||||
|
createUi();
|
||||||
|
}
|
||||||
|
|
||||||
|
HotkeySettingsWidget::~HotkeySettingsWidget() = default;
|
||||||
|
|
||||||
|
void HotkeySettingsWidget::createUi()
|
||||||
|
{
|
||||||
|
QGridLayout* layout = new QGridLayout(this);
|
||||||
|
|
||||||
|
m_tab_widget = new QTabWidget(this);
|
||||||
|
|
||||||
|
createButtons();
|
||||||
|
|
||||||
|
layout->addWidget(m_tab_widget, 0, 0, 1, 1);
|
||||||
|
|
||||||
|
setLayout(layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HotkeySettingsWidget::createButtons()
|
||||||
|
{
|
||||||
|
std::vector<QtHostInterface::HotkeyInfo> hotkeys = m_host_interface->getHotkeyList();
|
||||||
|
|
||||||
|
for (const QtHostInterface::HotkeyInfo& hi : hotkeys)
|
||||||
|
{
|
||||||
|
auto iter = m_categories.find(hi.category);
|
||||||
|
if (iter == m_categories.end())
|
||||||
|
{
|
||||||
|
QWidget* container = new QWidget(m_tab_widget);
|
||||||
|
QVBoxLayout* vlayout = new QVBoxLayout(container);
|
||||||
|
QGridLayout* layout = new QGridLayout();
|
||||||
|
layout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
vlayout->addLayout(layout);
|
||||||
|
vlayout->addStretch(1);
|
||||||
|
iter = m_categories.insert(hi.category, Category{container, layout});
|
||||||
|
m_tab_widget->addTab(container, hi.category);
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget* container = iter->container;
|
||||||
|
QGridLayout* layout = iter->layout;
|
||||||
|
const int layout_count = layout->count() / 2;
|
||||||
|
const int target_column = (layout_count / ROWS_PER_COLUMN) * 2;
|
||||||
|
const int target_row = layout_count % ROWS_PER_COLUMN;
|
||||||
|
|
||||||
|
const QString setting_name = QStringLiteral("Hotkeys/%1").arg(hi.name);
|
||||||
|
layout->addWidget(new QLabel(hi.display_name, container), target_row, target_column);
|
||||||
|
layout->addWidget(new InputButtonBindingWidget(m_host_interface, setting_name, container), target_row,
|
||||||
|
target_column + 1);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
#pragma once
|
||||||
|
#include "core/types.h"
|
||||||
|
#include <QtWidgets/QTabWidget>
|
||||||
|
#include <QtCore/QMap>
|
||||||
|
#include <array>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class QtHostInterface;
|
||||||
|
class QGridLayout;
|
||||||
|
|
||||||
|
class HotkeySettingsWidget : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
HotkeySettingsWidget(QtHostInterface* host_interface, QWidget* parent = nullptr);
|
||||||
|
~HotkeySettingsWidget();
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum : u32
|
||||||
|
{
|
||||||
|
ROWS_PER_COLUMN = 10
|
||||||
|
};
|
||||||
|
|
||||||
|
void createUi();
|
||||||
|
void createButtons();
|
||||||
|
|
||||||
|
QtHostInterface* m_host_interface;
|
||||||
|
|
||||||
|
QTabWidget* m_tab_widget;
|
||||||
|
|
||||||
|
struct Category
|
||||||
|
{
|
||||||
|
QWidget* container;
|
||||||
|
QGridLayout* layout;
|
||||||
|
};
|
||||||
|
QMap<QString, Category> m_categories;
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
#include "inputbindingwidgets.h"
|
||||||
|
#include "core/settings.h"
|
||||||
|
#include "qthostinterface.h"
|
||||||
|
#include "qtutils.h"
|
||||||
|
#include <QtCore/QTimer>
|
||||||
|
#include <QtGui/QKeyEvent>
|
||||||
|
|
||||||
|
InputButtonBindingWidget::InputButtonBindingWidget(QtHostInterface* host_interface, QString setting_name,
|
||||||
|
QWidget* parent)
|
||||||
|
: QPushButton(parent), m_host_interface(host_interface), m_setting_name(std::move(setting_name))
|
||||||
|
{
|
||||||
|
m_current_binding_value = m_host_interface->getQSettings().value(m_setting_name).toString();
|
||||||
|
setText(m_current_binding_value);
|
||||||
|
|
||||||
|
connect(this, &QPushButton::pressed, this, &InputButtonBindingWidget::onPressed);
|
||||||
|
}
|
||||||
|
|
||||||
|
InputButtonBindingWidget::~InputButtonBindingWidget() = default;
|
||||||
|
|
||||||
|
void InputButtonBindingWidget::keyPressEvent(QKeyEvent* event)
|
||||||
|
{
|
||||||
|
// ignore the key press if we're listening for input
|
||||||
|
if (isListeningForInput())
|
||||||
|
return;
|
||||||
|
|
||||||
|
QPushButton::keyPressEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputButtonBindingWidget::keyReleaseEvent(QKeyEvent* event)
|
||||||
|
{
|
||||||
|
if (!isListeningForInput())
|
||||||
|
{
|
||||||
|
QPushButton::keyReleaseEvent(event);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString key_name = QtUtils::GetKeyIdentifier(event->key());
|
||||||
|
if (!key_name.isEmpty())
|
||||||
|
{
|
||||||
|
// TODO: Update input map
|
||||||
|
m_current_binding_value = QStringLiteral("Keyboard/%1").arg(key_name);
|
||||||
|
m_host_interface->getQSettings().setValue(m_setting_name, m_current_binding_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
stopListeningForInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputButtonBindingWidget::onPressed()
|
||||||
|
{
|
||||||
|
if (isListeningForInput())
|
||||||
|
stopListeningForInput();
|
||||||
|
|
||||||
|
startListeningForInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputButtonBindingWidget::onInputListenTimerTimeout()
|
||||||
|
{
|
||||||
|
m_input_listen_remaining_seconds--;
|
||||||
|
if (m_input_listen_remaining_seconds == 0)
|
||||||
|
{
|
||||||
|
stopListeningForInput();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setText(tr("Push Button... [%1]").arg(m_input_listen_remaining_seconds));
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputButtonBindingWidget::startListeningForInput()
|
||||||
|
{
|
||||||
|
m_input_listen_timer = new QTimer(this);
|
||||||
|
m_input_listen_timer->setSingleShot(false);
|
||||||
|
m_input_listen_timer->start(1000);
|
||||||
|
|
||||||
|
m_input_listen_timer->connect(m_input_listen_timer, &QTimer::timeout, this,
|
||||||
|
&InputButtonBindingWidget::onInputListenTimerTimeout);
|
||||||
|
m_input_listen_remaining_seconds = 5;
|
||||||
|
setText(tr("Push Button... [%1]").arg(m_input_listen_remaining_seconds));
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputButtonBindingWidget::stopListeningForInput()
|
||||||
|
{
|
||||||
|
setText(m_current_binding_value);
|
||||||
|
delete m_input_listen_timer;
|
||||||
|
m_input_listen_timer = nullptr;
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
#pragma once
|
||||||
|
#include "core/types.h"
|
||||||
|
#include <QtWidgets/QPushButton>
|
||||||
|
|
||||||
|
class QTimer;
|
||||||
|
|
||||||
|
class QtHostInterface;
|
||||||
|
|
||||||
|
class InputButtonBindingWidget : public QPushButton
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
InputButtonBindingWidget(QtHostInterface* host_interface, QString setting_name, QWidget* parent);
|
||||||
|
~InputButtonBindingWidget();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void keyPressEvent(QKeyEvent* event) override;
|
||||||
|
void keyReleaseEvent(QKeyEvent* event) override;
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void onPressed();
|
||||||
|
void onInputListenTimerTimeout();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool isListeningForInput() const { return m_input_listen_timer != nullptr; }
|
||||||
|
void startListeningForInput();
|
||||||
|
void stopListeningForInput();
|
||||||
|
|
||||||
|
QtHostInterface* m_host_interface;
|
||||||
|
QString m_setting_name;
|
||||||
|
QString m_current_binding_value;
|
||||||
|
QTimer* m_input_listen_timer = nullptr;
|
||||||
|
u32 m_input_listen_remaining_seconds = 0;
|
||||||
|
};
|
|
@ -72,8 +72,9 @@
|
||||||
</widget>
|
</widget>
|
||||||
<addaction name="actionFullscreen"/>
|
<addaction name="actionFullscreen"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="actionConsoleSettings"/>
|
|
||||||
<addaction name="actionGameListSettings"/>
|
<addaction name="actionGameListSettings"/>
|
||||||
|
<addaction name="actionHotkeySettings"/>
|
||||||
|
<addaction name="actionConsoleSettings"/>
|
||||||
<addaction name="actionPortSettings"/>
|
<addaction name="actionPortSettings"/>
|
||||||
<addaction name="actionGPUSettings"/>
|
<addaction name="actionGPUSettings"/>
|
||||||
<addaction name="actionAudioSettings"/>
|
<addaction name="actionAudioSettings"/>
|
||||||
|
@ -219,13 +220,13 @@
|
||||||
<string>&Port Settings...</string>
|
<string>&Port Settings...</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="actionCPUSettings">
|
<action name="actionHotkeySettings">
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset resource="icons.qrc">
|
<iconset resource="icons.qrc">
|
||||||
<normaloff>:/icons/applications-other.png</normaloff>:/icons/applications-other.png</iconset>
|
<normaloff>:/icons/applications-other.png</normaloff>:/icons/applications-other.png</iconset>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>&CPU Settings...</string>
|
<string>&Hotkey Settings...</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="actionGPUSettings">
|
<action name="actionGPUSettings">
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "portsettingswidget.h"
|
#include "portsettingswidget.h"
|
||||||
#include "core/controller.h"
|
#include "core/controller.h"
|
||||||
#include "core/settings.h"
|
#include "core/settings.h"
|
||||||
|
#include "inputbindingwidgets.h"
|
||||||
#include "qthostinterface.h"
|
#include "qthostinterface.h"
|
||||||
#include "qtutils.h"
|
#include "qtutils.h"
|
||||||
#include <QtCore/QTimer>
|
#include <QtCore/QTimer>
|
||||||
|
@ -94,7 +95,7 @@ void PortSettingsWidget::createPortBindingSettingsUi(int index, PortSettingsUI*
|
||||||
const QString button_name_q = QString::fromStdString(button_name);
|
const QString button_name_q = QString::fromStdString(button_name);
|
||||||
const QString setting_name = QStringLiteral("Controller%1/Button%2").arg(index + 1).arg(button_name_q);
|
const QString setting_name = QStringLiteral("Controller%1/Button%2").arg(index + 1).arg(button_name_q);
|
||||||
QLabel* label = new QLabel(button_name_q, container);
|
QLabel* label = new QLabel(button_name_q, container);
|
||||||
InputButtonBindingWidget* button = new InputButtonBindingWidget(m_host_interface, setting_name, ctype, container);
|
InputButtonBindingWidget* button = new InputButtonBindingWidget(m_host_interface, setting_name, container);
|
||||||
layout->addWidget(label, start_row + current_row, current_column);
|
layout->addWidget(label, start_row + current_row, current_column);
|
||||||
layout->addWidget(button, start_row + current_row, current_column + 1);
|
layout->addWidget(button, start_row + current_row, current_column + 1);
|
||||||
|
|
||||||
|
@ -129,83 +130,3 @@ void PortSettingsWidget::onControllerTypeChanged(int index)
|
||||||
QString::fromStdString(Settings::GetControllerTypeName(static_cast<ControllerType>(type_index))));
|
QString::fromStdString(Settings::GetControllerTypeName(static_cast<ControllerType>(type_index))));
|
||||||
createPortBindingSettingsUi(index, &m_port_ui[index]);
|
createPortBindingSettingsUi(index, &m_port_ui[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
InputButtonBindingWidget::InputButtonBindingWidget(QtHostInterface* host_interface, QString setting_name,
|
|
||||||
ControllerType controller_type, QWidget* parent)
|
|
||||||
: QPushButton(parent), m_host_interface(host_interface), m_setting_name(std::move(setting_name)),
|
|
||||||
m_controller_type(controller_type)
|
|
||||||
{
|
|
||||||
m_current_binding_value = m_host_interface->getQSettings().value(m_setting_name).toString();
|
|
||||||
setText(m_current_binding_value);
|
|
||||||
|
|
||||||
connect(this, &QPushButton::pressed, this, &InputButtonBindingWidget::onPressed);
|
|
||||||
}
|
|
||||||
|
|
||||||
InputButtonBindingWidget::~InputButtonBindingWidget() = default;
|
|
||||||
|
|
||||||
void InputButtonBindingWidget::keyPressEvent(QKeyEvent* event)
|
|
||||||
{
|
|
||||||
// ignore the key press if we're listening for input
|
|
||||||
if (isListeningForInput())
|
|
||||||
return;
|
|
||||||
|
|
||||||
QPushButton::keyPressEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputButtonBindingWidget::keyReleaseEvent(QKeyEvent* event)
|
|
||||||
{
|
|
||||||
if (!isListeningForInput())
|
|
||||||
{
|
|
||||||
QPushButton::keyReleaseEvent(event);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString key_name = QtUtils::GetKeyIdentifier(event->key());
|
|
||||||
if (!key_name.isEmpty())
|
|
||||||
{
|
|
||||||
// TODO: Update input map
|
|
||||||
m_current_binding_value = QStringLiteral("Keyboard/%1").arg(key_name);
|
|
||||||
m_host_interface->getQSettings().setValue(m_setting_name, m_current_binding_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
stopListeningForInput();
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputButtonBindingWidget::onPressed()
|
|
||||||
{
|
|
||||||
if (isListeningForInput())
|
|
||||||
stopListeningForInput();
|
|
||||||
|
|
||||||
startListeningForInput();
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputButtonBindingWidget::onInputListenTimerTimeout()
|
|
||||||
{
|
|
||||||
m_input_listen_remaining_seconds--;
|
|
||||||
if (m_input_listen_remaining_seconds == 0)
|
|
||||||
{
|
|
||||||
stopListeningForInput();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setText(tr("Push Button... [%1]").arg(m_input_listen_remaining_seconds));
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputButtonBindingWidget::startListeningForInput()
|
|
||||||
{
|
|
||||||
m_input_listen_timer = new QTimer(this);
|
|
||||||
m_input_listen_timer->setSingleShot(false);
|
|
||||||
m_input_listen_timer->start(1000);
|
|
||||||
|
|
||||||
m_input_listen_timer->connect(m_input_listen_timer, &QTimer::timeout, this,
|
|
||||||
&InputButtonBindingWidget::onInputListenTimerTimeout);
|
|
||||||
m_input_listen_remaining_seconds = 5;
|
|
||||||
setText(tr("Push Button... [%1]").arg(m_input_listen_remaining_seconds));
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputButtonBindingWidget::stopListeningForInput()
|
|
||||||
{
|
|
||||||
setText(m_current_binding_value);
|
|
||||||
delete m_input_listen_timer;
|
|
||||||
m_input_listen_timer = nullptr;
|
|
||||||
}
|
|
||||||
|
|
|
@ -45,33 +45,3 @@ private:
|
||||||
|
|
||||||
std::array<PortSettingsUI, 2> m_port_ui = {};
|
std::array<PortSettingsUI, 2> m_port_ui = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
class InputButtonBindingWidget : public QPushButton
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
InputButtonBindingWidget(QtHostInterface* host_interface, QString setting_name, ControllerType controller_type,
|
|
||||||
QWidget* parent);
|
|
||||||
~InputButtonBindingWidget();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void keyPressEvent(QKeyEvent* event) override;
|
|
||||||
void keyReleaseEvent(QKeyEvent* event) override;
|
|
||||||
|
|
||||||
private Q_SLOTS:
|
|
||||||
void onPressed();
|
|
||||||
void onInputListenTimerTimeout();
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool isListeningForInput() const { return m_input_listen_timer != nullptr; }
|
|
||||||
void startListeningForInput();
|
|
||||||
void stopListeningForInput();
|
|
||||||
|
|
||||||
QtHostInterface* m_host_interface;
|
|
||||||
QString m_setting_name;
|
|
||||||
QString m_current_binding_value;
|
|
||||||
ControllerType m_controller_type;
|
|
||||||
QTimer* m_input_listen_timer = nullptr;
|
|
||||||
u32 m_input_listen_remaining_seconds = 0;
|
|
||||||
};
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "qthostinterface.h"
|
#include "qthostinterface.h"
|
||||||
#include "YBaseLib/Log.h"
|
#include "YBaseLib/Log.h"
|
||||||
|
#include "YBaseLib/String.h"
|
||||||
#include "common/null_audio_stream.h"
|
#include "common/null_audio_stream.h"
|
||||||
#include "core/controller.h"
|
#include "core/controller.h"
|
||||||
#include "core/game_list.h"
|
#include "core/game_list.h"
|
||||||
|
@ -198,6 +199,12 @@ void QtHostInterface::doUpdateInputMap()
|
||||||
{
|
{
|
||||||
m_keyboard_input_handlers.clear();
|
m_keyboard_input_handlers.clear();
|
||||||
|
|
||||||
|
updateControllerInputMap();
|
||||||
|
updateHotkeyInputMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QtHostInterface::updateControllerInputMap()
|
||||||
|
{
|
||||||
for (u32 controller_index = 0; controller_index < 2; controller_index++)
|
for (u32 controller_index = 0; controller_index < 2; controller_index++)
|
||||||
{
|
{
|
||||||
const ControllerType ctype = m_settings.controller_types[controller_index];
|
const ControllerType ctype = m_settings.controller_types[controller_index];
|
||||||
|
@ -212,38 +219,102 @@ void QtHostInterface::doUpdateInputMap()
|
||||||
if (!var.isValid())
|
if (!var.isValid())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto handler = [this, controller_index, button_code](bool pressed) {
|
addButtonToInputMap(var.toString(), [this, controller_index, button_code](bool pressed) {
|
||||||
if (!m_system)
|
if (!m_system)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Controller* controller = m_system->GetController(controller_index);
|
Controller* controller = m_system->GetController(controller_index);
|
||||||
if (controller)
|
if (controller)
|
||||||
controller->SetButtonState(button_code, pressed);
|
controller->SetButtonState(button_code, pressed);
|
||||||
};
|
});
|
||||||
|
|
||||||
const QString value = var.toString();
|
|
||||||
const QString device = value.section('/', 0, 0);
|
|
||||||
const QString button = value.section('/', 1, 1);
|
|
||||||
if (device == QStringLiteral("Keyboard"))
|
|
||||||
{
|
|
||||||
std::optional<int> key_id = QtUtils::GetKeyIdForIdentifier(button);
|
|
||||||
if (!key_id.has_value())
|
|
||||||
{
|
|
||||||
qWarning() << "Unknown keyboard key " << button;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_keyboard_input_handlers.emplace(key_id.value(), std::move(handler));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
qWarning() << "Unknown input device: " << device;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<QtHostInterface::HotkeyInfo> QtHostInterface::getHotkeyList() const
|
||||||
|
{
|
||||||
|
std::vector<HotkeyInfo> hotkeys = {
|
||||||
|
{QStringLiteral("FastForward"), QStringLiteral("Toggle Fast Forward"), QStringLiteral("General")},
|
||||||
|
{QStringLiteral("Fullscreen"), QStringLiteral("Toggle Fullscreen"), QStringLiteral("General")},
|
||||||
|
{QStringLiteral("Pause"), QStringLiteral("Toggle Pause"), QStringLiteral("General")}};
|
||||||
|
|
||||||
|
for (u32 i = 1; i <= NUM_SAVE_STATE_HOTKEYS; i++)
|
||||||
|
{
|
||||||
|
hotkeys.push_back(
|
||||||
|
{QStringLiteral("LoadState%1").arg(i), QStringLiteral("Load State %1").arg(i), QStringLiteral("Save States")});
|
||||||
|
}
|
||||||
|
for (u32 i = 1; i <= NUM_SAVE_STATE_HOTKEYS; i++)
|
||||||
|
{
|
||||||
|
hotkeys.push_back(
|
||||||
|
{QStringLiteral("SaveState%1").arg(i), QStringLiteral("Save State %1").arg(i), QStringLiteral("Save States")});
|
||||||
|
}
|
||||||
|
|
||||||
|
return hotkeys;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QtHostInterface::updateHotkeyInputMap()
|
||||||
|
{
|
||||||
|
auto hk = [this](const QString& hotkey_name, InputButtonHandler handler) {
|
||||||
|
QVariant var = m_qsettings.value(QStringLiteral("Hotkeys/%1").arg(hotkey_name));
|
||||||
|
if (!var.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
addButtonToInputMap(var.toString(), std::move(handler));
|
||||||
|
};
|
||||||
|
|
||||||
|
hk(QStringLiteral("FastForward"), [this](bool pressed) {
|
||||||
|
m_speed_limiter_temp_disabled = pressed;
|
||||||
|
HostInterface::UpdateSpeedLimiterState();
|
||||||
|
});
|
||||||
|
|
||||||
|
hk(QStringLiteral("Fullscreen"), [this](bool pressed) {
|
||||||
|
if (!pressed)
|
||||||
|
toggleFullscreen();
|
||||||
|
});
|
||||||
|
|
||||||
|
hk(QStringLiteral("Pause"), [this](bool pressed) {
|
||||||
|
if (!pressed)
|
||||||
|
pauseSystem(!m_paused);
|
||||||
|
});
|
||||||
|
|
||||||
|
for (u32 i = 1; i <= NUM_SAVE_STATE_HOTKEYS; i++)
|
||||||
|
{
|
||||||
|
hk(QStringLiteral("LoadState%1").arg(i), [this, i](bool pressed) {
|
||||||
|
if (!pressed)
|
||||||
|
HostInterface::LoadState(TinyString::FromFormat("savestate_%u.bin", i));
|
||||||
|
});
|
||||||
|
|
||||||
|
hk(QStringLiteral("SaveState%1").arg(i), [this, i](bool pressed) {
|
||||||
|
if (!pressed)
|
||||||
|
HostInterface::SaveState(TinyString::FromFormat("savestate_%u.bin", i));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QtHostInterface::addButtonToInputMap(const QString& binding, InputButtonHandler handler)
|
||||||
|
{
|
||||||
|
const QString device = binding.section('/', 0, 0);
|
||||||
|
const QString button = binding.section('/', 1, 1);
|
||||||
|
if (device == QStringLiteral("Keyboard"))
|
||||||
|
{
|
||||||
|
std::optional<int> key_id = QtUtils::GetKeyIdForIdentifier(button);
|
||||||
|
if (!key_id.has_value())
|
||||||
|
{
|
||||||
|
qWarning() << "Unknown keyboard key " << button;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_keyboard_input_handlers.emplace(key_id.value(), std::move(handler));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qWarning() << "Unknown input device: " << device;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QtHostInterface::updateFullscreen() {}
|
||||||
|
|
||||||
void QtHostInterface::powerOffSystem()
|
void QtHostInterface::powerOffSystem()
|
||||||
{
|
{
|
||||||
if (!isOnWorkerThread())
|
if (!isOnWorkerThread())
|
||||||
|
@ -295,6 +366,18 @@ void QtHostInterface::pauseSystem(bool paused)
|
||||||
|
|
||||||
void QtHostInterface::changeDisc(QString new_disc_filename) {}
|
void QtHostInterface::changeDisc(QString new_disc_filename) {}
|
||||||
|
|
||||||
|
void QtHostInterface::toggleFullscreen()
|
||||||
|
{
|
||||||
|
if (!isOnWorkerThread())
|
||||||
|
{
|
||||||
|
QMetaObject::invokeMethod(this, "toggleFullscreen", Qt::QueuedConnection);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_settings.display_fullscreen = !m_settings.display_fullscreen;
|
||||||
|
updateFullscreen();
|
||||||
|
}
|
||||||
|
|
||||||
void QtHostInterface::doBootSystem(QString initial_filename, QString initial_save_state_filename)
|
void QtHostInterface::doBootSystem(QString initial_filename, QString initial_save_state_filename)
|
||||||
{
|
{
|
||||||
if (!m_display_window->initializeDeviceContext())
|
if (!m_display_window->initializeDeviceContext())
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
class QWidget;
|
class QWidget;
|
||||||
|
|
||||||
|
@ -49,6 +51,14 @@ public:
|
||||||
void updateInputMap();
|
void updateInputMap();
|
||||||
void handleKeyEvent(int key, bool pressed);
|
void handleKeyEvent(int key, bool pressed);
|
||||||
|
|
||||||
|
struct HotkeyInfo
|
||||||
|
{
|
||||||
|
QString name;
|
||||||
|
QString display_name;
|
||||||
|
QString category;
|
||||||
|
};
|
||||||
|
std::vector<HotkeyInfo> getHotkeyList() const;
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void emulationStarting();
|
void emulationStarting();
|
||||||
void emulationStarted();
|
void emulationStarted();
|
||||||
|
@ -61,6 +71,7 @@ public Q_SLOTS:
|
||||||
void resetSystem();
|
void resetSystem();
|
||||||
void pauseSystem(bool paused);
|
void pauseSystem(bool paused);
|
||||||
void changeDisc(QString new_disc_filename);
|
void changeDisc(QString new_disc_filename);
|
||||||
|
void toggleFullscreen();
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void doStopThread();
|
void doStopThread();
|
||||||
|
@ -70,6 +81,13 @@ private Q_SLOTS:
|
||||||
void onDisplayWindowResized(int width, int height);
|
void onDisplayWindowResized(int width, int height);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
using InputButtonHandler = std::function<void(bool)>;
|
||||||
|
|
||||||
|
enum : u32
|
||||||
|
{
|
||||||
|
NUM_SAVE_STATE_HOTKEYS = 8
|
||||||
|
};
|
||||||
|
|
||||||
class Thread : public QThread
|
class Thread : public QThread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -85,6 +103,10 @@ private:
|
||||||
|
|
||||||
void checkSettings();
|
void checkSettings();
|
||||||
void createGameList();
|
void createGameList();
|
||||||
|
void updateControllerInputMap();
|
||||||
|
void updateHotkeyInputMap();
|
||||||
|
void addButtonToInputMap(const QString& binding, InputButtonHandler handler);
|
||||||
|
void updateFullscreen();
|
||||||
void createThread();
|
void createThread();
|
||||||
void stopThread();
|
void stopThread();
|
||||||
void threadEntryPoint();
|
void threadEntryPoint();
|
||||||
|
@ -100,5 +122,5 @@ private:
|
||||||
std::atomic_bool m_shutdown_flag{false};
|
std::atomic_bool m_shutdown_flag{false};
|
||||||
|
|
||||||
// input key maps, todo hotkeys
|
// input key maps, todo hotkeys
|
||||||
std::map<int, std::function<void(bool)>> m_keyboard_input_handlers;
|
std::map<int, InputButtonHandler> m_keyboard_input_handlers;
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "consolesettingswidget.h"
|
#include "consolesettingswidget.h"
|
||||||
#include "gamelistsettingswidget.h"
|
#include "gamelistsettingswidget.h"
|
||||||
#include "gpusettingswidget.h"
|
#include "gpusettingswidget.h"
|
||||||
|
#include "hotkeysettingswidget.h"
|
||||||
#include "portsettingswidget.h"
|
#include "portsettingswidget.h"
|
||||||
#include "qthostinterface.h"
|
#include "qthostinterface.h"
|
||||||
#include <QtWidgets/QTextEdit>
|
#include <QtWidgets/QTextEdit>
|
||||||
|
@ -11,17 +12,19 @@ SettingsDialog::SettingsDialog(QtHostInterface* host_interface, QWidget* parent
|
||||||
{
|
{
|
||||||
m_ui.setupUi(this);
|
m_ui.setupUi(this);
|
||||||
|
|
||||||
m_console_settings = new ConsoleSettingsWidget(host_interface, m_ui.settingsContainer);
|
|
||||||
m_game_list_settings = new GameListSettingsWidget(host_interface, m_ui.settingsContainer);
|
m_game_list_settings = new GameListSettingsWidget(host_interface, m_ui.settingsContainer);
|
||||||
|
m_hotkey_settings = new HotkeySettingsWidget(host_interface, m_ui.settingsContainer);
|
||||||
|
m_console_settings = new ConsoleSettingsWidget(host_interface, m_ui.settingsContainer);
|
||||||
m_port_settings = new PortSettingsWidget(host_interface, m_ui.settingsContainer);
|
m_port_settings = new PortSettingsWidget(host_interface, m_ui.settingsContainer);
|
||||||
m_gpu_settings = new GPUSettingsWidget(host_interface, m_ui.settingsContainer);
|
m_gpu_settings = new GPUSettingsWidget(host_interface, m_ui.settingsContainer);
|
||||||
m_audio_settings = new QWidget(m_ui.settingsContainer);
|
m_audio_settings = new QWidget(m_ui.settingsContainer);
|
||||||
|
|
||||||
m_ui.settingsContainer->insertWidget(0, m_console_settings);
|
m_ui.settingsContainer->insertWidget(0, m_game_list_settings);
|
||||||
m_ui.settingsContainer->insertWidget(1, m_game_list_settings);
|
m_ui.settingsContainer->insertWidget(1, m_hotkey_settings);
|
||||||
m_ui.settingsContainer->insertWidget(2, m_port_settings);
|
m_ui.settingsContainer->insertWidget(2, m_console_settings);
|
||||||
m_ui.settingsContainer->insertWidget(3, m_gpu_settings);
|
m_ui.settingsContainer->insertWidget(3, m_port_settings);
|
||||||
m_ui.settingsContainer->insertWidget(4, m_audio_settings);
|
m_ui.settingsContainer->insertWidget(4, m_gpu_settings);
|
||||||
|
m_ui.settingsContainer->insertWidget(5, m_audio_settings);
|
||||||
|
|
||||||
m_ui.settingsCategory->setCurrentRow(0);
|
m_ui.settingsCategory->setCurrentRow(0);
|
||||||
m_ui.settingsContainer->setCurrentIndex(0);
|
m_ui.settingsContainer->setCurrentIndex(0);
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QtWidgets/QDialog>
|
|
||||||
#include "ui_settingsdialog.h"
|
#include "ui_settingsdialog.h"
|
||||||
|
#include <QtWidgets/QDialog>
|
||||||
|
|
||||||
class QtHostInterface;
|
class QtHostInterface;
|
||||||
|
|
||||||
|
class GameListSettingsWidget;
|
||||||
|
class HotkeySettingsWidget;
|
||||||
class ConsoleSettingsWidget;
|
class ConsoleSettingsWidget;
|
||||||
|
class PortSettingsWidget;
|
||||||
|
class GPUSettingsWidget;
|
||||||
|
|
||||||
class SettingsDialog : public QDialog
|
class SettingsDialog : public QDialog
|
||||||
{
|
{
|
||||||
|
@ -14,15 +18,16 @@ class SettingsDialog : public QDialog
|
||||||
public:
|
public:
|
||||||
enum class Category
|
enum class Category
|
||||||
{
|
{
|
||||||
ConsoleSettings,
|
|
||||||
GameListSettings,
|
GameListSettings,
|
||||||
|
HotkeySettings,
|
||||||
|
ConsoleSettings,
|
||||||
PortSettings,
|
PortSettings,
|
||||||
GPUSettings,
|
GPUSettings,
|
||||||
AudioSettings,
|
AudioSettings,
|
||||||
Count
|
Count
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit SettingsDialog(QtHostInterface* host_interface, QWidget* parent = nullptr);
|
SettingsDialog(QtHostInterface* host_interface, QWidget* parent = nullptr);
|
||||||
~SettingsDialog();
|
~SettingsDialog();
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
|
@ -36,10 +41,10 @@ private:
|
||||||
|
|
||||||
QtHostInterface* m_host_interface;
|
QtHostInterface* m_host_interface;
|
||||||
|
|
||||||
|
GameListSettingsWidget* m_game_list_settings = nullptr;
|
||||||
|
HotkeySettingsWidget* m_hotkey_settings = nullptr;
|
||||||
ConsoleSettingsWidget* m_console_settings = nullptr;
|
ConsoleSettingsWidget* m_console_settings = nullptr;
|
||||||
QWidget* m_game_list_settings = nullptr;
|
PortSettingsWidget* m_port_settings = nullptr;
|
||||||
QWidget* m_port_settings = nullptr;
|
GPUSettingsWidget* m_gpu_settings = nullptr;
|
||||||
QWidget* m_cpu_settings = nullptr;
|
|
||||||
QWidget* m_gpu_settings = nullptr;
|
|
||||||
QWidget* m_audio_settings = nullptr;
|
QWidget* m_audio_settings = nullptr;
|
||||||
};
|
};
|
||||||
|
|
|
@ -40,15 +40,6 @@
|
||||||
<height>32</height>
|
<height>32</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>Console Settings</string>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset resource="icons.qrc">
|
|
||||||
<normaloff>:/icons/utilities-system-monitor.png</normaloff>:/icons/utilities-system-monitor.png</iconset>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
<item>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Game List Settings</string>
|
<string>Game List Settings</string>
|
||||||
|
@ -58,6 +49,24 @@
|
||||||
<normaloff>:/icons/folder-open.png</normaloff>:/icons/folder-open.png</iconset>
|
<normaloff>:/icons/folder-open.png</normaloff>:/icons/folder-open.png</iconset>
|
||||||
</property>
|
</property>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Hotkey Settings</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="icons.qrc">
|
||||||
|
<normaloff>:/icons/applications-other.png</normaloff>:/icons/applications-other.png</iconset>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Console Settings</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="icons.qrc">
|
||||||
|
<normaloff>:/icons/utilities-system-monitor.png</normaloff>:/icons/utilities-system-monitor.png</iconset>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Port Settings</string>
|
<string>Port Settings</string>
|
||||||
|
|
Loading…
Reference in New Issue