summaryrefslogtreecommitdiffstats
path: root/kcontrol/joystick/joywidget.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kcontrol/joystick/joywidget.cpp')
-rw-r--r--kcontrol/joystick/joywidget.cpp379
1 files changed, 379 insertions, 0 deletions
diff --git a/kcontrol/joystick/joywidget.cpp b/kcontrol/joystick/joywidget.cpp
new file mode 100644
index 000000000..a4d42e3f1
--- /dev/null
+++ b/kcontrol/joystick/joywidget.cpp
@@ -0,0 +1,379 @@
+/***************************************************************************
+ * Copyright (C) 2003 by Martin Koller *
+ * This file is part of the KDE Control Center Module for Joysticks *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+#include "joywidget.h"
+#include "joydevice.h"
+#include "poswidget.h"
+#include "caldialog.h"
+
+#include <qhbox.h>
+#include <qvbox.h>
+#include <qtable.h>
+#include <qlabel.h>
+#include <qcombobox.h>
+#include <qlistbox.h>
+#include <qcheckbox.h>
+#include <qtimer.h>
+#include <qfontmetrics.h>
+#include <qpushbutton.h>
+
+#include <klocale.h>
+#include <kdialog.h>
+#include <kmessagebox.h>
+#include <kiconloader.h>
+
+//--------------------------------------------------------------
+static QString PRESSED = I18N_NOOP("PRESSED");
+//--------------------------------------------------------------
+
+JoyWidget::JoyWidget(QWidget *parent, const char *name)
+ : QWidget(parent, name), idle(0), joydev(0)
+{
+ QVBox *mainVbox = new QVBox(parent);
+ mainVbox->setSpacing(KDialog::spacingHint());
+
+ // create area to show an icon + message if no joystick was detected
+ {
+ messageBox = new QHBox(mainVbox);
+ messageBox->setSpacing(KDialog::spacingHint());
+ QLabel *icon = new QLabel(messageBox);
+ icon->setPixmap(KGlobal::iconLoader()->loadIcon("messagebox_warning", KIcon::NoGroup,
+ KIcon::SizeMedium, KIcon::DefaultState, 0, true));
+ icon->setFixedSize(icon->sizeHint());
+ message = new QLabel(messageBox);
+ messageBox->hide();
+ }
+
+ QHBox *devHbox = new QHBox(mainVbox);
+ new QLabel(i18n("Device:"), devHbox);
+ device = new QComboBox(true, devHbox);
+ device->setInsertionPolicy(QComboBox::NoInsertion);
+ connect(device, SIGNAL(activated(const QString &)), this, SLOT(deviceChanged(const QString &)));
+ devHbox->setStretchFactor(device, 3);
+
+ QHBox *hbox = new QHBox(mainVbox);
+ hbox->setSpacing(KDialog::spacingHint());
+
+ QVBox *vboxLeft = new QVBox(hbox);
+ vboxLeft->setSpacing(KDialog::spacingHint());
+
+ new QLabel(i18n("Position:"), vboxLeft);
+ xyPos = new PosWidget(vboxLeft);
+ trace = new QCheckBox(i18n("Show trace"), mainVbox);
+ connect(trace, SIGNAL(toggled(bool)), this, SLOT(traceChanged(bool)));
+
+ QVBox *vboxMid = new QVBox(hbox);
+ vboxMid->setSpacing(KDialog::spacingHint());
+
+ QVBox *vboxRight = new QVBox(hbox);
+ vboxRight->setSpacing(KDialog::spacingHint());
+
+ // calculate the column width we need
+ QFontMetrics fm(font());
+ int colWidth = QMAX(fm.width(PRESSED), fm.width("-32767")) + 10; // -32767 largest string
+
+ new QLabel(i18n("Buttons:"), vboxMid);
+ buttonTbl = new QTable(0, 1, vboxMid);
+ buttonTbl->setReadOnly(true);
+ buttonTbl->horizontalHeader()->setLabel(0, i18n("State"));
+ buttonTbl->horizontalHeader()->setClickEnabled(false);
+ buttonTbl->horizontalHeader()->setResizeEnabled(false);
+ buttonTbl->verticalHeader()->setClickEnabled(false);
+ buttonTbl->verticalHeader()->setResizeEnabled(false);
+ buttonTbl->setColumnWidth(0, colWidth);
+
+ new QLabel(i18n("Axes:"), vboxRight);
+ axesTbl = new QTable(0, 1, vboxRight);
+ axesTbl->setReadOnly(true);
+ axesTbl->horizontalHeader()->setLabel(0, i18n("Value"));
+ axesTbl->horizontalHeader()->setClickEnabled(false);
+ axesTbl->horizontalHeader()->setResizeEnabled(false);
+ axesTbl->verticalHeader()->setClickEnabled(false);
+ axesTbl->verticalHeader()->setResizeEnabled(false);
+ axesTbl->setColumnWidth(0, colWidth);
+
+ // calibrate button
+ calibrate = new QPushButton(i18n("Calibrate"), mainVbox);
+ connect(calibrate, SIGNAL(clicked()), this, SLOT(calibrateDevice()));
+ calibrate->setEnabled(false);
+
+ // set up a timer for idle processing of joystick events
+ idle = new QTimer(this);
+ connect(idle, SIGNAL(timeout()), this, SLOT(checkDevice()));
+
+ // check which devicefiles we have
+ init();
+
+ vboxLeft->adjustSize();
+ vboxMid->adjustSize();
+ vboxRight->adjustSize();
+ hbox->adjustSize();
+ mainVbox->adjustSize();
+
+ setMinimumSize(mainVbox->size());
+}
+
+//--------------------------------------------------------------
+
+JoyWidget::~JoyWidget()
+{
+ delete joydev;
+}
+
+//--------------------------------------------------------------
+
+void JoyWidget::init()
+{
+ // check which devicefiles we have
+ int i;
+ bool first = true;
+ char dev[30];
+
+ device->clear();
+ buttonTbl->setNumRows(0);
+ axesTbl->setNumRows(0);
+
+ for (i = 0; i < 5; i++) // check the first 5 devices
+ {
+ sprintf(dev, "/dev/js%d", i); // first look in /dev
+ JoyDevice *joy = new JoyDevice(dev);
+
+ if ( joy->open() != JoyDevice::SUCCESS )
+ {
+ delete joy;
+ sprintf(dev, "/dev/input/js%d", i); // then look in /dev/input
+ joy = new JoyDevice(dev);
+
+ if ( joy->open() != JoyDevice::SUCCESS )
+ {
+ delete joy;
+ continue; // try next number
+ }
+ }
+
+ // we found one
+
+ device->insertItem(QString("%1 (%2)").arg(joy->text()).arg(joy->device()));
+
+ // display values for first device
+ if ( first )
+ {
+ showDeviceProps(joy); // this sets the joy object into this->joydev
+ first = false;
+ }
+ else
+ delete joy;
+ }
+
+ /* KDE 4: Remove this check(and i18n) when all KCM wrappers properly test modules */
+ if ( device->count() == 0 )
+ {
+ messageBox->show();
+ message->setText(QString("<qt><b>%1</b></qt>").arg(
+ i18n("No joystick device automatically found on this computer.<br>"
+ "Checks were done in /dev/js[0-4] and /dev/input/js[0-4]<br>"
+ "If you know that there is one attached, please enter the correct device file.")));
+ }
+}
+
+//--------------------------------------------------------------
+
+void JoyWidget::traceChanged(bool state)
+{
+ xyPos->showTrace(state);
+}
+
+//--------------------------------------------------------------
+
+void JoyWidget::restoreCurrDev()
+{
+ if ( !joydev ) // no device open
+ {
+ device->setCurrentText("");
+ calibrate->setEnabled(false);
+ }
+ else
+ {
+ // try to find the current open device in the combobox list
+ QListBoxItem *item;
+ item = device->listBox()->findItem(joydev->device(), Qt::Contains);
+
+ if ( !item ) // the current open device is one the user entered (not in the list)
+ device->setCurrentText(joydev->device());
+ else
+ device->setCurrentText(item->text());
+ }
+}
+
+//--------------------------------------------------------------
+
+void JoyWidget::deviceChanged(const QString &dev)
+{
+ // find "/dev" in given string
+ int start, stop;
+ QString devName;
+
+ if ( (start = dev.find("/dev")) == -1 )
+ {
+ KMessageBox::sorry(this,
+ i18n("The given device name is invalid (does not contain /dev).\n"
+ "Please select a device from the list or\n"
+ "enter a device file, like /dev/js0."), i18n("Unknown Device"));
+
+ restoreCurrDev();
+ return;
+ }
+
+ if ( (stop = dev.find(")", start)) != -1 ) // seems to be text selected from our list
+ devName = dev.mid(start, stop - start);
+ else
+ devName = dev.mid(start);
+
+ if ( joydev && (devName == joydev->device()) ) return; // user selected the current device; ignore it
+
+ JoyDevice *joy = new JoyDevice(devName);
+ JoyDevice::ErrorCode ret = joy->open();
+
+ if ( ret != JoyDevice::SUCCESS )
+ {
+ KMessageBox::error(this, joy->errText(ret), i18n("Device Error"));
+
+ delete joy;
+ restoreCurrDev();
+ return;
+ }
+
+ showDeviceProps(joy);
+}
+
+//--------------------------------------------------------------
+
+void JoyWidget::showDeviceProps(JoyDevice *joy)
+{
+ joydev = joy;
+
+ buttonTbl->setNumRows(joydev->numButtons());
+
+ axesTbl->setNumRows(joydev->numAxes());
+ if ( joydev->numAxes() >= 2 )
+ {
+ axesTbl->verticalHeader()->setLabel(0, "1(x)");
+ axesTbl->verticalHeader()->setLabel(1, "2(y)");
+ }
+
+ calibrate->setEnabled(true);
+ idle->start(0);
+
+ // make both tables use the same space for header; this looks nicer
+ buttonTbl->setLeftMargin(QMAX(buttonTbl->verticalHeader()->width(),
+ axesTbl->verticalHeader()->width()));
+ axesTbl->setLeftMargin(buttonTbl->verticalHeader()->width());
+}
+
+//--------------------------------------------------------------
+
+void JoyWidget::checkDevice()
+{
+ if ( !joydev ) return; // no open device yet
+
+ JoyDevice::EventType type;
+ int number, value;
+
+ if ( !joydev->getEvent(type, number, value) )
+ return;
+
+ if ( type == JoyDevice::BUTTON )
+ {
+ if ( value == 0 ) // button release
+ buttonTbl->setText(number, 0, "-");
+ else
+ buttonTbl->setText(number, 0, PRESSED);
+ }
+
+ if ( type == JoyDevice::AXIS )
+ {
+ if ( number == 0 ) // x-axis
+ xyPos->changeX(value);
+
+ if ( number == 1 ) // y-axis
+ xyPos->changeY(value);
+
+ axesTbl->setText(number, 0, QString("%1").arg(int(value)));
+ }
+}
+
+//--------------------------------------------------------------
+
+void JoyWidget::calibrateDevice()
+{
+ if ( !joydev ) return; // just to be save
+
+ JoyDevice::ErrorCode ret = joydev->initCalibration();
+
+ if ( ret != JoyDevice::SUCCESS )
+ {
+ KMessageBox::error(this, joydev->errText(ret), i18n("Communication Error"));
+ return;
+ }
+
+ if ( KMessageBox::messageBox(this, KMessageBox::Information,
+ i18n("<qt>Calibration is about to check the precision.<br><br>"
+ "<b>Please move all axes to their center position and then "
+ "do not touch the joystick anymore.</b><br><br>"
+ "Click OK to start the calibration.</qt>"),
+ i18n("Calibration"),
+ KStdGuiItem::ok(), KStdGuiItem::cancel()) != KMessageBox::Ok )
+ return;
+
+ idle->stop(); // stop the joystick event getting; this must be done inside the calibrate dialog
+
+ CalDialog dlg(this, joydev);
+ dlg.calibrate();
+
+ // user cancelled somewhere during calibration, therefore the device is in a bad state
+ if ( dlg.result() == QDialog::Rejected )
+ joydev->restoreCorr();
+
+ idle->start(0); // continue with event getting
+}
+
+//--------------------------------------------------------------
+
+void JoyWidget::resetCalibration()
+{
+ if ( !joydev ) return; // just to be save
+
+ JoyDevice::ErrorCode ret = joydev->restoreCorr();
+
+ if ( ret != JoyDevice::SUCCESS )
+ {
+ KMessageBox::error(this, joydev->errText(ret), i18n("Communication Error"));
+ }
+ else
+ {
+ KMessageBox::information(this,
+ i18n("Restored all calibration values for joystick device %1.").arg(joydev->device()),
+ i18n("Calibration Success"));
+ }
+}
+
+//--------------------------------------------------------------
+
+#include "joywidget.moc"