#include "joypadw.h" JoyPadWidget::JoyPadWidget( JoyPad* jp, int i, QWidget* parent ) : QWidget(parent) { //initialize things, build the accessible dialog joypad = jp; index = i; flashcount = 0; quickset = NULL; // Create main vertical layout layoutMain = new QVBoxLayout(this); layoutMain->setSpacing(10); layoutMain->setMargin(10); // Create horizontal layout for axes and buttons groups topLayout = new QHBoxLayout(); // Create axes group axesGroup = new QGroupBox("Axes", this); QVBoxLayout *axesLayout = new QVBoxLayout(axesGroup); axesList = new QListWidget(axesGroup); axesList->setAccessibleName("Axes List"); axesList->setAccessibleDescription("List of joystick axes for configuration"); axesLayout->addWidget(axesList); btnConfigureAxis = new QPushButton("Configure Selected Axis", axesGroup); btnConfigureAxis->setEnabled(false); btnConfigureAxis->setAccessibleDescription("Configure the currently selected axis"); btnConfigureAxis->setFocusPolicy(Qt::TabFocus); connect(btnConfigureAxis, SIGNAL(clicked()), this, SLOT(configureSelectedAxis())); axesLayout->addWidget(btnConfigureAxis); axisStatusLabel = new QLabel("Select an axis to configure", axesGroup); axisStatusLabel->setWordWrap(true); axesLayout->addWidget(axisStatusLabel); // Create buttons group buttonsGroup = new QGroupBox("Buttons", this); QVBoxLayout *buttonsLayout = new QVBoxLayout(buttonsGroup); buttonsList = new QListWidget(buttonsGroup); buttonsList->setAccessibleName("Buttons List"); buttonsList->setAccessibleDescription("List of joystick buttons for configuration"); buttonsLayout->addWidget(buttonsList); btnConfigureButton = new QPushButton("Configure Selected Button", buttonsGroup); btnConfigureButton->setEnabled(false); btnConfigureButton->setAccessibleDescription("Configure the currently selected button"); btnConfigureButton->setFocusPolicy(Qt::TabFocus); connect(btnConfigureButton, SIGNAL(clicked()), this, SLOT(configureSelectedButton())); buttonsLayout->addWidget(btnConfigureButton); buttonStatusLabel = new QLabel("Select a button to configure", buttonsGroup); buttonStatusLabel->setWordWrap(true); buttonsLayout->addWidget(buttonStatusLabel); // Add groups to horizontal layout topLayout->addWidget(axesGroup); topLayout->addWidget(buttonsGroup); layoutMain->addLayout(topLayout); // Create the underlying widgets for compatibility foreach (Axis *axis, joypad->axes) { AxisWidget *aw = new AxisWidget(axis, this); aw->setVisible(false); // Hide the old widgets axes.append(aw); connect( aw, SIGNAL( flashed( bool ) ), this, SLOT( flash( bool ))); } foreach (Button *button, joypad->buttons) { ButtonWidget *bw = new ButtonWidget(button, this); bw->setVisible(false); // Hide the old widgets buttons.append(bw); connect( bw, SIGNAL( flashed( bool ) ), this, SLOT( flash( bool ))); } // Control buttons QHBoxLayout *controlLayout = new QHBoxLayout(); btnClear = new QPushButton(QIcon::fromTheme("edit-clear"), "Clear All", this); btnClear->setAccessibleDescription("Clear all axis and button configurations"); btnClear->setFocusPolicy(Qt::StrongFocus); btnClear->setAccessibleName("Clear All Button"); connect(btnClear, SIGNAL(clicked()), this, SLOT(clear())); controlLayout->addWidget(btnClear); btnAll = new QPushButton("Quick Set", this); btnAll->setAccessibleDescription("Quick configuration mode for all controls"); btnAll->setFocusPolicy(Qt::StrongFocus); // Try StrongFocus instead of TabFocus btnAll->setAccessibleName("Quick Set Button"); connect(btnAll, SIGNAL(clicked()), this, SLOT(setAll())); controlLayout->addWidget(btnAll); controlLayout->addStretch(); layoutMain->addLayout(controlLayout); // Connect selection change signals connect(axesList, SIGNAL(itemSelectionChanged()), this, SLOT(onAxisSelectionChanged())); connect(buttonsList, SIGNAL(itemSelectionChanged()), this, SLOT(onButtonSelectionChanged())); // Set explicit tab order to ensure all widgets are accessible setTabOrder(axesList, btnConfigureAxis); setTabOrder(btnConfigureAxis, buttonsList); setTabOrder(buttonsList, btnConfigureButton); setTabOrder(btnConfigureButton, btnClear); setTabOrder(btnClear, btnAll); // Populate the lists update(); } JoyPadWidget::~JoyPadWidget() { //so the joypad knows that we're done. joypad->releaseWidget(); } void JoyPadWidget::flash( bool on ) { //true iff this entire widget was considered "flashed" before bool wasOn = (flashcount != 0); //adjust the count based on this new flash flashcount += (on?1:-1); //if we were on and should now be off, or visa versa, flash the whole widget if (wasOn != (flashcount != 0)) { emit flashed(index); } } void JoyPadWidget::update() { // Update underlying widgets foreach (AxisWidget *axis, axes) { axis->update(); } foreach (ButtonWidget *button, buttons) { button->update(); } // Update accessible lists axesList->clear(); for (int i = 0; i < axes.size(); i++) { QString axisName = QString("Axis %1").arg(i + 1); QString axisDesc = axes[i]->text(); // Get current configuration description axesList->addItem(QString("%1: %2").arg(axisName, axisDesc)); } buttonsList->clear(); for (int i = 0; i < buttons.size(); i++) { QString buttonName = QString("Button %1").arg(i + 1); QString buttonDesc = buttons[i]->text(); // Get current configuration description buttonsList->addItem(QString("%1: %2").arg(buttonName, buttonDesc)); } } void JoyPadWidget::clear() { joypad->toDefault(); update(); } void JoyPadWidget::setAll() { //quickset is NULL if there is no quickset dialog, and a pointer to the //dialog otherwise. This is so we can forward jsevents properly. quickset = new QuickSet(joypad, this); quickset->exec(); update(); delete quickset; quickset = NULL; } void JoyPadWidget::jsevent( const js_event& msg ) { //notify the component this event applies to. this cannot generate anything //other than a flash :) unsigned int type = msg.type & ~JS_EVENT_INIT; if (type == JS_EVENT_AXIS) { if (msg.number < axes.size()) axes[msg.number]->jsevent(msg.value); else debug_mesg("DEBUG: axis index out of range: %d\n", msg.value); } else if (type == JS_EVENT_BUTTON) { if (msg.number < buttons.size()) buttons[msg.number]->jsevent(msg.value); else debug_mesg("DEBUG: button index out of range: %d\n", msg.value); } //if we're doing quickset, it needs to know when we do something. if (quickset != NULL) { quickset->jsevent(msg); } } void JoyPadWidget::updateButtonLayoutLists(const QStringList layoutNames) { foreach (ButtonWidget *bw, buttons) { bw->layoutNames = layoutNames; } } void JoyPadWidget::configureSelectedAxis() { int selectedRow = axesList->currentRow(); if (selectedRow >= 0 && selectedRow < axes.size()) { // Use the public configure method for accessibility axes[selectedRow]->configure(); // Update the display after configuration update(); } } void JoyPadWidget::configureSelectedButton() { int selectedRow = buttonsList->currentRow(); if (selectedRow >= 0 && selectedRow < buttons.size()) { // Use the public configure method for accessibility buttons[selectedRow]->configure(); // Update the display after configuration update(); } } void JoyPadWidget::onAxisSelectionChanged() { bool hasSelection = axesList->currentRow() >= 0; btnConfigureAxis->setEnabled(hasSelection); if (hasSelection) { int selectedRow = axesList->currentRow(); if (selectedRow < axes.size()) { axisStatusLabel->setText(QString("Selected: %1").arg(axesList->currentItem()->text())); } } else { axisStatusLabel->setText("Select an axis to configure"); } } void JoyPadWidget::onButtonSelectionChanged() { bool hasSelection = buttonsList->currentRow() >= 0; btnConfigureButton->setEnabled(hasSelection); if (hasSelection) { int selectedRow = buttonsList->currentRow(); if (selectedRow < buttons.size()) { buttonStatusLabel->setText(QString("Selected: %1").arg(buttonsList->currentItem()->text())); } } else { buttonStatusLabel->setText("Select a button to configure"); } }