Logo Search packages:      
Sourcecode: kamera version File versions  Download package

kameradevice.cpp

/*

    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 "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= 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_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-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) {
                  if (strncmp(info.path, "serial:", 7) == 0)
                        m_serialPortCombo->addItem(QString::fromLocal8Bit(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 );
}

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);
}

Generated by  Doxygen 1.6.0   Back to index