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.
tdegraphics/kamera/kcontrol/kameradevice.cpp

477 lines
13 KiB

/*
Copyright (C) 2001 The Kompany
2002-2003 Ilya Konstantinov <kde-devel@future.shiny.co.il>
2002-2003 Marcus Meissner <marcus@jet.franken.de>
2003 Nadeem Hasan <nhasan@nadmm.com>
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);
}