/*************************************************************************** * copyright : (C) 2006 Seb Ruiz * **************************************************************************/ /*************************************************************************** * * * 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. * * * ***************************************************************************/ #include "ipodheader.h" #include "imagelist.h" #include "imagelistitem.h" #include "ipodexportdialog.h" #include "ipodlistitem.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // add images #include #include //new album #include #include #include #include #include #include #if KIPI_PLUGIN #include #endif #define debug() kdDebug() using namespace IpodExport; UploadDialog *UploadDialog::s_instance = 0; UploadDialog::UploadDialog( #if KIPI_PLUGIN KIPI::Interface* interface, #endif TQString caption, TQWidget *parent ) : KDialogBase( KDialogBase::Plain, caption, /*Help|*/Close, Cancel, parent, "TripodDialog", false, false ) #if KIPI_PLUGIN , m_interface( interface ) #endif , m_itdb( 0 ) , m_ipodInfo( 0 ) , m_ipodHeader( 0 ) , m_transferring( false ) , m_destinationAlbum( 0 ) , m_ipodAlbumList( 0 ) , m_mountPoint( TQString() ) , m_deviceNode( TQString() ) { s_instance = this; TQWidget *box = plainPage(); TQVBoxLayout *dvlay = new TQVBoxLayout( box, 6 ); dvlay->setMargin( 2 ); m_ipodHeader = new IpodHeader( box ); dvlay->addWidget( m_ipodHeader ); m_destinationBox = new TQHGroupBox( i18n("iPod"), box ); m_ipodAlbumList = new ImageList( ImageList::IpodType, m_destinationBox ); m_ipodAlbumList->setMinimumHeight( 80 ); TQWidget *buttons = new TQWidget( m_destinationBox ); TQVBoxLayout *buttonLayout = new TQVBoxLayout( buttons, 0, spacingHint() ); m_createAlbumButton = new TQPushButton( i18n("&New..."), buttons, "addAlbumButton"); TQWhatsThis::add( m_createAlbumButton, i18n("Create a new photo album on the iPod.")); m_removeAlbumButton = new TQPushButton( i18n("&Remove"), buttons, "remAlbumButton"); m_renameAlbumButton = new TQPushButton( i18n("R&ename..."), buttons, "renameAlbumsButton"); m_removeAlbumButton->setEnabled( false ); m_renameAlbumButton->setEnabled( false ); TQWhatsThis::add( m_removeAlbumButton, i18n("Remove the selected photos or albums from the iPod.")); TQWhatsThis::add( m_renameAlbumButton, i18n("Rename the selected photo album on the iPod.")); TQLabel *ipod_icon = new TQLabel( buttons ); ipod_icon->setPixmap( TDEGlobal::iconLoader()->loadIcon( "ipod", TDEIcon::Desktop, TDEIcon::SizeHuge ) ); m_ipodPreview = new TQLabel( buttons ); m_ipodPreview->setFixedHeight( 80 ); m_ipodPreview->setAlignment( TQt::AlignHCenter | TQt::AlignVCenter ); m_ipodPreview->setSizePolicy( TQSizePolicy( TQSizePolicy::Preferred, TQSizePolicy::Preferred ) ); buttonLayout->addWidget( m_createAlbumButton ); buttonLayout->addWidget( m_removeAlbumButton ); buttonLayout->addWidget( m_renameAlbumButton ); buttonLayout->addWidget( m_ipodPreview ); buttonLayout->addStretch( 1 ); buttonLayout->addWidget( ipod_icon ); dvlay->addWidget( m_destinationBox ); m_urlListBox = new TQHGroupBox( i18n("Hard Disk"), box ); TQWidget* urlBox = new TQWidget( m_urlListBox ); TQHBoxLayout* urlLayout = new TQHBoxLayout( urlBox, 0, spacingHint() ); m_uploadList = new ImageList( ImageList::UploadType, urlBox ); m_uploadList->setMinimumHeight( 80 ); urlLayout->addWidget( m_uploadList ); m_uploadList->setSizePolicy( TQSizePolicy::Expanding, TQSizePolicy::MinimumExpanding ); TQVBoxLayout* uploadPaneLayout = new TQVBoxLayout( urlLayout ); m_addImagesButton = new TQPushButton ( i18n( "&Add..." ), urlBox ); uploadPaneLayout->addWidget( m_addImagesButton ); TQWhatsThis::add( m_addImagesButton, i18n("Add images to be queued for the iPod.") ); m_remImagesButton = new TQPushButton ( i18n( "&Remove" ), urlBox ); uploadPaneLayout->addWidget( m_remImagesButton ); TQWhatsThis::add( m_remImagesButton, i18n("Remove selected image from the list.") ); m_transferImagesButton = new TQPushButton( i18n( "&Transfer" ), urlBox ); uploadPaneLayout->addWidget( m_transferImagesButton ); TQWhatsThis::add( m_transferImagesButton, i18n("Transfer images to the selected iPod album.") ); m_imagePreview = new TQLabel( urlBox ); m_imagePreview->setFixedHeight( 80 ); m_imagePreview->setAlignment( TQt::AlignHCenter | TQt::AlignVCenter ); m_imagePreview->setSizePolicy( TQSizePolicy( TQSizePolicy::Preferred, TQSizePolicy::Preferred ) ); TQWhatsThis::add( m_imagePreview, i18n( "The preview of the selected image in the list." ) ); TQLabel *hdd_icon = new TQLabel( urlBox ); hdd_icon->setPixmap( TDEGlobal::iconLoader()->loadIcon( "system", TDEIcon::Desktop, TDEIcon::SizeHuge ) ); uploadPaneLayout->addWidget( m_imagePreview ); uploadPaneLayout->addStretch( 1 ); uploadPaneLayout->addWidget( hdd_icon ); dvlay->addWidget( m_urlListBox ); /// populate the ipod view with a list of albums etc refreshDevices(); #if KIPI_PLUGIN /// add selected items to the ImageList KIPI::ImageCollection images = interface->currentSelection(); if ( images.isValid() ) { KURL::List selected = images.images(); for( KURL::List::Iterator it = selected.begin(); it != selected.end(); ++it ) { addUrlToList( (*it).path() ); } } #endif enableButtons(); /// connect the signals & slots connect( m_createAlbumButton, TQT_SIGNAL( clicked() ), TQT_SLOT( createIpodAlbum() ) ); connect( m_removeAlbumButton, TQT_SIGNAL( clicked() ), TQT_SLOT( deleteIpodAlbum() ) ); connect( m_renameAlbumButton, TQT_SIGNAL( clicked() ), TQT_SLOT( renameIpodAlbum() ) ); connect( m_uploadList, TQT_SIGNAL( addedDropItems(TQStringList) ), TQT_SLOT( addDropItems(TQStringList) ) ); connect( m_uploadList, TQT_SIGNAL( currentChanged(TQListViewItem*) ), TQT_SLOT( imageSelected(TQListViewItem*) ) ); connect( m_ipodAlbumList, TQT_SIGNAL( currentChanged(TQListViewItem*) ), TQT_SLOT( ipodItemSelected(TQListViewItem*) ) ); connect( m_addImagesButton, TQT_SIGNAL( clicked() ), TQT_SLOT( imagesFilesButtonAdd() ) ); connect( m_remImagesButton, TQT_SIGNAL( clicked() ), TQT_SLOT( imagesFilesButtonRem() ) ); connect( m_transferImagesButton, TQT_SIGNAL( clicked() ), TQT_SLOT( startTransfer() ) ); } void UploadDialog::getIpodAlbums() { if( !m_itdb ) return; debug() << "populating ipod view" << endl; // clear cache while( m_ipodAlbumList->firstChild() ) delete m_ipodAlbumList->firstChild(); IpodAlbumItem *last = 0; for( GList *it = m_itdb->photoalbums; it; it = it->next ) { Itdb_PhotoAlbum *ipodAlbum = (Itdb_PhotoAlbum *)it->data; debug() << " found album: " << ipodAlbum->name << endl; last = new IpodAlbumItem( m_ipodAlbumList, last, ipodAlbum ); last->setPixmap( 0, TDEGlobal::iconLoader()->loadIcon( "folder", TDEIcon::Toolbar, TDEIcon::SizeSmall ) ); getIpodAlbumPhotos( last, ipodAlbum ); } } void UploadDialog::getIpodAlbumPhotos( IpodAlbumItem *item, Itdb_PhotoAlbum *album ) { if( !item || !album || !m_itdb ) return; IpodPhotoItem *last = 0; for( GList *it = album->members; it; it = it->next ) { Itdb_Artwork *photo = (Itdb_Artwork*)it->data; gint photo_id = photo->id; last = new IpodPhotoItem( item, last, photo ); last->setText( 0, TQString::number( photo_id ) ); last->setPixmap( 0, TDEGlobal::iconLoader()->loadIcon( "image", TDEIcon::Toolbar, TDEIcon::SizeSmall ) ); } } void UploadDialog::reloadIpodAlbum( IpodAlbumItem *item, Itdb_PhotoAlbum *album ) { if( !item ) return; while( item->firstChild() ) delete item->firstChild(); // clear the items, so we can reload them again Itdb_PhotoAlbum *ipodAlbum = 0; for( GList *it = m_itdb->photoalbums; it; it = it->next ) { ipodAlbum = (Itdb_PhotoAlbum *)it->data; if( strcmp( ipodAlbum->name, album->name ) == 0 ) break; // we found the album } dynamic_cast(item)->setPhotoAlbum( ipodAlbum ); getIpodAlbumPhotos( item, ipodAlbum ); } void UploadDialog::enableButtons() { // enable the start button only if there are albums to transfer to, items to transfer // and a database to add to! const bool transfer = m_uploadList->childCount() > 0 && // we have items to transfer m_ipodAlbumList->childCount() > 0 && // the ipod has albums !m_transferring && // we aren't transferring m_ipodAlbumList->selectedItem() && // selected a destination album m_itdb; m_transferImagesButton->setEnabled( transfer ); enableButton( KDialogBase::Close, !m_transferring ); const TQListViewItem *ipodSelection = m_ipodAlbumList->selectedItem(); const bool isMasterLibrary = ( ipodSelection == m_ipodAlbumList->firstChild() ); m_removeAlbumButton->setEnabled( ipodSelection && !isMasterLibrary ); m_renameAlbumButton->setEnabled( ipodSelection && !isMasterLibrary && ipodSelection->depth() == 0 ); } void UploadDialog::startTransfer() { if( !m_itdb || !m_uploadList->childCount() ) return; TQListViewItem *selected = m_ipodAlbumList->selectedItem(); if( !selected || selected->depth() != 0 /*not album*/) return; m_transferring = true; #define selected static_cast( selected ) Itdb_PhotoAlbum *album = selected->photoAlbum(); enableButton( KDialogBase::User1, false ); enableButton( KDialogBase::Close, false ); GError *err = 0; while( TQListViewItem *item = m_uploadList->firstChild() ) { #define item static_cast(item) debug() << "Uploading " << item->pathSrc() << " to ipod album " << album->name << endl; Itdb_Artwork *art = itdb_photodb_add_photo( m_itdb, TQFile::encodeName( item->pathSrc() ), 0, 0, &err ); if( !art ) { if( err ) { debug() << "Error adding photo " << item->pathSrc() << " to database:" << err->message << endl; err = 0; } } else itdb_photodb_photoalbum_add_photo( m_itdb, album, art, 0 ); delete item; #undef item } itdb_photodb_write( m_itdb, &err ); if( err ) debug() << "Failed with error: " << err->message << endl; reloadIpodAlbum( selected, album ); IpodAlbumItem *library = static_cast( m_ipodAlbumList->firstChild() ); reloadIpodAlbum( library, library->photoAlbum() ); m_transferring = false; enableButtons(); #undef selected } void UploadDialog::ipodItemSelected( TQListViewItem *item ) { m_ipodPreview->clear(); if( m_ipodAlbumList->currentItem() ) m_ipodAlbumList->currentItem()->setSelected( true ); enableButtons(); #define item dynamic_cast(item) if( !item ) return; Itdb_Artwork *artwork = item->artwork(); // Itdb_Thumb *thumb = itdb_artwork_get_thumb_by_type( artwork, ITDB_THUMB_PHOTO_SMALL ); // if( !thumb ) // { debug() << "no thumb was found" << endl; return; // } #undef item // GdkPixbuf *buf = itdb_thumb_get_gdk_pixbuf( m_itdb->device, thumb ); // int size = 0; // TQImage *image = buf->convertToImage(); // debug() << "image size: " << image->size() << endl; // // TQPixmap pix; // pix.convertFromImage( image ); // m_ipodPreview->setPixmap( pix ); } void UploadDialog::imageSelected( TQListViewItem *item ) { if( !item || m_uploadList->childCount() == 0 || m_transferring ) { m_imagePreview->clear(); return; } ImageListItem *pitem = static_cast( item ); if ( !pitem ) return; m_imagePreview->clear(); TQString IdemIndexed = "file:" + pitem->pathSrc(); KURL url( IdemIndexed ); TDEIO::PreviewJob* m_thumbJob = TDEIO::filePreview( url, m_imagePreview->height() ); connect( m_thumbJob, TQT_SIGNAL( gotPreview(const KFileItem*, const TQPixmap&) ), this, TQT_SLOT( gotImagePreview(const KFileItem*, const TQPixmap&) ) ); } void UploadDialog::gotImagePreview( const KFileItem* url, const TQPixmap &pixmap ) { #if KIPI_PLUGIN TQPixmap pix( pixmap ); // Rotate the thumbnail compared to the angle the host application dictate KIPI::ImageInfo info = m_interface->info( url->url() ); if ( info.angle() != 0 ) { TQImage img = pix.convertToImage(); TQWMatrix matrix; matrix.rotate( info.angle() ); img = img.xForm( matrix ); pix.convertFromImage( img ); } m_imagePreview->setPixmap(pix); #else Q_UNUSED( url ); m_imagePreview->setPixmap( pixmap ); #endif } void UploadDialog::imagesFilesButtonAdd() { TQStringList fileList; KURL::List urls; #if KIPI_PLUGIN urls = KIPI::ImageDialog::getImageURLs( this, m_interface ); #else const TQString filter = TQString( "*.jpg *.jpeg *.jpe *.tiff *.gif *.png *.bmp|" + i18n("Image files") ); KFileDialog dlg( TQString(), filter, this, "addImagesDlg", true ); dlg.setCaption( i18n("Add Images") ); dlg.setMode( KFile::Files | KFile::Directory ); dlg.exec(); urls = dlg.selectedURLs(); #endif for( KURL::List::Iterator it = urls.begin() ; it != urls.end() ; ++it ) fileList << (*it).path(); if ( urls.isEmpty() ) return; addDropItems( fileList ); } void UploadDialog::imagesFilesButtonRem() { TQPtrList selected = m_uploadList->selectedItems(); for( TQListViewItem *it = selected.first(); it; it = selected.next() ) delete it; enableButton( KDialogBase::User1, m_uploadList->childCount() > 0 ); } void UploadDialog::createIpodAlbum() { TQString helper; #if KIPI_PLUGIN KIPI::ImageCollection album = m_interface->currentAlbum(); if( album.isValid() ) helper = album.name(); #endif bool ok = false; TQString newAlbum = KInputDialog::getText( i18n("New iPod Photo Album"), i18n("Create a new album:"), helper, &ok, this ); if( ok ) { debug() << "creating album " << newAlbum << endl; IpodAlbumItem *last = static_cast(m_ipodAlbumList->lastItem()); // FIXME?? O(n) Itdb_PhotoAlbum *photoAlbum = itdb_photodb_photoalbum_create( m_itdb, TQFile::encodeName( newAlbum ), -1/*end*/ ); // add the new album to the list view IpodAlbumItem *i = new IpodAlbumItem( m_ipodAlbumList, last, photoAlbum ); i->setPixmap( 0, TDEGlobal::iconLoader()->loadIcon( "folder", TDEIcon::Toolbar, TDEIcon::SizeSmall ) ); m_ipodAlbumList->clearSelection(); m_ipodAlbumList->setSelected( i, true ); // commit the changes to the iPod GError *err = 0; itdb_photodb_write( m_itdb, &err ); } } void UploadDialog::renameIpodAlbum() { IpodAlbumItem *selected = dynamic_cast(m_ipodAlbumList->selectedItem()); // only allow renaming of album items if( !selected || selected->depth() != 0 ) return; bool ok = false; TQString newName = KInputDialog::getText( i18n("Rename iPod Photo Album"), i18n("New album title:"), selected->text(0), &ok, this ); if( ok ) { // change the name on the ipod, and rename the listviewitem selected->setName( newName ); // commit changes to the iPod GError *err = 0; itdb_photodb_write( m_itdb, &err ); } } bool UploadDialog::deleteIpodPhoto( IpodPhotoItem *photo ) { if( !photo ) return false; IpodAlbumItem *album = static_cast( photo->parent() ); if( !album ) return false; Itdb_Artwork *artwork = photo->artwork(); if( !artwork ) { debug() << "Could not find photo artwork with id: " << photo->text(0) << endl; return false; } Itdb_PhotoAlbum *photo_album = album->photoAlbum(); itdb_photodb_remove_photo( m_itdb, photo_album, artwork ); // if we remove from the library, remove from all sub albums too if( photo_album->album_type == 0x01 ) // master album { for( TQListViewItem *albumIt = m_ipodAlbumList->firstChild()->nextSibling(); //skip library albumIt; albumIt = albumIt->nextSibling() ) { for( TQListViewItem *photoIt = albumIt->firstChild(); photoIt; photoIt = photoIt->nextSibling() ) { if( photoIt->text(0) == photo->text(0) ) { debug() << "removing reference to photo from album " << albumIt->text(0) << endl; delete photoIt; } } } } return true; } bool UploadDialog::deleteIpodAlbum( IpodAlbumItem *album ) { debug() << "deleting album: " << album->name() << ", and removing all photos" << endl; itdb_photodb_photoalbum_remove( m_itdb, album->photoAlbum(), true/*remove photos*/); return true; } void UploadDialog::deleteIpodAlbum() { TQListViewItem *selected = m_ipodAlbumList->selectedItem(); if( !selected ) return; bool result = false; switch( selected->depth() ) { case 0: //album result = deleteIpodAlbum( dynamic_cast( selected ) ); break; case 1: //image result = deleteIpodPhoto( dynamic_cast( selected ) ); break; } if( result ) //selected item may have been deleted by deleteIpodPhoto delete selected; GError *err = 0; itdb_photodb_write( m_itdb, &err ); } void UploadDialog::addDropItems( TQStringList filesPath ) { if( filesPath.isEmpty() ) return; for( TQStringList::Iterator it = filesPath.begin() ; it != filesPath.end() ; ++it ) { TQString currentDropFile = *it; // Check if the new item already exist in the list. bool itemExists = false; TQListViewItemIterator it2( m_uploadList ); while( it2.current() ) { ImageListItem *item = static_cast(it2.current()); if( item->pathSrc() == currentDropFile.section('/', 0, -1) ) { itemExists = true; break; } ++it2; } if( !itemExists ) addUrlToList( currentDropFile ); } enableButton( KDialogBase::User1, m_uploadList->childCount() > 0 ); } void UploadDialog::addUrlToList( TQString file ) { TQFileInfo *fi = new TQFileInfo( file ); new ImageListItem( m_uploadList, file.section('/', 0, -1), fi->fileName() ); delete fi; } bool UploadDialog::openDevice() { if( m_itdb ) { debug() << "ipod at " << m_mountPoint << " already opened" << endl; return false; } // try to find a mounted ipod bool ipodFound = false; KMountPoint::List currentmountpoints = KMountPoint::currentMountPoints(); for( KMountPoint::List::Iterator mountiter = currentmountpoints.begin(); mountiter != currentmountpoints.end(); ++mountiter ) { TQString devicenode = (*mountiter)->mountedFrom(); TQString mountpoint = (*mountiter)->mountPoint(); if( !m_mountPoint.isEmpty() && mountpoint != m_mountPoint ) continue; if( mountpoint.startsWith( "/proc" ) || mountpoint.startsWith( "/sys" ) || mountpoint.startsWith( "/dev" ) || mountpoint.startsWith( "/boot" ) ) continue; if( !m_deviceNode.isEmpty() && devicenode != m_deviceNode ) continue; /// Detecting whether an iPod exists. TQString path = TQString( itdb_get_control_dir( TQFile::encodeName( mountpoint ) ) ); TQDir d( path ); if( path.isEmpty() || !d.exists() ) continue; if( m_mountPoint.isEmpty() ) m_mountPoint = mountpoint; /// Here, we have found an ipod, but we are not sure if the photo db exists. /// Try and parse it to determine whether we have initialised the iPod. ipodFound = true; GError *err = 0; m_itdb = itdb_photodb_parse( TQFile::encodeName( mountpoint ), &err ); if( err ) { g_error_free( err ); if( m_itdb ) { itdb_photodb_free( m_itdb ); m_itdb = 0; } } break; } if( !ipodFound ) { debug() << "no mounted ipod found" << endl; if( m_itdb ) { itdb_photodb_free( m_itdb ); m_itdb = 0; } return false; } debug() << "ipod found mounted at " << m_mountPoint << endl; /// No photodb was able to be parsed, so offer to initialise the ipod for the user. if( !m_itdb ) { debug() << "could not find iTunesDB on device mounted at " << m_mountPoint << endl; TQString msg = i18n( "An iPod photo database could not be found on device mounted at %1. " "Should I try to initialize your iPod photo database?" ).arg( m_mountPoint ); if( KMessageBox::warningContinueCancel( this, msg, i18n( "Initialize iPod Photo Database?" ), KGuiItem(i18n("&Initialize"), "new") ) == KMessageBox::Continue ) { m_itdb = itdb_photodb_create( TQFile::encodeName( m_mountPoint ) ); itdb_device_set_mountpoint( m_itdb->device, TQFile::encodeName( m_mountPoint ) ); if( !m_itdb ) { debug() << "Could not initialise photodb..." << endl; return false; } GError *err = 0; itdb_photodb_write( m_itdb, &err ); } else return false; } return true; } Itdb_Artwork * UploadDialog::photoFromId( const uint id ) { if( !m_itdb ) return 0; for( GList *it = m_itdb->photos; it; it=it->next ) { Itdb_Artwork *photo = (Itdb_Artwork*)it->data; if( !photo ) return 0; if( photo->id == id ) return photo; } return 0; } TQString UploadDialog::ipodModel() const { if( m_ipodInfo ) return TQString( itdb_info_get_ipod_model_name_string( m_ipodInfo->ipod_model ) ); return TQString(); } void UploadDialog::refreshDevices() { debug() << "refreshing ipod devices" << endl; if( !m_ipodHeader ) return; m_ipodHeader->disconnect(); if( !openDevice() ) { m_ipodHeader->setViewType( IpodHeader::NoIpod ); connect( m_ipodHeader, TQT_SIGNAL( refreshDevices() ), TQT_SLOT( refreshDevices() ) ); } else //device opened! hooray! { m_ipodInfo = const_cast( itdb_device_get_ipod_info( m_itdb->device ) ); const TQString model = ipodModel(); if( !m_ipodInfo || model.isEmpty() || model == "Invalid" ) { debug() << "the ipod model must be set before photos can be added" << endl; m_ipodHeader->setViewType( IpodHeader::IncompatibleIpod ); connect( m_ipodHeader, TQT_SIGNAL( updateSysInfo() ), TQT_SLOT( updateSysInfo() ) ); return; } else { m_ipodHeader->setViewType( IpodHeader::ValidIpod ); } } if( m_ipodAlbumList ) getIpodAlbums(); m_destinationBox->setEnabled( m_itdb ); m_urlListBox->setEnabled( m_itdb ); } void UploadDialog::updateSysInfo() { debug() << "updateSysInfo()" << endl; }