Commit b8b7b0d9 authored by Csaba Karai's avatar Csaba Karai
Browse files

CHANGED: the packers are job based

parent d11d982e
ADDED: lock tabs, close inactive tabs, close duplicated tabs
ADDED: better trash integration
CHANGED: the packer/unpacker/archive tester are job based now
FIXED: panels sometimes lose focus
FIXED: directory compare modes don't work
FIXED: [ 2609483 ] unpacking to directories with international characters
......
......@@ -187,6 +187,8 @@ KrVfsModel::~KrVfsModel()
void KrVfsModel::clear()
{
_vfiles.clear();
_vfileNdx.clear();
_nameNdx.clear();
}
int KrVfsModel::rowCount(const QModelIndex& parent) const
......@@ -638,6 +640,7 @@ void KrVfsModel::sort ( int column, Qt::SortOrder order )
_vfiles.clear();
_vfileNdx.clear();
_nameNdx.clear();
QHash<int, int> changeMap;
for (int i = 0; i < sorting.count(); ++i) {
......
......@@ -65,7 +65,7 @@ void KrViewOperator::startDrag()
if ( items.empty() )
return ; // don't drag an empty thing
QPixmap px;
if ( items.count() > 1 )
if ( items.count() > 1 || _view->getCurrentKrViewItem() == 0 )
px = FL_LOADICON( "queue" ); // how much are we dragging
else
px = _view->getCurrentKrViewItem() ->icon();
......@@ -318,7 +318,8 @@ void KrView::getSelectedKrViewItems( KrViewItemList *items )
// if all else fails, take the current item
QString item = getCurrentItem();
if ( items->empty() && item!=QString() && item!=".." ) items->append( getCurrentKrViewItem() );
if ( items->empty() && item!=QString() && item!=".." && getCurrentKrViewItem() != 0 )
items->append( getCurrentKrViewItem() );
}
QString KrView::statistics()
......@@ -378,7 +379,7 @@ void KrView::changeSelection( const KRQuery& filter, bool select, bool includeDi
if( op() ) op()->setMassSelectionUpdate( false );
updateView();
if( ensureVisibilityAfterSelect() )
if( ensureVisibilityAfterSelect() && temp != 0 )
makeItemVisible( temp );
}
......@@ -403,12 +404,15 @@ void KrView::invertSelection()
}
if( op() ) op()->setMassSelectionUpdate( false );
updateView();
if( ensureVisibilityAfterSelect() )
if( ensureVisibilityAfterSelect() && temp != 0 )
makeItemVisible( temp );
}
QString KrView::firstUnmarkedBelowCurrent()
{
if( getCurrentKrViewItem() == 0 )
return QString();
KrViewItem * iterator = getNext( getCurrentKrViewItem() );
while ( iterator && iterator->isSelected() )
iterator = getNext( iterator );
......@@ -545,6 +549,8 @@ bool KrView::handleKeyEventInt (QKeyEvent *e) {
e->ignore();
else {
KrViewItem * i = getCurrentKrViewItem();
if( i == 0 )
return true;
QString tmp = i->name();
op()->emitExecuted(tmp);
}
......@@ -644,7 +650,8 @@ bool KrView::handleKeyEventInt (QKeyEvent *e) {
e->ignore();
} else { // just a normal click - do a lynx-like moving thing
KrViewItem *i = getCurrentKrViewItem();
op()->emitGoInside( i->name() );
if( i )
op()->emitGoInside( i->name() );
}
return true;
case Qt::Key_Up :
......
......@@ -66,6 +66,7 @@ A
#include "../VFS/krvfshandler.h"
#include "../VFS/preservingcopyjob.h"
#include "../VFS/virtualcopyjob.h"
#include "../VFS/packjob.h"
#include "../Dialogs/packgui.h"
#include "../Dialogs/krdialogs.h"
#include "../Dialogs/krpleasewait.h"
......@@ -78,6 +79,8 @@ A
#include "../Queue/queue_mgr.h"
#include <QDrag>
#include <QMimeData>
#include <kio/jobuidelegate.h>
#include <kuiserverjobtracker.h>
//////////////////////////////////////////////////////////
////// ---------- List Panel ------------- ////////
......@@ -916,93 +919,29 @@ void ListPanelFunc::pack() {
== KMessageBox::Cancel )
return ; // stop operation
}
// tell the user to wait
krApp->startWaiting( i18n( "Counting files to pack" ), 0, true );
// get the files to be packed:
files() ->vfs_getFiles( &fileNames );
KIO::filesize_t totalSize = 0;
unsigned long totalDirs = 0, totalFiles = 0;
if( !calcSpace( fileNames, totalSize, totalFiles, totalDirs ) )
return;
// download remote URL-s if necessary
QString arcDir;
KTempDir *tempDir = 0;
if ( files() ->vfs_getOrigin().isLocalFile() )
arcDir = files() ->vfs_workingDir();
else {
tempDir = new KTempDir();
arcDir = tempDir->name();
KUrl::List *urlList = files() ->vfs_getFiles( &fileNames );
KIO::NetAccess::dircopy( *urlList, KUrl( arcDir ), 0 );
delete urlList;
}
// pack the files
// we must chdir() first because we supply *names* not URL's
QString save = QDir::currentPath();
QDir::setCurrent( arcDir );
KRarcHandler::pack( fileNames, PackGUI::type, arcFile, totalFiles + totalDirs, PackGUI::extraProps );
QDir::setCurrent( save );
// delete the temporary directory if created
if ( tempDir )
delete tempDir;
// copy from the temp file to it's right place
if ( tempDestFile ) {
KIO::NetAccess::move( KUrl( arcFile ), destURL );
delete tempDestFile;
}
PackJob * job = PackJob::createPacker( files()->vfs_getOrigin(), destURL, fileNames, PackGUI::type, PackGUI::extraProps );
job->setUiDelegate(new KIO::JobUiDelegate() );
KIO::getJobTracker()->registerJob(job);
job->ui()->setAutoErrorHandlingEnabled( true );
if ( packToOtherPanel )
panel->otherPanel->func->refresh();
connect( job, SIGNAL( result( KJob* ) ), panel->otherPanel->func, SLOT( refresh() ) );
}
void ListPanelFunc::testArchive() {
QString arcName = panel->getCurrentName();
if ( arcName.isNull() )
return ;
if ( arcName == ".." )
return ; // safety
KUrl arcURL = files() ->vfs_getFile( arcName );
QString url = QString();
// download the file if it's on a remote filesystem
if ( !arcURL.isLocalFile() ) {
url = KStandardDirs::locateLocal( "tmp", QString( arcName ) );
if ( !KIO::NetAccess::download( arcURL, url, 0 ) ) {
KMessageBox::sorry( krApp, i18n( "Krusader is unable to download: " ) + arcURL.fileName() );
return ;
}
} else
url = arcURL.path( KUrl::RemoveTrailingSlash );
QString mime = files() ->vfs_search( arcName ) ->vfile_getMime();
bool encrypted = false;
QString type = KRarcHandler::getType( encrypted, url, mime );
// check we that archive is supported
if ( !KRarcHandler::arcSupported( type ) ) {
KMessageBox::sorry( krApp, i18n( "%1, unknown archive type.", arcName ) );
return ;
}
QString password = encrypted ? KRarcHandler::getPassword( url ) : QString();
QStringList fileNames;
panel->getSelectedNames( &fileNames );
if ( fileNames.isEmpty() )
return ; // safety
// test the archive
if ( KRarcHandler::test( url, type, password ) )
KMessageBox::information( krApp, i18n( "%1, test passed.", arcName ) );
else
KMessageBox::error( krApp, i18n( "%1, test failed!", arcName ) );
// remove the downloaded file if necessary
if ( url != arcURL.path( KUrl::RemoveTrailingSlash ) )
QFile( url ).remove();
TestArchiveJob * job = TestArchiveJob::testArchives( files()->vfs_getOrigin(), fileNames );
job->setUiDelegate(new KIO::JobUiDelegate() );
KIO::getJobTracker()->registerJob(job);
job->ui()->setAutoErrorHandlingEnabled( true );
}
void ListPanelFunc::unpack() {
......@@ -1023,71 +962,14 @@ void ListPanelFunc::unpack() {
if ( dest.isEmpty() ) return ; // the user canceled
bool packToOtherPanel = ( dest.equals( panel->otherPanel->virtualPath(), KUrl::CompareWithoutTrailingSlash ) );
for ( int i = 0; i < fileNames.count(); ++i ) {
QString arcName = fileNames[ i ];
if ( arcName.isNull() )
return ;
if ( arcName == ".." )
return ; // safety
// download the file if it's on a remote filesystem
KUrl arcURL = files() ->vfs_getFile( arcName );
QString url = QString();
if ( !arcURL.isLocalFile() ) {
url = KStandardDirs::locateLocal( "tmp", QString( arcName ) );
if ( !KIO::NetAccess::download( arcURL, url, 0 ) ) {
KMessageBox::sorry( krApp, i18n( "Krusader is unable to download: " ) + arcURL.fileName() );
continue;
}
} else
url = arcURL.path( KUrl::RemoveTrailingSlash );
// if the destination is in remote directory use temporary one instead
dest.adjustPath(KUrl::AddTrailingSlash);
KUrl originalDestURL;
KTempDir *tempDir = 0;
if ( !dest.isLocalFile() ) {
originalDestURL = dest;
tempDir = new KTempDir();
dest = tempDir->name();
}
// determining the type
QString mime = files() ->vfs_search( arcName ) ->vfile_getMime();
bool encrypted = false;
QString type = KRarcHandler::getType( encrypted, url, mime );
// check we that archive is supported
if ( !KRarcHandler::arcSupported( type ) ) {
KMessageBox::sorry( krApp, i18n( "%1, unknown archive type", arcName ) );
continue;
}
QString password = encrypted ? KRarcHandler::getPassword( url ) : QString();
// unpack the files
KRarcHandler::unpack( url, type, password, dest.path( KUrl::RemoveTrailingSlash ) );
// remove the downloaded file if necessary
if ( url != arcURL.path( KUrl::RemoveTrailingSlash ) )
QFile( url ).remove();
// copy files to the destination directory at remote files
if ( tempDir ) {
QStringList nameList = QDir( dest.path( KUrl::RemoveTrailingSlash ) ).entryList();
KUrl::List urlList;
for ( int i = 0; i != nameList.count(); i++ )
if ( nameList[ i ] != "." && nameList[ i ] != ".." )
urlList.append( KUrl( dest.path( KUrl::AddTrailingSlash ) + nameList[ i ] ) );
if ( urlList.count() > 0 )
KIO::NetAccess::dircopy( urlList, originalDestURL, 0 );
delete tempDir;
}
}
UnpackJob * job = UnpackJob::createUnpacker( files()->vfs_getOrigin(), dest, fileNames );
job->setUiDelegate(new KIO::JobUiDelegate() );
KIO::getJobTracker()->registerJob(job);
job->ui()->setAutoErrorHandlingEnabled( true );
if ( packToOtherPanel )
panel->otherPanel->func->refresh();
connect( job, SIGNAL( result( KJob* ) ), panel->otherPanel->func, SLOT( refresh() ) );
}
// a small ugly function, used to prevent duplication of EVERY line of
......
......@@ -17,7 +17,9 @@ set( VFS_SRCS
ftp_vfs.cpp
krquery.cpp
kiojobwrapper.cpp
preserveattrcopyjob.cpp )
preserveattrcopyjob.cpp
packjob.cpp
abstractthreadedjob.cpp )
kde4_add_library(VFS STATIC ${VFS_SRCS} )
......
/***************************************************************************
packjob.cpp - description
-------------------
copyright : (C) 2009 + by Csaba Karai
e-mail : krusader@users.sourceforge.net
web site : http://krusader.sourceforge.net
---------------------------------------------------------------------------
Description
***************************************************************************
A
db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
S o u r c e F i l e
***************************************************************************
* *
* 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 "abstractthreadedjob.h"
#include <qtimer.h>
#include <klocale.h>
#include <QEventLoop>
#include <KTempDir>
#include <KTemporaryFile>
#include <qapplication.h>
#include <qdir.h>
#include "krvfshandler.h"
#include "krarchandler.h"
#include "vfs.h"
#include "preservingcopyjob.h"
#include <kio/jobuidelegate.h>
#include <kmessagebox.h>
#include "../krusader.h"
AbstractThreadedJob::AbstractThreadedJob() : KIO::Job(), _locker(), _waiter(), _stack(), _maxProgressValue( 0 ),
_currentProgress( 0 ), _exiting( false ),_jobThread( 0 )
{
}
void AbstractThreadedJob::start( AbstractJobThread * jobThread )
{
_jobThread = jobThread;
_jobThread->setJob( this );
_jobThread->moveToThread( _jobThread );
_jobThread->start();
}
AbstractThreadedJob::~AbstractThreadedJob()
{
_exiting = true;
if( _jobThread )
{
_jobThread->abort();
_locker.lock();
_waiter.wakeAll();
_locker.unlock();
_jobThread->wait();
delete _jobThread;
}
}
bool AbstractThreadedJob::event(QEvent *e)
{
if( e->type() == QEvent::User )
{
UserEvent *event = (UserEvent*) e;
switch( event->command() )
{
case CMD_SUCCESS:
{
emitResult();
}
break;
case CMD_ERROR:
{
int error = event->args() [ 0 ].value<int>();
QString errorText = event->args() [ 1 ].value<QString>();
setError( error );
setErrorText( errorText );
emitResult();
}
break;
case CMD_INFO:
{
QString info = event->args() [ 0 ].value<QString>();
QString arg1 = event->args() [ 1 ].value<QString>();
QString arg2 = event->args() [ 2 ].value<QString>();
QString arg3 = event->args() [ 3 ].value<QString>();
QString arg4 = event->args() [ 4 ].value<QString>();
_title = info;
emit description(this, info,
qMakePair(arg1,arg2),
qMakePair(arg3,arg4));
}
break;
case CMD_RESET:
{
QString info = event->args() [ 0 ].value<QString>();
QString arg1 = event->args() [ 1 ].value<QString>();
QString arg2 = event->args() [ 2 ].value<QString>();
QString arg3 = event->args() [ 3 ].value<QString>();
QString arg4 = event->args() [ 4 ].value<QString>();
_title = info;
setProcessedAmount( KJob::Bytes, 0 );
setTotalAmount( KJob::Bytes, 0 );
emitSpeed( 0 );
emit description(this, info,
qMakePair(arg1,arg2),
qMakePair(arg3,arg4));
}
break;
case CMD_UPLOAD_FILES:
case CMD_DOWNLOAD_FILES:
{
KUrl::List sources = event->args() [ 0 ].value<KUrl::List>();
KUrl dest = event->args() [ 1 ].value<KUrl>();
KIO::Job *job = PreservingCopyJob::createCopyJob( PM_PRESERVE_ATTR, sources, dest, KIO::CopyJob::Copy, false, false );
addSubjob( job );
job->setUiDelegate( new KIO::JobUiDelegate () );
connect( job, SIGNAL( result( KJob* ) ), this, SLOT( slotDownloadResult( KJob* ) ) );
connect( job, SIGNAL( processedAmount( KJob *, KJob::Unit, qulonglong ) ),
this, SLOT( slotProcessedAmount( KJob *, KJob::Unit, qulonglong ) ) );
connect( job, SIGNAL( totalAmount( KJob *, KJob::Unit, qulonglong ) ),
this, SLOT( slotTotalAmount( KJob *, KJob::Unit, qulonglong ) ) );
connect( job, SIGNAL( speed( KJob *, unsigned long ) ),
this, SLOT( slotSpeed( KJob *, unsigned long ) ) );
connect( job, SIGNAL( description( KJob *, const QString &, const QPair<QString, QString> &,const QPair<QString, QString> & ) ),
this, SLOT( slotDescription( KJob *, const QString &, const QPair<QString, QString> &,const QPair<QString, QString> & ) ) );
}
break;
case CMD_MAXPROGRESSVALUE:
{
qulonglong maxValue = event->args() [ 0 ].value<qulonglong>();
_maxProgressValue = maxValue;
_currentProgress = 0;
}
break;
case CMD_ADD_PROGRESS:
{
qulonglong progress = event->args() [ 0 ].value<qulonglong>();
_currentProgress += progress;
if( _maxProgressValue != 0 )
{
setPercent( 100 * _currentProgress / _maxProgressValue );
int elapsed = _time.isNull() ? 1 : _time.secsTo( QTime::currentTime() );
if( elapsed !=0 && event->args().count() > 1 )
{
_time = QTime::currentTime();
QString progressString = (event->args() [ 1 ].value<QString>());
emit description(this, _title,
qMakePair(progressString,QString("%1/%2").arg( _currentProgress ).arg( _maxProgressValue )),
qMakePair(QString(),QString())
);
}
}
}
break;
case CMD_GET_PASSWORD:
{
QString path = event->args() [ 0 ].value<QString>();
QString password = KRarcHandler::getPassword( path );
QList<QVariant> *resultResp = new QList<QVariant> ();
(*resultResp) << password;
addEventResponse( resultResp );
}
break;
case CMD_MESSAGE:
{
QString message = event->args() [ 0 ].value<QString>();
KMessageBox::information( krApp, message );
QList<QVariant> *resultResp = new QList<QVariant> ();
addEventResponse( resultResp );
}
break;
}
return true;
} else {
return KIO::Job::event( e );
}
}
void AbstractThreadedJob::addEventResponse( QList<QVariant> * obj )
{
_locker.lock();
_stack.push( obj );
_waiter.wakeOne();
_locker.unlock();
}
QList<QVariant> * AbstractThreadedJob::getEventResponse( UserEvent * event )
{
_locker.lock();
QApplication::postEvent( this, event );
_waiter.wait( &_locker );
if( _exiting )
return 0;
QList<QVariant> *resp = _stack.pop();
_locker.unlock();
return resp;
}
void AbstractThreadedJob::sendEvent( UserEvent * event )
{
QApplication::postEvent( this, event );
}
void AbstractThreadedJob::slotDownloadResult( KJob* job )
{
QList<QVariant> *resultResp = new QList<QVariant> ();
if ( job )
{
(*resultResp) << QVariant( job->error() );
(*resultResp) << QVariant( job->errorText() );
} else {
(*resultResp) << QVariant( KJob::UserDefinedError );
(*resultResp) << QVariant( QString( i18n( "Internal error, undefined <job> in result signal!" ) ) );
}
addEventResponse( resultResp );
}
void AbstractThreadedJob::slotProcessedAmount( KJob *, KJob::Unit unit, qulonglong xu )
{
setProcessedAmount( unit, xu );
}
void AbstractThreadedJob::slotTotalAmount( KJob *, KJob::Unit unit, qulonglong xu )
{
setTotalAmount( unit, xu );
}
void AbstractThreadedJob::slotSpeed( KJob *, unsigned long spd)
{
emitSpeed( spd );
}
void AbstractThreadedJob::slotDescription( KJob *, const QString &title, const QPair<QString, QString> &field1,
const QPair<QString, QString> &field2 )
{
QString mytitle = title;
if( !_title.isNull() )
mytitle = _title;
emit description( this, mytitle, field1, field2 );
}
class AbstractJobObserver : public KRarcObserver
{
protected:
AbstractJobThread * _jobThread;
public:
AbstractJobObserver( AbstractJobThread * thread ): _jobThread( thread ) {}
virtual ~AbstractJobObserver() {}
virtual void processEvents()
{
usleep( 1000 );
qApp->processEvents();
}
virtual void subJobStarted( const QString & jobTitle, int count )
{
_jobThread->sendReset( jobTitle );
_jobThread->sendMaxProgressValue( count );
}
virtual void subJobStopped()
{
}
virtual bool wasCancelled()
{
return _jobThread->_exited;
}