TDE base libraries and programs
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

380 lines
12KB

  1. /***************************************************************************
  2. * Copyright (C) 2003 by Martin Koller *
  3. * m.koller@surfeu.at *
  4. * This file is part of the Trinity Control Center Module for Joysticks *
  5. * *
  6. * This program is free software; you can redistribute it and/or modify *
  7. * it under the terms of the GNU General Public License as published by *
  8. * the Free Software Foundation; either version 2 of the License, or *
  9. * (at your option) any later version. *
  10. * *
  11. * This program is distributed in the hope that it will be useful, *
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  14. * GNU General Public License for more details. *
  15. * *
  16. * You should have received a copy of the GNU General Public License *
  17. * along with this program; if not, write to the *
  18. * Free Software Foundation, Inc., *
  19. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
  20. ***************************************************************************/
  21. #include "joywidget.h"
  22. #include "joydevice.h"
  23. #include "poswidget.h"
  24. #include "caldialog.h"
  25. #include <tqhbox.h>
  26. #include <tqvbox.h>
  27. #include <tqtable.h>
  28. #include <tqlabel.h>
  29. #include <tqcombobox.h>
  30. #include <tqlistbox.h>
  31. #include <tqcheckbox.h>
  32. #include <tqtimer.h>
  33. #include <tqfontmetrics.h>
  34. #include <tqpushbutton.h>
  35. #include <tdelocale.h>
  36. #include <kdialog.h>
  37. #include <tdemessagebox.h>
  38. #include <kiconloader.h>
  39. //--------------------------------------------------------------
  40. static TQString PRESSED = I18N_NOOP("PRESSED");
  41. //--------------------------------------------------------------
  42. JoyWidget::JoyWidget(TQWidget *parent, const char *name)
  43. : TQWidget(parent, name), idle(0), joydev(0)
  44. {
  45. TQVBox *mainVbox = new TQVBox(parent);
  46. mainVbox->setSpacing(KDialog::spacingHint());
  47. // create area to show an icon + message if no joystick was detected
  48. {
  49. messageBox = new TQHBox(mainVbox);
  50. messageBox->setSpacing(KDialog::spacingHint());
  51. TQLabel *icon = new TQLabel(messageBox);
  52. icon->setPixmap(TDEGlobal::iconLoader()->loadIcon("messagebox_warning", TDEIcon::NoGroup,
  53. TDEIcon::SizeMedium, TDEIcon::DefaultState, 0, true));
  54. icon->setFixedSize(icon->sizeHint());
  55. message = new TQLabel(messageBox);
  56. messageBox->hide();
  57. }
  58. TQHBox *devHbox = new TQHBox(mainVbox);
  59. new TQLabel(i18n("Device:"), devHbox);
  60. device = new TQComboBox(true, devHbox);
  61. device->setInsertionPolicy(TQComboBox::NoInsertion);
  62. connect(device, TQT_SIGNAL(activated(const TQString &)), this, TQT_SLOT(deviceChanged(const TQString &)));
  63. devHbox->setStretchFactor(device, 3);
  64. TQHBox *hbox = new TQHBox(mainVbox);
  65. hbox->setSpacing(KDialog::spacingHint());
  66. TQVBox *vboxLeft = new TQVBox(hbox);
  67. vboxLeft->setSpacing(KDialog::spacingHint());
  68. new TQLabel(i18n("Position:"), vboxLeft);
  69. xyPos = new PosWidget(vboxLeft);
  70. trace = new TQCheckBox(i18n("Show trace"), mainVbox);
  71. connect(trace, TQT_SIGNAL(toggled(bool)), this, TQT_SLOT(traceChanged(bool)));
  72. TQVBox *vboxMid = new TQVBox(hbox);
  73. vboxMid->setSpacing(KDialog::spacingHint());
  74. TQVBox *vboxRight = new TQVBox(hbox);
  75. vboxRight->setSpacing(KDialog::spacingHint());
  76. // calculate the column width we need
  77. TQFontMetrics fm(font());
  78. int colWidth = TQMAX(fm.width(PRESSED), fm.width("-32767")) + 10; // -32767 largest string
  79. new TQLabel(i18n("Buttons:"), vboxMid);
  80. buttonTbl = new TQTable(0, 1, vboxMid);
  81. buttonTbl->setReadOnly(true);
  82. buttonTbl->horizontalHeader()->setLabel(0, i18n("State"));
  83. buttonTbl->horizontalHeader()->setClickEnabled(false);
  84. buttonTbl->horizontalHeader()->setResizeEnabled(false);
  85. buttonTbl->verticalHeader()->setClickEnabled(false);
  86. buttonTbl->verticalHeader()->setResizeEnabled(false);
  87. buttonTbl->setColumnWidth(0, colWidth);
  88. new TQLabel(i18n("Axes:"), vboxRight);
  89. axesTbl = new TQTable(0, 1, vboxRight);
  90. axesTbl->setReadOnly(true);
  91. axesTbl->horizontalHeader()->setLabel(0, i18n("Value"));
  92. axesTbl->horizontalHeader()->setClickEnabled(false);
  93. axesTbl->horizontalHeader()->setResizeEnabled(false);
  94. axesTbl->verticalHeader()->setClickEnabled(false);
  95. axesTbl->verticalHeader()->setResizeEnabled(false);
  96. axesTbl->setColumnWidth(0, colWidth);
  97. // calibrate button
  98. calibrate = new TQPushButton(i18n("Calibrate"), mainVbox);
  99. connect(calibrate, TQT_SIGNAL(clicked()), this, TQT_SLOT(calibrateDevice()));
  100. calibrate->setEnabled(false);
  101. // set up a timer for idle processing of joystick events
  102. idle = new TQTimer(this);
  103. connect(idle, TQT_SIGNAL(timeout()), this, TQT_SLOT(checkDevice()));
  104. // check which devicefiles we have
  105. init();
  106. vboxLeft->adjustSize();
  107. vboxMid->adjustSize();
  108. vboxRight->adjustSize();
  109. hbox->adjustSize();
  110. mainVbox->adjustSize();
  111. setMinimumSize(mainVbox->size());
  112. }
  113. //--------------------------------------------------------------
  114. JoyWidget::~JoyWidget()
  115. {
  116. delete joydev;
  117. }
  118. //--------------------------------------------------------------
  119. void JoyWidget::init()
  120. {
  121. // check which devicefiles we have
  122. int i;
  123. bool first = true;
  124. char dev[30];
  125. device->clear();
  126. buttonTbl->setNumRows(0);
  127. axesTbl->setNumRows(0);
  128. for (i = 0; i < 5; i++) // check the first 5 devices
  129. {
  130. sprintf(dev, "/dev/js%d", i); // first look in /dev
  131. JoyDevice *joy = new JoyDevice(dev);
  132. if ( joy->open() != JoyDevice::SUCCESS )
  133. {
  134. delete joy;
  135. sprintf(dev, "/dev/input/js%d", i); // then look in /dev/input
  136. joy = new JoyDevice(dev);
  137. if ( joy->open() != JoyDevice::SUCCESS )
  138. {
  139. delete joy;
  140. continue; // try next number
  141. }
  142. }
  143. // we found one
  144. device->insertItem(TQString("%1 (%2)").arg(joy->text()).arg(joy->device()));
  145. // display values for first device
  146. if ( first )
  147. {
  148. showDeviceProps(joy); // this sets the joy object into this->joydev
  149. first = false;
  150. }
  151. else
  152. delete joy;
  153. }
  154. /* KDE 4: Remove this check(and i18n) when all KCM wrappers properly test modules */
  155. if ( device->count() == 0 )
  156. {
  157. messageBox->show();
  158. message->setText(TQString("<qt><b>%1</b></qt>").arg(
  159. i18n("No joystick device automatically found on this computer.<br>"
  160. "Checks were done in /dev/js[0-4] and /dev/input/js[0-4]<br>"
  161. "If you know that there is one attached, please enter the correct device file.")));
  162. }
  163. }
  164. //--------------------------------------------------------------
  165. void JoyWidget::traceChanged(bool state)
  166. {
  167. xyPos->showTrace(state);
  168. }
  169. //--------------------------------------------------------------
  170. void JoyWidget::restoreCurrDev()
  171. {
  172. if ( !joydev ) // no device open
  173. {
  174. device->setCurrentText("");
  175. calibrate->setEnabled(false);
  176. }
  177. else
  178. {
  179. // try to find the current open device in the combobox list
  180. TQListBoxItem *item;
  181. item = device->listBox()->findItem(joydev->device(), TQt::Contains);
  182. if ( !item ) // the current open device is one the user entered (not in the list)
  183. device->setCurrentText(joydev->device());
  184. else
  185. device->setCurrentText(item->text());
  186. }
  187. }
  188. //--------------------------------------------------------------
  189. void JoyWidget::deviceChanged(const TQString &dev)
  190. {
  191. // find "/dev" in given string
  192. int start, stop;
  193. TQString devName;
  194. if ( (start = dev.find("/dev")) == -1 )
  195. {
  196. KMessageBox::sorry(this,
  197. i18n("The given device name is invalid (does not contain /dev).\n"
  198. "Please select a device from the list or\n"
  199. "enter a device file, like /dev/js0."), i18n("Unknown Device"));
  200. restoreCurrDev();
  201. return;
  202. }
  203. if ( (stop = dev.find(")", start)) != -1 ) // seems to be text selected from our list
  204. devName = dev.mid(start, stop - start);
  205. else
  206. devName = dev.mid(start);
  207. if ( joydev && (devName == joydev->device()) ) return; // user selected the current device; ignore it
  208. JoyDevice *joy = new JoyDevice(devName);
  209. JoyDevice::ErrorCode ret = joy->open();
  210. if ( ret != JoyDevice::SUCCESS )
  211. {
  212. KMessageBox::error(this, joy->errText(ret), i18n("Device Error"));
  213. delete joy;
  214. restoreCurrDev();
  215. return;
  216. }
  217. showDeviceProps(joy);
  218. }
  219. //--------------------------------------------------------------
  220. void JoyWidget::showDeviceProps(JoyDevice *joy)
  221. {
  222. joydev = joy;
  223. buttonTbl->setNumRows(joydev->numButtons());
  224. axesTbl->setNumRows(joydev->numAxes());
  225. if ( joydev->numAxes() >= 2 )
  226. {
  227. axesTbl->verticalHeader()->setLabel(0, "1(x)");
  228. axesTbl->verticalHeader()->setLabel(1, "2(y)");
  229. }
  230. calibrate->setEnabled(true);
  231. idle->start(0);
  232. // make both tables use the same space for header; this looks nicer
  233. buttonTbl->setLeftMargin(TQMAX(buttonTbl->verticalHeader()->width(),
  234. axesTbl->verticalHeader()->width()));
  235. axesTbl->setLeftMargin(buttonTbl->verticalHeader()->width());
  236. }
  237. //--------------------------------------------------------------
  238. void JoyWidget::checkDevice()
  239. {
  240. if ( !joydev ) return; // no open device yet
  241. JoyDevice::EventType type;
  242. int number, value;
  243. if ( !joydev->getEvent(type, number, value) )
  244. return;
  245. if ( type == JoyDevice::BUTTON )
  246. {
  247. if ( value == 0 ) // button release
  248. buttonTbl->setText(number, 0, "-");
  249. else
  250. buttonTbl->setText(number, 0, PRESSED);
  251. }
  252. if ( type == JoyDevice::AXIS )
  253. {
  254. if ( number == 0 ) // x-axis
  255. xyPos->changeX(value);
  256. if ( number == 1 ) // y-axis
  257. xyPos->changeY(value);
  258. axesTbl->setText(number, 0, TQString("%1").arg(int(value)));
  259. }
  260. }
  261. //--------------------------------------------------------------
  262. void JoyWidget::calibrateDevice()
  263. {
  264. if ( !joydev ) return; // just to be save
  265. JoyDevice::ErrorCode ret = joydev->initCalibration();
  266. if ( ret != JoyDevice::SUCCESS )
  267. {
  268. KMessageBox::error(this, joydev->errText(ret), i18n("Communication Error"));
  269. return;
  270. }
  271. if ( KMessageBox::messageBox(this, KMessageBox::Information,
  272. i18n("<qt>Calibration is about to check the precision.<br><br>"
  273. "<b>Please move all axes to their center position and then "
  274. "do not touch the joystick anymore.</b><br><br>"
  275. "Click OK to start the calibration.</qt>"),
  276. i18n("Calibration"),
  277. KStdGuiItem::ok(), KStdGuiItem::cancel()) != KMessageBox::Ok )
  278. return;
  279. idle->stop(); // stop the joystick event getting; this must be done inside the calibrate dialog
  280. CalDialog dlg(this, joydev);
  281. dlg.calibrate();
  282. // user cancelled somewhere during calibration, therefore the device is in a bad state
  283. if ( dlg.result() == TQDialog::Rejected )
  284. joydev->restoreCorr();
  285. idle->start(0); // continue with event getting
  286. }
  287. //--------------------------------------------------------------
  288. void JoyWidget::resetCalibration()
  289. {
  290. if ( !joydev ) return; // just to be save
  291. JoyDevice::ErrorCode ret = joydev->restoreCorr();
  292. if ( ret != JoyDevice::SUCCESS )
  293. {
  294. KMessageBox::error(this, joydev->errText(ret), i18n("Communication Error"));
  295. }
  296. else
  297. {
  298. KMessageBox::information(this,
  299. i18n("Restored all calibration values for joystick device %1.").arg(joydev->device()),
  300. i18n("Calibration Success"));
  301. }
  302. }
  303. //--------------------------------------------------------------
  304. #include "joywidget.moc"