libkipi from trunk (KDE 4.3) : add support of kipi host settings "file timestamp...
[kdegraphics.git] / kamera / kcontrol / kamera.cpp
blob8eb0c071025752c10d856a4372c2d1a4722f3a82
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 } else {
78 displayGPFailureDialogue();
81 // store instance for frontend_prompt
82 m_instance = this;
85 KKameraConfig::~KKameraConfig()
87 delete m_config;
90 void KKameraConfig::defaults()
94 void KKameraConfig::displayGPFailureDialogue(void)
96 QVBoxLayout *topLayout = new QVBoxLayout(this);
97 topLayout->setSpacing(0);
98 topLayout->setMargin(0);
99 QLabel *label = new QLabel(i18n("Unable to initialize the gPhoto2 libraries."), this);
100 topLayout->addWidget(label);
103 void KKameraConfig::displayGPSuccessDialogue(void)
105 // set the kcontrol module buttons
106 setButtons(Help | Apply );
108 // create a layout with two vertical boxes
109 QVBoxLayout *topLayout = new QVBoxLayout(this);
110 topLayout->setSpacing(0);
111 topLayout->setMargin(0);
113 m_toolbar = new KToolBar(this, "ToolBar");
114 topLayout->addWidget(m_toolbar);
115 m_toolbar->setMovable(false);
117 // create list of devices
118 m_deviceSel = new K3IconView(this);
119 topLayout->addWidget(m_deviceSel);
121 connect(m_deviceSel, SIGNAL(rightButtonClicked(Q3IconViewItem *, const QPoint &)),
122 SLOT(slot_deviceMenu(Q3IconViewItem *, const QPoint &)));
123 connect(m_deviceSel, SIGNAL(doubleClicked(Q3IconViewItem *)),
124 SLOT(slot_configureCamera()));
125 connect(m_deviceSel, SIGNAL(selectionChanged(Q3IconViewItem *)),
126 SLOT(slot_deviceSelected(Q3IconViewItem *)));
128 m_deviceSel->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
130 // create actions
131 QAction *act;
133 act = m_actions->addAction("camera_add");
134 act->setIcon(KIcon("camera-photo"));
135 act->setText(i18n("Add"));
136 connect(act, SIGNAL(triggered(bool)), this, SLOT(slot_addCamera()));
137 act->setWhatsThis(i18n("Click this button to add a new camera."));
138 m_toolbar->addAction(act);
139 m_toolbar->addSeparator();
140 act = m_actions->addAction("camera_test");
141 act->setIcon(KIcon("dialog-ok"));
142 act->setText(i18n("Test"));
143 connect(act, SIGNAL(triggered(bool)), this, SLOT(slot_testCamera()));
144 act->setWhatsThis(i18n("Click this button to test the connection to the selected camera."));
145 m_toolbar->addAction(act);
146 act = m_actions->addAction("camera_remove");
147 act->setIcon(KIcon("user-trash"));
148 act->setText(i18n("Remove"));
149 connect(act, SIGNAL(triggered(bool)), this, SLOT(slot_removeCamera()));
150 act->setWhatsThis(i18n("Click this button to remove the selected camera from the list."));
151 m_toolbar->addAction(act);
152 act = m_actions->addAction("camera_configure");
153 act->setIcon(KIcon("configure"));
154 act->setText(i18n("Configure..."));
155 connect(act, SIGNAL(triggered(bool)), this, SLOT(slot_configureCamera()));
156 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."));
157 m_toolbar->addAction(act);
158 act = m_actions->addAction("camera_summary");
159 act->setIcon(KIcon("hwinfo"));
160 act->setText(i18n("Information"));
161 connect(act, SIGNAL(triggered(bool)), this, SLOT(slot_cameraSummary()));
162 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 Information dialog depend on the camera model."));
163 m_toolbar->addAction(act);
164 m_toolbar->addSeparator();
165 act = m_actions->addAction("camera_cancel");
166 act->setIcon(KIcon("process-stop"));
167 act->setText(i18n("Cancel"));
168 connect(act, SIGNAL(triggered(bool)), this, SLOT(slot_cancelOperation()));
169 act->setWhatsThis(i18n("Click this button to cancel the current camera operation."));
170 act->setEnabled(false);
171 m_toolbar->addAction(act);
173 load();
176 void KKameraConfig::populateDeviceListView(void)
178 m_deviceSel->clear();
179 CameraDevicesMap::Iterator it;
180 for (it = m_devices.begin(); it != m_devices.end(); it++) {
181 if (it.value()) {
182 new Q3IconViewItem(m_deviceSel, it.key(), DesktopIcon("camera-photo"));
185 slot_deviceSelected(m_deviceSel->currentItem());
188 void KKameraConfig::save(void)
190 CameraDevicesMap::Iterator it;
192 for (it = m_devices.begin(); it != m_devices.end(); it++)
194 it.value()->save(m_config);
196 m_config->sync();
199 void KKameraConfig::load(void)
201 QStringList groupList = m_config->groupList();
202 QStringList::Iterator it;
203 int i, count;
204 CameraList *list;
205 CameraAbilitiesList *al;
206 GPPortInfoList *il;
207 const char *model, *value;
208 KCamera *kcamera;
210 for (it = groupList.begin(); it != groupList.end(); it++) {
211 if (*it != "<default>") {
212 KConfigGroup cg(m_config, *it);
213 if (cg.readEntry("Path").contains("usb:"))
214 continue;
216 kcamera = new KCamera(*it, cg.readEntry("Path"));
217 connect(kcamera, SIGNAL(error(const QString &)), SLOT(slot_error(const QString &)));
218 connect(kcamera, SIGNAL(error(const QString &, const QString &)), SLOT(slot_error(const QString &, const QString &)));
219 kcamera->load(m_config);
220 m_devices[*it] = kcamera;
223 m_cancelPending = false;
225 gp_list_new (&list);
227 gp_abilities_list_new (&al);
228 gp_abilities_list_load (al, m_context);
229 gp_port_info_list_new (&il);
230 gp_port_info_list_load (il);
231 gp_abilities_list_detect (al, il, list, m_context);
232 gp_abilities_list_free (al);
233 gp_port_info_list_free (il);
235 count = gp_list_count (list);
237 QMap<QString,QString> ports, names;
239 for (i = 0 ; i<count ; i++) {
240 gp_list_get_name (list, i, &model);
241 gp_list_get_value (list, i, &value);
243 ports[value] = model;
244 if (!strcmp(value,"usb:"))
245 names[model] = value;
247 if (ports.contains("usb:") && names[ports["usb:"]]!="usb:")
248 ports.remove("usb:");
250 QMap<QString,QString>::iterator portit;
252 for (portit = ports.begin() ; portit != ports.end(); portit++) {
253 /* kDebug() << "Adding USB camera: " << portit.data() << " at " << portit.key(); */
255 kcamera = new KCamera(portit.value(), portit.key());
256 connect(kcamera, SIGNAL(error(const QString &)), SLOT(slot_error(const QString &)));
257 connect(kcamera, SIGNAL(error(const QString &, const QString &)), SLOT(slot_error(const QString &, const QString &)));
258 m_devices[portit.value()] = kcamera;
260 populateDeviceListView();
262 gp_list_free (list);
265 void KKameraConfig::beforeCameraOperation(void)
267 m_cancelPending = false;
269 m_actions->action("camera_test")->setEnabled(false);
270 m_actions->action("camera_remove")->setEnabled(false);
271 m_actions->action("camera_configure")->setEnabled(false);
272 m_actions->action("camera_summary")->setEnabled(false);
274 m_actions->action("camera_cancel")->setEnabled(true);
277 void KKameraConfig::afterCameraOperation(void)
279 m_actions->action("camera_cancel")->setEnabled(false);
281 // if we're regaining control after a Cancel...
282 if (m_cancelPending) {
283 qApp->restoreOverrideCursor();
284 m_cancelPending = false;
287 // if any item was selected before the operation was run
288 // it makes sense for the relevant toolbar buttons to be enabled
289 slot_deviceSelected(m_deviceSel->currentItem());
292 QString KKameraConfig::suggestName(const QString &name)
294 QString new_name = name;
295 new_name.replace("/", ""); // we cannot have a slash in a URI's host
297 if (!m_devices.contains(new_name)) return new_name;
299 // try new names with a number appended until we find a free one
300 int i = 1;
301 while (i++ < 0xffff) {
302 new_name = name + " (" + QString::number(i) + ')';
303 if (!m_devices.contains(new_name)) return new_name;
306 return QString();
309 void KKameraConfig::slot_addCamera()
311 KCamera *m_device = new KCamera(QString::null, QString()); //krazy:exclusion=nullstrassign for old broken gcc
312 connect(m_device, SIGNAL(error(const QString &)), SLOT(slot_error(const QString &)));
313 connect(m_device, SIGNAL(error(const QString &, const QString &)), SLOT(slot_error(const QString &, const QString &)));
314 KameraDeviceSelectDialog dialog(this, m_device);
315 if (dialog.exec() == QDialog::Accepted) {
316 dialog.save();
317 m_device->setName(suggestName(m_device->model()));
318 m_devices.insert(m_device->name(), m_device);
319 populateDeviceListView();
320 emit changed(true);
321 } else {
322 delete m_device;
326 void KKameraConfig::slot_removeCamera()
328 QString name = m_deviceSel->currentItem()->text();
329 if (m_devices.contains(name)) {
330 KCamera *m_device = m_devices[name];
331 m_devices.remove(name);
332 delete m_device;
333 m_config->deleteGroup(name);
334 populateDeviceListView();
335 emit changed(true);
339 void KKameraConfig::slot_testCamera()
341 beforeCameraOperation();
343 QString name = m_deviceSel->currentItem()->text();
344 if (m_devices.contains(name)) {
345 KCamera *m_device = m_devices[name];
346 if (m_device->test())
347 KMessageBox::information(this, i18n("Camera test was successful."));
350 afterCameraOperation();
353 void KKameraConfig::slot_configureCamera()
355 QString name = m_deviceSel->currentItem()->text();
356 if (m_devices.contains(name)) {
357 KCamera *m_device = m_devices[name];
358 m_device->configure();
362 void KKameraConfig::slot_cameraSummary()
364 QString summary;
365 QString name = m_deviceSel->currentItem()->text();
366 if (m_devices.contains(name)) {
367 KCamera *m_device = m_devices[name];
368 summary = m_device->summary();
369 if (!summary.isNull()) {
370 KMessageBox::information(this, summary);
375 void KKameraConfig::slot_cancelOperation()
377 m_cancelPending = true;
378 // Prevent the user from keeping clicking Cancel
379 m_actions->action("camera_cancel")->setEnabled(false);
380 // and indicate that the click on Cancel did have some effect
381 qApp->setOverrideCursor(Qt::WaitCursor);
384 void KKameraConfig::slot_deviceMenu(Q3IconViewItem *item, const QPoint &point)
386 if (item) {
387 m_devicePopup->clear();
388 m_devicePopup->addAction(m_actions->action("camera_test"));
389 m_devicePopup->addAction(m_actions->action("camera_remove"));
390 m_devicePopup->addAction(m_actions->action("camera_configure"));
391 m_devicePopup->addAction(m_actions->action("camera_summary"));
392 m_devicePopup->popup(point);
396 void KKameraConfig::slot_deviceSelected(Q3IconViewItem *item)
398 m_actions->action("camera_test")->setEnabled(item);
399 m_actions->action("camera_remove")->setEnabled(item);
400 m_actions->action("camera_configure")->setEnabled(item);
401 m_actions->action("camera_summary")->setEnabled(item);
404 void KKameraConfig::cbGPIdle(GPContext * /*context*/, void * /*data*/)
406 /*KKameraConfig *self( reinterpret_cast<KKameraConfig*>(data) );*/
408 qApp->processEvents();
411 GPContextFeedback KKameraConfig::cbGPCancel(GPContext * /*context*/, void *data)
413 KKameraConfig *self( reinterpret_cast<KKameraConfig*>(data) );
415 // Since in practice no camera driver supports idle callbacks yet,
416 // we'll use the cancel callback as opportunity to process events
417 qApp->processEvents();
419 // If a cancel request is pending, ask gphoto to cancel
420 if (self->m_cancelPending)
421 return GP_CONTEXT_FEEDBACK_CANCEL;
422 else
423 return GP_CONTEXT_FEEDBACK_OK;
426 QString KKameraConfig::quickHelp() const
428 return i18n("<h1>Digital Camera</h1>\n"
429 "This module allows you to configure support for your digital camera.\n"
430 "You would need to select the camera's model and the port it is connected\n"
431 "to on your computer (e.g. USB, Serial, Firewire). If your camera doesn't\n"
432 "appear in the list of <i>Supported Cameras</i>, go to the\n"
433 "<a href=\"http://www.gphoto.org\">GPhoto web site</a> for a possible update.<br><br>\n"
434 "To view and download images from the digital camera, go to address\n"
435 "<a href=\"camera:/\">camera:/</a> in Konqueror and other KDE applications.");
438 void KKameraConfig::slot_error(const QString &message)
440 KMessageBox::error(this, message);
443 void KKameraConfig::slot_error(const QString &message, const QString &details)
445 KMessageBox::detailedError(this, message, details);