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.
1262 lines
35 KiB
1262 lines
35 KiB
/***************************************************************************
|
|
scanpackager.cpp - description
|
|
-------------------
|
|
begin : Fri Dec 17 1999
|
|
copyright : (C) 1999 by Klaas Freitag
|
|
email : freitag@suse.de
|
|
|
|
$Id$
|
|
***************************************************************************/
|
|
|
|
/***************************************************************************
|
|
* *
|
|
* This file may be distributed and/or modified under the terms of the *
|
|
* GNU General Public License version 2 as published by the Free Software *
|
|
* Foundation and appearing in the file COPYING included in the *
|
|
* packaging of this file. *
|
|
*
|
|
* As a special exception, permission is given to link this program *
|
|
* with any version of the KADMOS ocr/icr engine of reRecognition GmbH, *
|
|
* Kreuzlingen and distribute the resulting executable without *
|
|
* including the source code for KADMOS in the source distribution. *
|
|
*
|
|
* As a special exception, permission is given to link this program *
|
|
* with any edition of TQt, and distribute the resulting executable, *
|
|
* without including the source code for TQt in the source distribution. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#include "scanpackager.h"
|
|
#include "resource.h"
|
|
#include "img_saver.h"
|
|
#include "kookaimage.h"
|
|
#include "kookaimagemeta.h"
|
|
#include "previewer.h"
|
|
#include "devselector.h"
|
|
|
|
#include <tqapplication.h>
|
|
#include <tqdir.h>
|
|
#include <tqfile.h>
|
|
#include <tqpopupmenu.h>
|
|
#include <tqdict.h>
|
|
#include <tqpixmap.h>
|
|
#include <kmessagebox.h>
|
|
#include <tqfiledialog.h>
|
|
#include <tqstringlist.h>
|
|
#include <tqheader.h>
|
|
|
|
#include <kfiletreeview.h>
|
|
#include <kfiletreeviewitem.h>
|
|
#include <kfiletreebranch.h>
|
|
|
|
#include <kurldrag.h>
|
|
#include <kpopupmenu.h>
|
|
#include <kaction.h>
|
|
#include <kinputdialog.h>
|
|
#include <kiconloader.h>
|
|
#include <kfiledialog.h>
|
|
#include <kurl.h>
|
|
#include <kdebug.h>
|
|
#include <klocale.h>
|
|
#include <kglobal.h>
|
|
#include <kio/global.h>
|
|
#include <kio/progressbase.h>
|
|
#include <kio/netaccess.h>
|
|
#include <kio/jobclasses.h>
|
|
#include <kio/file.h>
|
|
#include <kio/job.h>
|
|
|
|
#define STARTUP_FIRST_START "firstStart"
|
|
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
/* Constructor Scan Packager */
|
|
ScanPackager::ScanPackager( TQWidget *parent ) : KFileTreeView( parent )
|
|
{
|
|
// TODO:
|
|
setItemsRenameable (true );
|
|
setDefaultRenameAction( TQListView::Reject );
|
|
addColumn( i18n("Image Name" ));
|
|
setColumnAlignment( 0, AlignLeft );
|
|
|
|
addColumn( i18n("Size") );
|
|
setColumnAlignment( 1, AlignRight );
|
|
setColumnAlignment( 2, AlignRight );
|
|
|
|
addColumn( i18n("Format" )); setColumnAlignment( 3, AlignRight );
|
|
|
|
/* Drag and Drop */
|
|
setDragEnabled( true );
|
|
setDropVisualizer(true);
|
|
setAcceptDrops(true);
|
|
|
|
connect( this, TQT_SIGNAL(dropped( TQWidget*, TQDropEvent*, KURL::List&, KURL& )),
|
|
this, TQT_SLOT( slotUrlsDropped( TQWidget*, TQDropEvent*, KURL::List&, KURL& )));
|
|
|
|
kdDebug(28000) << "connected Drop-Signal" << endl;
|
|
setRenameable ( 0, true );
|
|
setRenameable ( 1, false );
|
|
setRenameable ( 2, false );
|
|
setRenameable ( 3, false );
|
|
|
|
setRootIsDecorated( false );
|
|
|
|
connect( this, TQT_SIGNAL( clicked( TQListViewItem*)),
|
|
TQT_SLOT( slClicked(TQListViewItem*)));
|
|
|
|
connect( this, TQT_SIGNAL( rightButtonPressed( TQListViewItem *, const TQPoint &, int )),
|
|
TQT_SLOT( slShowContextMenue(TQListViewItem *, const TQPoint &, int )));
|
|
|
|
connect( this, TQT_SIGNAL(itemRenamed (TQListViewItem*, const TQString &, int ) ), this,
|
|
TQT_SLOT(slFileRename( TQListViewItem*, const TQString&, int)));
|
|
|
|
|
|
img_counter = 1;
|
|
/* Set the current export dir to home */
|
|
m_currCopyDir = TQDir::home().absPath();
|
|
m_currImportDir = m_currCopyDir;
|
|
|
|
/* Preload frequently used icons */
|
|
KIconLoader *loader = KGlobal::iconLoader();
|
|
m_floppyPixmap = loader->loadIcon( "3floppy_unmount", KIcon::Small );
|
|
m_grayPixmap = loader->loadIcon( "palette_gray", KIcon::Small );
|
|
m_bwPixmap = loader->loadIcon( "palette_lineart", KIcon::Small );
|
|
m_colorPixmap = loader->loadIcon( "palette_color", KIcon::Small );
|
|
|
|
m_startup = true;
|
|
|
|
/* create a context menu and set the title */
|
|
m_contextMenu = new KPopupMenu();
|
|
static_cast<KPopupMenu*>(m_contextMenu)->insertTitle( i18n( "Gallery" ));
|
|
|
|
}
|
|
|
|
void ScanPackager::openRoots()
|
|
{
|
|
/* standard root always exists, ImgRoot creates it */
|
|
KURL rootUrl(Previewer::galleryRoot());
|
|
kdDebug(28000) << "Open standard root " << rootUrl.url() << endl;
|
|
|
|
openRoot( rootUrl, true );
|
|
m_defaultBranch->setOpen(true);
|
|
|
|
/* open more configurable image repositories TODO */
|
|
}
|
|
|
|
KFileTreeBranch* ScanPackager::openRoot( const KURL& root, bool )
|
|
{
|
|
KIconLoader *loader = KGlobal::iconLoader();
|
|
|
|
/* working on the global branch. FIXME */
|
|
m_defaultBranch = addBranch( root, i18n("Kooka Gallery"),
|
|
loader->loadIcon( "folder_image", KIcon::Small ),
|
|
false /* do not showHidden */ );
|
|
|
|
// Q_CHECK_PTR( m_defaultBranch );
|
|
m_defaultBranch->setOpenPixmap( loader->loadIcon( "folder_blue_open", KIcon::Small ));
|
|
|
|
setDirOnlyMode( m_defaultBranch, false );
|
|
m_defaultBranch->setShowExtensions( true ); // false );
|
|
|
|
connect( m_defaultBranch, TQT_SIGNAL( newTreeViewItems( KFileTreeBranch*, const KFileTreeViewItemList& )),
|
|
this, TQT_SLOT( slotDecorate(KFileTreeBranch*, const KFileTreeViewItemList& )));
|
|
|
|
connect( m_defaultBranch, TQT_SIGNAL( directoryChildCount( KFileTreeViewItem* , int )),
|
|
this, TQT_SLOT( slotDirCount( KFileTreeViewItem *, int )));
|
|
|
|
connect( m_defaultBranch, TQT_SIGNAL( deleteItem( KFileItem* )),
|
|
this, TQT_SLOT( slotDeleteFromBranch(KFileItem*)));
|
|
|
|
connect( m_defaultBranch, TQT_SIGNAL( populateFinished( KFileTreeViewItem * )),
|
|
this, TQT_SLOT( slotStartupFinished( KFileTreeViewItem * )));
|
|
|
|
|
|
return( m_defaultBranch );
|
|
}
|
|
|
|
void ScanPackager::slotStartupFinished( KFileTreeViewItem *it )
|
|
{
|
|
if( m_startup && (it == m_defaultBranch->root()) )
|
|
{
|
|
kdDebug(28000) << "Slot population finished hit!" << endl;
|
|
|
|
/* If nothing is selected, select the root. */
|
|
if( ! currentKFileTreeViewItem() )
|
|
{
|
|
(m_defaultBranch->root())->setSelected( true );
|
|
}
|
|
|
|
m_startup = false;
|
|
}
|
|
}
|
|
|
|
void ScanPackager::slotDirCount( KFileTreeViewItem* item, int cnt )
|
|
{
|
|
if( item && item->isDir() )
|
|
{
|
|
TQString cc = i18n( "one item", "%n items", cnt);
|
|
item->setText( 1, cc );
|
|
}
|
|
else
|
|
{
|
|
kdDebug(28000) << "Item is NOT directory - do not set child count!" << endl;
|
|
}
|
|
}
|
|
|
|
void ScanPackager::slotDecorate( KFileTreeViewItem* item )
|
|
{
|
|
if( !item ) return;
|
|
if( item->isDir())
|
|
{
|
|
// done in extra slot.
|
|
kdDebug(28000) << "Decorating directory!" << endl;
|
|
}
|
|
else
|
|
|
|
{
|
|
KFileItem *kfi = item->fileItem();
|
|
|
|
KookaImage *img = 0L;
|
|
|
|
if( kfi )
|
|
{
|
|
img = static_cast<KookaImage*>(kfi->extraData( this ));
|
|
}
|
|
|
|
if( img )
|
|
{
|
|
|
|
/* The image appears to be loaded to memory. */
|
|
if( img->depth() == 1 )
|
|
{
|
|
/* a bw-image */
|
|
item->setPixmap( 0, m_bwPixmap );
|
|
}
|
|
else
|
|
{
|
|
if( img->isGrayscale() )
|
|
{
|
|
item->setPixmap( 0, m_grayPixmap );
|
|
}
|
|
else
|
|
{
|
|
item->setPixmap( 0, m_colorPixmap );
|
|
}
|
|
}
|
|
|
|
/* set image size in pixels */
|
|
TQString t = i18n( "%1 x %2" ).arg( img->width()).arg(img->height());
|
|
item->setText( 1, t );
|
|
kdDebug( 28000) << "Image loaded and decorated!" << endl;
|
|
}
|
|
else
|
|
{
|
|
/* Item is not yet loaded. Display file information */
|
|
item->setPixmap( 0, m_floppyPixmap );
|
|
if ( kfi )
|
|
{
|
|
item->setText(1, KIO::convertSize( kfi->size() ));
|
|
}
|
|
}
|
|
|
|
/* Image format */
|
|
TQString format = getImgFormat( item );
|
|
item->setText( 2, format );
|
|
}
|
|
|
|
// This code is quite similar to m_nextUrlToSelect in KFileTreeView::slotNewTreeViewItems
|
|
// When scanning a new image, we wait for the KDirLister to notice the new file,
|
|
// and then we have the KFileTreeViewItem that we need to display the image.
|
|
if ( ! m_nextUrlToShow.isEmpty() )
|
|
{
|
|
if( m_nextUrlToShow.equals(item->url(), true ))
|
|
{
|
|
m_nextUrlToShow = KURL(); // do this first to prevent recursion
|
|
slClicked( item );
|
|
setCurrentItem(item); // neccessary in case of new file from D&D
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
void ScanPackager::slotDecorate( KFileTreeBranch* branch, const KFileTreeViewItemList& list )
|
|
{
|
|
(void) branch;
|
|
kdDebug(28000) << "decorating slot for list !" << endl;
|
|
|
|
KFileTreeViewItemListIterator it( list );
|
|
|
|
bool end = false;
|
|
for( ; !end && it.current(); ++it )
|
|
{
|
|
KFileTreeViewItem *kftvi = *it;
|
|
slotDecorate( kftvi );
|
|
emit fileChanged( kftvi->fileItem() );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void ScanPackager::slFileRename( TQListViewItem* it, const TQString& newStr, int )
|
|
{
|
|
|
|
bool success = true;
|
|
if( !it ) return;
|
|
|
|
if( newStr.isEmpty() )
|
|
success = false;
|
|
|
|
KFileTreeViewItem *item = static_cast<KFileTreeViewItem*>(it);
|
|
|
|
/* Free memory and imform everybody who is interested. */
|
|
KURL urlFrom = item->url();
|
|
KURL urlTo( urlFrom );
|
|
|
|
/* clean filename and apply new name */
|
|
urlTo.setFileName("");
|
|
urlTo.setFileName(newStr);
|
|
|
|
if( success )
|
|
{
|
|
if( urlFrom == urlTo )
|
|
{
|
|
kdDebug(28000) << "Renaming to same url does not make sense!" << endl;
|
|
success = false;
|
|
}
|
|
else
|
|
{
|
|
/* clear selection, because the renamed image comes in through
|
|
* kdirlister again
|
|
*/
|
|
slotUnloadItem( item );
|
|
|
|
kdDebug(28000) << "Renaming to " << urlTo.prettyURL() <<
|
|
" from " << urlFrom.prettyURL() << endl;
|
|
|
|
/* to urlTo the really used filename is written */
|
|
setSelected( item, false );
|
|
|
|
if( ImgSaver::renameImage( urlFrom, urlTo, false, this ) )
|
|
{
|
|
kdDebug(28000) << "renaming OK" << endl;
|
|
emit fileRenamed( item->fileItem(), urlTo );
|
|
success=true;
|
|
}
|
|
else
|
|
{
|
|
success = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( !success )
|
|
{
|
|
kdDebug(28000) << "renaming failed" << endl;
|
|
/* restore the name */
|
|
item->setText(0, urlFrom.fileName() );
|
|
setSelected( item, true );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
/*
|
|
* Method that checks if the new filename a user enters while renaming an image is valid.
|
|
* It checks for a proper extension.
|
|
*/
|
|
TQString ScanPackager::buildNewFilename( TQString cmplFilename, TQString currFormat ) const
|
|
{
|
|
/* cmplFilename = new name the user wishes.
|
|
* currFormat = the current format of the image.
|
|
* if the new filename has a valid extension, which is the same as the
|
|
* format of the current, fine. A ''-String has to be returned.
|
|
*/
|
|
TQFileInfo fiNew( cmplFilename );
|
|
TQString base = fiNew.baseName();
|
|
TQString newExt = fiNew.extension( false ).lower();
|
|
TQString nowExt = currFormat.lower();
|
|
TQString ext = "";
|
|
|
|
kdDebug(28000) << "Filename wanted: "<< cmplFilename << " <"<<newExt<<"> <" << nowExt<<">" <<endl;
|
|
|
|
if( newExt.isEmpty() )
|
|
{
|
|
/* ok, fine -> return the currFormat-Extension */
|
|
ext = base + "." + currFormat;
|
|
}
|
|
else if( newExt == nowExt )
|
|
{
|
|
/* also good, no reason to put another extension */
|
|
ext = cmplFilename;
|
|
}
|
|
else
|
|
{
|
|
/* new Ext. differs from the current extension. Later. */
|
|
KMessageBox::sorry( 0L, i18n( "You entered a file extension that differs from the existing one. That is not yet possible. Converting 'on the fly' is planned for a future release.\n"
|
|
"Kooka corrects the extension."),
|
|
i18n("On the Fly Conversion"));
|
|
ext = base + "." + currFormat;
|
|
}
|
|
return( ext );
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
/* This method returns the directory of an image or directory.
|
|
*/
|
|
TQString ScanPackager::itemDirectory( const KFileTreeViewItem* item, bool relativ ) const
|
|
{
|
|
if( ! item )
|
|
{
|
|
kdDebug(28000) << "ERR: itemDirectory without item" << endl;
|
|
return TQString();
|
|
}
|
|
|
|
TQString relativUrl= (item->url()).prettyURL();
|
|
|
|
if( ! item->isDir() )
|
|
{
|
|
// Cut off the filename in case it is not a dir
|
|
relativUrl.truncate( relativUrl.findRev( '/' )+1);
|
|
}
|
|
else
|
|
{
|
|
/* add a "/" to the directory if not there */
|
|
if( ! relativUrl.endsWith( "/" ) )
|
|
relativUrl.append( "/" );
|
|
}
|
|
|
|
if( relativ )
|
|
{
|
|
KFileTreeBranch *branch = item->branch();
|
|
if( branch )
|
|
{
|
|
kdDebug(28000) << "Relativ URL of the file " << relativUrl << endl;
|
|
TQString rootUrl = (branch->rootUrl()).prettyURL(); // directory of branch root
|
|
|
|
if( relativUrl.startsWith( rootUrl ))
|
|
{
|
|
relativUrl.remove( 0, rootUrl.length() );
|
|
|
|
if( relativUrl.isEmpty() ) relativUrl = "/"; // The root
|
|
}
|
|
else
|
|
{
|
|
kdDebug(28000) << "ERR: Item-URL does not start with root url " << rootUrl << endl;
|
|
}
|
|
}
|
|
}
|
|
return( relativUrl );
|
|
}
|
|
/* ----------------------------------------------------------------------- */
|
|
/* This slot receives a string from the gallery-path combobox shown under the
|
|
* image gallery. The form of the string coming in here is <branch-name> - <
|
|
* relativ directory under the branch. Now it is to assemble a complete path
|
|
* from the data, find out which KFileTreeViewItem is associated with it and
|
|
* call slClicked with it.
|
|
*/
|
|
|
|
void ScanPackager::slotSelectDirectory( const TQString & dirString )
|
|
{
|
|
kdDebug(28000) << "Trying to decode directory string " << dirString << endl;
|
|
|
|
TQString searchFor = TQString::fromLatin1(" - ");
|
|
int pos = dirString.find( searchFor );
|
|
|
|
if( pos > -1 )
|
|
{
|
|
/* Splitting up the string coming in */
|
|
TQString branchName = dirString.left( pos );
|
|
TQString relPath( dirString );
|
|
|
|
relPath = relPath.remove( 0, pos + searchFor.length());
|
|
|
|
kdDebug(28000) << "Splitted up to branch <" << branchName << "> and <" << relPath << endl;
|
|
|
|
KFileTreeViewItem *kfi = findItem( branchName, relPath );
|
|
|
|
if( kfi )
|
|
{
|
|
kdDebug(28000) << "got a new item to select !" << endl;
|
|
ensureItemVisible(kfi);
|
|
setCurrentItem(kfi);
|
|
slClicked(kfi); // load thumbnails for this dir etc.
|
|
}
|
|
}
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
/* This slot is called when clicking on an item. */
|
|
void ScanPackager::slClicked( TQListViewItem *newItem )
|
|
{
|
|
KFileTreeViewItem *item = static_cast<KFileTreeViewItem*>(newItem);
|
|
|
|
if( item ) // can be 0, when clicking where no item is present
|
|
{
|
|
kdDebug(28000) << "Clicked - newItem !" << endl;
|
|
/* Check if directory, hide image for now, later show a thumb view */
|
|
if( item->isDir())
|
|
{
|
|
kdDebug(28000) << "clicked: Is a directory !" << endl;
|
|
emit( showImage( 0L ));
|
|
kdDebug(28000) << "emitting showThumbnails" << endl;
|
|
}
|
|
else
|
|
{
|
|
/* if not a dir, load the image if necessary. This is done by loadImageForItem,
|
|
* which is async( TODO ). The image finally arrives in slotImageArrived */
|
|
TQApplication::setOverrideCursor(waitCursor);
|
|
emit( aboutToShowImage( item->url()));
|
|
loadImageForItem( item );
|
|
TQApplication::restoreOverrideCursor();
|
|
}
|
|
|
|
/* emit a signal indicating the new directory if there is a new one */
|
|
TQString wholeDir = itemDirectory( item, false ); /* not relativ to root */
|
|
|
|
if( currSelectedDir != wholeDir )
|
|
{
|
|
currSelectedDir = wholeDir;
|
|
TQString relativUrl = itemDirectory( item, true );
|
|
kdDebug(28000) << "Emitting " << relativUrl << " as new relative Url" << endl;
|
|
/* Emit the signal with branch and the relative path */
|
|
emit( galleryPathSelected( item->branch(), relativUrl ));
|
|
|
|
if( item->isDir() )
|
|
{
|
|
emit( showThumbnails( item ));
|
|
}
|
|
else
|
|
{
|
|
emit( showThumbnails( static_cast<KFileTreeViewItem*>(item->parent())));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// kdDebug(28000) << "directory is not new: " << currSelectedDir << endl;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ScanPackager::loadImageForItem( KFileTreeViewItem *item )
|
|
{
|
|
|
|
if( ! item ) return;
|
|
bool result = true;
|
|
|
|
KFileItem *kfi = item->fileItem();
|
|
if( ! kfi ) return;
|
|
|
|
KookaImage *img = static_cast<KookaImage*>( kfi->extraData(this));
|
|
|
|
if( img )
|
|
{
|
|
kdDebug(28000) << "Image already loaded." << endl;
|
|
/* result is still true, image must be shown. */
|
|
}
|
|
else
|
|
{
|
|
/* The image needs to be loaded. Possibly it is a multi-page image.
|
|
* If it is, the kookaImage has a subImageCount larger than one. We
|
|
* create an subimage-item for every subimage, but do not yet load
|
|
* them.
|
|
*/
|
|
KURL url = item->url();
|
|
|
|
img = new KookaImage( );
|
|
if( !img || !img->loadFromUrl( url ) )
|
|
{
|
|
kdDebug(28000) << "Loading KookaImage from File failed!" << endl;
|
|
result = false;
|
|
}
|
|
else
|
|
{
|
|
/* store the fileitem */
|
|
img->setFileItem( kfi );
|
|
|
|
/* care for subimages, create items for them */
|
|
kdDebug(28000) << "subImage-count: " << img->subImagesCount() << endl;
|
|
if( img->subImagesCount() > 1 )
|
|
{
|
|
KIconLoader *loader = KGlobal::iconLoader();
|
|
kdDebug(28000) << "SubImages existing!" << endl;
|
|
|
|
/* Start at the image with index 1, that makes one less than are actually in the
|
|
* image. But image 0 was already created above. */
|
|
KFileTreeViewItem *prevItem=0;
|
|
for( int i = 1; i < img->subImagesCount(); i++ )
|
|
{
|
|
kdDebug(28000) << "Creating subimage no " << i << endl;
|
|
KFileItem *newKfi = new KFileItem( *kfi );
|
|
KFileTreeViewItem *subImgItem = new KFileTreeViewItem( item, newKfi, item->branch());
|
|
|
|
if( prevItem )
|
|
{
|
|
subImgItem->moveItem( prevItem );
|
|
}
|
|
prevItem = subImgItem;
|
|
|
|
subImgItem->setPixmap( 0, loader->loadIcon( "editcopy", KIcon::Small ));
|
|
subImgItem->setText( 0, i18n("Sub-image %1").arg( i ) );
|
|
KookaImage *subImgImg = new KookaImage( i, img );
|
|
subImgImg->setFileItem( newKfi );
|
|
newKfi->setExtraData( (void*) this, (void*) subImgImg );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if( result && img )
|
|
{
|
|
if( img->isSubImage() )
|
|
{
|
|
kdDebug(28000) << "it _is_ a subimage" << endl;
|
|
/* load if not loaded */
|
|
if( img->isNull())
|
|
{
|
|
kdDebug(28000) << "extracting subimage" << endl;
|
|
img->extractNow();
|
|
}
|
|
else
|
|
{
|
|
kdDebug(28000) << "Is not a null image" << endl;
|
|
}
|
|
}
|
|
slImageArrived( item, img );
|
|
}
|
|
}
|
|
|
|
/* Hit this slot with a file for a kfiletreeviewitem. */
|
|
void ScanPackager::slImageArrived( KFileTreeViewItem *item, KookaImage* image )
|
|
{
|
|
if( item && image )
|
|
{
|
|
/* Associate the image for the Scanpackager-Object. */
|
|
KFileItem *kfi = item->fileItem();
|
|
if( kfi )
|
|
{
|
|
kfi->setExtraData( (void*) this, (void*) image );
|
|
}
|
|
slotDecorate( item );
|
|
emit( showImage( image ));
|
|
}
|
|
}
|
|
|
|
KookaImage* ScanPackager::getCurrImage() const
|
|
{
|
|
KFileTreeViewItem *curr = currentKFileTreeViewItem();
|
|
KookaImage *img = 0L;
|
|
|
|
if( curr )
|
|
{
|
|
KFileItem *kfi = curr->fileItem();
|
|
if( kfi )
|
|
{
|
|
img = static_cast<KookaImage*>(kfi->extraData( this ));
|
|
}
|
|
}
|
|
return(img);
|
|
}
|
|
|
|
|
|
TQString ScanPackager::getCurrImageFileName( bool withPath = true ) const
|
|
{
|
|
TQString result = "";
|
|
|
|
KFileTreeViewItem *curr = currentKFileTreeViewItem();
|
|
if( ! curr )
|
|
{
|
|
kdDebug( 28000) << "getCurrImageFileName: nothing selected !"<< endl;
|
|
}
|
|
else
|
|
{
|
|
if( withPath )
|
|
{
|
|
result = localFileName(curr);
|
|
}
|
|
else
|
|
{
|
|
KURL url( localFileName(curr));
|
|
url = curr->url();
|
|
result = url.fileName();
|
|
}
|
|
}
|
|
return( result );
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
TQCString ScanPackager::getImgFormat( KFileTreeViewItem* item ) const
|
|
{
|
|
|
|
TQCString cstr;
|
|
|
|
if( !item ) return( cstr );
|
|
#if 0
|
|
KFileItem *kfi = item->fileItem();
|
|
|
|
TQString mime = kfi->mimetype();
|
|
#endif
|
|
|
|
// TODO find the real extension for use with the filename !
|
|
// temporarely:
|
|
TQString f = localFileName( item );
|
|
|
|
return( TQImage::imageFormat( f ));
|
|
|
|
}
|
|
|
|
TQString ScanPackager::localFileName( KFileTreeViewItem *it ) const
|
|
{
|
|
if( ! it ) return( TQString() );
|
|
|
|
KURL url = it->url();
|
|
|
|
TQString res;
|
|
|
|
if( url.isLocalFile())
|
|
{
|
|
res = url.directory( false, true ) + url.fileName();
|
|
}
|
|
|
|
return( res );
|
|
}
|
|
|
|
/* Called if the image exists but was changed by image manipulation func */
|
|
void ScanPackager::slotCurrentImageChanged( TQImage *img )
|
|
{
|
|
KFileTreeViewItem *curr = currentKFileTreeViewItem();
|
|
if( ! curr )
|
|
{
|
|
kdDebug(28000) << "ImageChanged: nothing selected !" << endl;
|
|
return;
|
|
}
|
|
|
|
/* Do not save directories */
|
|
if( curr->isDir() ) return;
|
|
|
|
/* unload image and free memory */
|
|
slotUnloadItem( curr );
|
|
|
|
const TQString filename = localFileName( curr );
|
|
const TQCString format = getImgFormat( curr );
|
|
ImgSaver saver( this );
|
|
ImgSaveStat is_stat = ISS_OK;
|
|
is_stat = saver.saveImage( img, filename, format );
|
|
|
|
if( is_stat == ISS_ERR_FORMAT_NO_WRITE )
|
|
{
|
|
KMessageBox::error( this, i18n( "Cannot write this image format.\nImage will not be saved!"),
|
|
i18n("Save Error") );
|
|
}
|
|
else if( is_stat == ISS_ERR_PERM )
|
|
{
|
|
KMessageBox::error( this, i18n( "Image file is write protected.\nImage will not be saved!"),
|
|
i18n("Save Error") );
|
|
|
|
}
|
|
else if( is_stat == ISS_ERR_PROTOCOL )
|
|
{
|
|
KMessageBox::sorry( this, i18n( "Cannot save the image, because the file is local.\n"
|
|
"Kooka will support other protocols later."),
|
|
i18n("Save Error") );
|
|
|
|
}
|
|
else if( is_stat != ISS_OK )
|
|
{
|
|
kdDebug(28000) << "Error while saving existing image !" << endl;
|
|
}
|
|
|
|
if( img && !img->isNull())
|
|
{
|
|
emit( imageChanged( curr->fileItem()));
|
|
KookaImage *newImage = new KookaImage(*img);
|
|
slImageArrived( curr, newImage );
|
|
}
|
|
}
|
|
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
/* This slot takes a new scanned Picture and saves it.
|
|
* It urgently needs to make a deep copy of the image !
|
|
*/
|
|
void ScanPackager::slAddImage( TQImage *img, KookaImageMeta* )
|
|
{
|
|
ImgSaveStat is_stat = ISS_OK;
|
|
/* Save the image with the help of the ImgSaver */
|
|
if( ! img ) return;
|
|
|
|
/* currently selected item is the directory or a file item */
|
|
KFileTreeViewItem *curr = currentKFileTreeViewItem();
|
|
|
|
/* Use root if nothing is selected */
|
|
if( ! curr )
|
|
{
|
|
KFileTreeBranch *b = branches().at(0); /* There should be at least one */
|
|
|
|
if( b )
|
|
{
|
|
curr = findItem( b, i18n( "Incoming/" ) );
|
|
if( ! curr ) curr = b->root();
|
|
}
|
|
|
|
/* If curr is still undefined, something very tough has happend. Go away here */
|
|
if( !curr ) return;
|
|
|
|
setSelected( curr, true );
|
|
}
|
|
|
|
/* find the directory above the current one */
|
|
|
|
KURL dir(itemDirectory( curr ));
|
|
|
|
/* Path of curr sel item */
|
|
ImgSaver img_saver( this, dir );
|
|
|
|
is_stat = img_saver.saveImage( img );
|
|
if( is_stat == ISS_ERR_FORMAT_NO_WRITE )
|
|
{
|
|
KMessageBox::error( this, i18n( "Cannot write this image format.\nImage will not be saved!"),
|
|
i18n("Save Error") );
|
|
}
|
|
else if( is_stat == ISS_ERR_PERM )
|
|
{
|
|
KMessageBox::error( this, i18n( "Image file is write protected.\nImage will not be saved!"),
|
|
i18n("Save Error") );
|
|
|
|
}
|
|
else if( is_stat != ISS_OK )
|
|
{
|
|
if( is_stat == ISS_SAVE_CANCELED )
|
|
{
|
|
return;
|
|
}
|
|
kdDebug(28000) << "ERROR: Saving failed: " << img_saver.errorString( is_stat ) << endl;
|
|
/* And now ?? */
|
|
}
|
|
|
|
/* Add the new image to the list of new images */
|
|
KURL lurl = img_saver.lastFileUrl();
|
|
|
|
KFileTreeBranchList branchlist = branches();
|
|
KFileTreeBranch *kookaBranch = branchlist.at(0);
|
|
|
|
TQString strdir = itemDirectory(curr);
|
|
if(strdir.endsWith(TQString("/"))) strdir.truncate( strdir.length() - 1 );
|
|
kdDebug(28000) << "Updating directory with " << strdir << endl;
|
|
|
|
if( kookaBranch ) kookaBranch->updateDirectory( KURL(strdir) );
|
|
slotSetNextUrlToSelect( lurl );
|
|
m_nextUrlToShow = lurl;
|
|
|
|
TQString s;
|
|
/* Count amount of children of the father */
|
|
TQListViewItem *paps = curr->parent();
|
|
if( curr->isDir() ) /* take only father if the is no directory */
|
|
paps = curr;
|
|
|
|
if( paps )
|
|
{
|
|
int childcount = paps->childCount();
|
|
s = i18n("%1 images").arg(childcount);
|
|
paps->setText( 1, s);
|
|
setOpen( paps, true );
|
|
}
|
|
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
/* selects and opens the file with the given name. This is used to restore the
|
|
* last displayed image by its name.
|
|
*/
|
|
void ScanPackager::slSelectImage( const KURL& name )
|
|
{
|
|
|
|
KFileTreeViewItem *found = spFindItem( UrlSearch, name.url() );
|
|
|
|
if( found )
|
|
{
|
|
kdDebug(28000) << "slSelectImage: Found an item !" << endl;
|
|
ensureItemVisible( found );
|
|
setCurrentItem( found );
|
|
slClicked( found );
|
|
}
|
|
|
|
}
|
|
|
|
|
|
KFileTreeViewItem *ScanPackager::spFindItem( SearchType type, const TQString name, const KFileTreeBranch *branch )
|
|
{
|
|
/* Prepare a list of branches to go through. If the parameter branch is set, search
|
|
* only in the parameter branch. If it is zero, search all branches returned by
|
|
* kfiletreeview.branches()
|
|
*/
|
|
KFileTreeBranchList branchList;
|
|
|
|
if( branch )
|
|
{
|
|
branchList.append( branch );
|
|
}
|
|
else
|
|
{
|
|
branchList = branches();
|
|
}
|
|
|
|
|
|
KFileTreeBranchIterator it( branchList );
|
|
KFileItem *kfi = 0L;
|
|
KFileTreeViewItem *foundItem = 0L;
|
|
|
|
/* Leave the loop in case kfi is defined */
|
|
KFileTreeBranch *branchloop = 0L;
|
|
for( ; !kfi && it.current(); ++it )
|
|
{
|
|
branchloop = *it;
|
|
KURL url(name);
|
|
switch( type )
|
|
{
|
|
case Dummy:
|
|
kdDebug(28000) << "Dummy search skipped !" << endl;
|
|
break;
|
|
case NameSearch:
|
|
kdDebug(28000) << "ScanPackager: searching for " << name << endl;
|
|
kfi = branchloop->findByName( name );
|
|
break;
|
|
case UrlSearch:
|
|
kdDebug(28000) << "ScanPackager: URL search for " << name << endl;
|
|
kfi = branchloop->find( url );
|
|
break;
|
|
default:
|
|
kdDebug(28000) << "Scanpackager: Wrong search type !" << endl;
|
|
break;
|
|
}
|
|
|
|
}
|
|
if( kfi )
|
|
{
|
|
foundItem = static_cast<KFileTreeViewItem*>(kfi->extraData(branchloop));
|
|
kdDebug(28000) << "spFindItem: Success !" << foundItem << endl;
|
|
}
|
|
return( foundItem );
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
void ScanPackager::slShowContextMenue(TQListViewItem *lvi, const TQPoint &p, int col )
|
|
{
|
|
kdDebug(28000) << "Showing Context Menue" << endl;
|
|
(void) col;
|
|
|
|
KFileTreeViewItem *curr = 0;
|
|
|
|
if( lvi )
|
|
{
|
|
curr = currentKFileTreeViewItem();
|
|
if( curr->isDir() )
|
|
setSelected( curr, true );
|
|
}
|
|
|
|
if( m_contextMenu )
|
|
{
|
|
m_contextMenu->exec( p );
|
|
}
|
|
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
|
|
void ScanPackager::slotExportFile( )
|
|
{
|
|
KFileTreeViewItem *curr = currentKFileTreeViewItem();
|
|
if( ! curr ) return;
|
|
|
|
if( curr->isDir() )
|
|
{
|
|
kdDebug(28000) << "Not yet implemented!" << endl;
|
|
}
|
|
else
|
|
{
|
|
KURL fromUrl( curr->url());
|
|
TQString filter = "*." + getImgFormat(curr).lower();
|
|
filter += "\n*|" + i18n( "All Files" );
|
|
|
|
// initial += fromUrl.filename(false);
|
|
TQString initial = m_currCopyDir + "/";
|
|
initial += fromUrl.filename(false);
|
|
KURL fileName = KFileDialog::getSaveURL ( initial,
|
|
filter, this );
|
|
|
|
if ( fileName.isValid() ) // got a file name
|
|
{
|
|
if( fromUrl == fileName ) return;
|
|
|
|
/* Since it is asynchron, we will never get if it succeeded. */
|
|
ImgSaver::copyImage( fromUrl, fileName );
|
|
|
|
/* remember the filename for the next export */
|
|
fileName.setFileName( TQString());
|
|
m_currCopyDir = fileName.url( );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void ScanPackager::slotImportFile()
|
|
{
|
|
KFileTreeViewItem *curr = currentKFileTreeViewItem();
|
|
if( ! curr ) return;
|
|
|
|
KURL impTarget = curr->url();
|
|
|
|
if( ! curr->isDir() )
|
|
{
|
|
KFileTreeViewItem *pa = static_cast<KFileTreeViewItem*>(curr->parent());
|
|
impTarget = pa->url();
|
|
}
|
|
kdDebug(28000) << "Importing to " << impTarget.url() << endl;
|
|
|
|
KURL impUrl = KFileDialog::getImageOpenURL ( m_currImportDir, this, i18n("Import Image File to Gallery"));
|
|
|
|
if( ! impUrl.isEmpty() )
|
|
{
|
|
m_currImportDir = impUrl.url();
|
|
impTarget.addPath( impUrl.fileName()); // append the name of the sourcefile to the path
|
|
m_nextUrlToShow = impTarget;
|
|
ImgSaver::copyImage( impUrl, impTarget );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void ScanPackager::slotUrlsDropped( TQWidget*, TQDropEvent* ev, KURL::List& urls, KURL& copyTo )
|
|
{
|
|
if( !urls.isEmpty() )
|
|
{
|
|
kdDebug(28000) << "Kooka drop event!" << endl;
|
|
// kdDebug(28000) << "Kooka drop event. First src url=" << urls.first() << " copyTo=" << copyTo
|
|
// << " move=" << ( ev->action() == TQDropEvent::Move ) << endl;
|
|
|
|
/* first make the last url to copy to the one to select next */
|
|
if( ! urls.empty() )
|
|
{
|
|
KURL nextSel = copyTo;
|
|
nextSel.addPath( urls.back().fileName(false));
|
|
|
|
kdDebug(28000) << "Selecting next url: " << nextSel.url() << endl;
|
|
m_nextUrlToShow = nextSel;
|
|
// slotSetNextUrlToSelect( nextSel );
|
|
}
|
|
|
|
if ( ev->action() == TQDropEvent::Move )
|
|
copyjob = KIO::move( urls, copyTo, true );
|
|
else
|
|
copyjob = KIO::copy( urls, copyTo, true );
|
|
}
|
|
}
|
|
|
|
void ScanPackager::slotCanceled( KIO::Job* )
|
|
{
|
|
kdDebug(28000) << i18n("Canceled by user") << endl;
|
|
}
|
|
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
void ScanPackager::slotUnloadItems( )
|
|
{
|
|
KFileTreeViewItem *curr = currentKFileTreeViewItem();
|
|
emit( showImage( 0L ));
|
|
slotUnloadItem( curr );
|
|
}
|
|
|
|
void ScanPackager::slotUnloadItem( KFileTreeViewItem *curr )
|
|
{
|
|
if( ! curr ) return;
|
|
|
|
if( curr->isDir())
|
|
{
|
|
KFileTreeViewItem *child = static_cast<KFileTreeViewItem*>(curr->firstChild());
|
|
while( child )
|
|
{
|
|
kdDebug(28000) << "Unloading item " << child << endl;
|
|
slotUnloadItem( child );
|
|
child = static_cast<KFileTreeViewItem*> (child->nextSibling());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
KFileItem *kfi = curr->fileItem();
|
|
KookaImage *image = static_cast<KookaImage*>(kfi->extraData( this ));
|
|
|
|
/* If image is zero, ok, than there is nothing to unload :) */
|
|
if( image )
|
|
{
|
|
if( image->subImagesCount() > 0 )
|
|
{
|
|
KFileTreeViewItem *child = static_cast<KFileTreeViewItem*>(curr->firstChild());
|
|
|
|
while( child )
|
|
{
|
|
KFileTreeViewItem *nextChild = 0;
|
|
kdDebug(28000) << "Unloading subimage item " << child << endl;
|
|
slotUnloadItem( child );
|
|
nextChild = static_cast<KFileTreeViewItem*> (child->nextSibling());
|
|
delete child;
|
|
child = nextChild;
|
|
}
|
|
}
|
|
|
|
emit( unloadImage( image ));
|
|
delete image;
|
|
kfi->removeExtraData( this );
|
|
slotDecorate( curr );
|
|
}
|
|
}
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
void ScanPackager::slotDeleteItems( )
|
|
{
|
|
KFileTreeViewItem *curr = currentKFileTreeViewItem();
|
|
if( ! curr ) return;
|
|
|
|
KURL urlToDel = curr->url();
|
|
TQListViewItem *nextToSelect = curr->nextSibling();
|
|
|
|
kdDebug(28000) << "Deleting: " << urlToDel.prettyURL() << endl;
|
|
bool ask = true; /* for later use */
|
|
|
|
int result = KMessageBox::Yes;
|
|
|
|
KFileItem *item = curr->fileItem();
|
|
if( ask )
|
|
{
|
|
TQString s;
|
|
s = i18n("Do you really want to delete this image?\nIt cannot be restored!" );
|
|
if( item->isDir() )
|
|
{
|
|
s = i18n("Do you really want to delete the folder %1\nand all the images inside?").arg("");
|
|
}
|
|
result = KMessageBox::warningContinueCancel(this, s, i18n( "Delete Collection Item"),
|
|
KStdGuiItem::del(), "AskForDeleteFiles" );
|
|
}
|
|
|
|
/* Since we are currently talking about local files here, NetAccess is OK */
|
|
if( result == KMessageBox::Continue )
|
|
{
|
|
if( KIO::NetAccess::del( urlToDel, 0 ))
|
|
{
|
|
if( nextToSelect )
|
|
setSelected( nextToSelect, true );
|
|
/* TODO: remove the directory from the imageNameCombobox */
|
|
if( curr && item->isDir() )
|
|
{
|
|
/* The directory needs to be removed from the name combo */
|
|
emit(directoryToRemove( curr->branch(), itemDirectory( curr, true ) ));
|
|
}
|
|
|
|
}
|
|
else
|
|
kdDebug(28000) << "Deleting files failed" << endl;
|
|
|
|
}
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
void ScanPackager::slotCreateFolder( )
|
|
{
|
|
bool ok;
|
|
TQString folder = KInputDialog::getText( i18n( "New Folder" ),
|
|
i18n( "Please enter a name for the new folder:" ), TQString(),
|
|
&ok, this );
|
|
|
|
if( ok )
|
|
{
|
|
/* KIO create folder goes here */
|
|
|
|
KFileTreeViewItem *it = currentKFileTreeViewItem();
|
|
if( it )
|
|
{
|
|
KURL url = it->url();
|
|
|
|
/* If a directory is selected, the filename needs not to be deleted */
|
|
if( ! it->isDir())
|
|
url.setFileName( "" );
|
|
/* add the folder name from user input */
|
|
url.addPath( folder );
|
|
kdDebug(28000) << "Creating folder " << url.prettyURL() << endl;
|
|
|
|
/* Since the new directory arrives in the packager in the newItems-slot, we set a
|
|
* variable urlToSelectOnArrive here. The newItems-slot will honor it and select
|
|
* the treeviewitem with that url.
|
|
*/
|
|
slotSetNextUrlToSelect( url );
|
|
|
|
if( ! KIO::NetAccess::mkdir( url, 0, -1 ))
|
|
{
|
|
kdDebug(28000) << "ERR: creation of " << url.prettyURL() << " failed !" << endl;
|
|
}
|
|
else
|
|
{
|
|
/* created successfully */
|
|
/* open the branch if necessary and select the new folder */
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
TQString ScanPackager::getImgName( TQString name_on_disk )
|
|
{
|
|
TQString s;
|
|
(void) name_on_disk;
|
|
|
|
s = i18n("image %1").arg(img_counter++);
|
|
return( s );
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
ScanPackager::~ScanPackager(){
|
|
kdDebug(29000) << "Destructor of ScanPackager" << endl;
|
|
|
|
}
|
|
|
|
/* called whenever one branch detects a deleted file */
|
|
void ScanPackager::slotDeleteFromBranch( KFileItem* kfi )
|
|
{
|
|
emit fileDeleted( kfi );
|
|
}
|
|
|
|
void ScanPackager::contentsDragMoveEvent( TQDragMoveEvent *e )
|
|
{
|
|
if( ! acceptDrag( e ) )
|
|
{
|
|
e->ignore();
|
|
return;
|
|
}
|
|
|
|
TQListViewItem *afterme = 0;
|
|
TQListViewItem *parent = 0;
|
|
|
|
findDrop( e->pos(), parent, afterme );
|
|
|
|
// "afterme" is 0 when aiming at a directory itself
|
|
TQListViewItem *item = afterme ? afterme : parent;
|
|
|
|
if( item )
|
|
{
|
|
bool isDir = static_cast<KFileTreeViewItem*> (item)->isDir();
|
|
if( isDir ) {
|
|
KFileTreeView::contentsDragMoveEvent( e ); // for the autoopen code
|
|
return;
|
|
}
|
|
}
|
|
e->acceptAction();
|
|
}
|
|
|
|
|
|
#include "scanpackager.moc"
|