mirror of
https://bitbucket.org/smil3y/kde-playground.git
synced 2025-02-23 18:32:51 +00:00
525 lines
16 KiB
C++
525 lines
16 KiB
C++
/*
|
|
|
|
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 <QtGui/QComboBox>
|
|
#include <QtGui/QGroupBox>
|
|
#include <QtGui/QHBoxLayout>
|
|
#include <QtGui/QLabel>
|
|
#include <QtGui/QListView>
|
|
#include <QtGui/QRadioButton>
|
|
#include <QtGui/QStackedWidget>
|
|
#include <QtGui/QVBoxLayout>
|
|
#include <QStandardItemModel>
|
|
|
|
#include <KLocale>
|
|
#include <KConfig>
|
|
#include <KMessageBox>
|
|
|
|
extern "C" {
|
|
#include <gphoto2.h>
|
|
}
|
|
|
|
#include "kamera.h"
|
|
#include "kameraconfigdialog.h"
|
|
#include "moc_kameradevice.cpp"
|
|
|
|
// 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= 2;
|
|
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;
|
|
m_abilitylist = 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.isNull()) {
|
|
return false;
|
|
}
|
|
|
|
if (gp_abilities_list_new(&m_abilitylist) != GP_OK) {
|
|
emit error(i18n("Could not allocate memory for the 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.toLocal8Bit().data());
|
|
if (index < 0) {
|
|
emit error(i18n("Description of abilities for camera %1 is not available."
|
|
" Configuration options may be incorrect.", 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.isNull() || m_path.isNull()) {
|
|
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.toLocal8Bit().data()), &info);
|
|
gp_camera_set_abilities(m_camera, m_abilities);
|
|
gp_camera_set_port_info(m_camera, info);
|
|
gp_port_info_list_free(il);
|
|
|
|
// this might take some time (esp. for non-existent 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."),
|
|
QString::fromLocal8Bit(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::fromLocal8Bit(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."), QString::fromLocal8Bit(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."), QString::fromLocal8Bit(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)
|
|
{
|
|
KConfigGroup group = config->group(m_name);
|
|
if (m_model.isNull()) {
|
|
m_model = group.readEntry("Model");
|
|
}
|
|
if (m_path.isNull()) {
|
|
m_path = group.readEntry("Path");
|
|
}
|
|
invalidateCamera();
|
|
}
|
|
|
|
void KCamera::save(KConfig *config)
|
|
{
|
|
KConfigGroup group = config->group(m_name);
|
|
group.writeEntry("Model", m_model);
|
|
group.writeEntry("Path", m_path);
|
|
}
|
|
|
|
QString KCamera::portName()
|
|
{
|
|
QString port = m_path.left(m_path.indexOf(":")).toLower();
|
|
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)
|
|
: KDialog(parent)
|
|
{
|
|
setCaption(i18n("Select Camera Device"));
|
|
setButtons(Ok | Cancel);
|
|
setDefaultButton(Ok);
|
|
setModal(true);
|
|
showButtonSeparator(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);
|
|
topLayout->setSpacing(KDialog::spacingHint());
|
|
topLayout->setMargin(0);
|
|
|
|
// the models list
|
|
m_modelSel = new QListView(page);
|
|
m_model = new QStandardItemModel(this);
|
|
m_model->setColumnCount(1);
|
|
m_model->setHeaderData(0, Qt::Horizontal, i18nc("@title:column", "Supported Cameras"));
|
|
m_modelSel->setModel(m_model);
|
|
|
|
topLayout->addWidget( m_modelSel );
|
|
connect(m_modelSel, SIGNAL(activated(const QModelIndex &)),
|
|
SLOT(slot_setModel(const QModelIndex &)));
|
|
// make sure listview only as wide as it needs to be
|
|
m_modelSel->setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred));
|
|
|
|
QVBoxLayout *rightLayout = new QVBoxLayout();
|
|
rightLayout->setSpacing(KDialog::spacingHint());
|
|
rightLayout->setMargin(0);
|
|
topLayout->addLayout( rightLayout );
|
|
|
|
m_portSelectGroup = new QGroupBox(i18n("Port"), page);
|
|
QVBoxLayout *vertLayout = new QVBoxLayout;
|
|
m_portSelectGroup->setLayout( vertLayout );
|
|
rightLayout->addWidget(m_portSelectGroup);
|
|
m_portSettingsGroup = new QGroupBox(i18n("Port Settings"), page);
|
|
QVBoxLayout *lay = new QVBoxLayout;
|
|
m_portSettingsGroup->setLayout( lay );
|
|
rightLayout->addWidget(m_portSettingsGroup);
|
|
// Create port type selection radiobuttons.
|
|
m_serialRB = new QRadioButton(i18n("Serial"));
|
|
vertLayout->addWidget(m_serialRB );
|
|
m_serialRB->setWhatsThis( i18n("If this option is checked, the camera has to be connected to one of the computer's serial ports (known as COM ports in Microsoft Windows.)"));
|
|
m_USBRB = new QRadioButton(i18n("USB"));
|
|
vertLayout->addWidget(m_USBRB );
|
|
m_USBRB->setWhatsThis( i18n("If this option is checked, the camera has to be connected to one of the computer's USB ports, or to a USB hub."));
|
|
// Create port settings widget stack
|
|
m_settingsStack = new QStackedWidget;
|
|
QWidget *grid2 = new QWidget(m_settingsStack);
|
|
QGridLayout *gridLayout2 = new QGridLayout(grid2);
|
|
gridLayout2->setSpacing(KDialog::spacingHint());
|
|
grid2->setLayout(gridLayout2);
|
|
QLabel *label2 = new QLabel(i18n("Port"), grid2);
|
|
gridLayout2->addWidget(label2, 0, 0, Qt::AlignLeft);
|
|
|
|
lay->addWidget(grid2);
|
|
lay->addWidget( m_settingsStack );
|
|
connect(m_serialRB, SIGNAL( toggled(bool) ),
|
|
this, SLOT( changeCurrentIndex() ) );
|
|
connect(m_USBRB, SIGNAL( toggled(bool) ),
|
|
this, SLOT( changeCurrentIndex() ) );
|
|
// none tab
|
|
m_settingsStack->insertWidget(INDEX_NONE, new QLabel(i18n("No port type selected."), m_settingsStack));
|
|
|
|
// serial tab
|
|
QWidget *grid = new QWidget(m_settingsStack);
|
|
QGridLayout *gridLayout = new QGridLayout(grid);
|
|
gridLayout->setSpacing(KDialog::spacingHint());
|
|
grid->setLayout(gridLayout);
|
|
|
|
QLabel *label = new QLabel(i18n("Port:"), grid);
|
|
m_serialPortCombo = new QComboBox(grid);
|
|
m_serialPortCombo->setEditable(true);
|
|
m_serialPortCombo->setWhatsThis( i18n("Specify here the serial port to which you connect the camera."));
|
|
|
|
gridLayout->addWidget(label, 1, 0, Qt::AlignLeft);
|
|
gridLayout->addWidget(m_serialPortCombo, 1, 1, Qt::AlignRight);
|
|
m_settingsStack->insertWidget(INDEX_SERIAL, grid);
|
|
|
|
m_settingsStack->insertWidget(INDEX_USB, new
|
|
QLabel(i18n("No further configuration is required for USB cameras."),
|
|
m_settingsStack));
|
|
|
|
// 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) {
|
|
char *xpath;
|
|
gp_port_info_get_path(info, &xpath);
|
|
if (strncmp(xpath, "serial:", 7) == 0) {
|
|
m_serialPortCombo->addItem(QString::fromLocal8Bit(xpath).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);
|
|
}
|
|
|
|
void KameraDeviceSelectDialog::changeCurrentIndex()
|
|
{
|
|
QRadioButton *send = dynamic_cast<QRadioButton*>(sender());
|
|
if (send) {
|
|
if (send == m_serialRB) {
|
|
m_settingsStack->setCurrentIndex(INDEX_SERIAL);
|
|
} else if (send == m_USBRB) {
|
|
m_settingsStack->setCurrentIndex(INDEX_USB);
|
|
}
|
|
}
|
|
}
|
|
|
|
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) {
|
|
QStandardItem *cameraItem = new QStandardItem;
|
|
cameraItem->setEditable(false);
|
|
cameraItem->setText(a.model);
|
|
m_model->appendRow(cameraItem);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
|
|
void KameraDeviceSelectDialog::save()
|
|
{
|
|
m_device->setModel(m_modelSel->currentIndex().data(Qt::DisplayRole).toString());
|
|
|
|
if (m_serialRB->isChecked()) {
|
|
m_device->setPath("serial:" + m_serialPortCombo->currentText());
|
|
} else if (m_USBRB->isChecked() ) {
|
|
m_device->setPath("usb:");
|
|
}
|
|
}
|
|
|
|
void KameraDeviceSelectDialog::load()
|
|
{
|
|
QString path = m_device->path();
|
|
QString port = path.left(path.indexOf(':')).toLower();
|
|
|
|
if (port == "serial") {
|
|
setPortType(INDEX_SERIAL);
|
|
}
|
|
if (port == "usb") {
|
|
setPortType(INDEX_USB);
|
|
}
|
|
|
|
QList<QStandardItem *> items = m_model->findItems(m_device->model());
|
|
foreach (QStandardItem *item, items) {
|
|
const QModelIndex index = m_model->indexFromItem(item);
|
|
m_modelSel->selectionModel()->select(index, QItemSelectionModel::Select);
|
|
}
|
|
}
|
|
|
|
void KameraDeviceSelectDialog::slot_setModel(const QModelIndex &modelIndex)
|
|
{
|
|
enableButtonOk(true);
|
|
m_portSelectGroup->setEnabled(true);
|
|
m_portSettingsGroup->setEnabled(true);
|
|
|
|
QString model = modelIndex.data(Qt::DisplayRole).toString();
|
|
|
|
CameraAbilities abilities;
|
|
int index = gp_abilities_list_lookup_model(m_device->m_abilitylist, model.toLocal8Bit().data());
|
|
if(index < 0) {
|
|
slot_error(i18n("Description of abilities for camera %1 is not available."
|
|
" Configuration options may be incorrect.", 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);
|
|
// 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.", model));
|
|
}
|
|
}
|
|
|
|
void KameraDeviceSelectDialog::setPortType(int type)
|
|
{
|
|
// Enable the correct button
|
|
if (type == INDEX_USB) {
|
|
m_USBRB->setChecked(true);
|
|
} else if (type == INDEX_SERIAL) {
|
|
m_serialRB->setChecked(true);
|
|
}
|
|
|
|
// Bring the right tab to the front
|
|
m_settingsStack->setCurrentIndex(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);
|
|
}
|