diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..99032e3c --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +antimicro.pro.user + diff --git a/antimicro.pro b/antimicro.pro new file mode 100644 index 00000000..7166bec4 --- /dev/null +++ b/antimicro.pro @@ -0,0 +1,63 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2012-11-13T22:35:33 +# +#------------------------------------------------- + +QT += core gui + +TARGET = antimicro +TEMPLATE = app + + +SOURCES += main.cpp\ + mainwindow.cpp \ + joybuttonwidget.cpp \ + joystick.cpp \ + joybutton.cpp \ + event.cpp \ + inputdaemon.cpp \ + buttoneditdialog.cpp \ + keygrabberbutton.cpp \ + joyaxis.cpp \ + joyaxiswidget.cpp \ + joydpad.cpp \ + joydpadbutton.cpp \ + dpadbuttoneditdialog.cpp \ + axiseditdialog.cpp \ + xmlconfigreader.cpp \ + xmlconfigwriter.cpp \ + joytabwidget.cpp + +HEADERS += mainwindow.h \ + joybuttonwidget.h \ + joystick.h \ + joybutton.h \ + event.h \ + inputdaemon.h \ + buttoneditdialog.h \ + keygrabberbutton.h \ + joyaxis.h \ + joyaxiswidget.h \ + joydpad.h \ + joydpadbutton.h \ + dpadbuttoneditdialog.h \ + axiseditdialog.h \ + xmlconfigreader.h \ + xmlconfigwriter.h \ + common.h \ + joytabwidget.h + +FORMS += mainwindow.ui \ + buttoneditdialog.ui \ + dpadbuttoneditdialog.ui \ + axiseditdialog.ui + + +LIBS += -lSDL -lXtst -lX11 + +#INCLUDEPATH += $$PWD/../../../../usr/include/SDL +#DEPENDPATH += $$PWD/../../../../usr/include/SDL + +RESOURCES += \ + resources.qrc diff --git a/axiseditdialog.cpp b/axiseditdialog.cpp new file mode 100644 index 00000000..be4c5f90 --- /dev/null +++ b/axiseditdialog.cpp @@ -0,0 +1,216 @@ +#include + +#include "axiseditdialog.h" +#include "ui_axiseditdialog.h" +#include "event.h" + +AxisEditDialog::AxisEditDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::AxisEditDialog) +{ + ui->setupUi(this); + + setAttribute(Qt::WA_DeleteOnClose); + axis = 0; +} + +AxisEditDialog::AxisEditDialog(JoyAxis *axis, QWidget *parent) : + QDialog(parent), + ui(new Ui::AxisEditDialog) +{ + ui->setupUi(this); + setAttribute(Qt::WA_DeleteOnClose); + + this->axis = axis; + + this->setWindowTitle(QString("Set Axis %1").arg(axis->getRealJoyIndex())); + + if (this->axis->getAxisMode() == 0) + { + ui->comboBox->setCurrentIndex(0); + } + else + { + ui->comboBox->setCurrentIndex(axis->getMouseMode()+1); + ui->spinBox->setEnabled(true); + ui->pushButton->setEnabled(false); + ui->pushButton_2->setEnabled(false); + ui->comboBox_2->setEnabled(false); + } + + ui->spinBox->setValue(axis->getMouseSpeed()); + updateSpeedConvertLabel(axis->getMouseSpeed()); + + ui->horizontalSlider->setValue(axis->getDeadZone()); + ui->lineEdit->setText(QString::number(axis->getDeadZone())); + + ui->horizontalSlider_2->setValue(axis->getMaxZoneValue()); + ui->lineEdit_2->setText(QString::number(axis->getMaxZoneValue())); + + if (axis->getNKey() > 0) + { + int keycode = axis->getNKey(); + ui->pushButton->setValue(keycode); + if (keycode > MOUSE_OFFSET) + { + keycode -= MOUSE_OFFSET; + ui->pushButton->setText(QString("Mouse ").append(QString::number(keycode))); + } + else + { + ui->pushButton->setText(keycodeToKey(keycode).toUpper()); + } + } + + if (axis->getPKey() > 0) + { + int keycode = axis->getPKey(); + ui->pushButton_2->setValue(keycode); + if (keycode > MOUSE_OFFSET) + { + keycode -= MOUSE_OFFSET; + ui->pushButton_2->setText(QString("Mouse ").append(QString::number(keycode))); + } + else + { + ui->pushButton_2->setText(keycodeToKey(keycode).toUpper()); + } + } + + int currentThrottle = axis->getThrottle(); + ui->comboBox_2->setCurrentIndex(currentThrottle+1); + if (currentThrottle == -1) + { + ui->pushButton->setEnabled(true); + ui->pushButton_2->setEnabled(false); + } + else if (currentThrottle == 1) + { + ui->pushButton_2->setEnabled(true); + ui->pushButton->setEnabled(false); + } + + connect(this, SIGNAL(accepted()), this, SLOT(saveAxisChanges())); + connect(ui->comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateModeUi(int))); + connect(ui->spinBox, SIGNAL(valueChanged(int)), this, SLOT(updateSpeedConvertLabel(int))); + connect(ui->horizontalSlider, SIGNAL(valueChanged(int)), this, SLOT(updateDeadZoneBox(int))); + connect(ui->horizontalSlider_2, SIGNAL(valueChanged(int)), this, SLOT(updateMaxZoneBox(int))); + connect(ui->comboBox_2, SIGNAL(currentIndexChanged(int)), this, SLOT(updateThrottleUi(int))); +} + +void AxisEditDialog::saveAxisChanges() +{ + if (ui->pushButton->getValue() >= 0) + { + int keycode = ui->pushButton->getValue(); + if (keycode == 0) + { + axis->setNKey(keycode); + } + else if (keycode <= MOUSE_OFFSET) + { + axis->setNKey(keycode); + } + else + { + axis->setNKey(keycode); + } + } + + if (ui->pushButton_2->getValue() >= 0) + { + int keycode = ui->pushButton_2->getValue(); + if (keycode == 0) + { + axis->setPKey(keycode); + } + else if (keycode <= MOUSE_OFFSET) + { + axis->setPKey(keycode); + } + else + { + axis->setPKey(keycode); + } + } + + axis->setDeadZone(ui->horizontalSlider->value()); + axis->setMaxZoneValue(ui->horizontalSlider_2->value()); + + if (ui->comboBox->currentIndex() == 0) + { + axis->setAxisMode(0); + } + else + { + axis->setAxisMode(1); + axis->setMouseMode(ui->comboBox->currentIndex() - 1); + axis->setMouseSpeed(ui->spinBox->value()); + } + + int currentThrottle = 0; + if (ui->comboBox_2->isEnabled()) + { + currentThrottle = ui->comboBox_2->currentIndex() - 1; + } + axis->setThrottle(currentThrottle); +} + +void AxisEditDialog::updateModeUi(int index) +{ + if (index > 0) + { + ui->spinBox->setEnabled(true); + ui->pushButton->setEnabled(false); + ui->pushButton_2->setEnabled(false); + ui->comboBox_2->setEnabled(false); + } + else + { + ui->spinBox->setEnabled(false); + ui->pushButton->setEnabled(true); + ui->pushButton_2->setEnabled(true); + ui->comboBox_2->setEnabled(true); + } +} + +void AxisEditDialog::updateDeadZoneBox(int value) +{ + ui->lineEdit->setText(QString::number(value)); +} + +void AxisEditDialog::updateMaxZoneBox(int value) +{ + ui->lineEdit_2->setText(QString::number(value)); +} + +void AxisEditDialog::updateSpeedConvertLabel(int value) +{ + QString label = QString (QString::number(value)); + label = label.append(" = ").append(QString::number(JoyAxis::JOYSPEED * value)).append(" pps"); + ui->label_5->setText(label); +} + +void AxisEditDialog::updateThrottleUi(int index) +{ + if (index == 0) + { + ui->pushButton->setEnabled(true); + ui->pushButton_2->setEnabled(false); + } + else if (index == 1) + { + ui->pushButton->setEnabled(true); + ui->pushButton_2->setEnabled(true); + } + else if (index == 2) + { + ui->pushButton_2->setEnabled(true); + ui->pushButton->setEnabled(false); + } +} + +AxisEditDialog::~AxisEditDialog() +{ + delete ui; +} diff --git a/axiseditdialog.h b/axiseditdialog.h new file mode 100644 index 00000000..e6f0c452 --- /dev/null +++ b/axiseditdialog.h @@ -0,0 +1,36 @@ +#ifndef AXISEDITDIALOG_H +#define AXISEDITDIALOG_H + +#include + +#include "joyaxis.h" + +namespace Ui { +class AxisEditDialog; +} + +class AxisEditDialog : public QDialog +{ + Q_OBJECT + +public: + explicit AxisEditDialog(QWidget *parent = 0); + AxisEditDialog(JoyAxis *axis, QWidget *parent=0); + ~AxisEditDialog(); + +protected: + JoyAxis *axis; + +private: + Ui::AxisEditDialog *ui; + +private slots: + void saveAxisChanges(); + void updateModeUi(int index); + void updateDeadZoneBox(int value); + void updateMaxZoneBox(int value); + void updateSpeedConvertLabel(int value); + void updateThrottleUi(int index); +}; + +#endif // AXISEDITDIALOG_H diff --git a/axiseditdialog.ui b/axiseditdialog.ui new file mode 100644 index 00000000..d25cccad --- /dev/null +++ b/axiseditdialog.ui @@ -0,0 +1,411 @@ + + + AxisEditDialog + + + + 0 + 0 + 419 + 233 + + + + + 0 + 0 + + + + + 419 + 233 + + + + Axis + + + false + + + true + + + + QLayout::SetDefaultConstraint + + + + + 20 + + + + + 10 + + + + + 1 + + + Mode: + + + + + + + false + + + false + + + 5 + + + 5 + + + + Keyboard + + + + + Mouse (Horizontal) + + + + + Mouse (Inverted Horizontal) + + + + + Mouse (Vertical) + + + + + Mouse (Inverted Vertical) + + + + + + + + + + + + Mouse Speed: + + + + + + + false + + + false + + + true + + + QAbstractSpinBox::PlusMinus + + + 1 + + + 50 + + + + + + + + + + + + 0 + 0 + + + + + 16777215 + 20 + + + + 1 = 20 pps + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + 10 + + + 10 + + + + + 0 + + + 32000 + + + 100 + + + 1000 + + + 30000 + + + Qt::Horizontal + + + QSlider::NoTicks + + + 1000 + + + + + + + Dead Zone: + + + + + + + true + + + + 0 + 0 + + + + + 100 + 16777215 + + + + 5000 + + + true + + + + + + + + 0 + 0 + + + + + 100 + 16777215 + + + + 30000 + + + true + + + + + + + Max Zone: + + + + + + + 0 + + + 32000 + + + 100 + + + 1000 + + + 5000 + + + 5000 + + + true + + + Qt::Horizontal + + + false + + + false + + + QSlider::NoTicks + + + 1000 + + + + + + + + + + + [NO KEY] + + + + + + + 1 + + + 3 + + + 3 + + + + Negative Throttle + + + + + Normal + + + + + Positive Throttle + + + + + + + + [NO KEY] + + + + + + + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + false + + + + + buttonBox + line + + label_5 + + + + KeyGrabberButton + QPushButton +
keygrabberbutton.h
+
+
+ + + + buttonBox + accepted() + AxisEditDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + AxisEditDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + +
diff --git a/buttoneditdialog.cpp b/buttoneditdialog.cpp new file mode 100644 index 00000000..6d6eb723 --- /dev/null +++ b/buttoneditdialog.cpp @@ -0,0 +1,150 @@ +#include + +#include "buttoneditdialog.h" +#include "ui_buttoneditdialog.h" +#include "event.h" + +ButtonEditDialog::ButtonEditDialog(JoyButton *button, QWidget *parent) : + QDialog(parent), + ui(new Ui::ButtonEditDialog) +{ + ui->setupUi(this); + setAttribute(Qt::WA_DeleteOnClose); + + this->button = button; + this->setWindowTitle(QString("Set ").append(button->getPartialName())); + isEditing = false; + + defaultLabel = QString ("Click below to change key or mouse button for "); + QString currentlabel = defaultLabel; + ui->label->setText(currentlabel.append(button->getPartialName())); + + ui->pushButton->setText("[NO KEY]"); + if (button->getKey() > 0 && button->getKey() <= MOUSE_OFFSET) + { + ui->pushButton->setText(keycodeToKey(button->getKey()).toUpper()); + ui->pushButton->setValue(button->getKey()); + } + else if (button->getMouse() > 0) + { + ui->pushButton->setText(QString("Mouse %1").arg(button->getMouse())); + ui->pushButton->setValue(button->getMouse() + MOUSE_OFFSET); + } + + if (button->getToggleState()) + { + ui->checkBox_2->setChecked(true); + } + + if (button->isUsingTurbo()) + { + int interval = (int)(button->getTurboInterval() / 100); + this->changeTurboText(interval); + ui->checkBox->setChecked(true); + ui->horizontalSlider->setEnabled(true); + ui->horizontalSlider->setValue(interval); + } + else + { + int interval = (int)(button->getTurboInterval() / 100); + this->changeTurboText(interval); + ui->checkBox->setChecked(false); + ui->horizontalSlider->setValue(interval); + } + + connect (ui->buttonBox, SIGNAL(accepted()), this, SLOT(saveButtonChanges())); + connect (ui->buttonBox, SIGNAL(rejected()), this, SLOT(close())); + connect (ui->pushButton, SIGNAL(clicked()), this, SLOT(changeDialogText())); + connect(ui->checkBox, SIGNAL(clicked(bool)), ui->horizontalSlider, SLOT(setEnabled(bool))); + connect(ui->pushButton, SIGNAL(grabFinished(bool)), this, SLOT(changeDialogText(bool))); + connect(ui->pushButton, SIGNAL(grabFinished(bool)), this, SLOT(enableDialogButtons())); + connect(ui->pushButton, SIGNAL(grabStarted()), this, SLOT(disableDialogButtons())); + connect(ui->horizontalSlider, SIGNAL(valueChanged(int)), this, SLOT(changeTurboText(int))); + //connect(ui->pushButton, SIGNAL(mouseCode(int)), this, SLOT(changeMouseSetting(int))); +} + +ButtonEditDialog::~ButtonEditDialog() +{ + delete ui; +} + +void ButtonEditDialog::saveButtonChanges() +{ + button->reset (); + + if (ui->pushButton->getValue() >= 0) + { + int keycode = ui->pushButton->getValue(); + if (keycode == 0) + { + button->setKey(keycode); + } + else if (keycode <= MOUSE_OFFSET) + { + button->setKey(keycode); + } + else + { + button->setMouse(keycode - MOUSE_OFFSET); + button->setUseMouse(true); + } + } + + int turboInterval = ui->horizontalSlider->value() * 100; + button->setTurboInterval(turboInterval); + + if (ui->checkBox->isChecked()) + { + button->setUseTurbo(true); + } + + if (ui->checkBox_2->isChecked()) + { + button->setToggle(true); + } + + //button->joyEvent(false); + this->close(); +} + +void ButtonEditDialog::changeDialogText(bool edited) +{ + isEditing = !isEditing; + + if (edited) + { + QString label = defaultLabel; + label = label.append(button->getPartialName()); + ui->label->setText(label); + } + else + { + if (isEditing) + { + QString label = QString ("Choose a new key or mouse button for "); + label = label.append(button->getPartialName()); + ui->label->setText(label); + } + } +} + +void ButtonEditDialog::changeTurboText(int value) +{ + if (value == 0) + { + value = 1; + } + double clicks = 100 / (value * 10.0); + QString labeltext = QString(QString::number(clicks, 'g', 2)).append("/sec."); + ui->label_3->setText(labeltext); +} + +void ButtonEditDialog::enableDialogButtons() +{ + ui->buttonBox->setEnabled(true); +} + +void ButtonEditDialog::disableDialogButtons() +{ + ui->buttonBox->setEnabled(false); +} diff --git a/buttoneditdialog.h b/buttoneditdialog.h new file mode 100644 index 00000000..ebb1bd08 --- /dev/null +++ b/buttoneditdialog.h @@ -0,0 +1,43 @@ +#ifndef BUTTONEDITDIALOG_H +#define BUTTONEDITDIALOG_H + +#include + +#include "joybutton.h" +#include "joydpadbutton.h" + +namespace Ui { +class ButtonEditDialog; +} + +class ButtonEditDialog : public QDialog +{ + Q_OBJECT + +public: + explicit ButtonEditDialog(JoyButton* button, QWidget *parent=0); + ~ButtonEditDialog(); + +private: + Ui::ButtonEditDialog *ui; + +protected: + JoyButton* button; + bool isEditing; + QString defaultLabel; + +signals: + +public slots: + + +private slots: + void saveButtonChanges(); + void changeDialogText(bool edited=false); + void changeTurboText(int value); + void disableDialogButtons(); + void enableDialogButtons(); + //void enableTurboSlider(bool enable); +}; + +#endif // BUTTONEDITDIALOG_H diff --git a/buttoneditdialog.ui b/buttoneditdialog.ui new file mode 100644 index 00000000..cf377e22 --- /dev/null +++ b/buttoneditdialog.ui @@ -0,0 +1,278 @@ + + + ButtonEditDialog + + + Qt::NonModal + + + true + + + + 0 + 0 + 450 + 250 + + + + + 0 + 0 + + + + + 450 + 250 + + + + + 450 + 250 + + + + Button + + + false + + + true + + + + + + + 0 + 0 + + + + + 0 + 30 + + + + + 16777215 + 30 + + + + + 11 + + + + ClickButton 1 + + + Qt::AlignCenter + + + false + + + + + + + + 0 + 0 + + + + + 200 + 40 + + + + + 200 + 40 + + + + Qt::WheelFocus + + + Qt::LeftToRight + + + false + + + [NO KEY] + + + false + + + false + + + true + + + false + + + false + + + + + + + 10 + + + 10 + + + 10 + + + 10 + + + + + Toggle + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Turbo + + + + + + + + + + + Rate: + + + + + + + false + + + 1 + + + 20 + + + 5 + + + Qt::Horizontal + + + false + + + false + + + + + + + 10/sec. + + + + + + + + + Qt::Horizontal + + + + + + + 10 + + + 0 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + false + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + true + + + + + + + + + + KeyGrabberButton + QPushButton +
keygrabberbutton.h
+
+
+ + + + saveButtonChanges() + +
diff --git a/common.h b/common.h new file mode 100644 index 00000000..a7b22d2c --- /dev/null +++ b/common.h @@ -0,0 +1,15 @@ +#ifndef COMMON_H +#define COMMON_H + +#include +#include +#include + +namespace PadderCommon +{ + const QString configPath = QDir::homePath() + "/.antimicro"; + const QString configFileName = "antimicro_settings.ini"; + const QString configFilePath = configPath + "/" + configFileName; +} + +#endif // COMMON_H diff --git a/dpadbuttoneditdialog.cpp b/dpadbuttoneditdialog.cpp new file mode 100644 index 00000000..a28a68e1 --- /dev/null +++ b/dpadbuttoneditdialog.cpp @@ -0,0 +1,114 @@ +#include + +#include "dpadbuttoneditdialog.h" +#include "ui_dpadbuttoneditdialog.h" +#include "event.h" + +DPadButtonEditDialog::DPadButtonEditDialog(JoyDPadButton *button, QWidget *parent) : + QDialog(parent), + ui(new Ui::DPadButtonEditDialog) +{ + ui->setupUi(this); + + this->button = button; + this->setWindowTitle(QString("Set ").append(button->getPartialName())); + + isEditing = false; + pendingMouseCode = 0; + + if (button->getMouse() > 0) + { + pendingMouseCode = button->getMouse(); + } + + QString currentlabel = QString ("Click below to change key for "); + ui->label->setText(currentlabel.append(button->getDirectionName())); + + if (button->getKey() >= 0) + { + ui->pushButton->setText(keycodeToKey(button->getKey()).toUpper()); + } + else if (button->getMouse()) + { + ui->pushButton->setText(QString("Mouse %1").arg(button->getMouse())); + } + + if (button->getToggleState()) + { + ui->checkBox_2->setChecked(true); + } + + if (button->getTurboInterval() > 0.0) + { + ui->checkBox->setChecked(true); + } + + connect (ui->buttonBox, SIGNAL(accepted()), this, SLOT(saveButtonChanges())); + connect (ui->buttonBox, SIGNAL(rejected()), this, SLOT(close())); + connect (ui->pushButton, SIGNAL(clicked()), this, SLOT(changeDialogText())); + connect(ui->pushButton, SIGNAL(grabFinished(bool)), this, SLOT(changeDialogText(bool))); + connect(ui->pushButton, SIGNAL(mouseCode(int)), this, SLOT(changeMouseSetting(int))); +} + +DPadButtonEditDialog::~DPadButtonEditDialog() +{ + delete ui; +} + +void DPadButtonEditDialog::saveButtonChanges() +{ + button->reset (); + + if (!pendingMouseCode && ui->pushButton->text() != "") + { + int keycode = keyToKeycode(ui->pushButton->text()); + if (keycode >= 0) + { + button->setKey(keycode); + } + } + else if (pendingMouseCode > 0) + { + button->setMouse(pendingMouseCode); + } + + + if (ui->checkBox->isChecked()) + { + button->setTurboInterval(500); + } + + if (ui->checkBox_2->isChecked()) + { + button->setToggle(true); + } + + //button->joyEvent(false); + this->close(); +} + +void DPadButtonEditDialog::changeDialogText(bool edited) +{ + isEditing = !isEditing; + + if (edited) + { + QString label = QString ("Click below to change key for "); + label = label.append (button->getName()); + ui->label->setText(label); + } + else + { + if (isEditing) + { + QString label = QString ("Choose a new key or mouse button for "); + label = label.append(button->getName()); + ui->label->setText(label); + } + } +} + +void DPadButtonEditDialog::changeMouseSetting(int mousecode) +{ + pendingMouseCode = mousecode; +} diff --git a/dpadbuttoneditdialog.h b/dpadbuttoneditdialog.h new file mode 100644 index 00000000..94b52b51 --- /dev/null +++ b/dpadbuttoneditdialog.h @@ -0,0 +1,35 @@ +#ifndef DPADBUTTONEDITDIALOG_H +#define DPADBUTTONEDITDIALOG_H + +#include + +#include "joydpadbutton.h" + +namespace Ui { +class DPadButtonEditDialog; +} + +class DPadButtonEditDialog : public QDialog +{ + Q_OBJECT + +public: + explicit DPadButtonEditDialog(JoyDPadButton *button, QWidget *parent=0); + ~DPadButtonEditDialog(); + +protected: + JoyDPadButton* button; + bool isEditing; + int pendingMouseCode; + +private: + Ui::DPadButtonEditDialog *ui; + +private slots: + void saveButtonChanges(); + void changeDialogText(bool edited=false); + void changeMouseSetting(int mousecode); + +}; + +#endif // DPADBUTTONEDITDIALOG_H diff --git a/dpadbuttoneditdialog.ui b/dpadbuttoneditdialog.ui new file mode 100644 index 00000000..47d67131 --- /dev/null +++ b/dpadbuttoneditdialog.ui @@ -0,0 +1,203 @@ + + + DPadButtonEditDialog + + + + 0 + 0 + 360 + 196 + + + + Dialog + + + + + + + 0 + 0 + + + + + 0 + 30 + + + + + 16777215 + 30 + + + + + 11 + + + + ClickButton 1 + + + Qt::AlignCenter + + + false + + + + + + + + 0 + 0 + + + + + 200 + 40 + + + + + 200 + 40 + + + + Qt::ClickFocus + + + Qt::LeftToRight + + + false + + + Key + + + false + + + false + + + true + + + false + + + false + + + + + + + 10 + + + 10 + + + 10 + + + 10 + + + + + Toggle + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Turbo + + + + + + + + + 10 + + + 0 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + false + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + true + + + + + + + buttonBox + horizontalSpacer + horizontalSpacer + buttonBox + label + pushButton + layoutWidget + layoutWidget_2 + + + + KeyGrabberButton + QPushButton +
keygrabberbutton.h
+
+
+ + +
diff --git a/event.cpp b/event.cpp new file mode 100644 index 00000000..0ac57172 --- /dev/null +++ b/event.cpp @@ -0,0 +1,73 @@ +#include +#include +#include +#include + +#include "event.h" + +QMutex mutex; +Display* display; + +//actually creates an XWindows event :) +void sendevent( int code, bool pressed, JoyInputDevice device) { + //mutex.lock(); + display = QX11Info::display(); + + XLockDisplay (display); + + //qDebug () << "IN SENDEVENT: " << code << endl; + + + if (device == JoyKeyboard) + { + XTestFakeKeyEvent(display, code, pressed, 0); + } + else if (device == JoyMouse) + { + XTestFakeButtonEvent(display, code, pressed, 0); + } + + XFlush(display); + XUnlockDisplay (display); + + //mutex.unlock(); +} + +void sendevent(int code1, int code2) +{ + display = QX11Info::display(); + + XLockDisplay (display); + + XTestFakeRelativeMotionEvent(display, code1, code2, 0); + + XFlush(display); + XUnlockDisplay (display); +} + +int keyToKeycode (QString key) +{ + int tempcode = -1; + Display* display = QX11Info::display(); + if (key.length() == 1) + { + tempcode = XKeysymToKeycode(display, XStringToKeysym(key.toUtf8().data())); + } + return tempcode; +} + +QString keycodeToKey(int keycode) +{ + display = QX11Info::display(); + QString newkey; + if (keycode <= 0) + { + newkey = "[NO KEY]"; + } + else + { + newkey = XKeysymToString(XKeycodeToKeysym(display, keycode,0)); + } + + return newkey; +} diff --git a/event.h b/event.h new file mode 100644 index 00000000..6713f2cb --- /dev/null +++ b/event.h @@ -0,0 +1,13 @@ +#ifndef EVENT_H +#define EVENT_H + +#include + +enum JoyInputDevice {JoyKeyboard=0, JoyMouse}; + +void sendevent (int code, bool pressed=true, JoyInputDevice device=JoyKeyboard); +void sendevent(int code1, int code2); +int keyToKeycode (QString key); +QString keycodeToKey(int keycode); + +#endif // EVENT_H diff --git a/images/joystick_icon.png b/images/joystick_icon.png new file mode 100644 index 00000000..b55ee1e5 Binary files /dev/null and b/images/joystick_icon.png differ diff --git a/inputdaemon.cpp b/inputdaemon.cpp new file mode 100644 index 00000000..ad7ea49f --- /dev/null +++ b/inputdaemon.cpp @@ -0,0 +1,151 @@ +#include +#include +#include +#include + +#include "inputdaemon.h" + +InputDaemon::InputDaemon(QHash *joysticks, QObject *parent) : + QObject(parent) +{ + this->joysticks = joysticks; + this->stopped = true; +} + +void InputDaemon::initSDL() +{ + SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK); + SDL_JoystickEventState(SDL_ENABLE); +} + +void InputDaemon::closeSDL() +{ + SDL_Event event; + for (int i=0; i < SDL_NumJoysticks(); i++) + { + if (SDL_JoystickOpened(i) && joysticks->value(i)) + { + SDL_Joystick *handle = (joysticks->value(i))->getSDLHandle(); + SDL_JoystickClose(handle); + } + } + + // Clear any pending events + while (SDL_PollEvent(&event) > 0) + { + } + SDL_Quit(); +} + +void InputDaemon::run () +{ + stopped = false; + + initSDL(); + + refreshJoysticks(); + + if (joysticks->count() > 0) + { + SDL_Event event; + + while (SDL_PollEvent(&event) >= 0 && !stopped) + { + switch (event.type) + { + case SDL_JOYBUTTONDOWN: { + Joystick *joy = joysticks->value(event.button.which); + JoyButton *button = joy->getJoyButton(event.button.button); + button->joyEvent(true); + break; + } + + case SDL_JOYBUTTONUP: + { + Joystick *joy = joysticks->value(event.button.which); + JoyButton *button = joy->getJoyButton(event.button.button); + button->joyEvent(false); + break; + } + + case SDL_JOYAXISMOTION: { + Joystick *joy = joysticks->value(event.jaxis.which); + JoyAxis *axis = joy->getJoyAxis(event.jaxis.axis); + axis->joyEvent(event.jaxis.value); + break; + } + + case SDL_JOYHATMOTION: { + Joystick *joy = joysticks->value(event.jhat.which); + JoyDPad *dpad = joy->getJoyDPad(event.jhat.hat); + dpad->joyEvent(event.jhat.value); + + break; + } + + default: + break; + } + + QCoreApplication::processEvents(); + } + } + + closeSDL(); + + stopped = false; + + if (joysticks->count() > 0) + { + emit complete(joysticks->value(0)); + } + + emit complete(); +} + +void InputDaemon::refreshJoysticks() +{ + joysticks->clear(); + + for (int i=0; i < SDL_NumJoysticks(); i++) + { + SDL_Joystick* joystick = SDL_JoystickOpen (i); + Joystick *curJoystick = new Joystick (joystick, this); + curJoystick->refreshAxes(); + curJoystick->refreshHats(); + curJoystick->refreshButtons(); + + joysticks->insert(i, curJoystick); + } + + if (joysticks->count() > 0) + { + emit joysticksRefreshed(joysticks); + } +} + +void InputDaemon::stop() +{ + stopped = true; +} + +void InputDaemon::refresh() +{ + stop(); + // Event loop should be reached after old instance of run has finished + QTimer::singleShot(0, this, SLOT(run())); +} + +bool InputDaemon::isRunning() +{ + return stopped; +} + +void InputDaemon::refreshJoystick(Joystick *joystick) +{ + joystick->refreshAxes(); + joystick->refreshHats(); + joystick->refreshButtons(); + + emit joystickRefreshed(joystick); +} diff --git a/inputdaemon.h b/inputdaemon.h new file mode 100644 index 00000000..82ff2cce --- /dev/null +++ b/inputdaemon.h @@ -0,0 +1,38 @@ +#ifndef INPUTDAEMONTHREAD_H +#define INPUTDAEMONTHREAD_H + +#include + +#include "joystick.h" + +class InputDaemon : public QObject +{ + Q_OBJECT +public: + InputDaemon (QHash *joysticks, QObject *parent=0); + bool isRunning(); + +protected: + void initSDL(); + void closeSDL(); + + QHash *joysticks; + bool stopped; + +signals: + void joystickRefreshed (Joystick *joystick); + void joysticksRefreshed(QHash *joysticks); + void complete(Joystick* joystick); + void complete(); + +public slots: + void run (); + void stop (); + void refresh(); + void refreshJoystick(Joystick *joystick); + +private slots: + void refreshJoysticks (); +}; + +#endif // INPUTDAEMONTHREAD_H diff --git a/joyaxis.cpp b/joyaxis.cpp new file mode 100644 index 00000000..18161bb8 --- /dev/null +++ b/joyaxis.cpp @@ -0,0 +1,516 @@ +#include +#include + +#include "joyaxis.h" +#include "event.h" + +const int JoyAxis::AXISMIN = -32767; +const int JoyAxis::AXISMAX = 32767; +const int JoyAxis::AXISDEADZONE = 5000; +const int JoyAxis::AXISMAXZONE = 30000; + +// Set event interval to allow one event every 50 ms. +// Should create around 20 events per second. +// mouseSpeed * 20 will give the number of pixels per second +// the mouse cursor will move on screen +const int JoyAxis::JOYINTERVAL = 50; +// Speed in pixels/second +const float JoyAxis::JOYSPEED = 20.0; + + +JoyAxis::JoyAxis(QObject *parent) : + QObject(parent) +{ + index = 0; + deadZone = 5000; + isActive = false; + mouseSpeed = 20; + axisMode = KeyboardAxis; + timer = new QTimer (); + interval = QTime (); + eventActive = false; + currentValue = 0; + maxZoneValue = 30000; + throttle = 0; + sumDist = 0.0; + mouseOffset = 400; + lastkey = 0; + pkeycode = 0; + nkeycode = 0; +} + +JoyAxis::JoyAxis(int index, QObject *parent) : + QObject(parent) +{ + this->index = index; + deadZone = 5000; + isActive = false; + axisMode = KeyboardAxis; + mouseSpeed = 20; + timer = new QTimer (); + interval = QTime (); + eventActive = false; + currentValue = 0; + maxZoneValue = 30000; + throttle = 0; + sumDist = 0.0; + mouseOffset = 400; + lastkey = 0; + pkeycode = 0; + nkeycode = 0; +} + +void JoyAxis::joyEvent(int value) +{ + int temp = value; + if (throttle == -1) + { + value = (value + AXISMIN) / 2; + } + else if (throttle == 1) + { + value = (value + AXISMAX) / 2; + } + + bool safezone = !inDeadZone(temp); + currentValue = value; + + if (axisMode == KeyboardAxis) + { + if (safezone && !isActive) + { + isActive = eventActive = true; + emit active(value); + + createDeskEvent(); + } + else if (!safezone && isActive) + { + isActive = eventActive = false; + emit released(value); + + createDeskEvent(); + lastkey = 0; + } + } + else if (axisMode == MouseAxis) + { + if (safezone) + { + if (!isActive) + { + isActive = eventActive = true; + emit active(value); + createDeskEvent(); + + connect(timer, SIGNAL(timeout()), this, SLOT(timerEvent())); + sumDist = 0.0; + timer->start(0); + interval.start(); + } + } + else + { + isActive = eventActive = false; + interval.restart(); + timer->stop(); + sumDist = 0.0; + disconnect(timer, SIGNAL(timeout()), 0, 0); + emit released(value); + } + } + + emit moved(value); +} + +bool JoyAxis::inDeadZone(int value) +{ + bool result = false; + if (throttle == -1) + { + value = (value + AXISMIN) / 2; + } + else if (throttle == 1) + { + value = (value + AXISMAX) / 2; + } + + + if (abs(value) <= deadZone) + { + result = true; + } + + return result; +} + +QString JoyAxis::getName() +{ + QString label = QString("Axis ").append(QString::number(getRealJoyIndex())) + .append(": "); + if (axisMode == KeyboardAxis) + { + label = label.append("[KEYBOARD]"); + } + else if (axisMode == MouseAxis) + { + label = label.append("[MOUSE]"); + } + + return label; +} + +int JoyAxis::getRealJoyIndex() +{ + return index + 1; +} + +void JoyAxis::setIndex(int index) +{ + this->index = index; +} + +int JoyAxis::getIndex() +{ + return index; +} + +void JoyAxis::setPKey(int code) +{ + pkeycode = code; +} + +int JoyAxis::getPKey() +{ + return pkeycode; +} + +void JoyAxis::setNKey(int code) +{ + nkeycode = code; +} + +int JoyAxis::getNKey() +{ + return nkeycode; +} + +void JoyAxis::createDeskEvent() +{ + if (axisMode == KeyboardAxis) + { + JoyInputDevice currentMode = JoyKeyboard; + int temppkey = pkeycode; + int tempnkey = nkeycode; + + if (currentValue > deadZone) + { + if (pkeycode > mouseOffset) + { + temppkey -= mouseOffset; + currentMode = JoyMouse; + } + sendevent(temppkey, eventActive, currentMode); + lastkey = pkeycode; + } + else if (currentValue < -deadZone) + { + if (nkeycode > mouseOffset) + { + tempnkey -= mouseOffset; + currentMode = JoyMouse; + } + sendevent(tempnkey, eventActive, currentMode); + lastkey = nkeycode; + } + else if (lastkey > 0) + { + int templast = lastkey; + if (lastkey > mouseOffset) + { + templast -= mouseOffset; + currentMode = JoyMouse; + } + sendevent(templast, eventActive, currentMode); + lastkey = 0; + } + } + else if (axisMode == MouseAxis) + { + if (interval.elapsed() >= (1000.0/(mouseSpeed*JOYSPEED))) + { + float difference = (abs(currentValue) - deadZone)/(float)(maxZoneValue - deadZone); + sumDist += difference; + + int distance = (int)floor (sumDist + 0.5); + if (currentValue < 0) + { + distance = -distance; + } + + int mouse1 = 0; + int mouse2 = 0; + if (mousemode == MouseHorizontal) + { + mouse1 = distance; + } + else if (mousemode == MouseInvHorizontal) + { + mouse1 = -distance; + } + else if (mousemode == MouseVertical) + { + mouse2 = distance; + } + else if (mousemode == MouseInvVertical) + { + mouse2 = -distance; + } + + if (sumDist >= 1.0) + { + sendevent(mouse1, mouse2); + sumDist = 0.0; + } + + interval.restart(); + } + } +} + +void JoyAxis::setDeadZone(int value) +{ + deadZone = abs(value); +} + +int JoyAxis::getDeadZone() +{ + return deadZone; +} + + +void JoyAxis::setMouseMode(int mode) +{ + JoyAxisMouseMode temp = (JoyAxisMouseMode) mode; + switch (mode) { + case MouseHorizontal: + case MouseInvHorizontal: + case MouseVertical: + case MouseInvVertical: + { + mousemode = temp; + break; + } + + default: + { + break; + } + } +} + +int JoyAxis::getMouseMode() +{ + int mode = (int)mousemode; + return mode; +} + +void JoyAxis::setMouseSpeed(int speed) +{ + if (speed >= 1 && speed <= 50) + { + mouseSpeed = speed; + } +} + +int JoyAxis::getMouseSpeed() +{ + return mouseSpeed; +} + +void JoyAxis::setAxisMode(int mode) +{ + JoyAxisMode temp = (JoyAxisMode) mode; + switch (mode) + { + case KeyboardAxis: + case MouseAxis: + { + axisMode = temp; + break; + } + + default: + { + break; + } + } +} + +int JoyAxis::getAxisMode() +{ + int temp = (int) axisMode; + return temp; +} + +void JoyAxis::setMaxZoneValue(int value) +{ + value = abs(value); + if (value >= AXISMAX) + { + maxZoneValue = AXISMAX; + } + else + { + maxZoneValue = value; + } +} + +int JoyAxis::getMaxZoneValue() +{ + return maxZoneValue; +} + +void JoyAxis::setThrottle(int value) +{ + if (value >= -1 && value <= 1) + { + throttle = value; + } +} + +int JoyAxis::getThrottle() +{ + return throttle; +} + +void JoyAxis::readConfig(QXmlStreamReader *xml) +{ + if (xml->isStartElement() && xml->name() == "axis") + { + xml->readNextStartElement(); + while (!xml->atEnd() && (!xml->isEndElement() && xml->name() != "axis")) + { + if (xml->name() == "deadZone" && xml->isStartElement()) + { + QString temptext = xml->readElementText(); + int tempchoice = temptext.toInt(); + this->setDeadZone(tempchoice); + } + + else if (xml->name() == "maxZone" && xml->isStartElement()) + { + QString temptext = xml->readElementText(); + int tempchoice = temptext.toInt(); + this->setMaxZoneValue(tempchoice); + } + + else if (xml->name() == "pkeycode" && xml->isStartElement()) + { + QString temptext = xml->readElementText(); + int tempchoice = temptext.toInt(); + this->setPKey(tempchoice); + } + else if (xml->name() == "nkeycode" && xml->isStartElement()) + { + QString temptext = xml->readElementText(); + int tempchoice = temptext.toInt(); + this->setNKey(tempchoice); + } + else if (xml->name() == "axismode" && xml->isStartElement()) + { + QString temptext = xml->readElementText(); + int tempchoice = temptext.toInt(); + this->setAxisMode(tempchoice); + } + else if (xml->name() == "mousemode" && xml->isStartElement()) + { + QString temptext = xml->readElementText(); + int tempchoice = temptext.toInt(); + this->setMouseMode(tempchoice); + } + else if (xml->name() == "throttle" && xml->isStartElement()) + { + QString temptext = xml->readElementText(); + if (temptext == "negative") + { + this->setThrottle(-1); + } + else if (temptext == "normal") + { + this->setThrottle(0); + } + else if (temptext == "positive") + { + this->setThrottle(1); + } + } + else if (xml->name() == "mousespeed" && xml->isStartElement()) + { + QString temptext = xml->readElementText(); + int tempchoice = temptext.toInt(); + this->setMouseSpeed(tempchoice); + } + else + { + xml->skipCurrentElement(); + } + + xml->readNextStartElement(); + } + } +} + +void JoyAxis::writeConfig(QXmlStreamWriter *xml) +{ + xml->writeStartElement("axis"); + xml->writeAttribute("index", QString::number(index+1)); + + xml->writeTextElement("deadZone", QString::number(deadZone)); + xml->writeTextElement("maxZone", QString::number(maxZoneValue)); + xml->writeTextElement("nkeycode", QString::number(nkeycode)); + xml->writeTextElement("pkeycode", QString::number(pkeycode)); + xml->writeTextElement("axismode", QString::number(axisMode)); + xml->writeTextElement("mousemode", QString::number(mousemode)); + xml->writeTextElement("mousespeed", QString::number(mouseSpeed)); + + xml->writeStartElement("throttle"); + if (throttle == -1) + { + xml->writeCharacters("negative"); + } + else if (throttle == 0) + { + xml->writeCharacters("normal"); + } + else if (throttle == 1) + { + xml->writeCharacters("positive"); + } + xml->writeEndElement(); + + xml->writeEndElement(); +} + +void JoyAxis::timerEvent() +{ + if (axisMode == KeyboardAxis) + { + eventActive = !eventActive; + createDeskEvent(); + } + else + { + eventActive = true; + createDeskEvent(); + } +} + +JoyAxis::~JoyAxis() +{ + if (timer) + { + delete timer; + timer = 0; + } +} diff --git a/joyaxis.h b/joyaxis.h new file mode 100644 index 00000000..bbc28d0e --- /dev/null +++ b/joyaxis.h @@ -0,0 +1,88 @@ +#ifndef JOYAXIS_H +#define JOYAXIS_H + +#include +#include +#include +#include +#include + +class JoyAxis : public QObject +{ + Q_OBJECT +public: + explicit JoyAxis(QObject *parent = 0); + explicit JoyAxis(int index, QObject *parent=0); + ~JoyAxis(); + + void joyEvent(int value); + bool inDeadZone(int value); + QString getName(); + void setIndex(int index); + int getIndex(); + int getRealJoyIndex(); + void setPKey(int code); + int getPKey(); + void setNKey(int code); + int getNKey(); + void setDeadZone(int value); + int getDeadZone(); + void setMouseMode(int mode); + int getMouseMode(); + void setMouseSpeed(int speed); + int getMouseSpeed(); + void setAxisMode(int mode); + int getAxisMode(); + void setMaxZoneValue(int value); + int getMaxZoneValue(); + void setThrottle(int value); + int getThrottle(); + void readConfig(QXmlStreamReader *xml); + void writeConfig(QXmlStreamWriter *xml); + + static const int AXISMIN; + static const int AXISMAX; + static const int AXISDEADZONE; + static const int AXISMAXZONE; + static const int JOYINTERVAL; + static const float JOYSPEED; + + enum JoyAxisMode {KeyboardAxis, MouseAxis}; + enum JoyAxisMouseMode {MouseHorizontal, MouseInvHorizontal, MouseVertical, MouseInvVertical}; + +protected: + void createDeskEvent(); + + int index; + int deadZone; + int maxZoneValue; + bool isActive; + int pkeycode; + int nkeycode; + int mouseSpeed; + + JoyAxisMode axisMode; + JoyAxisMouseMode mousemode; + bool trigger; + bool eventActive; + int currentValue; + QTimer *timer; + QTime interval; + int throttle; + float sumDist; + int mouseOffset; + int lastkey; + +signals: + void active(int value); + void released(int value); + void moved(int value); + +public slots: + +private slots: + void timerEvent(); + +}; + +#endif // JOYAXIS_H diff --git a/joyaxiswidget.cpp b/joyaxiswidget.cpp new file mode 100644 index 00000000..ac2faf27 --- /dev/null +++ b/joyaxiswidget.cpp @@ -0,0 +1,85 @@ +#include + +#include "joyaxiswidget.h" + +JoyAxisWidget::JoyAxisWidget(QWidget *parent) : + QPushButton(parent) +{ + axis = 0; + + normal = this->palette(); + flashing = this->palette(); + QColor highlightColor = QColor(0, 0, 255); + + flashing.setCurrentColorGroup(QPalette::Inactive); + flashing.setColor(QPalette::Button, highlightColor); + flashing.setColor(QPalette::Light, highlightColor.light(150)); + flashing.setColor(QPalette::Midlight, highlightColor.light(125)); + flashing.setColor(QPalette::Dark, highlightColor.dark(200)); + flashing.setColor(QPalette::Mid, highlightColor.dark(150)); + + setPalette(normal); + isflashing = false; +} + +JoyAxisWidget::JoyAxisWidget(JoyAxis *axis, QWidget *parent) : + QPushButton(parent) +{ + this->axis = axis; + + normal = this->palette(); + flashing = this->palette(); + QColor highlightColor = QColor(0, 0, 255); + + flashing.setCurrentColorGroup(QPalette::Inactive); + flashing.setColor(QPalette::Button, highlightColor); + flashing.setColor(QPalette::Light, highlightColor.light(150)); + flashing.setColor(QPalette::Midlight, highlightColor.light(125)); + flashing.setColor(QPalette::Dark, highlightColor.dark(200)); + flashing.setColor(QPalette::Mid, highlightColor.dark(150)); + + setPalette(normal); + isflashing = false; + + setText(axis->getName()); + + connect(axis, SIGNAL(active(int)), this, SLOT(flash())); + connect(axis, SIGNAL(released(int)), this, SLOT(unflash())); +} + +JoyAxis* JoyAxisWidget::getAxis() +{ + return axis; +} + +void JoyAxisWidget::flash() +{ + isflashing = true; + setPalette(flashing); + emit flashed(isflashing); +} + +void JoyAxisWidget::unflash() +{ + isflashing = false; + setPalette(normal); + emit flashed(isflashing); +} + +void JoyAxisWidget::refreshLabel() +{ + setText(axis->getName()); +} + +void JoyAxisWidget::disableFlashes() +{ + disconnect(axis, SIGNAL(active(int)), 0, 0); + disconnect(axis, SIGNAL(released(int)), 0, 0); + this->unflash(); +} + +void JoyAxisWidget::enableFlashes() +{ + connect(axis, SIGNAL(active(int)), this, SLOT(flash())); + connect(axis, SIGNAL(released(int)), this, SLOT(unflash())); +} diff --git a/joyaxiswidget.h b/joyaxiswidget.h new file mode 100644 index 00000000..c2a55696 --- /dev/null +++ b/joyaxiswidget.h @@ -0,0 +1,35 @@ +#ifndef JOYAXISWIDGET_H +#define JOYAXISWIDGET_H + +#include + +#include "joyaxis.h" + +class JoyAxisWidget : public QPushButton +{ + Q_OBJECT +public: + explicit JoyAxisWidget(QWidget *parent = 0); + explicit JoyAxisWidget(JoyAxis *axis, QWidget *parent=0); + JoyAxis* getAxis(); + +protected: + JoyAxis *axis; + QPalette normal; + QPalette flashing; + bool isflashing; + +signals: + void flashed(bool flashing); + +public slots: + void refreshLabel(); + void unflash(); + void disableFlashes(); + void enableFlashes(); + +private slots: + void flash(); +}; + +#endif // JOYAXISWIDGET_H diff --git a/joybutton.cpp b/joybutton.cpp new file mode 100644 index 00000000..9408b7b9 --- /dev/null +++ b/joybutton.cpp @@ -0,0 +1,316 @@ +#include +#include + +#include "joybutton.h" +#include "event.h" + +const QString JoyButton::xmlName = "button"; + +JoyButton::JoyButton(QObject *parent) : + QObject(parent) +{ + timer = new QTimer (this); + this->reset(); + index = 0; +} + +JoyButton::JoyButton(int index, QObject *parent) : + QObject(parent) +{ + timer = new QTimer (this); + this->reset(); + this->index = index; +} + +void JoyButton::joyEvent(bool pressed) +{ + if (toggle && pressed && (pressed != isDown)) + { + isButtonPressed = !isButtonPressed; + isDown = true; + emit clicked(index); + createDeskEvent(); + } + else if (toggle && !pressed && isDown) + { + isDown = false; + emit released(index); + } + + else if (!toggle && (pressed != isButtonPressed)) + { + if (pressed) + { + emit clicked(index); + } + else + { + emit released(index); + } + + isButtonPressed = pressed; + + if (isButtonPressed && useTurbo) + { + turboEvent(); + connect(timer, SIGNAL(timeout()), this, SLOT(turboEvent())); + } + else if (!isButtonPressed && useTurbo) + { + timer->stop(); + disconnect(timer, SIGNAL(timeout()), 0, 0); + if (isKeyPressed) + { + turboEvent(); + } + } + + if (!useTurbo) + { + createDeskEvent(); + } + } +} + +int JoyButton::getJoyNumber() +{ + return index; +} + +int JoyButton::getRealJoyNumber() +{ + return index + 1; +} + +void JoyButton::setJoyNumber(int index) +{ + this->index = index; +} + +void JoyButton::setKey(int keycode) +{ + this->keycode = keycode; + emit keyChanged(keycode); +} + +void JoyButton::setMouse(int mouse) +{ + if (mouse > 0 && mouse <= 8) + { + this->mousecode = mouse; + emit mouseChanged(mouse); + } +} + +int JoyButton::getMouse() +{ + return mousecode; +} + +void JoyButton::setToggle(bool toggle) +{ + this->toggle = toggle; +} + +void JoyButton::setTurboInterval(int interval) +{ + this->turboInterval = interval; +} + +void JoyButton::reset() +{ + isKeyPressed = isButtonPressed = false; + toggle = false; + turboInterval = 0; + keycode = 0; + mousecode = 0; + isDown = false; + useMouse = false; + useTurbo = false; + + if (timer) + { + timer->stop(); + } +} + +void JoyButton::reset(int index) +{ + JoyButton::reset(); + this->index = index; +} + +int JoyButton::getKey() +{ + return keycode; +} + +bool JoyButton::getToggleState() +{ + return toggle; +} + +int JoyButton::getTurboInterval() +{ + return turboInterval; +} + +void JoyButton::turboEvent() +{ + if (!isKeyPressed) + { + sendevent(keycode, true); + isKeyPressed = true; + timer->start(100); + } + else + { + sendevent(keycode, false); + isKeyPressed = false; + timer->start(turboInterval - 100); + } +} + +JoyButton::~JoyButton() +{ + if (timer) + { + timer->stop(); + } +} + +void JoyButton::setUseMouse(bool useMouse) +{ + this->useMouse = useMouse; +} + +bool JoyButton::isUsingMouse() +{ + return useMouse; +} + +void JoyButton::createDeskEvent() +{ + if (!useMouse && keycode > 0) + { + sendevent(keycode, isButtonPressed); + } + else if (useMouse && mousecode > 0) + { + sendevent(mousecode, isButtonPressed, JoyMouse); + } +} + +void JoyButton::setUseTurbo(bool useTurbo) +{ + this->useTurbo = useTurbo; +} + +bool JoyButton::isUsingTurbo() +{ + return useTurbo; +} + +QString JoyButton::getXmlName() +{ + return this->xmlName; +} + +void JoyButton::readConfig(QXmlStreamReader *xml) +{ + if (xml->isStartElement() && xml->name() == getXmlName()) + { + xml->readNextStartElement(); + while (!xml->atEnd() && (!xml->isEndElement() && xml->name() != getXmlName())) + { + if (xml->name() == "toggle" && xml->isStartElement()) + { + QString temptext = xml->readElementText(); + if (temptext == "true") + { + this->setToggle(true); + } + } + else if (xml->name() == "turbointerval" && xml->isStartElement()) + { + QString temptext = xml->readElementText(); + int tempchoice = temptext.toInt(); + this->setTurboInterval(tempchoice); + } + else if (xml->name() == "useturbo" && xml->isStartElement()) + { + QString temptext = xml->readElementText(); + if (temptext == "true") + { + this->setUseTurbo(true); + } + } + else if (xml->name() == "keycode" && xml->isStartElement()) + { + QString temptext = xml->readElementText(); + int tempchoice = temptext.toInt(); + this->setKey(tempchoice); + } + else if (xml->name() == "usemouse" && xml->isStartElement()) + { + QString temptext = xml->readElementText(); + if (temptext == "true") + { + this->setUseMouse(true); + } + } + else if (xml->name() == "mousecode" && xml->isStartElement()) + { + QString temptext = xml->readElementText(); + int tempchoice = temptext.toInt(); + this->setMouse(tempchoice); + } + else + { + xml->skipCurrentElement(); + } + + xml->readNextStartElement(); + } + } + +} + +void JoyButton::writeConfig(QXmlStreamWriter *xml) +{ + xml->writeStartElement(getXmlName()); + xml->writeAttribute("index", QString::number(getRealJoyNumber())); + + xml->writeTextElement("keycode", QString::number(keycode)); + xml->writeTextElement("usemouse", useMouse ? "true" : "false"); + xml->writeTextElement("mousecode", QString::number(mousecode)); + xml->writeTextElement("toggle", toggle ? "true" : "false"); + xml->writeTextElement("turbointerval", QString::number(turboInterval)); + xml->writeTextElement("useturbo", useTurbo ? "true" : "false"); + + xml->writeEndElement(); +} + +QString JoyButton::getName() +{ + QString newlabel = getPartialName(); + if (keycode > 0) + { + newlabel = newlabel.append(": ").append(keycodeToKey(keycode).toUpper()); + } + else if (mousecode > 0) + { + newlabel = newlabel.append(": Mouse ").append(QString::number(mousecode)); + } + else + { + newlabel = newlabel.append(": [NO KEY]"); + } + + return newlabel; +} + +QString JoyButton::getPartialName() +{ + return QString("Button ").append(QString::number(getRealJoyNumber())); +} diff --git a/joybutton.h b/joybutton.h new file mode 100644 index 00000000..5c42e4b6 --- /dev/null +++ b/joybutton.h @@ -0,0 +1,72 @@ +#ifndef JOYBUTTON_H +#define JOYBUTTON_H + +#include +#include +#include +#include + +class JoyButton : public QObject +{ + Q_OBJECT +public: + explicit JoyButton(QObject *parent = 0); + explicit JoyButton(int index, QObject *parent=0); + ~JoyButton(); + + void joyEvent (bool pressed); + int getJoyNumber (); + virtual int getRealJoyNumber (); + void setJoyNumber (int index); + void setKey(int keycode); + int getKey(); + void setMouse(int mouse); + int getMouse(); + bool getToggleState(); + int getTurboInterval(); + void reset(); + void reset(int index); + void setUseMouse(bool useMouse); + bool isUsingMouse(); + void setUseTurbo(bool useTurbo); + bool isUsingTurbo(); + virtual void readConfig(QXmlStreamReader *xml); + virtual void writeConfig(QXmlStreamWriter *xml); + + virtual QString getPartialName(); + virtual QString getName(); + virtual QString getXmlName(); + + static const QString xmlName; + +protected: + void createDeskEvent(); + + bool isButtonPressed; + bool isKeyPressed; + bool toggle; + int index; + int turboInterval; + int keycode; + int mousecode; + QTimer *timer; + bool isDown; + bool useMouse; + bool useTurbo; + +signals: + void clicked (int index); + void released (int index); + void keyChanged(int keycode); + void mouseChanged(int mousecode); + +public slots: + void setTurboInterval (int interval); + void setToggle (bool toggle); + +private slots: + void turboEvent(); +}; + + +#endif // JOYBUTTON_H diff --git a/joybuttonwidget.cpp b/joybuttonwidget.cpp new file mode 100644 index 00000000..6d3efcea --- /dev/null +++ b/joybuttonwidget.cpp @@ -0,0 +1,98 @@ +#include + +#include "joybuttonwidget.h" +#include "event.h" + +JoyButtonWidget::JoyButtonWidget(QWidget *parent) : + QPushButton(parent) +{ + + normal = this->palette(); + flashing = this->palette(); + + QColor highlightColor = QColor(0, 0, 255); + flashing.setCurrentColorGroup(QPalette::Inactive); + flashing.setColor(QPalette::Button, highlightColor); + flashing.setColor(QPalette::Light, highlightColor.light(150)); + flashing.setColor(QPalette::Midlight, highlightColor.light(125)); + flashing.setColor(QPalette::Dark, highlightColor.dark(200)); + flashing.setColor(QPalette::Mid, highlightColor.dark(150)); + + setPalette(flashing); + isflashing = false; +} + +JoyButtonWidget::JoyButtonWidget(JoyButton *button, QWidget *parent) : + QPushButton(parent) +{ + + this->button = button; + + normal = this->palette(); + flashing = this->palette(); + QColor highlightColor = QColor(0, 0, 255); + + flashing.setCurrentColorGroup(QPalette::Inactive); + flashing.setColor(QPalette::Button, highlightColor); + flashing.setColor(QPalette::Light, highlightColor.light(150)); + flashing.setColor(QPalette::Midlight, highlightColor.light(125)); + flashing.setColor(QPalette::Dark, highlightColor.dark(200)); + flashing.setColor(QPalette::Mid, highlightColor.dark(150)); + + setPalette(normal); + isflashing = false; + + setText(button->getName()); + + connect (button, SIGNAL(keyChanged(int)), this, SLOT(changeKeyLabel())); + connect (button, SIGNAL(mouseChanged(int)), this, SLOT(changeMouseLabel())); + connect (button, SIGNAL(clicked(int)), this, SLOT(flash())); + connect (button, SIGNAL(released(int)), this, SLOT(unflash())); +} + +JoyButton* JoyButtonWidget::getJoyButton() +{ + return button; +} + +void JoyButtonWidget::flash() +{ + isflashing = true; + setPalette(flashing); + emit flashed(isflashing); +} + +void JoyButtonWidget::unflash() +{ + isflashing = false; + setPalette(normal); + emit flashed(isflashing); +} + +void JoyButtonWidget::changeKeyLabel() +{ + setText(button->getName()); +} + +void JoyButtonWidget::changeMouseLabel() +{ + setText(button->getName()); +} + +void JoyButtonWidget::refreshLabel() +{ + setText(button->getName()); +} + +void JoyButtonWidget::disableFlashes() +{ + disconnect (button, SIGNAL(clicked(int)), 0, 0); + disconnect (button, SIGNAL(released(int)), 0, 0); + this->unflash(); +} + +void JoyButtonWidget::enableFlashes() +{ + connect (button, SIGNAL(clicked(int)), this, SLOT(flash())); + connect (button, SIGNAL(released(int)), this, SLOT(unflash())); +} diff --git a/joybuttonwidget.h b/joybuttonwidget.h new file mode 100644 index 00000000..24a106cb --- /dev/null +++ b/joybuttonwidget.h @@ -0,0 +1,40 @@ +#ifndef JOYBUTTONWIDGET_H +#define JOYBUTTONWIDGET_H + +#include +#include + +#include "joybutton.h" + +class JoyButtonWidget : public QPushButton +{ + Q_OBJECT +public: + explicit JoyButtonWidget(QWidget *parent = 0); + explicit JoyButtonWidget(JoyButton* button, QWidget *parent=0); + JoyButton* getJoyButton(); + +protected: + JoyButton* button; + QPalette normal; + QPalette flashing; + bool isflashing; + +signals: + void flashed(bool flashing); + +public slots: + void changeKeyLabel(); + //void changeKeyLabel(QString label); + void changeMouseLabel(); + //void changeMouseLabel(QString label); + void refreshLabel(); + void disableFlashes(); + void enableFlashes(); + +private slots: + void flash(); + void unflash(); +}; + +#endif // JOYBUTTONWIDGET_H diff --git a/joydpad.cpp b/joydpad.cpp new file mode 100644 index 00000000..d52e6bd3 --- /dev/null +++ b/joydpad.cpp @@ -0,0 +1,224 @@ +#include + +#include "joydpad.h" + +JoyDPad::JoyDPad(QObject *parent) : + QObject(parent) +{ + buttons = QHash (); + prevDirection = JoyDPadButton::DpadCentered; + previousValue = JoyDPadButton::DpadCentered; + populateButtons(); +} + +JoyDPad::JoyDPad(int index, QObject *parent) : + QObject(parent) +{ + this->index = index; + buttons = QHash (); + prevDirection = JoyDPadButton::DpadCentered; + previousValue = JoyDPadButton::DpadCentered; + populateButtons(); +} + +JoyDPadButton *JoyDPad::getJoyButton(int index) +{ + return buttons.value(index); +} + +void JoyDPad::populateButtons() +{ + JoyDPadButton* button = new JoyDPadButton (JoyDPadButton::DpadUp, this, this); + buttons.insert(JoyDPadButton::DpadUp, button); + + button = new JoyDPadButton (JoyDPadButton::DpadDown, this, this); + buttons.insert(JoyDPadButton::DpadDown, button); + + button = new JoyDPadButton(JoyDPadButton::DpadRight, this, this); + buttons.insert(JoyDPadButton::DpadRight, button); + + button = new JoyDPadButton(JoyDPadButton::DpadLeft, this, this); + buttons.insert(JoyDPadButton::DpadLeft, button); +} + +QString JoyDPad::getName() +{ + QString label = QString("DPad "); + label = label.append(QString::number(getRealJoyNumber())); + return label; +} + +int JoyDPad::getJoyNumber() +{ + return index; +} + +int JoyDPad::getRealJoyNumber() +{ + return index + 1; +} + +void JoyDPad::readConfig(QXmlStreamReader *xml) +{ + if (xml->isStartElement() && xml->name() == "dpad") + { + xml->readNextStartElement(); + while (!xml->atEnd() && (!xml->isEndElement() && xml->name() != "dpad")) + { + if (xml->name() == "dpadbutton" && xml->isStartElement()) + { + int index = xml->attributes().value("index").toString().toInt(); + JoyDPadButton* button = this->getJoyButton(index); + if (button) + { + button->readConfig(xml); + } + else + { + xml->skipCurrentElement(); + } + } + else + { + xml->skipCurrentElement(); + } + + xml->readNextStartElement(); + } + } +} + +void JoyDPad::writeConfig(QXmlStreamWriter *xml) +{ + xml->writeStartElement("dpad"); + xml->writeAttribute("index", QString::number(index+1)); + + QHash::iterator i; + for (i = buttons.begin(); i != buttons.end(); i++) + { + JoyDPadButton *button = (*i); + button->writeConfig(xml); + } + + xml->writeEndElement(); +} + +void JoyDPad::joyEvent(int value) +{ + JoyDPadButton *curButton; + JoyDPadButton *prevButton; + if (value != prevDirection) + { + if (prevDirection & JoyDPadButton::DpadUp) + { + prevButton = buttons.value(JoyDPadButton::DpadUp); + prevButton->joyEvent(false); + } + if (prevDirection & JoyDPadButton::DpadRight) + { + prevButton = buttons.value(JoyDPadButton::DpadRight); + prevButton->joyEvent(false); + } + if (prevDirection & JoyDPadButton::DpadDown) + { + prevButton = buttons.value(JoyDPadButton::DpadDown); + prevButton->joyEvent(false); + } + + if (prevDirection & JoyDPadButton::DpadLeft) + { + prevButton = buttons.value(JoyDPadButton::DpadLeft); + prevButton->joyEvent(false); + } + + /*if (prevDirection & JoyDPadButton::DpadRightUp) + { + prevButton = buttons.value(JoyDPadButton::DpadRightUp); + prevButton->joyEvent(false); + } + if (prevDirection & JoyDPadButton::DpadRightDown) + { + prevButton = buttons.value(JoyDPadButton::DpadRightDown); + prevButton->joyEvent(false); + } + if (prevDirection & JoyDPadButton::DpadLeftUp) + { + prevButton = buttons.value(JoyDPadButton::DpadLeftUp); + prevButton->joyEvent(false); + } + if (prevDirection & JoyDPadButton::DpadLeftDown) + { + prevButton = buttons.value(JoyDPadButton::DpadLeftDown); + prevButton->joyEvent(false); + }*/ + + if (value & JoyDPadButton::DpadUp) + { + curButton = buttons.value(JoyDPadButton::DpadUp); + curButton->joyEvent(true); + } + if (value & JoyDPadButton::DpadRight) + { + curButton = buttons.value(JoyDPadButton::DpadRight); + curButton->joyEvent(true); + } + if (value & JoyDPadButton::DpadDown) + { + curButton = buttons.value(JoyDPadButton::DpadDown); + curButton->joyEvent(true); + } + if (value & JoyDPadButton::DpadLeft) + { + curButton = buttons.value(JoyDPadButton::DpadLeft); + curButton->joyEvent(true); + } + /*if (value & JoyDPadButton::DpadRightUp) + { + curButton = buttons.value(JoyDPadButton::DpadRightUp); + curButton->joyEvent(true); + } + if (value & JoyDPadButton::DpadRightDown) + { + curButton = buttons.value(JoyDPadButton::DpadRightDown); + curButton->joyEvent(true); + } + if (value & JoyDPadButton::DpadLeftUp) + { + curButton = buttons.value(JoyDPadButton::DpadLeftUp); + curButton->joyEvent(true); + } + if (value & JoyDPadButton::DpadLeftDown) + { + curButton = buttons.value(JoyDPadButton::DpadLeftDown); + curButton->joyEvent(true); + }*/ + + } + + prevDirection = value; + + + /*if (value == JoyDPadButton::DpadCentered && prevDirection != JoyDPadButton::DpadCentered) + { + JoyDPadButton *button = buttons.value(prevDirection); + button->joyEvent(false); + } + else if (value != prevDirection) + { + if (prevDirection != JoyDPadButton::DpadCentered) + { + JoyDPadButton *prevButton = buttons.value(prevDirection); + prevButton->joyEvent(false); + } + + JoyDPadButton *curButton = buttons.value(value); + curButton->joyEvent(true); + } + + prevDirection = value;*/ +} + +QHash* JoyDPad::getJoyButtons() +{ + return &buttons; +} diff --git a/joydpad.h b/joydpad.h new file mode 100644 index 00000000..7e1d53e9 --- /dev/null +++ b/joydpad.h @@ -0,0 +1,41 @@ +#ifndef JOYDPAD_H +#define JOYDPAD_H + +#include +#include +#include +#include + +#include "joydpadbutton.h" + +class JoyDPad : public QObject +{ + Q_OBJECT +public: + explicit JoyDPad(QObject *parent = 0); + explicit JoyDPad(int index, QObject *parent=0); + JoyDPadButton* getJoyButton(int index); + QHash* getJoyButtons(); + + int getJoyNumber(); + int getRealJoyNumber(); + QString getName(); + void joyEvent(int value); + void readConfig(QXmlStreamReader *xml); + void writeConfig(QXmlStreamWriter *xml); + +protected: + void populateButtons(); + + QHash buttons; + int index; + int prevDirection; + int previousValue; + +signals: + +public slots: + +}; + +#endif // JOYDPAD_H diff --git a/joydpadbutton.cpp b/joydpadbutton.cpp new file mode 100644 index 00000000..993992d1 --- /dev/null +++ b/joydpadbutton.cpp @@ -0,0 +1,69 @@ +#include "joydpadbutton.h" +#include "joydpad.h" +#include "event.h" + +const QString JoyDPadButton::xmlName = "dpadbutton"; + +// Initially, qualify direction as the button's index +JoyDPadButton::JoyDPadButton(int direction, JoyDPad* dpad, QObject *parent) : + JoyButton(direction, parent) +{ + this->direction = direction; + this->dpad = dpad; + this->keycode = 0; + this->mousecode = 0; +} + +QString JoyDPadButton::getDirectionName() +{ + QString label = QString (); + if (direction & DpadUp) + { + label.append("Up"); + } + else if (direction & DpadDown) + { + label.append("Down"); + } + else if (direction & DpadLeft) + { + label.append("Left"); + } + else if (direction & DpadRight) + { + label.append("Right"); + } + else if (direction & DpadLeftUp) + { + label.append("Up+Left"); + } + else if (direction & DpadLeftDown) + { + label.append("Down+Left"); + } + else if (direction & DpadRightUp) + { + label.append("Up+Left"); + } + else if (direction & DpadRightDown) + { + label.append("Down+Right"); + } + + return label; +} + +QString JoyDPadButton::getXmlName() +{ + return this->xmlName; +} + +int JoyDPadButton::getRealJoyNumber() +{ + return index; +} + +QString JoyDPadButton::getPartialName() +{ + return dpad->getName().append(" - ").append(getDirectionName()); +} diff --git a/joydpadbutton.h b/joydpadbutton.h new file mode 100644 index 00000000..eb8ddc5b --- /dev/null +++ b/joydpadbutton.h @@ -0,0 +1,36 @@ +#ifndef JOYDPADBUTTON_H +#define JOYDPADBUTTON_H + +#include "joybutton.h" + +class JoyDPad; + +class JoyDPadButton : public JoyButton +{ + Q_OBJECT +public: + JoyDPadButton(int direction, JoyDPad* dpad, QObject *parent=0); + + QString getDirectionName(); + virtual int getRealJoyNumber(); + virtual QString getPartialName(); + virtual QString getXmlName(); + + enum JoyDPadDirections { + DpadCentered = 0, DpadUp = 1, DpadRight = 2, + DpadDown = 4, DpadLeft = 8, DpadRightUp = 3, + DpadRightDown = 6, DpadLeftUp = 9, DpadLeftDown = 12 + }; + static const QString xmlName; + +protected: + int direction; + JoyDPad *dpad; + +signals: + +public slots: + +}; + +#endif // JOYDPADBUTTON_H diff --git a/joystick.cpp b/joystick.cpp new file mode 100644 index 00000000..5935414d --- /dev/null +++ b/joystick.cpp @@ -0,0 +1,111 @@ +#include + +#include "joystick.h" + +Joystick::Joystick(QObject *parent) : + QObject(parent) +{ + joyhandle = 0; + buttons = QHash (); + axes = QHash (); +} + +Joystick::Joystick(SDL_Joystick *joyhandle, QObject *parent) : + QObject(parent) +{ + this->joyhandle = joyhandle; + buttons = QHash (); + axes = QHash (); +} + +int Joystick::getNumberButtons() +{ + return buttons.count(); +} + +int Joystick::getNumberAxes() +{ + return axes.count(); +} + +int Joystick::getNumberHats() +{ + return hats.count(); +} + +SDL_Joystick* Joystick::getSDLHandle() +{ + return joyhandle; +} + +int Joystick::getJoyNumber() +{ + int joynumber = SDL_JoystickIndex(joyhandle); + return joynumber; +} + +void Joystick::refreshButtons() +{ + buttons.clear(); + + for (int i=0; i < SDL_JoystickNumButtons(joyhandle); i++) + { + JoyButton *button = new JoyButton (i, this); + buttons.insert(i, button); + } +} + +void Joystick::refreshAxes() +{ + axes.clear(); + + for (int i=0; i < SDL_JoystickNumAxes(joyhandle); i++) + { + JoyAxis *axis = new JoyAxis(i, this); + axes.insert(i, axis); + } +} + +void Joystick::refreshHats() +{ + hats.clear(); + + for (int i=0; i < SDL_JoystickNumHats(joyhandle); i++) + { + JoyDPad *dpad = new JoyDPad(i, this); + hats.insert(i, dpad); + } +} + +int Joystick::getRealJoyNumber() +{ + int joynumber = getJoyNumber(); + return joynumber + 1; +} + +JoyButton* Joystick::getJoyButton(int index) +{ + return buttons.value(index); +} + +JoyAxis* Joystick::getJoyAxis(int index) +{ + return axes.value(index); +} + +JoyDPad* Joystick::getJoyDPad(int index) +{ + return hats.value(index); +} + +QString Joystick::getName() +{ + return QString("Joystick ").append(QString::number(getRealJoyNumber())); +} + +void Joystick::reset() +{ + refreshAxes(); + refreshButtons(); + refreshHats(); +} diff --git a/joystick.h b/joystick.h new file mode 100644 index 00000000..c7c80fb6 --- /dev/null +++ b/joystick.h @@ -0,0 +1,45 @@ +#ifndef JOYSTICK_H +#define JOYSTICK_H + +#include +#include +#include + +#include "joyaxis.h" +#include "joydpad.h" +#include "joybutton.h" + +class Joystick : public QObject +{ + Q_OBJECT +public: + explicit Joystick(QObject *parent = 0); + explicit Joystick(SDL_Joystick *joyhandle, QObject *parent=0); + + int getNumberButtons (); + int getNumberAxes(); + int getNumberHats(); + SDL_Joystick* getSDLHandle (); + int getJoyNumber (); + int getRealJoyNumber (); + void refreshButtons (); + void refreshAxes(); + void refreshHats(); + JoyAxis* getJoyAxis(int index); + JoyButton* getJoyButton(int index); + JoyDPad* getJoyDPad(int index); + QString getName(); + +protected: + QHash buttons; + QHash axes; + QHash hats; + SDL_Joystick* joyhandle; + +signals: + +public slots: + void reset(); +}; + +#endif // JOYSTICK_H diff --git a/joytabwidget.cpp b/joytabwidget.cpp new file mode 100644 index 00000000..420d75d7 --- /dev/null +++ b/joytabwidget.cpp @@ -0,0 +1,450 @@ +#include + +#include "joytabwidget.h" +#include "joyaxiswidget.h" +#include "joybuttonwidget.h" +#include "xmlconfigreader.h" +#include "xmlconfigwriter.h" + +JoyTabWidget::JoyTabWidget(Joystick *joystick, QWidget *parent) : + QWidget(parent) +{ + this->joystick = joystick; + + verticalLayout = new QVBoxLayout (this); + verticalLayout->setContentsMargins(4, 4, 4, 4); + + configHorizontalLayout = new QHBoxLayout(); + configBox = new QComboBox(this); + configBox->addItem("", ""); + + configBox->setObjectName(QString::fromUtf8("configBox")); + configBox->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + configHorizontalLayout->addWidget(configBox); + spacer1 = new QSpacerItem(30, 20, QSizePolicy::Fixed, QSizePolicy::Fixed); + configHorizontalLayout->addItem(spacer1); + + loadButton = new QPushButton(tr("Load"), this); + loadButton->setObjectName(QString::fromUtf8("loadButton")); + loadButton->setFixedWidth(100); + loadButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + configHorizontalLayout->addWidget(loadButton); + + saveButton = new QPushButton(tr("Save"), this); + saveButton->setObjectName(QString::fromUtf8("saveButton")); + saveButton->setFixedWidth(100); + saveButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + configHorizontalLayout->addWidget(saveButton); + //configHorizontalLayout->setSpacing(-1); + + saveAsButton = new QPushButton(tr("Save As"), this); + saveAsButton->setObjectName(QString::fromUtf8("saveAsButton")); + saveAsButton->setFixedWidth(100); + saveAsButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + configHorizontalLayout->addWidget(saveAsButton); + + verticalLayout->addLayout(configHorizontalLayout); + verticalLayout->setStretchFactor(configHorizontalLayout, 1); + + spacer2 = new QSpacerItem(20, 5, QSizePolicy::Fixed, QSizePolicy::Fixed); + verticalLayout->addItem(spacer2); + + gridLayout = new QGridLayout(); + gridLayout->setObjectName(QString::fromUtf8("gridLayout")); + //QPushButton *testButton = new QPushButton (tr("Push Button"), this); + //testButton->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + //gridLayout->addWidget(testButton); + verticalLayout->addLayout(gridLayout); + + spacer3 = new QSpacerItem(20, 5, QSizePolicy::Fixed, QSizePolicy::Fixed); + verticalLayout->addItem(spacer3); + + resetButton = new QPushButton(tr("Reset"), this); + resetButton->setObjectName(QString::fromUtf8("resetButton")); + resetButton->setFixedWidth(75); + resetButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + verticalLayout->addWidget(resetButton, 0, Qt::AlignRight); + + fileDialog = new QFileDialog(this, "Open Config", QDir::currentPath(), "Config Files (*.xml)"); + + connect(loadButton, SIGNAL(clicked()), this, SLOT(openConfigFileDialog())); + connect(saveButton, SIGNAL(clicked()), this, SLOT(saveConfigFile())); + connect(resetButton, SIGNAL(clicked()), this, SLOT(resetJoystick())); + connect(configBox, SIGNAL(currentIndexChanged(int)), this, SLOT(changeJoyConfig(int))); + connect(saveAsButton, SIGNAL(clicked()), this, SLOT(saveAsConfig())); +} + +void JoyTabWidget::openConfigFileDialog() +{ + QStringList filenames; + QString filename; + + if (fileDialog->exec()) + { + filenames = fileDialog->selectedFiles(); + filename = filenames.at(0); + } + + if (!filename.isEmpty()) + { + XMLConfigReader reader; + //QFile *configFile = new QFile(filename); + reader.setFileName(filename); + reader.configJoystick(joystick); + + fillButtons(); + + QFileInfo fileinfo(filename); + int searchIndex = configBox->findData(fileinfo.absoluteFilePath()); + if (searchIndex == -1) + { + if (configBox->count() == 5) + { + configBox->removeItem(4); + } + + configBox->insertItem(1, fileinfo.baseName(), fileinfo.absoluteFilePath()); + configBox->setCurrentIndex(1); + } + else + { + configBox->setCurrentIndex(searchIndex); + } + } +} + +void JoyTabWidget::fillButtons() +{ + QWidget *child; + //QList list = old_layout->findChildren(); + //qDeleteAll(list); + while (gridLayout && gridLayout->count() > 0) + { + child = gridLayout->takeAt(0)->widget(); + gridLayout->removeWidget (child); + //child->deleteLater(); + delete child; + child = 0; + } + + int row = 0; + int column = 0; + for (int i=0; i < joystick->getNumberAxes(); i++) + { + JoyAxis *axis = joystick->getJoyAxis(i); + JoyAxisWidget *axisWidget = new JoyAxisWidget(axis, this); + axisWidget->setText(axis->getName()); + axisWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + + connect(axisWidget, SIGNAL(clicked()), this, SLOT(showAxisDialog())); + + if (column > 1) + { + column = 0; + row++; + } + gridLayout->addWidget(axisWidget, row, column); + column++; + } + + for (int i=0; i < joystick->getNumberHats(); i++) + { + JoyDPad *dpad = joystick->getJoyDPad(i); + QHash::iterator i; + for (i = dpad->getJoyButtons()->begin(); i != dpad->getJoyButtons()->end(); i++) + { + JoyDPadButton *button = (*i); + JoyButtonWidget *dude = new JoyButtonWidget (button, this); + dude->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + connect (dude, SIGNAL(clicked()), this, SLOT(showButtonDialog())); + + if (column > 1) + { + column = 0; + row++; + } + + gridLayout->addWidget(dude, row, column); + column++; + } + } + + for (int i=0; i < joystick->getNumberButtons(); i++) + { + JoyButton *button = joystick->getJoyButton(i); + JoyButtonWidget *dude = new JoyButtonWidget (button, this); + dude->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + connect (dude, SIGNAL(clicked()), this, SLOT(showButtonDialog())); + + if (column > 1) + { + column = 0; + row++; + } + + gridLayout->addWidget(dude, row, column); + column++; + } +} + +void JoyTabWidget::showButtonDialog() +{ + QObject *sender = QObject::sender(); + JoyButtonWidget *buttonWidget = (JoyButtonWidget*)sender; + JoyButton *button = buttonWidget->getJoyButton(); + + buttonDialog = new ButtonEditDialog(button, this); + buttonDialog->show(); + connect(buttonDialog, SIGNAL(destroyed()), buttonWidget, SLOT(refreshLabel())); +} + +void JoyTabWidget::showAxisDialog() +{ + QObject *sender = QObject::sender(); + JoyAxisWidget *axisWidget = (JoyAxisWidget*) sender; + JoyAxis *axis = axisWidget->getAxis(); + + axisDialog = new AxisEditDialog (axis, this); + axisDialog->show(); + connect(axisDialog, SIGNAL(destroyed()), axisWidget, SLOT(refreshLabel())); +} + +void JoyTabWidget::saveConfigFile() +{ + int index = configBox->currentIndex(); + QString filename; + if (index == 0) + { + QString tempfilename = QFileDialog::getSaveFileName(this, "Save Config", QDir::currentPath(), "Config File (*.xml)"); + if (!tempfilename.isEmpty()) + { + filename = tempfilename; + } + } + else + { + filename = configBox->itemData(index).value (); + } + + if (!filename.isEmpty()) + { + QFileInfo fileinfo(filename); + if (fileinfo.suffix() != "xml") + { + filename = filename.append(".xml"); + } + fileinfo.setFile(filename); + + XMLConfigWriter writer; + writer.setFileName(fileinfo.absoluteFilePath()); + writer.write(joystick); + + if (index == 0) + { + if (configBox->count() == 5) + { + configBox->removeItem(4); + } + + configBox->insertItem(1, fileinfo.baseName(), fileinfo.absoluteFilePath()); + configBox->setCurrentIndex(1); + } + } +} + +void JoyTabWidget::resetJoystick() +{ + int currentIndex = configBox->currentIndex(); + if (currentIndex != 0) + { + XMLConfigReader reader; + + QString filename = configBox->itemData(currentIndex).toString(); + + reader.setFileName(filename); + reader.configJoystick(joystick); + fillButtons(); + } + else + { + joystick->reset(); + fillButtons(); + } + /*else + { + emit joystickRefreshRequested(joystick); + }*/ +} + +void JoyTabWidget::saveAsConfig() +{ + int index = configBox->currentIndex(); + QString filename; + if (index != 0) + { + QString configPath = configBox->itemData(index).toString(); + QFileInfo temp(configPath); + QString tempfilename = QFileDialog::getSaveFileName(this, "Save Config", temp.absoluteDir().absolutePath(), "Config File (*.xml)"); + if (!tempfilename.isEmpty()) + { + filename = tempfilename; + } + } + + if (!filename.isEmpty()) + { + QFileInfo fileinfo(filename); + if (fileinfo.suffix() != "xml") + { + filename = filename.append(".xml"); + } + fileinfo.setFile(filename); + + XMLConfigWriter writer; + writer.setFileName(fileinfo.absoluteFilePath()); + writer.write(joystick); + + if (configBox->count() == 5) + { + configBox->removeItem(4); + } + + configBox->insertItem(1, fileinfo.baseName(), fileinfo.absoluteFilePath()); + configBox->setCurrentIndex(1); + } +} + +void JoyTabWidget::changeJoyConfig(int index) +{ + QString filename; + + if (index != 0) + { + filename = configBox->itemData(index).toString(); + } + + if (!filename.isEmpty()) + { + XMLConfigReader reader; + //QFile *configFile = new QFile(filename); + + reader.setFileName(filename); + reader.configJoystick(joystick); + + fillButtons(); + + QFileInfo fileinfo(filename); + int searchIndex = configBox->findData(fileinfo.absoluteFilePath()); + configBox->setCurrentIndex(searchIndex); + } + else + { + emit joystickRefreshRequested(joystick); + //QMetaObject::invokeMethod(joystick, "reset"); + //joystick->reset(); + //fillButtons(); + } + + //fillButtons(joystick); +} + +void JoyTabWidget::saveSettings(QSettings *settings) +{ + QString filename = ""; + QString lastfile = ""; + + int joyindex = joystick->getRealJoyNumber(); + int index = configBox->currentIndex(); + int currentjoy = 1; + + QString controlString = QString("Controller%1ConfigFile%2").arg(QString::number(joyindex)); + QString controlLastSelected = QString("Controller%1LastSelected").arg(QString::number(joyindex)); + + if (index != 0) + { + filename = lastfile = configBox->itemData(index).toString(); + settings->setValue(controlString.arg(currentjoy), filename); + currentjoy++; + } + else + { + lastfile = ""; + } + + for (int i=1; i < configBox->count(); i++) + { + if (i != index) + { + filename = configBox->itemData(i).toString(); + settings->setValue(controlString.arg(currentjoy), filename); + currentjoy++; + } + } + + settings->setValue(controlLastSelected, lastfile); +} + +void JoyTabWidget::loadSettings(QSettings *settings) +{ + int joyindex = joystick->getRealJoyNumber(); + QString controlString = QString("Controllers/Controller%1ConfigFile%2").arg(QString::number(joyindex)); + QString controlLastSelected = QString("Controllers/Controller%1LastSelected").arg(QString::number(joyindex)); + + QString file1 = settings->value(controlString.arg(QString::number(1)), "").toString(); + + if (!file1.isEmpty()) + { + QFileInfo fileInfo(file1); + if (configBox->findData(fileInfo.absoluteFilePath()) == -1) + { + configBox->addItem(fileInfo.baseName(), fileInfo.absoluteFilePath()); + } + } + QString file2 = settings->value(controlString.arg(QString::number(2)), "").toString(); + if (!file2.isEmpty()) + { + QFileInfo fileInfo(file2); + if (configBox->findData(fileInfo.absoluteFilePath()) == -1) + { + configBox->addItem(fileInfo.baseName(), fileInfo.absoluteFilePath()); + } + } + QString file3 = settings->value(controlString.arg(QString::number(3)), "").toString(); + if (!file3.isEmpty()) + { + QFileInfo fileInfo(file3); + if (configBox->findData(fileInfo.absoluteFilePath()) == -1) + { + configBox->addItem(fileInfo.baseName(), fileInfo.absoluteFilePath()); + } + } + QString file4 = settings->value(controlString.arg(QString::number(4)), "").toString(); + if (!file4.isEmpty()) + { + QFileInfo fileInfo(file4); + if (configBox->findData(fileInfo.absoluteFilePath()) == -1) + { + configBox->addItem(fileInfo.baseName(), fileInfo.absoluteFilePath()); + } + } + QString file5 = settings->value(controlString.arg(QString::number(5)), "").toString(); + if (!file5.isEmpty()) + { + QFileInfo fileInfo(file5); + if (configBox->findData(fileInfo.absoluteFilePath()) == -1) + { + configBox->addItem(fileInfo.baseName(), fileInfo.absoluteFilePath()); + } + } + + QString lastfile = settings->value(controlLastSelected).toString(); + if (!lastfile.isEmpty()) + { + int lastindex = configBox->findData(lastfile); + if (lastindex > 0) + { + configBox->setCurrentIndex(lastindex); + } + } + +} diff --git a/joytabwidget.h b/joytabwidget.h new file mode 100644 index 00000000..68b5d3c2 --- /dev/null +++ b/joytabwidget.h @@ -0,0 +1,61 @@ +#ifndef JOYTABWIDGET_H +#define JOYTABWIDGET_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "joystick.h" +#include "axiseditdialog.h" +#include "buttoneditdialog.h" + +class JoyTabWidget : public QWidget +{ + Q_OBJECT +public: + explicit JoyTabWidget(Joystick *joystick, QWidget *parent = 0); + void saveSettings(QSettings *settings); + void loadSettings(QSettings *settings); + +protected: + QVBoxLayout *verticalLayout; + QHBoxLayout *configHorizontalLayout; + QPushButton *loadButton; + QPushButton *saveButton; + QPushButton *resetButton; + QPushButton *saveAsButton; + QComboBox *configBox; + QGridLayout *gridLayout; + QSpacerItem *spacer1; + QSpacerItem *spacer2; + QSpacerItem *spacer3; + QFileDialog *fileDialog; + ButtonEditDialog *buttonDialog; + AxisEditDialog *axisDialog; + + Joystick *joystick; + +signals: + void joystickRefreshRequested(); + void joystickRefreshRequested(Joystick *joystick); + +public slots: + void openConfigFileDialog(); + void fillButtons(); + +private slots: + void saveConfigFile(); + void resetJoystick(); + void saveAsConfig(); + void changeJoyConfig(int index); + void showAxisDialog(); + void showButtonDialog(); +}; + +#endif // JOYTABWIDGET_H diff --git a/keygrabberbutton.cpp b/keygrabberbutton.cpp new file mode 100644 index 00000000..932c2ee9 --- /dev/null +++ b/keygrabberbutton.cpp @@ -0,0 +1,216 @@ +#include + +#include "keygrabberbutton.h" +#include "event.h" + +KeyGrabberButton::KeyGrabberButton(QWidget *parent) : + QPushButton(parent) +{ + numSeconds = 5; + isGrabber = false; + oldcode = 0; + controlcode = 0; + connect (this, SIGNAL(clicked()), this, SLOT(beginCountdown())); + this->installEventFilter(this); +} + +void KeyGrabberButton::keyPressEvent(QKeyEvent *event) +{ + // Do not allow closing of dialog using Escape key + if (event->key() == Qt::Key_Escape) + { + return; + } +} + +void KeyGrabberButton::beginCountdown() +{ + disconnect(this, SIGNAL(clicked()), 0, 0); + + this->grabKeyboard(); + + emit grabStarted(); + + isGrabber = true; + qDebug () << "IT's THE FINAL COUNTDOWN" << endl; + oldvalue = this->text(); + this->setText(QString ("[%1]").arg(numSeconds)); + connect (&timer, SIGNAL(timeout()), this, SLOT(updateCountdown())); + timer.start(1000); +} + +void KeyGrabberButton::updateCountdown() +{ + if (numSeconds > 0) + { + numSeconds--; + this->setText(QString ("[%1]").arg(numSeconds)); + qDebug () << "TO BE FOUND" << endl; + } + else + { + endCountdown(); + this->setText(oldvalue); + emit grabFinished(false); + } +} + +void KeyGrabberButton::endCountdown() +{ + timer.stop(); + disconnect(&timer, SIGNAL(timeout()), 0, 0); + + this->releaseKeyboard(); + numSeconds = 5; + isGrabber = false; + + connect (this, SIGNAL(clicked()), this, SLOT(beginCountdown())); +} + +bool KeyGrabberButton::eventFilter(QObject *obj, QEvent *event) +{ + if (isGrabber && event->type() == QEvent::MouseButtonRelease) + { + int mouseValue = 0; + QMouseEvent *mouseEve = (QMouseEvent*) event; + qDebug() << "SOLITAIRE " << mouseEve->button() << endl; + + if (mouseEve->button() == Qt::RightButton) + { + mouseValue = 3; + } + else if (mouseEve->button() == Qt::MiddleButton) + { + mouseValue = 2; + } + else { + mouseValue = mouseEve->button(); + } + + setText(QString("Mouse ").append(QString::number(mouseValue))); + controlcode = mouseValue + MOUSE_OFFSET; + + this->clearFocus(); + this->endCountdown(); + emit grabFinished(true); + } + else if (isGrabber && event->type() == QEvent::KeyRelease) + { + QKeyEvent *keyEve = (QKeyEvent*) event; + qDebug() << "EVENT: " << keyEve->nativeVirtualKey() << endl; + qDebug() << "EVENT 2: " << keyEve->nativeScanCode() << endl; + controlcode = keyEve->nativeScanCode(); + + if ((keyEve->modifiers() & Qt::ControlModifier) && keyEve->key() == Qt::Key_X) + { + controlcode = 0; + setText("[NO KEY]"); + } + else if (controlcode < 0) + { + controlcode = 0; + setText("[NO KEY]"); + } + else + { + setText(keycodeToKey(controlcode).toUpper()); + } + + this->clearFocus(); + this->endCountdown(); + emit grabFinished(true); + } + else if (isGrabber && event->type() == QEvent::Wheel) + { + QWheelEvent *wheelEve = (QWheelEvent*) event; + QString text = QString("Mouse "); + if (wheelEve->delta() > 0) + { + controlcode = 4; + } + else + { + controlcode = 5; + } + + text = text.append(QString::number(controlcode)); + setText(text); + + controlcode += MOUSE_OFFSET; + this->clearFocus(); + this->endCountdown(); + emit grabFinished(true); + } + + return false; +} + +/*bool KeyGrabberButton::x11Event(XEvent *e) +{ + //QPushButton::x11Event(e); + qDebug () << "jfdsjfsdjkl: " << e->xbutton.button << endl; +}*/ + +/*bool KeyGrabberButton::x11Event(XEvent *e) +{ + //On a key press, return the key and quit + //Ctrl+X == [No Key] + if (e->type == KeyRelease) { + if ((int)XKeycodeToKeysym(e->xkey.display,e->xkey.keycode,0) == XK_x ) { + if (e->xkey.state & ControlMask) + { + controlcode = 0; + } + else + { + controlcode = e->xkey.keycode; + } + } + + else + { + controlcode = e->xkey.keycode; + } + + if (controlcode == 0) + { + setText("[NO KEY]"); + } + else + { + setText(keycodeToKey(controlcode).toUpper()); + } + + this->clearFocus(); + this->endCountdown(); + emit grabFinished(true); + + return true; + } + //if we're accepting mouse clicks and a mouse button was clicked... + else if (e->type == ButtonRelease) { + setText(QString("Mouse ").append(QString::number(controlcode))); + + controlcode = e->xbutton.button + MOUSE_OFFSET; + + this->clearFocus(); + this->endCountdown(); + emit grabFinished(true); + + return true; + } + + //any other events we will pass on to the dialog. This allows for closing + //the window and easy redrawing :) + return false; +}*/ + +int KeyGrabberButton::getValue() +{ + return controlcode; +} + +void KeyGrabberButton::setValue(int value) +{ + controlcode = value; +} diff --git a/keygrabberbutton.h b/keygrabberbutton.h new file mode 100644 index 00000000..652a7c83 --- /dev/null +++ b/keygrabberbutton.h @@ -0,0 +1,48 @@ +#ifndef KEYGRABBERBUTTON_H +#define KEYGRABBERBUTTON_H + +#include +#include +#include +#include +#include + +//#include + +//The KeySym for "x" +const int XK_x = 0x078; +const int MOUSE_OFFSET = 400; + +class KeyGrabberButton : public QPushButton +{ + Q_OBJECT +public: + explicit KeyGrabberButton(QWidget *parent = 0); + void setValue(int value); + int getValue (); + +protected: + void keyPressEvent(QKeyEvent *event); + void endCountdown(); + virtual bool eventFilter(QObject *obj, QEvent *event); + //virtual bool x11Event(XEvent *e); + + QTimer timer; + int numSeconds; + bool isGrabber; + QString oldvalue; + int oldcode; + int controlcode; + +signals: + void grabStarted(); + void grabFinished(bool changed); + //void grabFinished(int value); + void mouseCode(int mousecode); + +public slots: + void beginCountdown(); + void updateCountdown(); +}; + +#endif // KEYGRABBERBUTTON_H diff --git a/main.cpp b/main.cpp new file mode 100644 index 00000000..5881055d --- /dev/null +++ b/main.cpp @@ -0,0 +1,64 @@ +#include +#include +#include +#include + +#include + +#include "mainwindow.h" +#include "joystick.h" +#include "inputdaemon.h" +#include "xmlconfigreader.h" +#include "xmlconfigwriter.h" +#include "common.h" + +int main(int argc, char *argv[]) +{ + XInitThreads (); + + QHash *joysticks = new QHash (); + + QApplication a(argc, argv); + //Q_INIT_RESOURCE(resources); + //a.setQuitOnLastWindowClosed(false); + MainWindow w(joysticks); + w.show(); + + QDir configDir (PadderCommon::configPath); + if (!configDir.exists()) + { + configDir.mkdir(PadderCommon::configPath); + } + + InputDaemon *joypad_worker = new InputDaemon (joysticks); + QThread* joypad_thread = new QThread (); + + //QObject::connect(joypad_worker, SIGNAL(joystickRefreshed(Joystick*)), &joyConfigReader, SLOT(configJoystick(Joystick*))); + QObject::connect(joypad_thread, SIGNAL(started()), joypad_worker, SLOT(run())); + //QObject::connect(joypad_worker, SIGNAL(joysticksRefreshed(QHash*)), &w, SLOT(fillButtons(Joystick*))); + QObject::connect(joypad_worker, SIGNAL(joysticksRefreshed(QHash*)), &w, SLOT(fillButtons(QHash*))); + QObject::connect(&w, SIGNAL(joystickRefreshRequested()), joypad_worker, SLOT(refresh())); + //QObject::connect(joypad_worker, SIGNAL(complete()), &w, SLOT(resetInterface())); + QObject::connect(joypad_worker, SIGNAL(joystickRefreshed(Joystick*)), &w, SLOT(fillButtons(Joystick*))); + QObject::connect(&w, SIGNAL(joystickRefreshRequested(Joystick*)), joypad_worker, SLOT(refreshJoystick(Joystick*))); + QObject::connect(&a, SIGNAL(aboutToQuit()), &w, SLOT(saveAppConfig())); + + joypad_worker->moveToThread(joypad_thread); + joypad_thread->start(); + + int app_result = a.exec(); + + joypad_worker->stop(); + joypad_thread->quit(); + joypad_thread->wait(); + + delete joypad_worker; + joypad_worker = 0; + delete joypad_thread; + joypad_thread = 0; + delete joysticks; + joysticks = 0; + + return app_result; +} + diff --git a/mainwindow.cpp b/mainwindow.cpp new file mode 100644 index 00000000..a941a269 --- /dev/null +++ b/mainwindow.cpp @@ -0,0 +1,241 @@ +#include +#include +#include +#include + +#include "mainwindow.h" +#include "ui_mainwindow.h" +#include "joyaxiswidget.h" +#include "joybuttonwidget.h" +#include "joytabwidget.h" +#include "common.h" + +MainWindow::MainWindow(QHash *joysticks, QWidget *parent) : + QMainWindow(parent), + ui(new Ui::MainWindow) +{ + ui->setupUi(this); + ui->stackedWidget->setCurrentIndex(0); + ui->tab_2->deleteLater(); + ui->tab->deleteLater(); + + this->joysticks = joysticks; + + populateTrayIcon(); + trayIcon->show(); + + connect(ui->menuOptions, SIGNAL(aboutToShow()), this, SLOT(mainMenuChange())); +} + +MainWindow::~MainWindow() +{ + delete ui; + this->deleteLater(); +} + +void MainWindow::fillButtons(Joystick *joystick) +{ + int joyindex = joystick->getJoyNumber(); + JoyTabWidget *tabwidget = (JoyTabWidget*)ui->tabWidget->widget(joyindex); + tabwidget->fillButtons(); +} + +void MainWindow::fillButtons(QHash *joysticks) +{ + for (int i=0; i < joysticks->count(); i++) + { + Joystick *joystick = joysticks->value(i); + if (ui->tabWidget->widget(i) != 0) + { + ui->tabWidget->widget(i)->deleteLater(); + } + + JoyTabWidget *tabwidget = new JoyTabWidget(joystick, this); + tabwidget->fillButtons(); + ui->tabWidget->addTab(tabwidget, QString("Joystick %1").arg(joystick->getRealJoyNumber())); + connect(tabwidget, SIGNAL(joystickRefreshRequested(Joystick*)), this, SLOT(joystickRefreshPropogate(Joystick*))); + } + + if (joysticks->count() > 0) + { + loadAppConfig(); + + ui->tabWidget->setCurrentIndex(0); + ui->stackedWidget->setCurrentIndex(1); + } +} + +void MainWindow::joystickRefreshPropogate(Joystick *joystick) +{ + emit joystickRefreshRequested(joystick); +} + +// Intermediate slot to be used in Form Designer +void MainWindow::startJoystickRefresh() +{ + ui->stackedWidget->setCurrentIndex(0); + + /*for (int i=0; i < ui->tabWidget->count(); i++) + { + QLayout* old_layout = ui->tabWidget->widget(i)->findChild("gridLayout"); + QWidget* child = 0; + + while (old_layout && old_layout->count() > 0) + { + child = old_layout->takeAt(0)->widget(); + old_layout->removeWidget (child); + delete child; + child = 0; + } + }*/ + + emit joystickRefreshRequested(); +} + +void MainWindow::populateTrayIcon() +{ + QMenu *trayIconMenu = new QMenu(this); + + hideAction = new QAction(tr("Hide"), this); + connect(hideAction, SIGNAL(triggered()), this, SLOT(hide())); + connect(hideAction, SIGNAL(triggered()), this, SLOT(disableFlashActions())); + + restoreAction = new QAction(tr("Restore"), this); + connect(restoreAction, SIGNAL(triggered()), this, SLOT(enableFlashActions())); + connect(restoreAction, SIGNAL(triggered()), this, SLOT(show())); + + closeAction = new QAction(tr("Quit"), this); + connect(closeAction, SIGNAL(triggered()), this, SLOT(close())); + + updateJoy = new QAction(tr("Update Joysticks"), this); + connect(updateJoy, SIGNAL(triggered()), this, SLOT(startJoystickRefresh())); + + trayIconMenu->addAction(hideAction); + trayIconMenu->addAction(restoreAction); + trayIconMenu->addAction(updateJoy); + trayIconMenu->addAction(closeAction); + + QIcon icon = QIcon(":/images/joystick_icon.png"); + trayIcon = new QSystemTrayIcon(this); + trayIcon->setIcon(icon); + trayIcon->setContextMenu(trayIconMenu); + connect(trayIconMenu, SIGNAL(aboutToShow()), this, SLOT(refreshTrayIconMenu())); + //connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(refreshTrayIconMenu(QSystemTrayIcon::ActivationReason)), Qt::DirectConnection); +} + +void MainWindow::quitProgram() +{ + this->close(); +} + +void MainWindow::refreshTrayIconMenu() +{ + if (this->isHidden()) + { + hideAction->setEnabled(false); + restoreAction->setEnabled(true); + } + else + { + hideAction->setEnabled(true); + restoreAction->setEnabled(false); + } +} + +void MainWindow::mainMenuChange() +{ + if (QSystemTrayIcon::isSystemTrayAvailable()) + { + ui->actionHide->setEnabled(true); + } + else + { + ui->actionHide->setEnabled(false); + } +} + +void MainWindow::saveAppConfig() +{ + if (joysticks->count() > 0) + { + QSettings settings(PadderCommon::configFilePath, QSettings::IniFormat); + settings.clear(); + settings.beginGroup("Controllers"); + + for (int i=0; i < ui->tabWidget->count(); i++) + { + JoyTabWidget *tabwidget = (JoyTabWidget*)ui->tabWidget->widget(i); + tabwidget->saveSettings(&settings); + } + + settings.endGroup(); + } +} + +void MainWindow::loadAppConfig() +{ + QSettings settings(PadderCommon::configFilePath, QSettings::IniFormat); + for (int i=0; i < ui->tabWidget->count(); i++) + { + JoyTabWidget *tabwidget = (JoyTabWidget*)ui->tabWidget->widget(i); + tabwidget->loadSettings(&settings); + } +} + +void MainWindow::disableFlashActions() +{ + for (int i=0; i < ui->tabWidget->count(); i++) + { + QList list = ui->tabWidget->widget(i)->findChildren(); + QListIterator iter(list); + while (iter.hasNext()) + { + JoyButtonWidget *buttonWidget = iter.next(); + buttonWidget->disableFlashes(); + } + + QList list2 = ui->tabWidget->widget(i)->findChildren(); + QListIterator iter2(list2); + while (iter2.hasNext()) + { + JoyAxisWidget *axisWidget = iter2.next(); + axisWidget->disableFlashes(); + } + } +} + +void MainWindow::enableFlashActions() +{ + for (int i=0; i < ui->tabWidget->count(); i++) + { + QList list = ui->tabWidget->widget(i)->findChildren(); + QListIterator iter(list); + while (iter.hasNext()) + { + JoyButtonWidget *buttonWidget = iter.next(); + buttonWidget->enableFlashes(); + } + + QList list2 = ui->tabWidget->widget(i)->findChildren(); + QListIterator iter2(list2); + while (iter2.hasNext()) + { + JoyAxisWidget *axisWidget = iter2.next(); + axisWidget->enableFlashes(); + } + } +} + +// Intermediate slot used in Design mode +void MainWindow::hideWindow() +{ + hide(); + disableFlashActions(); +} + +// Intermediate slot used in Design mode +void MainWindow::restoreWindow() +{ + enableFlashActions(); + show(); +} diff --git a/mainwindow.h b/mainwindow.h new file mode 100644 index 00000000..b01e7cda --- /dev/null +++ b/mainwindow.h @@ -0,0 +1,60 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include +#include +#include +#include + +#include "joystick.h" + +namespace Ui { +class MainWindow; +} + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QHash *joysticks, QWidget *parent = 0); + ~MainWindow(); + +protected: + void populateTrayIcon(); + + QHash *joysticks; + QSystemTrayIcon *trayIcon; + QAction *hideAction; + QAction *restoreAction; + QAction *closeAction; + QAction *updateJoy; + +private: + Ui::MainWindow *ui; + +signals: + void joystickRefreshRequested(); + void joystickRefreshRequested(Joystick *joystick); + void readConfig(int index); + +public slots: + void fillButtons(Joystick *joystick); + void fillButtons(QHash* joysticks); + void startJoystickRefresh(); + void hideWindow(); + void restoreWindow(); + +private slots: + void quitProgram(); + void refreshTrayIconMenu(); + void mainMenuChange(); + void saveAppConfig(); + void loadAppConfig(); + void disableFlashActions(); + void enableFlashActions(); + void joystickRefreshPropogate(Joystick *joystick); +}; + +#endif // MAINWINDOW_H diff --git a/mainwindow.ui b/mainwindow.ui new file mode 100644 index 00000000..e18c6862 --- /dev/null +++ b/mainwindow.ui @@ -0,0 +1,421 @@ + + + MainWindow + + + Qt::WindowModal + + + + 0 + 0 + 700 + 526 + + + + AntiMicro + + + + + 4 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + QFrame::NoFrame + + + QFrame::Plain + + + 1 + + + 1 + + + + + 0 + + + + + No Joysticks have been found. + Please plug in a joystick and then choose the "Update Joysticks" option in the main menu + + + true + + + Qt::AlignCenter + + + true + + + + + + + + + 0 + + + + + true + + + Qt::LeftToRight + + + QTabWidget::North + + + QTabWidget::Rounded + + + 0 + + + true + + + false + + + false + + + false + + + + + 0 + 0 + + + + Qt::LeftToRight + + + Tab 1 + + + + + + + + + 0 + 0 + + + + false + + + + <None> + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 30 + 20 + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + Load + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + Save + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + Save As + + + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 5 + + + + + + + + QLayout::SetDefaultConstraint + + + + + + 0 + 0 + + + + + 0 + 0 + + + + PushButton + + + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 5 + + + + + + + + + 0 + 0 + + + + + 75 + 0 + + + + Reset + + + + + + + + Tab 2 + + + + + + + + + + + + + + + 0 + 0 + 700 + 21 + + + + + File + + + + + + + Options + + + + + + + + + TopToolBarArea + + + false + + + + + Quit + + + + + Update Joysticks + + + + + Hide + + + + + + + + actionQuit + activated() + MainWindow + close() + + + -1 + -1 + + + 199 + 149 + + + + + actionUpdate_Joysticks + activated() + MainWindow + startJoystickRefresh() + + + -1 + -1 + + + 349 + 262 + + + + + actionHide + activated() + MainWindow + hideWindow() + + + -1 + -1 + + + 349 + 262 + + + + + + startJoystickRefresh() + hideWindow() + + diff --git a/resources.qrc b/resources.qrc new file mode 100644 index 00000000..6eb4fc94 --- /dev/null +++ b/resources.qrc @@ -0,0 +1,5 @@ + + + images/joystick_icon.png + + diff --git a/xmlconfigreader.cpp b/xmlconfigreader.cpp new file mode 100644 index 00000000..70255f83 --- /dev/null +++ b/xmlconfigreader.cpp @@ -0,0 +1,136 @@ +#include +#include + +#include "xmlconfigreader.h" + +XMLConfigReader::XMLConfigReader(QObject *parent) : + QObject(parent) +{ + fileName = QString(PadderCommon::configPath + "/dudeman.xml"); + configFile = new QFile(fileName); + xml = new QXmlStreamReader(); + joystick = 0; +} + +void XMLConfigReader::setJoystick(Joystick *joystick) +{ + this->joystick = joystick; +} + +void XMLConfigReader::setFileName(QString filename) +{ + QFile *temp = new QFile(filename); + if (temp->exists()) + { + configFile = temp; + } + else + { + delete temp; + temp = 0; + } +} + +void XMLConfigReader::configJoystick(Joystick *joystick) +{ + this->joystick = joystick; + read(); +} + +bool XMLConfigReader::read() +{ + if (configFile->exists() && joystick) + { + xml->clear(); + + if (!configFile->isOpen()) + { + configFile->open(QFile::ReadOnly | QFile::Text); + xml->setDevice(configFile); + } + + xml->readNextStartElement(); + if (xml->name() != "joystick") + { + xml->raiseError("Root node is not a joystick"); + } + else + { + xml->readNextStartElement(); + } + + while (!xml->atEnd()) + { + if (xml->name() == "button" && xml->isStartElement()) + { + int index = xml->attributes().value("index").toString().toInt(); + JoyButton *button = joystick->getJoyButton(index-1); + if (button) + { + button->readConfig(xml); + } + else + { + xml->skipCurrentElement(); + } + } + else if (xml->name() == "axis" && xml->isStartElement()) + { + int index = xml->attributes().value("index").toString().toInt(); + JoyAxis *axis = joystick->getJoyAxis(index-1); + if (axis) + { + axis->readConfig(xml); + } + else + { + xml->skipCurrentElement(); + } + } + else if (xml->name() == "dpad" && xml->isStartElement()) + { + int index = xml->attributes().value("index").toString().toInt(); + JoyDPad *dpad = joystick->getJoyDPad(index-1); + if (dpad) + { + dpad->readConfig(xml); + } + else + { + xml->skipCurrentElement(); + } + } + else + { + // If none of the above, skip the element + xml->skipCurrentElement(); + } + + xml->readNextStartElement(); + } + + configFile->close(); + } + + return !xml->error(); +} + +XMLConfigReader::~XMLConfigReader() +{ + if (configFile) + { + if (configFile->isOpen()) + { + configFile->close(); + } + + delete configFile; + configFile = 0; + } + + if (xml) + { + delete xml; + xml = 0; + } +} diff --git a/xmlconfigreader.h b/xmlconfigreader.h new file mode 100644 index 00000000..67faecf1 --- /dev/null +++ b/xmlconfigreader.h @@ -0,0 +1,36 @@ +#ifndef XMLCONFIGREADER_H +#define XMLCONFIGREADER_H + +#include +#include +#include + +#include "joystick.h" +#include "common.h" + +class XMLConfigReader : public QObject +{ + Q_OBJECT +public: + explicit XMLConfigReader(QObject *parent = 0); + ~XMLConfigReader(); + void setJoystick(Joystick *joystick); + void setFileName(QString filename); + + bool read(); + + +protected: + QXmlStreamReader *xml; + QString fileName; + QFile *configFile; + Joystick* joystick; + +signals: + +public slots: + void configJoystick(Joystick *joystick); + +}; + +#endif // XMLCONFIGREADER_H diff --git a/xmlconfigwriter.cpp b/xmlconfigwriter.cpp new file mode 100644 index 00000000..1b0c6d92 --- /dev/null +++ b/xmlconfigwriter.cpp @@ -0,0 +1,76 @@ +#include + +#include "xmlconfigwriter.h" + +XMLConfigWriter::XMLConfigWriter(QObject *parent) : + QObject(parent) +{ + + fileName = QString(PadderCommon::configPath + "/brony.xml"); + configFile = new QFile(fileName); + xml = new QXmlStreamWriter(); + xml->setAutoFormatting(true); + joystick = 0; +} + +void XMLConfigWriter::write(Joystick *joystick) +{ + if (!configFile->isOpen()) + { + configFile->open(QFile::WriteOnly | QFile::Text); + xml->setDevice(configFile); + } + + xml->writeStartDocument(); + xml->writeStartElement("joystick"); + + for (int i=0; i < joystick->getNumberAxes(); i++) + { + JoyAxis *axis = joystick->getJoyAxis(i); + axis->writeConfig(xml); + } + + for (int i=0; i < joystick->getNumberHats(); i++) + { + JoyDPad *dpad = joystick->getJoyDPad(i); + dpad->writeConfig(xml); + } + + for (int i=0; i < joystick->getNumberButtons(); i++) + { + JoyButton *button = joystick->getJoyButton(i); + button->writeConfig(xml); + } + + xml->writeEndElement(); + xml->writeEndDocument(); + + configFile->close(); +} + +void XMLConfigWriter::setFileName(QString filename) +{ + QFile *temp = new QFile(filename); + fileName = filename; + configFile = temp; +} + +XMLConfigWriter::~XMLConfigWriter() +{ + if (configFile) + { + if (configFile->isOpen()) + { + configFile->close(); + } + + delete configFile; + configFile = 0; + } + + if (xml) + { + delete xml; + xml = 0; + } +} diff --git a/xmlconfigwriter.h b/xmlconfigwriter.h new file mode 100644 index 00000000..b3727acd --- /dev/null +++ b/xmlconfigwriter.h @@ -0,0 +1,32 @@ +#ifndef XMLCONFIGWRITER_H +#define XMLCONFIGWRITER_H + +#include +#include +#include + +#include "joystick.h" +#include "common.h" + +class XMLConfigWriter : public QObject +{ + Q_OBJECT +public: + explicit XMLConfigWriter(QObject *parent = 0); + ~XMLConfigWriter(); + void setFileName(QString filename); + +protected: + QXmlStreamWriter *xml; + QString fileName; + QFile *configFile; + Joystick* joystick; + +signals: + +public slots: + void write(Joystick* joystick); + +}; + +#endif // XMLCONFIGWRITER_H