diff options
Diffstat (limited to 'kcontrol/joystick')
-rw-r--r-- | kcontrol/joystick/Makefile.am | 17 | ||||
-rw-r--r-- | kcontrol/joystick/caldialog.cpp | 193 | ||||
-rw-r--r-- | kcontrol/joystick/caldialog.h | 54 | ||||
-rw-r--r-- | kcontrol/joystick/configure.in.in | 7 | ||||
-rw-r--r-- | kcontrol/joystick/joydevice.cpp | 397 | ||||
-rw-r--r-- | kcontrol/joystick/joydevice.h | 110 | ||||
-rw-r--r-- | kcontrol/joystick/joystick.cpp | 123 | ||||
-rw-r--r-- | kcontrol/joystick/joystick.desktop | 177 | ||||
-rw-r--r-- | kcontrol/joystick/joystick.h | 42 | ||||
-rw-r--r-- | kcontrol/joystick/joywidget.cpp | 379 | ||||
-rw-r--r-- | kcontrol/joystick/joywidget.h | 79 | ||||
-rw-r--r-- | kcontrol/joystick/poswidget.cpp | 138 | ||||
-rw-r--r-- | kcontrol/joystick/poswidget.h | 55 |
13 files changed, 1771 insertions, 0 deletions
diff --git a/kcontrol/joystick/Makefile.am b/kcontrol/joystick/Makefile.am new file mode 100644 index 000000000..269dec101 --- /dev/null +++ b/kcontrol/joystick/Makefile.am @@ -0,0 +1,17 @@ +AM_CPPFLAGS = $(all_includes) +METASOURCES = AUTO + +# Install this plugin in the KDE modules directory +kde_module_LTLIBRARIES = kcm_joystick.la + +kcm_joystick_la_SOURCES = joystick.cpp joywidget.cpp poswidget.cpp joydevice.cpp caldialog.cpp +kcm_joystick_la_LIBADD = $(LIB_KDEUI) +kcm_joystick_la_LDFLAGS = -module -avoid-version $(all_libraries) -no-undefined + +xdg_apps_DATA = joystick.desktop + +messages: + $(XGETTEXT) *.cpp -o $(podir)/joystick.pot + +noinst_HEADERS = joywidget.h joywidget.h poswidget.h joydevice.h caldialog.h + diff --git a/kcontrol/joystick/caldialog.cpp b/kcontrol/joystick/caldialog.cpp new file mode 100644 index 000000000..f8340d03c --- /dev/null +++ b/kcontrol/joystick/caldialog.cpp @@ -0,0 +1,193 @@ +/*************************************************************************** + * Copyright (C) 2003 by Martin Koller * + * m.koller@surfeu.at * + * 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 "caldialog.h" +#include "joydevice.h" + +#include <qlabel.h> +#include <qtimer.h> +#include <qapplication.h> +#include <qvbox.h> + +#include <klocale.h> +#include <kmessagebox.h> +#include <kdebug.h> + +//-------------------------------------------------------------- + +CalDialog::CalDialog(QWidget *parent, JoyDevice *joy) + : KDialogBase(parent, "calibrateDialog", true, + i18n("Calibration"), + KDialogBase::Cancel|KDialogBase::User1, KDialogBase::User1, true, KGuiItem(i18n("Next"))), + joydev(joy) +{ + QVBox *main = makeVBoxMainWidget(); + + text = new QLabel(main); + text->setMinimumHeight(200); + valueLbl = new QLabel(main); +} + +//-------------------------------------------------------------- + +void CalDialog::calibrate() +{ + text->setText(i18n("Please wait a moment to calculate the precision")); + setResult(-1); + show(); + + // calibrate precision (which min,max delivers the joystick in its center position) + // get values through the normal idle procedure + QTimer ti; + ti.start(2000, true); // single shot in 2 seconds + + // normally I'd like to hide the 'Next' button in this step, + // but it does not work - which means: in the steps after the first, + // the 'Next' button does not have the focus (to be the default button) + + do + { + qApp->processEvents(2000); + } + while ( ti.isActive() && (result() != QDialog::Rejected) ); + + if ( result() == QDialog::Rejected ) return; // user cancelled the dialog + + joydev->calcPrecision(); + + int i, lastVal; + int min[2], center[2], max[2]; + QString hint; + + for (i = 0; i < joydev->numAxes(); i++) + { + if ( i == 0 ) + hint = i18n("(usually X)"); + else if ( i == 1 ) + hint = i18n("(usually Y)"); + else + hint = ""; + + // minimum position + text->setText(i18n("<qt>Calibration is about to check the value range your device delivers.<br><br>" + "Please move <b>axis %1 %2</b> on your device to the <b>minimum</b> position.<br><br>" + "Press any button on the device or click on the 'Next' button " + "to continue with the next step.</qt>").arg(i+1).arg(hint)); + waitButton(i, true, lastVal); + + if ( result() == QDialog::Rejected ) return; // user cancelled the dialog + + joydev->resetMinMax(i, lastVal); + if ( result() != -2 ) waitButton(i, false, lastVal); + + if ( result() == QDialog::Rejected ) return; // user cancelled the dialog + + min[0] = joydev->axisMin(i); + min[1] = joydev->axisMax(i); + + // center position + text->setText(i18n("<qt>Calibration is about to check the value range your device delivers.<br><br>" + "Please move <b>axis %1 %2</b> on your device to the <b>center</b> position.<br><br>" + "Press any button on the device or click on the 'Next' button " + "to continue with the next step.</qt>").arg(i+1).arg(hint)); + waitButton(i, true, lastVal); + + if ( result() == QDialog::Rejected ) return; // user cancelled the dialog + + joydev->resetMinMax(i, lastVal); + if ( result() != -2 ) waitButton(i, false, lastVal); + + if ( result() == QDialog::Rejected ) return; // user cancelled the dialog + + center[0] = joydev->axisMin(i); + center[1] = joydev->axisMax(i); + + // maximum position + text->setText(i18n("<qt>Calibration is about to check the value range your device delivers.<br><br>" + "Please move <b>axis %1 %2</b> on your device to the <b>maximum</b> position.<br><br>" + "Press any button on the device or click on the 'Next' button " + "to continue with the next step.</qt>").arg(i+1).arg(hint)); + waitButton(i, true, lastVal); + + if ( result() == QDialog::Rejected ) return; // user cancelled the dialog + + joydev->resetMinMax(i, lastVal); + if ( result() != -2 ) waitButton(i, false, lastVal); + + if ( result() == QDialog::Rejected ) return; // user cancelled the dialog + + max[0] = joydev->axisMin(i); + max[1] = joydev->axisMax(i); + + joydev->calcCorrection(i, min, center, max); + } + + JoyDevice::ErrorCode ret = joydev->applyCalibration(); + + if ( ret != JoyDevice::SUCCESS ) + { + KMessageBox::error(this, joydev->errText(ret), i18n("Communication Error")); + reject(); + } + + KMessageBox::information(this, i18n("You have successfully calibrated your device"), i18n("Calibration Success")); + accept(); +} + +//-------------------------------------------------------------- + +void CalDialog::waitButton(int axis, bool press, int &lastVal) +{ + JoyDevice::EventType type; + int number, value; + bool button = false; + lastVal = 0; + + setResult(-1); + // loop until the user presses a button on the device or on the dialog + do + { + qApp->processEvents(100); + + if ( joydev->getEvent(type, number, value) ) + { + button = ( (type == JoyDevice::BUTTON) && (press ? (value == 1) : (value == 0)) ); + + if ( (type == JoyDevice::AXIS) && (number == axis) ) + valueLbl->setText(i18n("Value Axis %1: %2").arg(axis+1).arg(lastVal = value)); + } + } + while ( !button && (result() == -1) ); +} + +//-------------------------------------------------------------- +// Next button + +void CalDialog::slotUser1() +{ + setResult(-2); +} + +//-------------------------------------------------------------- + +#include "caldialog.moc" + +//-------------------------------------------------------------- diff --git a/kcontrol/joystick/caldialog.h b/kcontrol/joystick/caldialog.h new file mode 100644 index 000000000..678a0a2d1 --- /dev/null +++ b/kcontrol/joystick/caldialog.h @@ -0,0 +1,54 @@ +/*************************************************************************** + * Copyright (C) 2003 by Martin Koller * + * m.koller@surfeu.at * + * 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. * + ***************************************************************************/ +#ifndef _CALDIALOG_H_ +#define _CALDIALOG_H_ + +#include <kdialogbase.h> + +class QLabel; + +class JoyDevice; + +// the dialog which tells the user all steps to calibrate the device + +class CalDialog : public KDialogBase +{ + Q_OBJECT + + public: + CalDialog(QWidget *parent, JoyDevice *joy); + + void calibrate(); + + private: + void waitButton(int axis, bool press, int &lastVal); + + private slots: + virtual void slotUser1(); + + private: + JoyDevice *joydev; + + QLabel *text; + QLabel *valueLbl; +}; + +#endif diff --git a/kcontrol/joystick/configure.in.in b/kcontrol/joystick/configure.in.in new file mode 100644 index 000000000..a76ab434a --- /dev/null +++ b/kcontrol/joystick/configure.in.in @@ -0,0 +1,7 @@ +case "$host" in + *-*-linux*) + FOUND_LINUX=yes + ;; +esac + +AM_CONDITIONAL(include_kcontrol_joystick, test "$FOUND_LINUX" = "yes") diff --git a/kcontrol/joystick/joydevice.cpp b/kcontrol/joystick/joydevice.cpp new file mode 100644 index 000000000..2c1a16ce7 --- /dev/null +++ b/kcontrol/joystick/joydevice.cpp @@ -0,0 +1,397 @@ +/*************************************************************************** + * Copyright (C) 2003 by Martin Koller * + * m.koller@surfeu.at * + * 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 "joydevice.h" + +#include <klocale.h> +#include <kdebug.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/select.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <errno.h> +#include <math.h> + +//-------------------------------------------------------------- + +JoyDevice::JoyDevice(const QString &devicefile) + : devName(devicefile), joyFd(-1), buttons(0), axes(0), + amin(0), amax(0), corr(0), origCorr(0) +{ +} + +//-------------------------------------------------------------- + +QString JoyDevice::errText(ErrorCode code) const +{ + switch ( code ) + { + case SUCCESS: return ""; + + case OPEN_FAILED: + { + return i18n("The given device %1 could not be opened: %2") + .arg(devName).arg(strerror(errno)); + } + + case NO_JOYSTICK: + { + return i18n("The given device %1 is not a joystick.").arg(devName); + } + + case ERR_GET_VERSION: + { + return i18n("Could not get kernel driver version for joystick device %1: %2") + .arg(devName).arg(strerror(errno)); + } + + case WRONG_VERSION: + { + int version = 0; + int fd = ::open(devName.latin1(), O_RDONLY); + if ( fd != -1 ) + { + ::ioctl(fd, JSIOCGVERSION, &version); + ::close(fd); + } + + return i18n("The current running kernel driver version (%1.%2.%3) is not the one this module was compiled for (%4.%5.%6).") + .arg(version >> 16).arg((version >> 8) & 0xFF).arg(version & 0xFF) + .arg(JS_VERSION >> 16).arg((JS_VERSION >> 8) & 0xFF).arg(JS_VERSION & 0xFF); + } + + case ERR_GET_BUTTONS: + { + return i18n("Could not get number of buttons for joystick device %1: %2") + .arg(devName).arg(strerror(errno)); + } + + case ERR_GET_AXES: + { + return i18n("Could not get number of axes for joystick device %1: %2") + .arg(devName).arg(strerror(errno)); + } + + case ERR_GET_CORR: + { + return i18n("Could not get calibration values for joystick device %1: %2") + .arg(devName).arg(strerror(errno)); + } + + case ERR_RESTORE_CORR: + { + return i18n("Could not restore calibration values for joystick device %1: %2") + .arg(devName).arg(strerror(errno)); + } + + case ERR_INIT_CAL: + { + return i18n("Could not initialize calibration values for joystick device %1: %2") + .arg(devName).arg(strerror(errno)); + } + + case ERR_APPLY_CAL: + { + return i18n("Could not apply calibration values for joystick device %1: %2") + .arg(devName).arg(strerror(errno)); + } + + default: return i18n("internal error - code %1 unknown").arg(int(code)); + } +} + +//-------------------------------------------------------------- + +JoyDevice::ErrorCode JoyDevice::open() +{ + if ( joyFd != -1 ) return JoyDevice::SUCCESS; // already open + + int fd = ::open(devName.latin1(), O_RDONLY); + + if ( fd == -1 ) + return JoyDevice::OPEN_FAILED; + + // we could open the devicefile, now check if a joystick is attached + char name[128]; + + if ( ::ioctl(fd, JSIOCGNAME(sizeof(name)), &name) == -1 ) + { + ::close(fd); + return JoyDevice::NO_JOYSTICK; + } + + // check the kernel driver version + int version; + if ( ::ioctl(fd, JSIOCGVERSION, &version) == -1 ) + { + ::close(fd); + return JoyDevice::ERR_GET_VERSION; + } + + if ( version != JS_VERSION ) + { + ::close(fd); + return JoyDevice::WRONG_VERSION; + } + + char bt = 0, ax = 0; + if ( ::ioctl(fd, JSIOCGBUTTONS, &bt) == -1 ) + { + ::close(fd); + return JoyDevice::ERR_GET_BUTTONS; + } + + if ( ::ioctl(fd, JSIOCGAXES, &ax) == -1 ) + { + ::close(fd); + return JoyDevice::ERR_GET_AXES; + } + + struct js_corr *oldCorr = new struct js_corr[ax]; + + if ( ::ioctl(fd, JSIOCGCORR, oldCorr) == -1 ) + { + ::close(fd); + delete [] oldCorr; + return JoyDevice::ERR_GET_CORR; + } + + descr = name; + joyFd = fd; + axes = ax; + buttons = bt; + origCorr = oldCorr; + corr = new struct js_corr[axes]; + + amin = new int[axes]; + amax = new int[axes]; + + int i; + + for (i = 0; i < axes; i++) + resetMinMax(i); + + return JoyDevice::SUCCESS; +} + +//-------------------------------------------------------------- + +void JoyDevice::close() +{ + if ( joyFd == -1 ) return; + + ::close(joyFd); + + joyFd = -1; + descr = ""; + + delete [] amin; + delete [] amax; + amin = 0; + amax = 0; + + delete [] corr; + corr = 0; + delete [] origCorr; + origCorr = 0; +} + +//-------------------------------------------------------------- + +int JoyDevice::axisMin(int axis) const +{ + if ( (axis < 0) || (axis >= axes) ) return 0; + + return amin[axis]; +} + +//-------------------------------------------------------------- + +int JoyDevice::axisMax(int axis) const +{ + if ( (axis < 0) || (axis >= axes) ) return 0; + + return amax[axis]; +} + +//-------------------------------------------------------------- + +JoyDevice::ErrorCode JoyDevice::initCalibration() +{ + if ( joyFd == -1 ) return JoyDevice::ERR_INIT_CAL; + + int i; + + // Reset all current correction values + for (i = 0; i < axes; i++) + { + corr[i].type = JS_CORR_NONE; + corr[i].prec = 0; + } + + if ( ::ioctl(joyFd, JSIOCSCORR, corr) == -1 ) + return JoyDevice::ERR_INIT_CAL; + + for (i = 0; i < axes; i++) + corr[i].type = JS_CORR_BROKEN; + + return JoyDevice::SUCCESS; +} + +//-------------------------------------------------------------- + +JoyDevice::ErrorCode JoyDevice::applyCalibration() +{ + if ( joyFd == -1 ) return JoyDevice::ERR_APPLY_CAL; + + if ( ::ioctl(joyFd, JSIOCSCORR, corr) == -1 ) + return JoyDevice::ERR_APPLY_CAL; + + return JoyDevice::SUCCESS; +} + +//-------------------------------------------------------------- + +void JoyDevice::resetMinMax(int axis, int value) +{ + amin[axis] = value; + amax[axis] = value; +} + +//-------------------------------------------------------------- + +void JoyDevice::calcPrecision() +{ + if ( !corr ) return; + + int i; + + for (i = 0; i < axes; i++) + { + corr[i].prec = amax[i] - amin[i]; + kdDebug() << "Precision for axis: " << i << ": " << corr[i].prec << endl; + } +} + +//-------------------------------------------------------------- + +JoyDevice::ErrorCode JoyDevice::restoreCorr() +{ + if ( joyFd == -1 ) return JoyDevice::SUCCESS; + + if ( ::ioctl(joyFd, JSIOCSCORR, origCorr) == -1 ) + return JoyDevice::ERR_RESTORE_CORR; + else + return JoyDevice::SUCCESS; +} + +//-------------------------------------------------------------- + +JoyDevice::~JoyDevice() +{ + close(); +} + +//-------------------------------------------------------------- + +bool JoyDevice::getEvent(JoyDevice::EventType &type, int &number, int &value) +{ + number = value = 0; + + int ret; + + fd_set readSet; + + FD_ZERO(&readSet); + FD_SET(joyFd, &readSet); + + struct timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = 100000; + + ret = ::select(joyFd + 1, &readSet, 0, 0, &timeout); + + if ( ret == 1 ) // got an event from the joystick + { + struct js_event e; + + if ( ::read(joyFd, &e, sizeof(struct js_event)) == sizeof(struct js_event) ) + { + if ( e.type & JS_EVENT_BUTTON ) + { + type = JoyDevice::BUTTON; + value = e.value; + number = e.number; + + return true; + } + + if ( e.type & JS_EVENT_AXIS ) + { + type = JoyDevice::AXIS; + value = e.value; + number = e.number; + + // store min, max values + if ( e.value < amin[number] ) amin[number] = e.value; + if ( e.value > amax[number] ) amax[number] = e.value; + + return true; + } + } + } + + return false; // no event +} + +//-------------------------------------------------------------- + +void JoyDevice::calcCorrection(int axis, int *min, int *center, int *max) +{ + const int MIN = 0; + const int MAX = 1; + + double a, b, c, d; + + a = center[MIN]; // inputs.cmin[1]; + b = center[MAX]; // inputs.cmax[1]; + c = 32767.0 / (center[MIN] - min[MAX]); // (inputs.cmin[1] - inputs.cmax[0]); + d = 32767.0 / (max[MIN] - center[MAX]); // (inputs.cmin[2] - inputs.cmax[1]); + + corr[axis].coef[0] = (int)rint(a); + corr[axis].coef[1] = (int)rint(b); + corr[axis].coef[2] = (int)rint(c*16384.0); + corr[axis].coef[3] = (int)rint(d*16384.0); + + kdDebug() << "min min: " << min[0] << " max: " << min[1] << endl; + kdDebug() << "max min: " << max[0] << " max: " << max[1] << endl; + kdDebug() << "Correction values for axis: " << axis << ": " + << corr[axis].coef[0] << ", " + << corr[axis].coef[1] << ", " + << corr[axis].coef[2] << ", " + << corr[axis].coef[3] << endl; +} + +//-------------------------------------------------------------- diff --git a/kcontrol/joystick/joydevice.h b/kcontrol/joystick/joydevice.h new file mode 100644 index 000000000..b84464241 --- /dev/null +++ b/kcontrol/joystick/joydevice.h @@ -0,0 +1,110 @@ +/*************************************************************************** + * Copyright (C) 2003 by Martin Koller * + * m.koller@surfeu.at * + * 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. * + ***************************************************************************/ +#ifndef _JOYDEVICE_H_ +#define _JOYDEVICE_H_ + +#include <qstring.h> + +#include <sys/types.h> +#undef __STRICT_ANSI__ +#include <linux/joystick.h> +#define __STRICT_ANSI__ + +// helper class which holds all current values, file descriptor, etc. for +// one device +class JoyDevice +{ + public: + enum ErrorCode + { + SUCCESS, + OPEN_FAILED, + NO_JOYSTICK, + WRONG_VERSION, + ERR_GET_VERSION, + ERR_GET_BUTTONS, + ERR_GET_AXES, + ERR_GET_CORR, + ERR_RESTORE_CORR, + ERR_INIT_CAL, + ERR_APPLY_CAL + }; + + enum EventType + { + BUTTON, + AXIS + }; + + // devicefile to use, e.g. "/dev/js0" + JoyDevice(const QString &devicefile); + ~JoyDevice(); + + // returns one of the error-codes from above + ErrorCode open(); + + // return descriptive error text for given error code + QString errText(ErrorCode code) const; + + int fd() const { return joyFd; } + void close(); + ErrorCode restoreCorr(); + + // return devicefilename from constructor + const QString &device() const { return devName; } + + // descriptive text for this device read from the driver + QString text() const { return descr; } + + int numButtons() const { return buttons; } + int numAxes() const { return axes; } + int axisMin(int axis) const; + int axisMax(int axis) const; + + // read next event from device; returns true if there was an event during the short timeout + bool getEvent(JoyDevice::EventType &type, int &number, int &value); + + // methods for calibration + ErrorCode initCalibration(); // must be called first + void calcPrecision(); + + void resetMinMax(int axis, int value = 0); + + // calculate correction values + // min[2], center[2], max[2], index 0 == minimum, index 1 == maximum + void calcCorrection(int axis, int *min, int *center, int *max); + ErrorCode applyCalibration(); + + private: + QString devName; // device filename + QString descr; // descriptive text + int joyFd; + + int buttons; + int axes; + int *amin; // axes min values + int *amax; // axes max values + + struct js_corr *corr; // calibration values during the calib. steps + struct js_corr *origCorr; // original calibration correction values +}; + +#endif diff --git a/kcontrol/joystick/joystick.cpp b/kcontrol/joystick/joystick.cpp new file mode 100644 index 000000000..75115fcb7 --- /dev/null +++ b/kcontrol/joystick/joystick.cpp @@ -0,0 +1,123 @@ +/*************************************************************************** + * Copyright (C) 2003 by Martin Koller * + * m.koller@surfeu.at * + * 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 <kaboutdata.h> +#include <kgenericfactory.h> +#include <kglobal.h> +#include <klocale.h> + +#include "joystick.h" +#include "joywidget.h" +#include "joydevice.h" + +//--------------------------------------------------------------------------------------------- + +typedef KGenericFactory<joystick, QWidget> JoystickFactory; +K_EXPORT_COMPONENT_FACTORY(kcm_joystick, JoystickFactory("joystick")) + +extern "C" +{ + KDE_EXPORT bool test_joystick() + { /* Code stolen from JoyWidget::init() */ + int i; + char dev[30]; + + 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 + } + } + + return true; /* We have at least one joystick and should hence be shown */ + } + return false; + } +} + +//--------------------------------------------------------------------------------------------- + +joystick::joystick(QWidget *parent, const char *name, const QStringList &) + : KCModule(JoystickFactory::instance(), parent, name) +{ + setAboutData( new KAboutData("kcmjoystick", I18N_NOOP("KDE Joystick Control Module"), "1.0", + I18N_NOOP("KDE Control Center Module to test Joysticks"), + KAboutData::License_GPL, "(c) 2004, Martin Koller", + 0, "m.koller@surfeu.at")); + + setQuickHelp( i18n("<h1>Joystick</h1>" + "This module helps to check if your joystick is working correctly.<br>" + "If it delivers wrong values for the axes, you can try to solve this with " + "the calibration.<br>" + "This module tries to find all available joystick devices " + "by checking /dev/js[0-4] and /dev/input/js[0-4]<br>" + "If you have another device file, enter it in the combobox.<br>" + "The Buttons list shows the state of the buttons on your joystick, the Axes list " + "shows the current value for all axes.<br>" + "NOTE: the current Linux device driver (Kernel 2.4, 2.6) can only autodetect" + "<ul>" + "<li>2-axis, 4-button joystick</li>" + "<li>3-axis, 4-button joystick</li>" + "<li>4-axis, 4-button joystick</li>" + "<li>Saitek Cyborg 'digital' joysticks</li>" + "</ul>" + "(For details you can check your Linux source/Documentation/input/joystick.txt)" + )); + + joyWidget = new JoyWidget(this); + + setMinimumSize(joyWidget->minimumSize()); + + setButtons(KCModule::Default); +} + +//--------------------------------------------------------------------------------------------- + +void joystick::load() +{ + joyWidget->init(); +} + +//--------------------------------------------------------------------------------------------- + +void joystick::defaults() +{ + joyWidget->resetCalibration(); + + emit changed(true); +} + +//--------------------------------------------------------------------------------------------- + +//--------------------------------------------------------------------------------------------- + +#include "joystick.moc" diff --git a/kcontrol/joystick/joystick.desktop b/kcontrol/joystick/joystick.desktop new file mode 100644 index 000000000..92166c544 --- /dev/null +++ b/kcontrol/joystick/joystick.desktop @@ -0,0 +1,177 @@ +[Desktop Entry] +Comment=joystick - a kcontrol module to test joysticks +Comment[af]=joystick - 'n beheer module om joysticks mee te toets +Comment[be]=Модуль настаўлення джойстыка +Comment[bg]=Настройване на джойстика +Comment[bn]=joystick - জয়-স্টিক পরীক্ষা করার জন্য একটি নিয়ন্ত্রণ মডিউল +Comment[bs]=joystick - KControl modul za testiranje džojstika +Comment[ca]=Joystick - un mòdul de kcontrol per a provar palanques de control +Comment[cs]=Ovládací modul pro testování joysticků +Comment[csb]=joystick - mòduł Centróm kòntrolë dlô testowaniô joysticków +Comment[cy]=joystick - modiwl kcontrol i brofi ffyn rheoli +Comment[da]=joystick - et kcontrol modul til at test joystick +Comment[de]=Joystick-Testmodul +Comment[el]=χειριστήριο - ένα άρθρωμα ελέγχου χειριστηρίων +Comment[eo]=stirstango - kontrola modulo por testi stirstangojn +Comment[es]=joystick - un módulo de kcontrol para probar joysticks +Comment[et]=juhtpult - KDE juhtimiskeskuse moodul juhtpultide testimiseks +Comment[eu]=joystick - joystickak aztertzeko kontrol modulua +Comment[fa]=اهرم کنترل - پیمانۀ kcontrol برای آزمایش اهرمهای کنترل +Comment[fi]=peliohjain - KDE:n ohjauskeskuksen moduuli peliohjainta varten +Comment[fr]=joystick - un module pour tester les joysticks +Comment[fy]=joystick - in Konfiguraasjemodule foar it teste fan joysticks +Comment[gl]=joystick - un módulo de kcontrol para probar joysticks +Comment[he]=ג'ויסטיק - מודול לבדיקת ג'ויסטיקים +Comment[hi]=जॉयस्टिक - जॉयस्टिक को जाँचने का एक के-कंट्रोल मॉड्यूल +Comment[hr]=joystick - kcontrol modul za ispitivanje igraće palice +Comment[hu]=Botkormányok tesztelése, kalibrálása +Comment[is]=joystick - kcontrol stjórneining til að prófa stýripinna +Comment[it]=joystick - un modulo di kcontrol per provare i joystick +Comment[ja]=ジョイスティックをテストする kcontrol モジュール +Comment[ka]=joystick - kcontrol მოდული ჯოისტიკის ტესტირებისთვის +Comment[kk]=joystick - джойстикты сынау kcontrol модулі +Comment[km]=យ៉យស្ទីក - ម៉ូឌុល kcontrol ដើម្បីសាកល្បងយ៉យស្ទីក +Comment[ko]=joystick - 조이스틱을 테스트하기 위한 kcontrol 모듈 +Comment[lt]=valdymo svirtis - kcontrol modulis valdymo svirčių išbandymui +Comment[lv]=kursorsvira - kkontroles modulis kursorsviru testēšanai +Comment[mk]=joystick - модул на kcontrol за тестирање џојстици +Comment[mt]=joystick - modulu ta' kcontrol biex tittestja joysticks +Comment[nb]=Styrepinne – en kcontrolmodul for å prøve ut styrepinner +Comment[nds]=joystick - Moduul för't Utproberen vun Joysticks +Comment[ne]=जोयस्टिक - जोयस्टिक परीक्षण गर्ने के नियन्त्रण मोड्युल +Comment[nl]=joystick - een configuratiemodule voor het testen van joysticks +Comment[nn]=Styrespak – ein kontrollmodul for å prøva ut styrepinnar +Comment[pa]=joystick - ਜਾਏਸਟਿੱਕ ਜਾਂਚ ਲਈ ਕੇਕੰਟਰੋਲ ਮੈਡੀਊਲ +Comment[pl]=joystick - moduł Centrum sterowania do testowania joysticków +Comment[pt]=joystick - um módulo do kcontrol para testar joysticks +Comment[pt_BR]=joystick - um módulo de controle para testes de joysticks +Comment[ro]=Un modul pentru testarea joystick-urilor +Comment[ru]=joystick - модуль kcontrol для проверки джойстика +Comment[rw]=Agakoreshamukino - igice cya k-igenzura mu gusuzuma udukoreshamikino +Comment[se]=Stivrensággi – stivrenmoduvla mainna geahččala stivrensákkiid +Comment[sk]=Ovládací modul pre test joysticku +Comment[sl]=joystick - modul Nadzornega središča za preizkus igralnih palic +Comment[sr]=џојстик - модул контролног центра за тестирање џојстика +Comment[sr@Latn]=džojstik - modul kontrolnog centra za testiranje džojstika +Comment[sv]=Styrspak: en inställningsmodul för att testa styrspakar +Comment[ta]=இயக்கும் கருவி - கேகண்ட்ரோல் கூறு இயக்கும் கருவியை பரிசோதிக்கிறது +Comment[tg]=ҷостик - модули kидора барои санҷиши ҷостикҳо +Comment[th]=จอยสติก - โมดูลของศูนย์ควบคุม KDE สำหรับตรวจสอบจอยสติก +Comment[tr]=oyun kumandası - oyun kumandalarını denemek için bir kcontrol modülü +Comment[tt]=Joystik sınaw öçen kcontrol modulı +Comment[uk]=Джойстик - модуль центру керування для тестування джойстиків +Comment[uz]=Joystik uchun boshqaruv moduli +Comment[uz@cyrillic]=Жойстик учун бошқарув модули +Comment[vi]=cần điều khiển - một mô đun điều khiển KDE đêr kiểm tra cần lái +Comment[wa]=djîsse di djeu - on module di kcontrol po sayî les djîsses di djeu +Comment[zh_CN]=joystick - 测试游戏杆的 kcontrol 模块 +Comment[zh_TW]=搖桿 - 用來測試搖桿的 kcontrol 模組 +Exec=kcmshell joystick +Keywords=joystick,gamepad +Keywords[be]=Джойстык,joystick,gamepad +Keywords[bg]=джойстик, игра, игри, управление, joystick, gamepad +Keywords[bs]=joystick,gamepad,džojstik +Keywords[csb]=joystick,gamepad,dżojstik +Keywords[cy]=ffôn reoli,pad gêm +Keywords[da]=joystick,spilleplade +Keywords[de]=Joystick,Gamepad,Spiele +Keywords[el]=χειριστήριο,χειριστήριο κονσόλας παιχνιδιών +Keywords[eo]=stirstango,stirstangoj,ludotabuleto +Keywords[et]=juhtpult,mängupult +Keywords[fa]=اهرم کنترل، صفحه بازی +Keywords[fi]=joystick,peliohjain +Keywords[fr]=joystick,gamepad,manette de jeu +Keywords[ga]=luamhán stiúrtha,ceap cluiche +Keywords[he]=joystick,gamepad,ג'ויסטיק,גויסטיק +Keywords[hi]=जॉयस्टिक,गेमपेड +Keywords[hr]=joystick,gamepad,igraća palica,igraća konzola +Keywords[hu]=botkormány,joystick,gamepad +Keywords[is]=joystick,gamepad,stýripinni +Keywords[ja]=joystick,gamepad,ジョイスティック,ゲームパッド +Keywords[km]=យ៉យស្ទីក,បន្ទះល្បែង +Keywords[lt]=valdymo svirtis, joystick,gamepad +Keywords[lv]=kursorsvira,spēļu pults +Keywords[nb]=styrepinne,spillkontroll +Keywords[ne]=जोयस्टिक, गेमप्याड +Keywords[nn]=styrespak,spelkontroll +Keywords[pa]=joystick,gamepad,ਜਾਏਸਟਿੱਕ +Keywords[pl]=joystick,gamepad,dżojstik +Keywords[pt_BR]=joystick,gamepad, jogos +Keywords[rw]=agakoreshamukino, umwanyaumukino +Keywords[se]=stivrensággi,speallanstivrran +Keywords[sl]=joystick,gamepad,igralna palica,igralni plošček +Keywords[sr]=joystick,gamepad,џојстик +Keywords[sr@Latn]=joystick,gamepad,džojstik +Keywords[sv]=styrspak,spelkonsol +Keywords[ta]=இயக்கும் கருவி, விளையாட்டு பலகை +Keywords[te]=జాయ్ స్టిక్, గేమ్ పాడ్ +Keywords[th]=จอยสติก,แป้นคุมเกม,gamepad +Keywords[tr]=oyun çubuğu +Keywords[uk]=джойстик,gamepad +Keywords[uz]=joystik,geympad +Keywords[uz@cyrillic]=жойстик,геймпад +Keywords[vi]=cần điều khiển,bàn điều khiển trò chơi +Keywords[wa]=joystick,gamepad,djîsse,djîsse di djeu +Keywords[zh_CN]=joystick,gamepad,游戏杆,手柄 +Keywords[zh_TW]=joystick,gamepad,搖桿,遊戲台 +Name=Joystick +Name[be]=Джойстык +Name[bg]=Джойстик +Name[bn]=জয়-স্টিক +Name[br]=Lanker-c'hoari +Name[ca]=Palanca de control +Name[cy]=Ffôn reoli +Name[el]=Χειριστήριο +Name[eo]=Stirstango +Name[et]=Juhtpult +Name[fa]=اهرم کنترل +Name[fi]=Peliohjain +Name[ga]=Luamhán Stiúrtha +Name[he]=ג'ויסטיק +Name[hi]=जॉयस्टिक +Name[hr]=Igraća palica +Name[hu]=Botkormány +Name[is]=Stýripinnar +Name[ja]=ジョイスティック +Name[ka]=ჯოისტიკი +Name[kk]=Джойстик +Name[km]=យ៉យស្ទីក +Name[ko]=조이스틱 +Name[lo]=จอยสติ๊ก +Name[lt]=Valdymo svirtis +Name[lv]=Kursorsvira +Name[ms]=Kayu Bidik +Name[nb]=Styrepinne +Name[ne]=जोयस्टिक +Name[nn]=Styrespak +Name[oc]=Palanca de jogs +Name[pa]=ਜਾਏਸਟਿੱਕ +Name[ru]=Джойстик +Name[rw]=Agakoreshamukino +Name[se]=Stivrensággi +Name[sl]=Igralna palica +Name[sr]=Џојстик +Name[sr@Latn]=Džojstik +Name[sv]=Styrspak +Name[ta]=இயக்கு கருவி +Name[te]=జాయ్ స్టిక్ +Name[th]=จอยสติก +Name[tr]=Oyun Çubuğu +Name[tt]=Joystik +Name[uk]=Джойстик +Name[uz]=Joystik +Name[uz@cyrillic]=Жойстик +Name[ven]=Thambo dzau tumanya na tshishumiswa +Name[vi]=Cần điều khiển +Name[wa]=Djîsse di djeu +Name[xh]=Uvuyo +Name[zh_CN]=游戏杆 +Name[zh_TW]=玩具 +Name[zu]=Induku yenjabulo +Terminal=false +Type=Application +X-KDE-FactoryName=kcm_joystick +X-KDE-Library=joystick +X-KDE-Test-Module=true +Icon=joystick +Categories=Qt;KDE;X-KDE-settings-hardware; diff --git a/kcontrol/joystick/joystick.h b/kcontrol/joystick/joystick.h new file mode 100644 index 000000000..819a5f70d --- /dev/null +++ b/kcontrol/joystick/joystick.h @@ -0,0 +1,42 @@ +/*************************************************************************** + * Copyright (C) 2003 by Martin Koller * + * m.koller@surfeu.at * + * 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. * + ***************************************************************************/ +#ifndef _JOYSTICK_H_ +#define _JOYSTICK_H_ + +#include <kcmodule.h> + +class JoyWidget; + +class joystick: public KCModule +{ + Q_OBJECT + + public: + joystick(QWidget *parent = 0, const char *name = 0, const QStringList &list = QStringList()); + + virtual void load(); + virtual void defaults(); + + private: + JoyWidget *joyWidget; +}; + +#endif 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 * + * m.koller@surfeu.at * + * 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" diff --git a/kcontrol/joystick/joywidget.h b/kcontrol/joystick/joywidget.h new file mode 100644 index 000000000..5f561c0e5 --- /dev/null +++ b/kcontrol/joystick/joywidget.h @@ -0,0 +1,79 @@ +/*************************************************************************** + * Copyright (C) 2003 by Martin Koller * + * m.koller@surfeu.at * + * 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. * + ***************************************************************************/ +#ifndef _JOYWIDGET_H_ +#define _JOYWIDGET_H_ + +#include <qwidget.h> + +class JoyDevice; + +class PosWidget; +class QLabel; +class QTable; +class QTimer; +class QComboBox; +class QPushButton; +class QCheckBox; +class QHBox; + +// the widget which displays all buttons, values, etc. +class JoyWidget : public QWidget +{ + Q_OBJECT + + public: + JoyWidget(QWidget *parent = 0, const char *name = 0); + + ~JoyWidget(); + + // initialize list of possible devices and open the first available + void init(); + + public slots: + // reset calibration values to their value when this KCM was started + void resetCalibration(); + + private slots: + void checkDevice(); + void deviceChanged(const QString &dev); + void traceChanged(bool); + void calibrateDevice(); + + private: + void showDeviceProps(JoyDevice *joy); // fill widgets with given device parameters + void restoreCurrDev(); // restores the content of the combobox to reflect the current open device + + private: + QHBox *messageBox; + QLabel *message; // in case of no device, show here a message rather than in a dialog + QComboBox *device; + PosWidget *xyPos; + QTable *buttonTbl; + QTable *axesTbl; + QCheckBox *trace; + QPushButton *calibrate; + + QTimer *idle; + + JoyDevice *joydev; +}; + +#endif diff --git a/kcontrol/joystick/poswidget.cpp b/kcontrol/joystick/poswidget.cpp new file mode 100644 index 000000000..54e619d7a --- /dev/null +++ b/kcontrol/joystick/poswidget.cpp @@ -0,0 +1,138 @@ +/*************************************************************************** + * Copyright (C) 2003 by Martin Koller * + * m.koller@surfeu.at * + * 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 "poswidget.h" + +#include <qpainter.h> + +#define XY_WIDTH 220 +#define MARK_WIDTH 10 + +//----------------------------------------------------------------- + +PosWidget::PosWidget(QWidget *parent, const char *name) + : QWidget(parent, name, WRepaintNoErase), x(0), y(0), trace(false) +{ + setMinimumSize(XY_WIDTH, XY_WIDTH); + setMaximumSize(XY_WIDTH, XY_WIDTH); + setPaletteBackgroundColor(Qt::white); +} + +//----------------------------------------------------------------- + +void PosWidget::paintEvent(QPaintEvent *) +{ + QPainter paint(this); + + paint.drawRect(0, 0, width(), height()); + paint.setPen(Qt::gray); + + // draw a center grid + paint.drawLine(XY_WIDTH/2, 1, + XY_WIDTH/2, XY_WIDTH - 2); + + paint.drawLine(1, XY_WIDTH/2, + XY_WIDTH - 2, XY_WIDTH/2); + + // draw the current position marker + paint.setPen(Qt::blue); + + paint.drawLine(x - MARK_WIDTH/2, y - MARK_WIDTH/2, + x + MARK_WIDTH/2, y + MARK_WIDTH/2); + + paint.drawLine(x - MARK_WIDTH/2, y + MARK_WIDTH/2, + x + MARK_WIDTH/2, y - MARK_WIDTH/2); +} + +//----------------------------------------------------------------- + +void PosWidget::changeX(int newX) +{ + // transform coordinates from joystick to widget coordinates + newX = int((newX/65535.0)*XY_WIDTH + XY_WIDTH/2); + + if ( x == newX ) return; // avoid unnecessary redraw + + eraseOld(); + + x = newX; +} + +//----------------------------------------------------------------- + +void PosWidget::changeY(int newY) +{ + // transform coordinates from joystick to widget coordinates + newY = int((newY/65535.0)*XY_WIDTH + XY_WIDTH/2); + + if ( y == newY ) return; // avoid unnecessary redraw + + eraseOld(); + + y = newY; +} + +//----------------------------------------------------------------- + +void PosWidget::showTrace(bool t) +{ + trace = t; + + if ( !trace ) + { + erase(); + update(); + } +} + +//----------------------------------------------------------------- + +void PosWidget::eraseOld() +{ + QPainter paint(this); + + //paint.eraseRect(x - MARK_WIDTH/2, y - MARK_WIDTH/2, MARK_WIDTH + 1, MARK_WIDTH + 1); + + // erase previous cross (don't use eraseRect() so that trace flags will be not destroyed so much) + paint.setPen(Qt::white); + + paint.drawLine(x - MARK_WIDTH/2, y - MARK_WIDTH/2, + x + MARK_WIDTH/2, y + MARK_WIDTH/2); + + paint.drawLine(x - MARK_WIDTH/2, y + MARK_WIDTH/2, + x + MARK_WIDTH/2, y - MARK_WIDTH/2); + + if ( trace ) // show previous position with a smaller black cross + { + paint.setPen(Qt::black); + + paint.drawLine(x - 2, y - 2, + x + 2, y + 2); + + paint.drawLine(x - 2, y + 2, + x + 2, y - 2); + } + + update(); +} + +//----------------------------------------------------------------- + +#include "poswidget.moc" diff --git a/kcontrol/joystick/poswidget.h b/kcontrol/joystick/poswidget.h new file mode 100644 index 000000000..9151da57f --- /dev/null +++ b/kcontrol/joystick/poswidget.h @@ -0,0 +1,55 @@ +/*************************************************************************** + * Copyright (C) 2003 by Martin Koller * + * m.koller@surfeu.at * + * 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. * + ***************************************************************************/ +#ifndef _POSWIDGET_H_ +#define _POSWIDGET_H_ + +#include <qwidget.h> + +/** + Widget to display the joystick-selected (x,y) position +*/ +class PosWidget : public QWidget +{ + Q_OBJECT + + public: + PosWidget(QWidget *parent = 0, const char *name = 0); + + void changeX(int x); + void changeY(int y); + + // define if a trace of the moving joystick shall be displayed + // setting it to false will erase all previous marks from the widget + // NOTE: the traced positions are not stored and will be erased if the widget is covered/redisplayed + void showTrace(bool t); + + protected: + virtual void paintEvent(QPaintEvent *); + + private: + void eraseOld(); + + private: + int x, y; + bool trace; +}; + +#endif |