use kDebug
[kdegraphics.git] / kamera / kcontrol / kamera.cpp
blobf0ee8033a4e49236edd5835ab09f1823b256f0e1
1 /*
3 Copyright (C) 2001 The Kompany
4 2002-2003 Ilya Konstantinov <kde-devel@future.shiny.co.il>
5 2002-2003 Marcus Meissner <marcus@jet.franken.de>
6 2003 Nadeem Hasan <nhasan@nadmm.com>
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 #include <qlabel.h>
24 #include <qlayout.h>
25 //Added by qt3to4:
26 #include <QVBoxLayout>
27 #include <QApplication>
28 #include <kgenericfactory.h>
29 #include <kconfig.h>
30 #include <kaction.h>
31 #include <kiconloader.h>
32 #include <kmessagebox.h>
33 #include <k3iconview.h>
34 #include <kdialog.h>
35 #include <klocale.h>
36 #include <ktoolbar.h>
37 #include <kmenu.h>
38 #include <kprotocolinfo.h>
39 #include <kdebug.h>
40 #include <kactioncollection.h>
42 #include "kameraconfigdialog.h"
43 #include "kameradevice.h"
44 #include "kamera.h"
45 #include "kamera.moc"
47 // XXX HACK HACK HACK
48 // XXX All tocstr(string) references can be safely replaced with
49 // XXX string.latin1() as soon as the gphoto2 API uses 'const char *'
50 // XXX instead of 'char *' in calls that don't modify the string
51 #define tocstr(x) ((char *)((x).latin1()))
53 K_PLUGIN_FACTORY(KKameraConfigFactory, registerPlugin<KKameraConfig>();)
54 K_EXPORT_PLUGIN(KKameraConfigFactory("kcmkamera"))
56 // --------------- Camera control center module widget ---
58 KKameraConfig *KKameraConfig::m_instance = NULL;
60 KKameraConfig::KKameraConfig(QWidget *parent, const QVariantList &)
61 : KCModule(KKameraConfigFactory::componentData(), parent/*, name*/)
63 m_devicePopup = new KMenu(this);
64 m_actions = new KActionCollection(this);
65 m_config = new KConfig(KProtocolInfo::config("camera"), KConfig::SimpleConfig);
67 m_context = gp_context_new();
68 if (m_context) {
70 // Register the callback functions
71 gp_context_set_cancel_func(m_context, cbGPCancel, this);
72 gp_context_set_idle_func(m_context, cbGPIdle, this);
74 displayGPSuccessDialogue();
76 // load existing configuration
77 load();
79 } else {
81 displayGPFailureDialogue();
84 // store instance for frontend_prompt
85 m_instance = this;
88 KKameraConfig::~KKameraConfig()
90 delete m_config;
93 void KKameraConfig::defaults()
97 void KKameraConfig::displayGPFailureDialogue(void)
99 QVBoxLayout *topLayout = new QVBoxLayout(this);
100 topLayout->setSpacing(0);
101 topLayout->setMargin(0);
102 QLabel *label = new QLabel(i18n("Unable to initialize the gPhoto2 libraries."), this);
103 topLayout->addWidget(label);
106 void KKameraConfig::displayGPSuccessDialogue(void)
108 // set the kcontrol module buttons
109 setButtons(Help | Apply );
111 // create a layout with two vertical boxes
112 QVBoxLayout *topLayout = new QVBoxLayout(this);
113 topLayout->setSpacing(0);
114 topLayout->setMargin(0);
116 m_toolbar = new KToolBar(this, "ToolBar");
117 topLayout->addWidget(m_toolbar);
118 m_toolbar->setMovable(false);
120 // create list of devices
121 m_deviceSel = new K3IconView(this);
122 topLayout->addWidget(m_deviceSel);
124 connect(m_deviceSel, SIGNAL(rightButtonClicked(Q3IconViewItem *, const QPoint &)),
125 SLOT(slot_deviceMenu(Q3IconViewItem *, const QPoint &)));
126 connect(m_deviceSel, SIGNAL(doubleClicked(Q3IconViewItem *)),
127 SLOT(slot_configureCamera()));
128 connect(m_deviceSel, SIGNAL(selectionChanged(Q3IconViewItem *)),
129 SLOT(slot_deviceSelected(Q3IconViewItem *)));
131 m_deviceSel->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
133 // create actions
134 QAction *act;
136 act = m_actions->addAction("camera_add");
137 act->setIcon(KIcon("camera-photo"));
138 act->setText(i18n("Add"));
139 connect(act, SIGNAL(triggered(bool)), this, SLOT(slot_addCamera()));
140 act->setWhatsThis(i18n("Click this button to add a new camera."));
141 m_toolbar->addAction(act);
142 m_toolbar->addSeparator();
143 act = m_actions->addAction("camera_test");
144 act->setIcon(KIcon("dialog-ok"));
145 act->setText(i18n("Test"));
146 connect(act, SIGNAL(triggered(bool)), this, SLOT(slot_testCamera()));
147 act->setWhatsThis(i18n("Click this button to remove the selected camera from the list."));
148 m_toolbar->addAction(act);
149 act = m_actions->addAction("camera_remove");
150 act->setIcon(KIcon("user-trash"));
151 act->setText(i18n("Remove"));
152 connect(act, SIGNAL(triggered(bool)), this, SLOT(slot_removeCamera()));
153 act->setWhatsThis(i18n("Click this button to remove the selected camera from the list."));
154 m_toolbar->addAction(act);
155 act = m_actions->addAction("camera_configure");
156 act->setIcon(KIcon("configure"));
157 act->setText(i18n("Configure..."));
158 connect(act, SIGNAL(triggered(bool)), this, SLOT(slot_configureCamera()));
159 act->setWhatsThis(i18n("Click this button to change the configuration of the selected camera.<br><br>The availability of this feature and the contents of the Configuration dialog depend on the camera model."));
160 m_toolbar->addAction(act);
161 act = m_actions->addAction("camera_summary");
162 act->setIcon(KIcon("hwinfo"));
163 act->setText(i18n("Information"));
164 connect(act, SIGNAL(triggered(bool)), this, SLOT(slot_cameraSummary()));
165 act->setWhatsThis(i18n("Click this button to view a summary of the current status of the selected camera.<br><br>The availability of this feature and the contents of the Configuration dialog depend on the camera model."));
166 m_toolbar->addAction(act);
167 m_toolbar->addSeparator();
168 act = m_actions->addAction("camera_cancel");
169 act->setIcon(KIcon("process-stop"));
170 act->setText(i18n("Cancel"));
171 connect(act, SIGNAL(triggered(bool)), this, SLOT(slot_cancelOperation()));
172 act->setWhatsThis(i18n("Click this button to cancel the current camera operation."));
173 act->setEnabled(false);
174 m_toolbar->addAction(act);
177 void KKameraConfig::populateDeviceListView(void)
179 m_deviceSel->clear();
180 CameraDevicesMap::Iterator it;
181 for (it = m_devices.begin(); it != m_devices.end(); it++) {
182 if (it.value()) {
183 new Q3IconViewItem(m_deviceSel, it.key(), DesktopIcon("camera-photo"));
186 slot_deviceSelected(m_deviceSel->currentItem());
189 void KKameraConfig::save(void)
191 CameraDevicesMap::Iterator it;
193 for (it = m_devices.begin(); it != m_devices.end(); it++)
195 it.value()->save(m_config);
197 m_config->sync();
200 void KKameraConfig::load(void)
202 QStringList groupList = m_config->groupList();
203 QStringList::Iterator it;
204 int i, count;
205 CameraList *list;
206 CameraAbilitiesList *al;
207 GPPortInfoList *il;
208 const char *model, *value;
209 KCamera *kcamera;
211 for (it = groupList.begin(); it != groupList.end(); it++) {
212 if (*it != "<default>") {
213 KConfigGroup cg(m_config, *it);
214 if (cg.readEntry("Path").contains("usb:"))
215 continue;
217 kcamera = new KCamera(*it, cg.readEntry("Path"));
218 connect(kcamera, SIGNAL(error(const QString &)), SLOT(slot_error(const QString &)));
219 connect(kcamera, SIGNAL(error(const QString &, const QString &)), SLOT(slot_error(const QString &, const QString &)));
220 kcamera->load(m_config);
221 m_devices[*it] = kcamera;
224 m_cancelPending = false;
226 gp_list_new (&list);
228 gp_abilities_list_new (&al);
229 gp_abilities_list_load (al, m_context);
230 gp_port_info_list_new (&il);
231 gp_port_info_list_load (il);
232 gp_abilities_list_detect (al, il, list, m_context);
233 gp_abilities_list_free (al);
234 gp_port_info_list_free (il);
236 count = gp_list_count (list);
238 QMap<QString,QString> ports, names;
240 for (i = 0 ; i<count ; i++) {
241 gp_list_get_name (list, i, &model);
242 gp_list_get_value (list, i, &value);
244 ports[value] = model;
245 if (!strcmp(value,"usb:"))
246 names[model] = value;
248 if (ports.contains("usb:") && names[ports["usb:"]]!="usb:")
249 ports.remove("usb:");
251 QMap<QString,QString>::iterator portit;
253 for (portit = ports.begin() ; portit != ports.end(); portit++) {
254 /* kDebug() << "Adding USB camera: " << portit.data() << " at " << portit.key(); */
256 kcamera = new KCamera(portit.value(), portit.key());
257 connect(kcamera, SIGNAL(error(const QString &)), SLOT(slot_error(const QString &)));
258 connect(kcamera, SIGNAL(error(const QString &, const QString &)), SLOT(slot_error(const QString &, const QString &)));
259 m_devices[portit.value()] = kcamera;
261 populateDeviceListView();
263 gp_list_free (list);
266 void KKameraConfig::beforeCameraOperation(void)
268 m_cancelPending = false;
270 m_actions->action("camera_test")->setEnabled(false);
271 m_actions->action("camera_remove")->setEnabled(false);
272 m_actions->action("camera_configure")->setEnabled(false);
273 m_actions->action("camera_summary")->setEnabled(false);
275 m_actions->action("camera_cancel")->setEnabled(true);
278 void KKameraConfig::afterCameraOperation(void)
280 m_actions->action("camera_cancel")->setEnabled(false);
282 // if we're regaining control after a Cancel...
283 if (m_cancelPending) {
284 qApp->restoreOverrideCursor();
285 m_cancelPending = false;
288 // if any item was selected before the operation was run
289 // it makes sense for the relevant toolbar buttons to be enabled
290 slot_deviceSelected(m_deviceSel->currentItem());
293 QString KKameraConfig::suggestName(const QString &name)
295 QString new_name = name;
296 new_name.replace("/", ""); // we cannot have a slash in a URI's host
298 if (!m_devices.contains(new_name)) return new_name;
300 // try new names with a number appended until we find a free one
301 int i = 1;
302 while (i++ < 0xffff) {
303 new_name = name + " (" + QString::number(i) + ')';
304 if (!m_devices.contains(new_name)) return new_name;
307 return QString();
310 void KKameraConfig::slot_addCamera()
312 KCamera *m_device = new KCamera(QString::null, QString()); //krazy:exclusion=nullstrassign for old broken gcc
313 connect(m_device, SIGNAL(error(const QString &)), SLOT(slot_error(const QString &)));
314 connect(m_device, SIGNAL(error(const QString &, const QString &)), SLOT(slot_error(const QString &, const QString &)));
315 KameraDeviceSelectDialog dialog(this, m_device);
316 if (dialog.exec() == QDialog::Accepted) {
317 dialog.save();
318 m_device->setName(suggestName(m_device->model()));
319 m_devices.insert(m_device->name(), m_device);
320 populateDeviceListView();
321 emit changed(true);
322 } else {
323 delete m_device;
327 void KKameraConfig::slot_removeCamera()
329 QString name = m_deviceSel->currentItem()->text();
330 if (m_devices.contains(name)) {
331 KCamera *m_device = m_devices[name];
332 m_devices.remove(name);
333 delete m_device;
334 m_config->deleteGroup(name);
335 populateDeviceListView();
336 emit changed(true);
340 void KKameraConfig::slot_testCamera()
342 beforeCameraOperation();
344 QString name = m_deviceSel->currentItem()->text();
345 if (m_devices.contains(name)) {
346 KCamera *m_device = m_devices[name];
347 if (m_device->test())
348 KMessageBox::information(this, i18n("Camera test was successful."));
351 afterCameraOperation();
354 void KKameraConfig::slot_configureCamera()
356 QString name = m_deviceSel->currentItem()->text();
357 if (m_devices.contains(name)) {
358 KCamera *m_device = m_devices[name];
359 m_device->configure();
363 void KKameraConfig::slot_cameraSummary()
365 QString summary;
366 QString name = m_deviceSel->currentItem()->text();
367 if (m_devices.contains(name)) {
368 KCamera *m_device = m_devices[name];
369 summary = m_device->summary();
370 if (!summary.isNull()) {
371 KMessageBox::information(this, summary);
376 void KKameraConfig::slot_cancelOperation()
378 m_cancelPending = true;
379 // Prevent the user from keeping clicking Cancel
380 m_actions->action("camera_cancel")->setEnabled(false);
381 // and indicate that the click on Cancel did have some effect
382 qApp->setOverrideCursor(Qt::WaitCursor);
385 void KKameraConfig::slot_deviceMenu(Q3IconViewItem *item, const QPoint &point)
387 if (item) {
388 m_devicePopup->clear();
389 m_devicePopup->addAction(m_actions->action("camera_test"));
390 m_devicePopup->addAction(m_actions->action("camera_remove"));
391 m_devicePopup->addAction(m_actions->action("camera_configure"));
392 m_devicePopup->addAction(m_actions->action("camera_summary"));
393 m_devicePopup->popup(point);
397 void KKameraConfig::slot_deviceSelected(Q3IconViewItem *item)
399 m_actions->action("camera_test")->setEnabled(item);
400 m_actions->action("camera_remove")->setEnabled(item);
401 m_actions->action("camera_configure")->setEnabled(item);
402 m_actions->action("camera_summary")->setEnabled(item);
405 void KKameraConfig::cbGPIdle(GPContext * /*context*/, void * /*data*/)
407 /*KKameraConfig *self( reinterpret_cast<KKameraConfig*>(data) );*/
409 qApp->processEvents();
412 GPContextFeedback KKameraConfig::cbGPCancel(GPContext * /*context*/, void *data)
414 KKameraConfig *self( reinterpret_cast<KKameraConfig*>(data) );
416 // Since in practice no camera driver supports idle callbacks yet,
417 // we'll use the cancel callback as opportunity to process events
418 qApp->processEvents();
420 // If a cancel request is pending, ask gphoto to cancel
421 if (self->m_cancelPending)
422 return GP_CONTEXT_FEEDBACK_CANCEL;
423 else
424 return GP_CONTEXT_FEEDBACK_OK;
427 QString KKameraConfig::quickHelp() const
429 return i18n("<h1>Digital Camera</h1>\n"
430 "This module allows you to configure support for your digital camera.\n"
431 "You would need to select the camera's model and the port it is connected\n"
432 "to on your computer (e.g. USB, Serial, Firewire). If your camera doesn't\n"
433 "appear in the list of <i>Supported Cameras</i>, go to the\n"
434 "<a href=\"http://www.gphoto.org\">GPhoto web site</a> for a possible update.<br><br>\n"
435 "To view and download images from the digital camera, go to address\n"
436 "<a href=\"camera:/\">camera:/</a> in Konqueror and other KDE applications.");
439 void KKameraConfig::slot_error(const QString &message)
441 KMessageBox::error(this, message);
444 void KKameraConfig::slot_error(const QString &message, const QString &details)
446 KMessageBox::detailedError(this, message, details);