Merge pull request #56 from Robbi-Blechdose/master

Add ability to switch layouts via joystick buttons
This commit is contained in:
Mathias Panzenböck
2023-05-16 19:59:45 +02:00
committed by GitHub
12 changed files with 92 additions and 14 deletions

View File

@ -6,6 +6,7 @@ Button::Button( int i, QObject *parent ) : QObject(parent) {
isButtonPressed = false; isButtonPressed = false;
isDown = false; isDown = false;
rapidfire = false; rapidfire = false;
hasLayout = false;
toDefault(); toDefault();
tick = 0; tick = 0;
} }
@ -18,7 +19,7 @@ bool Button::read( QTextStream &stream ) {
// at this point, toDefault() has just been called. // at this point, toDefault() has just been called.
//read in a line of text and break it into words //read in a line of text and break it into words
QString input = stream.readLine().toLower(); QString input = stream.readLine();
QRegExp regex("[\\s,]+"); QRegExp regex("[\\s,]+");
QStringList words = input.split(regex); QStringList words = input.split(regex);
@ -29,7 +30,7 @@ bool Button::read( QTextStream &stream ) {
//go through every word on the line describing this button. //go through every word on the line describing this button.
for ( QStringList::Iterator it = words.begin(); it != words.end(); ++it ) { for ( QStringList::Iterator it = words.begin(); it != words.end(); ++it ) {
if (*it == "mouse") { if (QString::compare(*it, "mouse", Qt::CaseInsensitive) == 0) {
++it; ++it;
if (it == words.end()) return false; if (it == words.end()) return false;
val = (*it).toInt(&ok); val = (*it).toInt(&ok);
@ -39,7 +40,7 @@ bool Button::read( QTextStream &stream ) {
} }
else return false; else return false;
} }
else if (*it == "key") { else if (QString::compare(*it, "key", Qt::CaseInsensitive) == 0) {
++it; ++it;
if (it == words.end()) return false; if (it == words.end()) return false;
val = (*it).toInt(&ok); val = (*it).toInt(&ok);
@ -49,10 +50,16 @@ bool Button::read( QTextStream &stream ) {
} }
else return false; else return false;
} }
else if (*it == "rapidfire") { else if (QString::compare(*it, "layout", Qt::CaseInsensitive) == 0) {
++it;
if (it == words.end()) return false;
layout = (*it).replace("\\s", " ");
hasLayout = true;
}
else if (QString::compare(*it, "rapidfire", Qt::CaseInsensitive) == 0) {
rapidfire = true; rapidfire = true;
} }
else if (*it == "sticky") { else if (QString::compare(*it, "sticky", Qt::CaseInsensitive) == 0) {
sticky = true; sticky = true;
} }
} }
@ -63,7 +70,9 @@ void Button::write( QTextStream &stream ) {
stream << "\tButton " << (index+1) << ": "; stream << "\tButton " << (index+1) << ": ";
if (rapidfire) stream << "rapidfire, "; if (rapidfire) stream << "rapidfire, ";
if (sticky) stream << "sticky, "; if (sticky) stream << "sticky, ";
stream << (useMouse ? "mouse " : "key ") << keycode << "\n"; stream << (useMouse ? "mouse " : "key ") << keycode;
if (hasLayout) stream << " layout " << layout.replace(" ", "\\s");
stream << "\n";
} }
void Button::release() { void Button::release() {
@ -74,6 +83,18 @@ void Button::release() {
} }
void Button::jsevent( int value ) { void Button::jsevent( int value ) {
if (hasLayout) {
if (value == 1 && !isButtonPressed) {
isButtonPressed = 1;
//Change layout
emit loadLayout(layout);
}
else if (value == 0) {
isButtonPressed = 0;
}
return;
}
bool newval = (value == 1); bool newval = (value == 1);
if (sticky) { if (sticky) {
//the state of a sticky key only changes on button press, not button release. //the state of a sticky key only changes on button press, not button release.
@ -113,6 +134,7 @@ void Button::toDefault() {
sticky = false; sticky = false;
useMouse = false; useMouse = false;
keycode = 0; keycode = 0;
hasLayout = false;
timer.stop(); timer.stop();
} }
@ -120,7 +142,8 @@ bool Button::isDefault() {
return (rapidfire == false) && return (rapidfire == false) &&
(sticky == false) && (sticky == false) &&
(useMouse == false) && (useMouse == false) &&
(keycode == 0); (keycode == 0) &&
(hasLayout == false);
} }
QString Button::getName() { QString Button::getName() {
@ -128,7 +151,10 @@ QString Button::getName() {
} }
QString Button::status() { QString Button::status() {
if (useMouse) { if (hasLayout) {
return tr("%1 : %2").arg(getName(), layout);
}
else if (useMouse) {
return tr("%1 : Mouse %2").arg(getName()).arg(keycode); return tr("%1 : Mouse %2").arg(getName()).arg(keycode);
} }
else { else {

View File

@ -53,8 +53,13 @@ class Button : public QObject {
bool useMouse; bool useMouse;
int keycode; int keycode;
QTimer timer; QTimer timer;
//Layout settings
bool hasLayout;
QString layout;
public slots: public slots:
void timerCalled(); void timerCalled();
signals:
void loadLayout(QString name);
}; };
#endif #endif

View File

@ -4,7 +4,7 @@
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QVBoxLayout> #include <QVBoxLayout>
ButtonEdit::ButtonEdit(Button* butt) ButtonEdit::ButtonEdit(Button* butt, const QStringList *layoutNames)
: QDialog(0) { : QDialog(0) {
setModal(true); setModal(true);
//build the dialog! //build the dialog!
@ -28,6 +28,20 @@ ButtonEdit::ButtonEdit(Button* butt)
h->addWidget(chkRapid); h->addWidget(chkRapid);
v->addLayout(h); v->addLayout(h);
cmbLayout = new QComboBox(this);
cmbLayout->addItem(tr("[UNSET]"), QVariant(QString()));
foreach (const QString& layout, *layoutNames) {
cmbLayout->addItem(layout, layout);
}
//Keep selected layout (if any)
if (button->hasLayout) {
cmbLayout->setCurrentIndex(layoutNames->indexOf(button->layout) + 1);
}
else {
cmbLayout->setCurrentIndex(0);
}
v->addWidget(cmbLayout);
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, this); QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, this);
connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
@ -52,6 +66,13 @@ void ButtonEdit::accept() {
//if the user chose a mouse button... //if the user chose a mouse button...
button->useMouse = btnKey->choseMouse(); button->useMouse = btnKey->choseMouse();
button->keycode = btnKey->getValue(); button->keycode = btnKey->getValue();
if (cmbLayout->currentIndex() != 0) {
button->hasLayout = true;
button->layout = cmbLayout->currentText();
}
else {
button->hasLayout = false;
}
QDialog::accept(); QDialog::accept();
} }

View File

@ -4,6 +4,7 @@
#include <QPushButton> #include <QPushButton>
#include <QCheckBox> #include <QCheckBox>
#include <QDialogButtonBox> #include <QDialogButtonBox>
#include <QComboBox>
//we need to edit a Button //we need to edit a Button
#include "button.h" #include "button.h"
@ -15,7 +16,7 @@
class ButtonEdit : public QDialog { class ButtonEdit : public QDialog {
Q_OBJECT Q_OBJECT
public: public:
ButtonEdit(Button* butt); ButtonEdit(Button* butt, const QStringList *layoutNames);
void show(); void show();
protected slots: protected slots:
void accept(); void accept();
@ -23,6 +24,7 @@ class ButtonEdit : public QDialog {
Button *button; Button *button;
KeyButton *btnKey; KeyButton *btnKey;
QCheckBox *chkSticky, *chkRapid; QCheckBox *chkSticky, *chkRapid;
QComboBox *cmbLayout;
}; };

View File

@ -19,7 +19,7 @@ void ButtonWidget::update() {
} }
void ButtonWidget::mouseReleaseEvent( QMouseEvent* e ) { void ButtonWidget::mouseReleaseEvent( QMouseEvent* e ) {
ButtonEdit* be = new ButtonEdit(button); ButtonEdit* be = new ButtonEdit(button, &layoutNames);
be->exec(); be->exec();
delete be; delete be;

View File

@ -17,10 +17,11 @@ class ButtonWidget : public FlashButton {
Q_OBJECT Q_OBJECT
public: public:
ButtonWidget( Button* b, QWidget* parent); ButtonWidget( Button* b, QWidget* parent );
void jsevent( int val ); void jsevent( int val );
//reset the label to match the respective Button's current state. //reset the label to match the respective Button's current state.
void update(); void update();
QStringList layoutNames;
private: private:
void mouseReleaseEvent( QMouseEvent* e ); void mouseReleaseEvent( QMouseEvent* e );
bool on; bool on;

View File

@ -58,13 +58,14 @@ class JoyPad : public QObject {
JoyPadWidget* widget(QWidget* parent, int i); JoyPadWidget* widget(QWidget* parent, int i);
//called when the joypad is no longer being edited. //called when the joypad is no longer being edited.
void releaseWidget(); void releaseWidget();
protected:
//lookup axes and buttons. These are dictionaries to support //lookup axes and buttons. These are dictionaries to support
//layouts with different numbers of axes/buttons than the current //layouts with different numbers of axes/buttons than the current
//devices. Note that with the current layout settings, the defined //devices. Note that with the current layout settings, the defined
//buttons that don't actually exist on the device may not be contiguous. //buttons that don't actually exist on the device may not be contiguous.
QList<Axis*> axes;
QList<Button*> buttons; QList<Button*> buttons;
protected:
QList<Axis*> axes;
//the index of this device (devicenum) //the index of this device (devicenum)
int index; int index;

View File

@ -103,3 +103,9 @@ void JoyPadWidget::jsevent( const js_event& msg ) {
quickset->jsevent(msg); quickset->jsevent(msg);
} }
} }
void JoyPadWidget::updateButtonLayoutLists(const QStringList layoutNames) {
foreach (ButtonWidget *bw, buttons) {
bw->layoutNames = layoutNames;
}
}

View File

@ -26,6 +26,8 @@ class JoyPadWidget : public QWidget {
~JoyPadWidget(); ~JoyPadWidget();
//takes in an event and decides whether or not to flash anything //takes in an event and decides whether or not to flash anything
void jsevent(const js_event &msg ); void jsevent(const js_event &msg );
//Propagate changes in layout list
void updateButtonLayoutLists(const QStringList layoutNames);
public slots: public slots:
//called whenever one of the subwidgets flashes... used to determine //called whenever one of the subwidgets flashes... used to determine
//when to emit the flashed() signal. //when to emit the flashed() signal.

View File

@ -161,6 +161,10 @@ QString LayoutManager::getFileName(const QString& layoutname ) {
return QString("%1%2.lyt").arg(settingsDir, layoutname); return QString("%1%2.lyt").arg(settingsDir, layoutname);
} }
void LayoutManager::loadLayoutFromButton(QString name) {
load(name);
}
bool LayoutManager::load(const QString& name) { bool LayoutManager::load(const QString& name) {
//it's VERY easy to load NL :) //it's VERY easy to load NL :)
if (name.isNull()) { if (name.isNull()) {
@ -707,6 +711,9 @@ void LayoutManager::addJoyPad(int index, const QString& devpath) {
//if we've never seen this device before, make a new one! //if we've never seen this device before, make a new one!
if (joypad == 0) { if (joypad == 0) {
joypad = new JoyPad( index, joydev, this ); joypad = new JoyPad( index, joydev, this );
foreach (Button *button, joypad->buttons) {
connect(button, &Button::loadLayout, this, &LayoutManager::loadLayoutFromButton);
}
joypads.insert(index,joypad); joypads.insert(index,joypad);
} }
else { else {

View File

@ -43,6 +43,8 @@ class LayoutManager : public QObject {
//produces a list of the names of all the available layout. //produces a list of the names of all the available layout.
QStringList getLayoutNames() const; QStringList getLayoutNames() const;
public slots: public slots:
//This is necessary to prevent issues with the overloaded load() function
void loadLayoutFromButton(QString name);
//load a layout with a given name //load a layout with a given name
bool load(const QString& name); bool load(const QString& name);
//look for the last loaded layout and try to load that. //look for the last loaded layout and try to load that.

View File

@ -168,6 +168,11 @@ void LayoutEdit::updateLayoutList() {
cmbLayouts->setCurrentIndex(cmbLayouts->count() - 1); cmbLayouts->setCurrentIndex(cmbLayouts->count() - 1);
} }
} }
//Update layout list for all button edit widgets
for (int i = 0, n = lm->available.count(); i < n; i++) {
const QStringList layoutNames = lm->getLayoutNames();
((JoyPadWidget*)padStack->widget(i))->updateButtonLayoutLists(layoutNames);
}
} }
void LayoutEdit::updateJoypadWidgets() { void LayoutEdit::updateJoypadWidgets() {