TDE graphics utilities
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.

kameradevice.cpp 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. /*
  2. Copyright (C) 2001 The Kompany
  3. 2002-2003 Ilya Konstantinov <kde-devel@future.shiny.co.il>
  4. 2002-2003 Marcus Meissner <marcus@jet.franken.de>
  5. 2003 Nadeem Hasan <nhasan@nadmm.com>
  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. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  17. */
  18. #include <tqlayout.h>
  19. #include <tqwidgetstack.h>
  20. #include <tqvbuttongroup.h>
  21. #include <tqvgroupbox.h>
  22. #include <tqcombobox.h>
  23. #include <tqlineedit.h>
  24. #include <tqradiobutton.h>
  25. #include <tqwhatsthis.h>
  26. #include <tqlabel.h>
  27. #include <tqgrid.h>
  28. #include <klocale.h>
  29. #include <kconfig.h>
  30. #include <klistview.h>
  31. #include <kmessagebox.h>
  32. #include <kdebug.h>
  33. extern "C" {
  34. #include <gphoto2.h>
  35. }
  36. #include "kamera.h"
  37. #include "kameraconfigdialog.h"
  38. #include "kameradevice.moc"
  39. // Define some parts of the old API
  40. #define GP_PROMPT_OK 0
  41. #define GP_PROMPT_CANCEL -1
  42. static const int INDEX_NONE= 0;
  43. static const int INDEX_SERIAL = 1;
  44. static const int INDEX_USB= 3;
  45. static GPContext *glob_context = 0;
  46. KCamera::KCamera(const TQString &name, const TQString &path)
  47. {
  48. m_name = name;
  49. m_model = name;
  50. m_path = path;
  51. m_camera = NULL;
  52. }
  53. KCamera::~KCamera()
  54. {
  55. if(m_camera)
  56. gp_camera_free(m_camera);
  57. if(m_abilitylist)
  58. gp_abilities_list_free(m_abilitylist);
  59. }
  60. bool KCamera::initInformation()
  61. {
  62. if (!m_model)
  63. return false;
  64. if(gp_abilities_list_new(&m_abilitylist) != GP_OK) {
  65. emit error(i18n("Could not allocate memory for abilities list."));
  66. return false;
  67. }
  68. if(gp_abilities_list_load(m_abilitylist, glob_context) != GP_OK) {
  69. emit error(i18n("Could not load ability list."));
  70. return false;
  71. }
  72. int index = gp_abilities_list_lookup_model(m_abilitylist, m_model.local8Bit().data());
  73. if(index < 0) {
  74. emit error(i18n("Description of abilities for camera %1 is not available."
  75. " Configuration options may be incorrect.").arg(m_model));
  76. return false;
  77. }
  78. gp_abilities_list_get_abilities(m_abilitylist, index, &m_abilities);
  79. return true;
  80. }
  81. bool KCamera::initCamera()
  82. {
  83. if (m_camera)
  84. return m_camera;
  85. else {
  86. int result;
  87. initInformation();
  88. if (!m_model || !m_path)
  89. return false;
  90. result = gp_camera_new(&m_camera);
  91. if (result != GP_OK) {
  92. // m_camera is not initialized, so we cannot get result as string
  93. emit error(i18n("Could not access driver. Check your gPhoto2 installation."));
  94. return false;
  95. }
  96. // set the camera's model
  97. GPPortInfo info;
  98. GPPortInfoList *il;
  99. gp_port_info_list_new(&il);
  100. gp_port_info_list_load(il);
  101. gp_port_info_list_get_info(il, gp_port_info_list_lookup_path(il, m_path.local8Bit().data()), &info);
  102. gp_port_info_list_free(il);
  103. gp_camera_set_abilities(m_camera, m_abilities);
  104. gp_camera_set_port_info(m_camera, info);
  105. // this might take some time (esp. for non-existant camera) - better be done asynchronously
  106. result = gp_camera_init(m_camera, glob_context);
  107. if (result != GP_OK) {
  108. gp_camera_free(m_camera);
  109. m_camera = NULL;
  110. emit error(
  111. i18n("Unable to initialize camera. Check your port settings and camera connectivity and try again."),
  112. gp_result_as_string(result));
  113. return false;
  114. }
  115. return m_camera;
  116. }
  117. }
  118. Camera* KCamera::camera()
  119. {
  120. initCamera();
  121. return m_camera;
  122. }
  123. TQString KCamera::summary()
  124. {
  125. int result;
  126. CameraText summary;
  127. initCamera();
  128. result = gp_camera_get_summary(m_camera, &summary, glob_context);
  129. if (result != GP_OK)
  130. return i18n("No camera summary information is available.\n");
  131. return TQString(summary.text);
  132. }
  133. bool KCamera::configure()
  134. {
  135. CameraWidget *window;
  136. int result;
  137. initCamera();
  138. result = gp_camera_get_config(m_camera, &window, glob_context);
  139. if (result != GP_OK) {
  140. emit error(i18n("Camera configuration failed."), gp_result_as_string(result));
  141. return false;
  142. }
  143. KameraConfigDialog kcd(m_camera, window);
  144. result = kcd.exec() ? GP_PROMPT_OK : GP_PROMPT_CANCEL;
  145. if (result == GP_PROMPT_OK) {
  146. result = gp_camera_set_config(m_camera, window, glob_context);
  147. if (result != GP_OK) {
  148. emit error(i18n("Camera configuration failed."), gp_result_as_string(result));
  149. return false;
  150. }
  151. }
  152. return true;
  153. }
  154. bool KCamera::test()
  155. {
  156. // TODO: Make testing non-blocking (maybe via KIO?)
  157. // Currently, a failed serial test times out at about 30 sec.
  158. return camera() != 0;
  159. }
  160. void KCamera::load(KConfig *config)
  161. {
  162. config->setGroup(m_name);
  163. if (m_model.isNull())
  164. m_model = config->readEntry("Model");
  165. if (m_path.isNull())
  166. m_path = config->readEntry("Path");
  167. invalidateCamera();
  168. }
  169. void KCamera::save(KConfig *config)
  170. {
  171. config->setGroup(m_name);
  172. config->writeEntry("Model", m_model);
  173. config->writeEntry("Path", m_path);
  174. }
  175. TQString KCamera::portName()
  176. {
  177. TQString port = m_path.left(m_path.find(":")).lower();
  178. if (port == "serial") return i18n("Serial");
  179. if (port == "usb") return i18n("USB");
  180. return i18n("Unknown port");
  181. }
  182. void KCamera::setName(const TQString &name)
  183. {
  184. m_name = name;
  185. }
  186. void KCamera::setModel(const TQString &model)
  187. {
  188. m_model = model;
  189. invalidateCamera();
  190. initInformation();
  191. }
  192. void KCamera::setPath(const TQString &path)
  193. {
  194. m_path = path;
  195. invalidateCamera();
  196. }
  197. void KCamera::invalidateCamera()
  198. {
  199. if (m_camera) {
  200. gp_camera_free(m_camera);
  201. m_camera = NULL;
  202. }
  203. }
  204. bool KCamera::isTestable() const
  205. {
  206. return true;
  207. }
  208. bool KCamera::isConfigurable()
  209. {
  210. initInformation();
  211. return m_abilities.operations & GP_OPERATION_CONFIG;
  212. }
  213. TQStringList KCamera::supportedPorts()
  214. {
  215. initInformation();
  216. TQStringList ports;
  217. if (m_abilities.port & GP_PORT_SERIAL)
  218. ports.append("serial");
  219. if (m_abilities.port & GP_PORT_USB)
  220. ports.append("usb");
  221. return ports;
  222. }
  223. CameraAbilities KCamera::abilities()
  224. {
  225. return m_abilities;
  226. }
  227. // ---------- KameraSelectCamera ------------
  228. KameraDeviceSelectDialog::KameraDeviceSelectDialog(TQWidget *parent, KCamera *device)
  229. : KDialogBase(parent, "kkameradeviceselect", true, i18n("Select Camera Device"), Ok | Cancel, Ok, true)
  230. {
  231. m_device = device;
  232. connect(m_device, TQT_SIGNAL(error(const TQString &)),
  233. TQT_SLOT(slot_error(const TQString &)));
  234. connect(m_device, TQT_SIGNAL(error(const TQString &, const TQString &)),
  235. TQT_SLOT(slot_error(const TQString &, const TQString &)));
  236. TQWidget *page = new TQWidget( this );
  237. setMainWidget(page);
  238. // a tqlayout with vertical boxes
  239. TQHBoxLayout *topLayout = new TQHBoxLayout(page, 0, KDialog::spacingHint());
  240. // the models list
  241. m_modelSel = new KListView(page);
  242. topLayout->addWidget( m_modelSel );
  243. m_modelSel->addColumn(i18n("Supported Cameras"));
  244. m_modelSel->setColumnWidthMode(0, TQListView::Maximum);
  245. connect(m_modelSel, TQT_SIGNAL(selectionChanged(TQListViewItem *)),
  246. TQT_SLOT(slot_setModel(TQListViewItem *)));
  247. // make sure listview only as wide as it needs to be
  248. m_modelSel->setSizePolicy(TQSizePolicy(TQSizePolicy::Maximum,
  249. TQSizePolicy::Preferred));
  250. TQVBoxLayout *rightLayout = new TQVBoxLayout(0L, 0, KDialog::spacingHint());
  251. topLayout->addLayout( rightLayout );
  252. m_portSelectGroup = new TQVButtonGroup(i18n("Port"), page);
  253. rightLayout->addWidget(m_portSelectGroup);
  254. m_portSettingsGroup = new TQVGroupBox(i18n("Port Settings"), page);
  255. rightLayout->addWidget(m_portSettingsGroup);
  256. // Create port type selection radiobuttons.
  257. m_serialRB = new TQRadioButton(i18n("Serial"), m_portSelectGroup);
  258. m_portSelectGroup->insert(m_serialRB, INDEX_SERIAL);
  259. TQWhatsThis::add(m_serialRB, i18n("If this option is checked, the camera would have to be connected one of the serial ports (known as COM in Microsoft Windows) in your computer."));
  260. m_USBRB = new TQRadioButton(i18n("USB"), m_portSelectGroup);
  261. m_portSelectGroup->insert(m_USBRB, INDEX_USB);
  262. TQWhatsThis::add(m_USBRB, i18n("If this option is checked, the camera would have to be connected to one of the USB slots in your computer or USB hub."));
  263. // Create port settings widget stack
  264. m_settingsStack = new TQWidgetStack(m_portSettingsGroup);
  265. connect(m_portSelectGroup, TQT_SIGNAL(clicked(int)),
  266. m_settingsStack, TQT_SLOT(raiseWidget(int)));
  267. // none tab
  268. m_settingsStack->addWidget(new TQLabel(i18n("No port type selected."),
  269. m_settingsStack), INDEX_NONE);
  270. // serial tab
  271. TQGrid *grid = new TQGrid(2, m_settingsStack);
  272. grid->setSpacing(KDialog::spacingHint());
  273. new TQLabel(i18n("Port:"), grid);
  274. m_serialPortCombo = new TQComboBox(TRUE, grid);
  275. TQWhatsThis::add(m_serialPortCombo, i18n("Here you should choose the serial port you connect the camera to."));
  276. m_settingsStack->addWidget(grid, INDEX_SERIAL);
  277. grid = new TQGrid(2, m_settingsStack);
  278. grid->setSpacing(KDialog::spacingHint());
  279. new TQLabel(i18n("Port"), grid);
  280. m_settingsStack->addWidget(new
  281. TQLabel(i18n("No further configuration is required for USB."),
  282. m_settingsStack), INDEX_USB);
  283. // query gphoto2 for existing serial ports
  284. GPPortInfoList *list;
  285. GPPortInfo info;
  286. int gphoto_ports=0;
  287. gp_port_info_list_new(&list);
  288. if(gp_port_info_list_load(list) >= 0) {
  289. gphoto_ports = gp_port_info_list_count(list);
  290. }
  291. for (int i = 0; i < gphoto_ports; i++) {
  292. if (gp_port_info_list_get_info(list, i, &info) >= 0) {
  293. if (strncmp(info.path, "serial:", 7) == 0)
  294. m_serialPortCombo->insertItem(TQString::fromLatin1(info.path).mid(7));
  295. }
  296. }
  297. gp_port_info_list_free(list);
  298. // add a spacer
  299. rightLayout->addStretch();
  300. populateCameraListView();
  301. load();
  302. enableButtonOK(false );
  303. m_portSelectGroup->setEnabled( false );
  304. m_portSettingsGroup->setEnabled( false );
  305. }
  306. bool KameraDeviceSelectDialog::populateCameraListView()
  307. {
  308. gp_abilities_list_new (&m_device->m_abilitylist);
  309. gp_abilities_list_load(m_device->m_abilitylist, glob_context);
  310. int numCams = gp_abilities_list_count(m_device->m_abilitylist);
  311. CameraAbilities a;
  312. if(numCams < 0) {
  313. // XXX libgphoto2 failed to get te camera list
  314. return false;
  315. } else {
  316. for(int x = 0; x < numCams; ++x) {
  317. if(gp_abilities_list_get_abilities(m_device->m_abilitylist, x, &a) == GP_OK) {
  318. new TQListViewItem(m_modelSel, a.model);
  319. }
  320. }
  321. return true;
  322. }
  323. }
  324. void KameraDeviceSelectDialog::save()
  325. {
  326. m_device->setModel(m_modelSel->currentItem()->text(0));
  327. if (m_portSelectGroup->selected()) {
  328. TQString type = m_portSelectGroup->selected()->text();
  329. if(type == i18n("Serial"))
  330. m_device->setPath("serial:" + m_serialPortCombo->currentText());
  331. else if(type == i18n("USB"))
  332. m_device->setPath("usb:");
  333. } else {
  334. // This camera has no port type (e.g. "Directory Browse" camera).
  335. // Do nothing.
  336. }
  337. }
  338. void KameraDeviceSelectDialog::load()
  339. {
  340. TQString path = m_device->path();
  341. TQString port = path.left(path.find(":")).lower();
  342. if (port == "serial") setPortType(INDEX_SERIAL);
  343. if (port == "usb") setPortType(INDEX_USB);
  344. TQListViewItem *modelItem = m_modelSel->firstChild();
  345. if( modelItem)
  346. {
  347. do {
  348. if (modelItem->text(0) == m_device->model()) {
  349. m_modelSel->setSelected(modelItem, true);
  350. m_modelSel->ensureItemVisible(modelItem);
  351. }
  352. } while ( ( modelItem = modelItem->nextSibling() ) );
  353. }
  354. }
  355. void KameraDeviceSelectDialog::slot_setModel(TQListViewItem *item)
  356. {
  357. enableButtonOK(true);
  358. m_portSelectGroup->setEnabled(true);
  359. m_portSettingsGroup->setEnabled(true);
  360. TQString model = item->text(0);
  361. CameraAbilities abilities;
  362. int index = gp_abilities_list_lookup_model(m_device->m_abilitylist, model.local8Bit().data());
  363. if(index < 0) {
  364. slot_error(i18n("Description of abilities for camera %1 is not available."
  365. " Configuration options may be incorrect.").arg(model));
  366. }
  367. int result = gp_abilities_list_get_abilities(m_device->m_abilitylist, index, &abilities);
  368. if (result == GP_OK) {
  369. // enable radiobuttons for supported port types
  370. m_serialRB->setEnabled(abilities.port & GP_PORT_SERIAL);
  371. m_USBRB->setEnabled(abilities.port & GP_PORT_USB);
  372. // turn off any selected port
  373. TQButton *selected = m_portSelectGroup->selected();
  374. if(selected != NULL)
  375. selected->toggle();
  376. // if there's only one available port type, make sure it's selected
  377. if (abilities.port == GP_PORT_SERIAL)
  378. setPortType(INDEX_SERIAL);
  379. if (abilities.port == GP_PORT_USB)
  380. setPortType(INDEX_USB);
  381. } else {
  382. slot_error(i18n("Description of abilities for camera %1 is not available."
  383. " Configuration options may be incorrect.").arg(model));
  384. }
  385. }
  386. void KameraDeviceSelectDialog::setPortType(int type)
  387. {
  388. // Enable the correct button
  389. m_portSelectGroup->setButton(type);
  390. // Bring the right tab to the front
  391. m_settingsStack->raiseWidget(type);
  392. }
  393. void KameraDeviceSelectDialog::slot_error(const TQString &message)
  394. {
  395. KMessageBox::error(this, message);
  396. }
  397. void KameraDeviceSelectDialog::slot_error(const TQString &message, const TQString &details)
  398. {
  399. KMessageBox::detailedError(this, message, details);
  400. }