/*
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 <tqlayout.h>
# include <tqwidgetstack.h>
# include <tqvbuttongroup.h>
# include <tqvgroupbox.h>
# include <tqcombobox.h>
# include <tqlineedit.h>
# include <tqradiobutton.h>
# include <tqwhatsthis.h>
# include <tqlabel.h>
# include <tqgrid.h>
# include <tdelocale.h>
# include <tdeconfig.h>
# include <tdelistview.h>
# include <tdemessagebox.h>
# include <kdebug.h>
# include "config.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 TQString & name , const TQString & 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_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-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 ;
}
TQString 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 TQString ( 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 ( TDEConfig * 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 ( TDEConfig * config )
{
config - > setGroup ( m_name ) ;
config - > writeEntry ( " Model " , m_model ) ;
config - > writeEntry ( " Path " , m_path ) ;
}
TQString KCamera : : portName ( )
{
TQString 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 TQString & name )
{
m_name = name ;
}
void KCamera : : setModel ( const TQString & model )
{
m_model = model ;
invalidateCamera ( ) ;
initInformation ( ) ;
}
void KCamera : : setPath ( const TQString & 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 ;
}
TQStringList KCamera : : supportedPorts ( )
{
initInformation ( ) ;
TQStringList 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 ( TQWidget * parent , KCamera * device )
: KDialogBase ( parent , " kkameradeviceselect " , true , i18n ( " Select Camera Device " ) , Ok | Cancel , Ok , true )
{
m_device = device ;
connect ( m_device , TQT_SIGNAL ( error ( const TQString & ) ) ,
TQT_SLOT ( slot_error ( const TQString & ) ) ) ;
connect ( m_device , TQT_SIGNAL ( error ( const TQString & , const TQString & ) ) ,
TQT_SLOT ( slot_error ( const TQString & , const TQString & ) ) ) ;
TQWidget * page = new TQWidget ( this ) ;
setMainWidget ( page ) ;
// a layout with vertical boxes
TQHBoxLayout * topLayout = new TQHBoxLayout ( page , 0 , KDialog : : spacingHint ( ) ) ;
// the models list
m_modelSel = new TDEListView ( page ) ;
topLayout - > addWidget ( m_modelSel ) ;
m_modelSel - > addColumn ( i18n ( " Supported Cameras " ) ) ;
m_modelSel - > setColumnWidthMode ( 0 , TQListView : : Maximum ) ;
connect ( m_modelSel , TQT_SIGNAL ( selectionChanged ( TQListViewItem * ) ) ,
TQT_SLOT ( slot_setModel ( TQListViewItem * ) ) ) ;
// make sure listview only as wide as it needs to be
m_modelSel - > setSizePolicy ( TQSizePolicy ( TQSizePolicy : : Maximum ,
TQSizePolicy : : Preferred ) ) ;
TQVBoxLayout * rightLayout = new TQVBoxLayout ( 0L , 0 , KDialog : : spacingHint ( ) ) ;
topLayout - > addLayout ( rightLayout ) ;
m_portSelectGroup = new TQVButtonGroup ( i18n ( " Port " ) , page ) ;
rightLayout - > addWidget ( m_portSelectGroup ) ;
m_portSettingsGroup = new TQVGroupBox ( i18n ( " Port Settings " ) , page ) ;
rightLayout - > addWidget ( m_portSettingsGroup ) ;
// Create port type selection radiobuttons.
m_serialRB = new TQRadioButton ( i18n ( " Serial " ) , m_portSelectGroup ) ;
m_portSelectGroup - > insert ( m_serialRB , INDEX_SERIAL ) ;
TQWhatsThis : : 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 TQRadioButton ( i18n ( " USB " ) , m_portSelectGroup ) ;
m_portSelectGroup - > insert ( m_USBRB , INDEX_USB ) ;
TQWhatsThis : : 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 TQWidgetStack ( m_portSettingsGroup ) ;
connect ( m_portSelectGroup , TQT_SIGNAL ( clicked ( int ) ) ,
m_settingsStack , TQT_SLOT ( raiseWidget ( int ) ) ) ;
// none tab
m_settingsStack - > addWidget ( new TQLabel ( i18n ( " No port type selected. " ) ,
m_settingsStack ) , INDEX_NONE ) ;
// serial tab
TQGrid * grid = new TQGrid ( 2 , m_settingsStack ) ;
grid - > setSpacing ( KDialog : : spacingHint ( ) ) ;
new TQLabel ( i18n ( " Port: " ) , grid ) ;
m_serialPortCombo = new TQComboBox ( TRUE , grid ) ;
TQWhatsThis : : add ( m_serialPortCombo , i18n ( " Here you should choose the serial port you connect the camera to. " ) ) ;
m_settingsStack - > addWidget ( grid , INDEX_SERIAL ) ;
grid = new TQGrid ( 2 , m_settingsStack ) ;
grid - > setSpacing ( KDialog : : spacingHint ( ) ) ;
new TQLabel ( i18n ( " Port " ) , grid ) ;
m_settingsStack - > addWidget ( new
TQLabel ( 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 ) {
# ifdef HAVE_GPHOTO2_5
char * xpath ;
gp_port_info_get_path ( info , & xpath ) ;
if ( strncmp ( xpath , " serial: " , 7 ) = = 0 )
m_serialPortCombo - > insertItem ( TQString : : fromLatin1 ( xpath ) . mid ( 7 ) ) ;
# else
if ( strncmp ( info . path , " serial: " , 7 ) = = 0 )
m_serialPortCombo - > insertItem ( TQString : : fromLatin1 ( info . path ) . mid ( 7 ) ) ;
# endif
}
}
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 TQListViewItem ( m_modelSel , a . model ) ;
}
}
return true ;
}
}
void KameraDeviceSelectDialog : : save ( )
{
m_device - > setModel ( m_modelSel - > currentItem ( ) - > text ( 0 ) ) ;
if ( m_portSelectGroup - > selected ( ) ) {
TQString 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 ( )
{
TQString path = m_device - > path ( ) ;
TQString port = path . left ( path . find ( " : " ) ) . lower ( ) ;
if ( port = = " serial " ) setPortType ( INDEX_SERIAL ) ;
if ( port = = " usb " ) setPortType ( INDEX_USB ) ;
TQListViewItem * 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 ( TQListViewItem * item )
{
enableButtonOK ( true ) ;
m_portSelectGroup - > setEnabled ( true ) ;
m_portSettingsGroup - > setEnabled ( true ) ;
TQString 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
TQButton * 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 TQString & message )
{
KMessageBox : : error ( this , message ) ;
}
void KameraDeviceSelectDialog : : slot_error ( const TQString & message , const TQString & details )
{
KMessageBox : : detailedError ( this , message , details ) ;
}