diff options
Diffstat (limited to 'kamera/kcontrol/kameradevice.cpp')
-rw-r--r-- | kamera/kcontrol/kameradevice.cpp | 476 |
1 files changed, 476 insertions, 0 deletions
diff --git a/kamera/kcontrol/kameradevice.cpp b/kamera/kcontrol/kameradevice.cpp new file mode 100644 index 00000000..010bf694 --- /dev/null +++ b/kamera/kcontrol/kameradevice.cpp @@ -0,0 +1,476 @@ +/* + + Copyright (C) 2001 The Kompany + 2002-2003 Ilya Konstantinov <[email protected]> + 2002-2003 Marcus Meissner <[email protected]> + 2003 Nadeem Hasan <[email protected]> + + 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 <qlayout.h> +#include <qwidgetstack.h> +#include <qvbuttongroup.h> +#include <qvgroupbox.h> +#include <qcombobox.h> +#include <qlineedit.h> +#include <qradiobutton.h> +#include <qwhatsthis.h> +#include <qlabel.h> +#include <qgrid.h> + +#include <klocale.h> +#include <kconfig.h> +#include <klistview.h> +#include <kmessagebox.h> +#include <kdebug.h> + +extern "C" { + #include <gphoto2.h> +} + +#include "kamera.h" +#include "kameraconfigdialog.h" +#include "kameradevice.moc" + +// Define some parts of the old API +#define GP_PROMPT_OK 0 +#define GP_PROMPT_CANCEL -1 + +static const int INDEX_NONE= 0; +static const int INDEX_SERIAL = 1; +static const int INDEX_USB= 3; +static GPContext *glob_context = 0; + +KCamera::KCamera(const QString &name, const QString &path) +{ + m_name = name; + m_model = name; + m_path = path; + m_camera = NULL; +} + +KCamera::~KCamera() +{ + if(m_camera) + gp_camera_free(m_camera); + if(m_abilitylist) + gp_abilities_list_free(m_abilitylist); +} + +bool KCamera::initInformation() +{ + if (!m_model) + return false; + + if(gp_abilities_list_new(&m_abilitylist) != GP_OK) { + emit error(i18n("Could not allocate memory for abilities list.")); + return false; + } + if(gp_abilities_list_load(m_abilitylist, glob_context) != GP_OK) { + emit error(i18n("Could not load ability list.")); + return false; + } + int index = gp_abilities_list_lookup_model(m_abilitylist, m_model.local8Bit().data()); + if(index < 0) { + emit error(i18n("Description of abilities for camera %1 is not available." + " Configuration options may be incorrect.").arg(m_model)); + return false; + } + gp_abilities_list_get_abilities(m_abilitylist, index, &m_abilities); + return true; +} + +bool KCamera::initCamera() +{ + if (m_camera) + return m_camera; + else { + int result; + + initInformation(); + + if (!m_model || !m_path) + return false; + + result = gp_camera_new(&m_camera); + if (result != GP_OK) { + // m_camera is not initialized, so we cannot get result as string + emit error(i18n("Could not access driver. Check your gPhoto2 installation.")); + return false; + } + + // set the camera's model + GPPortInfo info; + GPPortInfoList *il; + gp_port_info_list_new(&il); + gp_port_info_list_load(il); + gp_port_info_list_get_info(il, gp_port_info_list_lookup_path(il, m_path.local8Bit().data()), &info); + gp_port_info_list_free(il); + gp_camera_set_abilities(m_camera, m_abilities); + gp_camera_set_port_info(m_camera, info); + + // this might take some time (esp. for non-existant camera) - better be done asynchronously + result = gp_camera_init(m_camera, glob_context); + if (result != GP_OK) { + gp_camera_free(m_camera); + m_camera = NULL; + emit error( + i18n("Unable to initialize camera. Check your port settings and camera connectivity and try again."), + gp_result_as_string(result)); + return false; + } + + return m_camera; + } +} + +Camera* KCamera::camera() +{ + initCamera(); + return m_camera; +} + +QString KCamera::summary() +{ + int result; + CameraText summary; + + initCamera(); + + result = gp_camera_get_summary(m_camera, &summary, glob_context); + if (result != GP_OK) + return i18n("No camera summary information is available.\n"); + return QString(summary.text); +} + +bool KCamera::configure() +{ + CameraWidget *window; + int result; + + initCamera(); + + result = gp_camera_get_config(m_camera, &window, glob_context); + if (result != GP_OK) { + emit error(i18n("Camera configuration failed."), gp_result_as_string(result)); + return false; + } + + KameraConfigDialog kcd(m_camera, window); + result = kcd.exec() ? GP_PROMPT_OK : GP_PROMPT_CANCEL; + + if (result == GP_PROMPT_OK) { + result = gp_camera_set_config(m_camera, window, glob_context); + if (result != GP_OK) { + emit error(i18n("Camera configuration failed."), gp_result_as_string(result)); + return false; + } + } + + return true; +} + +bool KCamera::test() +{ + // TODO: Make testing non-blocking (maybe via KIO?) + // Currently, a failed serial test times out at about 30 sec. + return camera() != 0; +} + +void KCamera::load(KConfig *config) +{ + config->setGroup(m_name); + if (m_model.isNull()) + m_model = config->readEntry("Model"); + if (m_path.isNull()) + m_path = config->readEntry("Path"); + invalidateCamera(); +} + +void KCamera::save(KConfig *config) +{ + config->setGroup(m_name); + config->writeEntry("Model", m_model); + config->writeEntry("Path", m_path); +} + +QString KCamera::portName() +{ + QString port = m_path.left(m_path.find(":")).lower(); + if (port == "serial") return i18n("Serial"); + if (port == "usb") return i18n("USB"); + return i18n("Unknown port"); +} + +void KCamera::setName(const QString &name) +{ + m_name = name; +} + +void KCamera::setModel(const QString &model) +{ + m_model = model; + invalidateCamera(); + initInformation(); +} + +void KCamera::setPath(const QString &path) +{ + m_path = path; + invalidateCamera(); +} + +void KCamera::invalidateCamera() +{ + if (m_camera) { + gp_camera_free(m_camera); + m_camera = NULL; + } +} + +bool KCamera::isTestable() const +{ + return true; +} + +bool KCamera::isConfigurable() +{ + initInformation(); + return m_abilities.operations & GP_OPERATION_CONFIG; +} + +QStringList KCamera::supportedPorts() +{ + initInformation(); + QStringList ports; + if (m_abilities.port & GP_PORT_SERIAL) + ports.append("serial"); + if (m_abilities.port & GP_PORT_USB) + ports.append("usb"); + return ports; +} + +CameraAbilities KCamera::abilities() +{ + return m_abilities; +} + +// ---------- KameraSelectCamera ------------ + +KameraDeviceSelectDialog::KameraDeviceSelectDialog(QWidget *parent, KCamera *device) + : KDialogBase(parent, "kkameradeviceselect", true, i18n("Select Camera Device"), Ok | Cancel, Ok, true) +{ + m_device = device; + connect(m_device, SIGNAL(error(const QString &)), + SLOT(slot_error(const QString &))); + connect(m_device, SIGNAL(error(const QString &, const QString &)), + SLOT(slot_error(const QString &, const QString &))); + + QWidget *page = new QWidget( this ); + setMainWidget(page); + + // a layout with vertical boxes + QHBoxLayout *topLayout = new QHBoxLayout(page, 0, KDialog::spacingHint()); + + // the models list + m_modelSel = new KListView(page); + topLayout->addWidget( m_modelSel ); + m_modelSel->addColumn(i18n("Supported Cameras")); + m_modelSel->setColumnWidthMode(0, QListView::Maximum); + connect(m_modelSel, SIGNAL(selectionChanged(QListViewItem *)), + SLOT(slot_setModel(QListViewItem *))); + // make sure listview only as wide as it needs to be + m_modelSel->setSizePolicy(QSizePolicy(QSizePolicy::Maximum, + QSizePolicy::Preferred)); + + QVBoxLayout *rightLayout = new QVBoxLayout(0L, 0, KDialog::spacingHint()); + topLayout->addLayout( rightLayout ); + + m_portSelectGroup = new QVButtonGroup(i18n("Port"), page); + rightLayout->addWidget(m_portSelectGroup); + m_portSettingsGroup = new QVGroupBox(i18n("Port Settings"), page); + rightLayout->addWidget(m_portSettingsGroup); + + // Create port type selection radiobuttons. + m_serialRB = new QRadioButton(i18n("Serial"), m_portSelectGroup); + m_portSelectGroup->insert(m_serialRB, INDEX_SERIAL); + QWhatsThis::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.")); + m_USBRB = new QRadioButton(i18n("USB"), m_portSelectGroup); + m_portSelectGroup->insert(m_USBRB, INDEX_USB); + QWhatsThis::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.")); + // Create port settings widget stack + m_settingsStack = new QWidgetStack(m_portSettingsGroup); + connect(m_portSelectGroup, SIGNAL(clicked(int)), + m_settingsStack, SLOT(raiseWidget(int))); + + // none tab + m_settingsStack->addWidget(new QLabel(i18n("No port type selected."), + m_settingsStack), INDEX_NONE); + + // serial tab + QGrid *grid = new QGrid(2, m_settingsStack); + grid->setSpacing(KDialog::spacingHint()); + new QLabel(i18n("Port:"), grid); + m_serialPortCombo = new QComboBox(TRUE, grid); + QWhatsThis::add(m_serialPortCombo, i18n("Here you should choose the serial port you connect the camera to.")); + m_settingsStack->addWidget(grid, INDEX_SERIAL); + + grid = new QGrid(2, m_settingsStack); + grid->setSpacing(KDialog::spacingHint()); + new QLabel(i18n("Port"), grid); + + m_settingsStack->addWidget(new + QLabel(i18n("No further configuration is required for USB."), + m_settingsStack), INDEX_USB); + + // query gphoto2 for existing serial ports + GPPortInfoList *list; + GPPortInfo info; + int gphoto_ports=0; + gp_port_info_list_new(&list); + if(gp_port_info_list_load(list) >= 0) { + gphoto_ports = gp_port_info_list_count(list); + } + for (int i = 0; i < gphoto_ports; i++) { + if (gp_port_info_list_get_info(list, i, &info) >= 0) { + if (strncmp(info.path, "serial:", 7) == 0) + m_serialPortCombo->insertItem(QString::fromLatin1(info.path).mid(7)); + } + } + gp_port_info_list_free(list); + + // add a spacer + rightLayout->addStretch(); + + populateCameraListView(); + load(); + + enableButtonOK(false ); + m_portSelectGroup->setEnabled( false ); + m_portSettingsGroup->setEnabled( false ); +} + +bool KameraDeviceSelectDialog::populateCameraListView() +{ + gp_abilities_list_new (&m_device->m_abilitylist); + gp_abilities_list_load(m_device->m_abilitylist, glob_context); + int numCams = gp_abilities_list_count(m_device->m_abilitylist); + CameraAbilities a; + + if(numCams < 0) { + // XXX libgphoto2 failed to get te camera list + return false; + } else { + for(int x = 0; x < numCams; ++x) { + if(gp_abilities_list_get_abilities(m_device->m_abilitylist, x, &a) == GP_OK) { + new QListViewItem(m_modelSel, a.model); + } + } + return true; + } +} + +void KameraDeviceSelectDialog::save() +{ + m_device->setModel(m_modelSel->currentItem()->text(0)); + + if (m_portSelectGroup->selected()) { + QString type = m_portSelectGroup->selected()->text(); + + if(type == i18n("Serial")) + m_device->setPath("serial:" + m_serialPortCombo->currentText()); + else if(type == i18n("USB")) + m_device->setPath("usb:"); + } else { + // This camera has no port type (e.g. "Directory Browse" camera). + // Do nothing. + } +} + +void KameraDeviceSelectDialog::load() +{ + QString path = m_device->path(); + QString port = path.left(path.find(":")).lower(); + + if (port == "serial") setPortType(INDEX_SERIAL); + if (port == "usb") setPortType(INDEX_USB); + + QListViewItem *modelItem = m_modelSel->firstChild(); + if( modelItem) + { + do { + if (modelItem->text(0) == m_device->model()) { + m_modelSel->setSelected(modelItem, true); + m_modelSel->ensureItemVisible(modelItem); + } + } while ( ( modelItem = modelItem->nextSibling() ) ); + } +} + +void KameraDeviceSelectDialog::slot_setModel(QListViewItem *item) +{ + enableButtonOK(true); + m_portSelectGroup->setEnabled(true); + m_portSettingsGroup->setEnabled(true); + + QString model = item->text(0); + + CameraAbilities abilities; + int index = gp_abilities_list_lookup_model(m_device->m_abilitylist, model.local8Bit().data()); + if(index < 0) { + slot_error(i18n("Description of abilities for camera %1 is not available." + " Configuration options may be incorrect.").arg(model)); + } + int result = gp_abilities_list_get_abilities(m_device->m_abilitylist, index, &abilities); + if (result == GP_OK) { + // enable radiobuttons for supported port types + m_serialRB->setEnabled(abilities.port & GP_PORT_SERIAL); + m_USBRB->setEnabled(abilities.port & GP_PORT_USB); + + // turn off any selected port + QButton *selected = m_portSelectGroup->selected(); + if(selected != NULL) + selected->toggle(); + + // if there's only one available port type, make sure it's selected + if (abilities.port == GP_PORT_SERIAL) + setPortType(INDEX_SERIAL); + if (abilities.port == GP_PORT_USB) + setPortType(INDEX_USB); + } else { + slot_error(i18n("Description of abilities for camera %1 is not available." + " Configuration options may be incorrect.").arg(model)); + } +} + +void KameraDeviceSelectDialog::setPortType(int type) +{ + // Enable the correct button + m_portSelectGroup->setButton(type); + + // Bring the right tab to the front + m_settingsStack->raiseWidget(type); +} + +void KameraDeviceSelectDialog::slot_error(const QString &message) +{ + KMessageBox::error(this, message); +} + +void KameraDeviceSelectDialog::slot_error(const QString &message, const QString &details) +{ + KMessageBox::detailedError(this, message, details); +} |