diff options
Diffstat (limited to 'src/app/Synchronizer')
-rwxr-xr-x | src/app/Synchronizer/Makefile.am | 13 | ||||
-rw-r--r-- | src/app/Synchronizer/feedtolistboxdialog.cpp | 200 | ||||
-rw-r--r-- | src/app/Synchronizer/feedtolistboxdialog.h | 66 | ||||
-rw-r--r-- | src/app/Synchronizer/synchronizedialog.cpp | 199 | ||||
-rw-r--r-- | src/app/Synchronizer/synchronizedialog.h | 92 | ||||
-rw-r--r-- | src/app/Synchronizer/synchronizer.cpp | 1493 | ||||
-rw-r--r-- | src/app/Synchronizer/synchronizer.h | 205 | ||||
-rw-r--r-- | src/app/Synchronizer/synchronizerdirlist.cpp | 216 | ||||
-rw-r--r-- | src/app/Synchronizer/synchronizerdirlist.h | 73 | ||||
-rw-r--r-- | src/app/Synchronizer/synchronizerfileitem.h | 170 | ||||
-rw-r--r-- | src/app/Synchronizer/synchronizergui.cpp | 2478 | ||||
-rw-r--r-- | src/app/Synchronizer/synchronizergui.h | 225 | ||||
-rw-r--r-- | src/app/Synchronizer/synchronizertask.cpp | 343 | ||||
-rw-r--r-- | src/app/Synchronizer/synchronizertask.h | 170 |
14 files changed, 5943 insertions, 0 deletions
diff --git a/src/app/Synchronizer/Makefile.am b/src/app/Synchronizer/Makefile.am new file mode 100755 index 0000000..f270b65 --- /dev/null +++ b/src/app/Synchronizer/Makefile.am @@ -0,0 +1,13 @@ +noinst_LIBRARIES = libSynchronizer.a + +INCLUDES = $(all_includes) + +libSynchronizer_a_METASOURCES = AUTO + +libSynchronizer_a_SOURCES = \ + synchronizedialog.cpp \ + synchronizer.cpp \ + synchronizergui.cpp \ + feedtolistboxdialog.cpp \ + synchronizertask.cpp \ + synchronizerdirlist.cpp diff --git a/src/app/Synchronizer/feedtolistboxdialog.cpp b/src/app/Synchronizer/feedtolistboxdialog.cpp new file mode 100644 index 0000000..b69503f --- /dev/null +++ b/src/app/Synchronizer/feedtolistboxdialog.cpp @@ -0,0 +1,200 @@ +/*************************************************************************** + feedtolistboxdialog.cpp - description + ------------------- + copyright : (C) 2006 + 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 "feedtolistboxdialog.h" +#include "synchronizer.h" +#include "synchronizergui.h" +#include "../VFS/vfs.h" +#include "../VFS/virt_vfs.h" +#include "../krusader.h" +#include "../krusaderview.h" +#include "../panelmanager.h" +#include <tdelocale.h> +#include <tdemessagebox.h> +#include <tqcheckbox.h> +#include <tqlayout.h> +#include <tqlineedit.h> +#include <tqlabel.h> +#include <tqhbox.h> +#include <tqcombobox.h> +#include <tqframe.h> + +#define S_LEFT 0 +#define S_RIGHT 1 +#define S_BOTH 2 + +FeedToListBoxDialog::FeedToListBoxDialog(TQWidget *parent, const char *name, Synchronizer *sync, + TQListView *syncL, bool equOK) : KDialogBase( parent, name, true, i18n( "Krusader::Feed to listbox" ), + KDialogBase::Ok | KDialogBase::Cancel | KDialogBase::User1, Ok, true, KStdGuiItem::clear() ), + synchronizer( sync ), syncList( syncL ), equalAllowed( equOK ), accepted( false ) { + + // autodetecting the parameters + + int selectedNum = 0; + int itemNum = 0; + int leftExistingNum = 0; + int rightExistingNum = 0; + + TQListViewItemIterator it( syncList ); + while( it.current() ) { + SynchronizerGUI::SyncViewItem *item = (SynchronizerGUI::SyncViewItem *) it.current(); + SynchronizerFileItem *syncItem = item->synchronizerItemRef(); + + if( syncItem && syncItem->isMarked() ) { + if( item->isSelected() || syncItem->task() != TT_EQUALS || equalAllowed ) { + itemNum++; + if( item->isSelected() ) + selectedNum++; + + if( syncItem->existsInLeft() ) + leftExistingNum++; + if( syncItem->existsInRight() ) + rightExistingNum++; + } + } + it++; + } + + if( itemNum == 0 ) { + hide(); + KMessageBox::error( parent, i18n( "No elements to feed!" ) ); + return; + } + + // guessing the collection name + + virt_vfs v(0,true); + if( !v.vfs_refresh( KURL( "virt:/" ) ) ) + return; + + krConfig->setGroup( "Synchronize" ); + int listBoxNum = krConfig->readNumEntry( "Feed To Listbox Counter", 1 ); + TQString queryName; + do { + queryName = i18n("Synchronize results")+TQString( " %1" ).arg( listBoxNum++ ); + }while( v.vfs_search( queryName ) != 0 ); + krConfig->writeEntry( "Feed To Listbox Counter", listBoxNum ); + + // creating the widget + + TQWidget *widget=new TQWidget(this, "feedToListBoxMainWidget"); + TQVBoxLayout *layout = new TQVBoxLayout( widget, 0, 10, "FeedToListBoxDialogLayout" ); + + TQLabel *label = new TQLabel( i18n("Here you can name the file collection"), widget, "fbLabel" ); + layout->addWidget( label ); + + lineEdit = new TQLineEdit( widget, "fbLineEdit" ); + lineEdit->setText( queryName ); + lineEdit->selectAll(); + layout->addWidget( lineEdit ); + + TQHBox *hbox = new TQHBox( widget, "fbHBox" ); + + TQLabel *label2 = new TQLabel( i18n( "Side to feed:" ), hbox, "fbSideLabel" ); + label2->setSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed ); + + sideCombo = new TQComboBox( hbox, "fbSideCombo" ); + sideCombo->setSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed ); + sideCombo->insertItem( i18n( "Left" ) ); + sideCombo->insertItem( i18n( "Right" ) ); + sideCombo->insertItem( i18n( "Both" ) ); + if( leftExistingNum == 0 ) { + sideCombo->setCurrentItem( 1 ); + sideCombo->setEnabled( false ); + } else if( rightExistingNum == 0 ) { + sideCombo->setCurrentItem( 0 ); + sideCombo->setEnabled( false ); + } else + sideCombo->setCurrentItem( 2 ); + + TQFrame *line = new TQFrame( hbox, "fbVLine" ); + line->setFrameStyle( TQFrame::VLine | TQFrame::Sunken ); + line->setSizePolicy( TQSizePolicy::Expanding, TQSizePolicy::Expanding ); + + cbSelected = new TQCheckBox( i18n( "Selected files only" ), hbox, "cbSelected" ); + cbSelected->setSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed ); + cbSelected->setEnabled( selectedNum != 0 ); + cbSelected->setChecked( selectedNum != 0 ); + + layout->addWidget( hbox ); + + setMainWidget(widget); + + exec(); +} + +void FeedToListBoxDialog::slotUser1() { + lineEdit->clear(); +} + +void FeedToListBoxDialog::slotOk() { + int side = sideCombo->currentItem(); + bool selected = cbSelected->isChecked(); + TQString name = lineEdit->text(); + KURL::List urlList; + + TQListViewItemIterator it( syncList ); + for( ;it.current(); it++ ) { + SynchronizerGUI::SyncViewItem *item = (SynchronizerGUI::SyncViewItem *) it.current(); + SynchronizerFileItem *syncItem = item->synchronizerItemRef(); + + if( !syncItem || !syncItem->isMarked() ) + continue; + if( selected && !item->isSelected() ) + continue; + if( !equalAllowed && syncItem->task() == TT_EQUALS && (!selected || !item->isSelected() ) ) + continue; + + if( ( side == S_BOTH || side == S_LEFT ) && syncItem->existsInLeft() ) { + TQString leftDirName = syncItem->leftDirectory().isEmpty() ? "" : syncItem->leftDirectory() + "/"; + KURL leftURL = vfs::fromPathOrURL( synchronizer->leftBaseDirectory() + leftDirName + syncItem->leftName() ); + urlList.push_back( leftURL ); + } + + if( ( side == S_BOTH || side == S_RIGHT ) && syncItem->existsInRight() ) { + TQString rightDirName = syncItem->rightDirectory().isEmpty() ? "" : syncItem->rightDirectory() + "/"; + KURL leftURL = vfs::fromPathOrURL( synchronizer->rightBaseDirectory() + rightDirName + syncItem->rightName() ); + urlList.push_back( leftURL ); + } + } + + KURL url = KURL::fromPathOrURL(TQString("virt:/")+ name); + virt_vfs v(0,true); + if( !v.vfs_refresh( url ) ) { + KMessageBox::error( parentWidget(), i18n( "Cannot open %1!" ).arg( url.prettyURL() ) ); + return; + } + v.vfs_addFiles( &urlList, TDEIO::CopyJob::Copy, 0 ); + ACTIVE_MNG->slotNewTab(url.prettyURL()); + accepted = true; + accept(); +} + +#include "feedtolistboxdialog.moc" diff --git a/src/app/Synchronizer/feedtolistboxdialog.h b/src/app/Synchronizer/feedtolistboxdialog.h new file mode 100644 index 0000000..8b10ff3 --- /dev/null +++ b/src/app/Synchronizer/feedtolistboxdialog.h @@ -0,0 +1,66 @@ +/*************************************************************************** + feedtolistboxdialog.h - description + ------------------- + copyright : (C) 2006 + 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 + + H e a d e r 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. * + * * + ***************************************************************************/ + +#ifndef __FEED_TO_LISTBOX_DIALOG__ +#define __FEED_TO_LISTBOX_DIALOG__ + +#include <kdialogbase.h> + +class Synchronizer; +class TQCheckBox; +class TQLineEdit; +class TQComboBox; +class TQListView; + +class FeedToListBoxDialog : public KDialogBase { + TQ_OBJECT + + + public: + FeedToListBoxDialog( TQWidget*, const char*, Synchronizer *, TQListView *, bool); + virtual ~FeedToListBoxDialog() {}; + + bool isAccepted() {return accepted;}; + + protected: + void slotUser1(); + void slotOk(); + + private: + Synchronizer * synchronizer; + TQListView * syncList; + TQCheckBox * cbSelected; + TQLineEdit * lineEdit; + TQComboBox * sideCombo; + bool equalAllowed; + bool accepted; +}; + +#endif /* __FEED_TO_LISTBOX_DIALOG__ */ diff --git a/src/app/Synchronizer/synchronizedialog.cpp b/src/app/Synchronizer/synchronizedialog.cpp new file mode 100644 index 0000000..55cbde6 --- /dev/null +++ b/src/app/Synchronizer/synchronizedialog.cpp @@ -0,0 +1,199 @@ +/*************************************************************************** + synchronizedialog.cpp - description + ------------------- + copyright : (C) 2003 + 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 "synchronizedialog.h" +#include "../VFS/krpermhandler.h" +#include "../krusader.h" +#include "../defaults.h" +#include <tqlayout.h> +#include <tqhbox.h> +#include <tdelocale.h> + +SynchronizeDialog::SynchronizeDialog( TQWidget* parent, const char* name, bool modal, WFlags fl, + Synchronizer *sync, int pleftCopyNr, TDEIO::filesize_t pleftCopySize, + int prightCopyNr, TDEIO::filesize_t prightCopySize, int pdeleteNr, + TDEIO::filesize_t pdeleteSize, int parThreads ) : TQDialog( parent, name, modal, fl ), + synchronizer( sync ), leftCopyNr ( pleftCopyNr ), + leftCopySize( pleftCopySize ), rightCopyNr ( prightCopyNr ), + rightCopySize( prightCopySize ), deleteNr( pdeleteNr ), + deleteSize( pdeleteSize ), parallelThreads( parThreads ), + isPause( true ), syncStarted( false ) +{ + setCaption( i18n("Krusader::Synchronize") ); + + TQVBoxLayout *layout = new TQVBoxLayout( this, 11, 6, "SynchronizeDialogLayout" ); + + cbRightToLeft = new TQCheckBox( i18n( "Right to left: Copy 1 file", "Right to left: Copy %n files", leftCopyNr) + " " + + i18n( "(1 byte)", "(%n bytes)", KRpermHandler::parseSize( leftCopySize ).stripWhiteSpace().toInt() ), + this, "labelRightToLeft" ); + cbRightToLeft->setChecked( leftCopyNr != 0 ); + cbRightToLeft->setEnabled( leftCopyNr != 0 ); + layout->addWidget( cbRightToLeft ); + + lbRightToLeft = new TQLabel( "\t" + i18n( "Ready: %1/1 file, %3/%4", "Ready: %1/%n files, %3/%4", leftCopyNr).arg( 0 ) + .arg( 0 ).arg( KRpermHandler::parseSize( leftCopySize ).stripWhiteSpace() ), + this, "lbRightToLeft" ); + lbRightToLeft->setEnabled( leftCopyNr != 0 ); + layout->addWidget( lbRightToLeft ); + + cbLeftToRight = new TQCheckBox( i18n( "Left to right: Copy 1 file", "Left to right: Copy %n files", rightCopyNr) + " " + + i18n( "(1 byte)", "(%n bytes)", KRpermHandler::parseSize( rightCopySize ).stripWhiteSpace().toInt() ), + this, "cbLeftToRight" ); + cbLeftToRight->setChecked( rightCopyNr != 0 ); + cbLeftToRight->setEnabled( rightCopyNr != 0 ); + layout->addWidget( cbLeftToRight ); + + lbLeftToRight = new TQLabel( "\t" + i18n( "Ready: %1/1 file, %3/%4", "Ready: %1/%n files, %3/%4", rightCopyNr ).arg( 0 ) + .arg( 0 ).arg( KRpermHandler::parseSize( rightCopySize ).stripWhiteSpace() ), + this, "lbLeftToRight" ); + lbLeftToRight->setEnabled( rightCopyNr != 0 ); + layout->addWidget( lbLeftToRight ); + + cbDeletable = new TQCheckBox( i18n( "Left: Delete 1 file", "Left: Delete %n files", deleteNr) + " " + + i18n( "(1 byte)", "(%n bytes)", KRpermHandler::parseSize( deleteSize ).stripWhiteSpace().toInt() ), + this, "cbDeletable" ); + cbDeletable->setChecked( deleteNr != 0 ); + cbDeletable->setEnabled( deleteNr != 0 ); + layout->addWidget( cbDeletable ); + + lbDeletable = new TQLabel( "\t" + i18n( "Ready: %1/1 file, %3/%4", "Ready: %1/%n files, %3/%4", deleteNr ).arg( 0 ) + .arg( 0 ).arg( KRpermHandler::parseSize( deleteSize ).stripWhiteSpace() ), + this, "lbDeletable" ); + lbDeletable->setEnabled( deleteNr != 0 ); + layout->addWidget( lbDeletable ); + + progress = new TQProgressBar(1000, this); + progress->setCenterIndicator(true); + progress->setProgress( 0 ); + progress->setMinimumWidth( 400 ); + layout->addWidget( progress ); + + TQHBox *hbox = new TQHBox( this, "SynchronizeDialogHBox" ); + hbox->setSpacing( 6 ); + + cbOverwrite = new TQCheckBox( i18n( "Confirm overwrites" ), this, "cbOverWrite" ); + krConfig->setGroup("Synchronize"); + cbOverwrite->setChecked( krConfig->readBoolEntry( "Confirm overwrites", _ConfirmOverWrites ) ); + layout->addWidget( cbOverwrite ); + + TQSpacerItem* spacer = new TQSpacerItem( 20, 20, TQSizePolicy::Expanding, TQSizePolicy::Minimum ); + hbox->layout()->addItem( spacer ); + + btnStart = new TQPushButton( hbox, "btnStart" ); + btnStart->setText( i18n( "&Start" ) ); + + btnPause = new TQPushButton( hbox, "btnPause" ); + btnPause->setEnabled( false ); + btnPause->setText( i18n( "&Pause" ) ); + + TQPushButton *btnClose = new TQPushButton( hbox, "btnClose" ); + btnClose->setText( i18n( "&Close" ) ); + + layout->addWidget( hbox ); + + connect( btnStart, TQ_SIGNAL( clicked() ), this, TQ_SLOT( startSynchronization() ) ); + connect( btnPause, TQ_SIGNAL( clicked() ), this, TQ_SLOT( pauseOrResume() ) ); + connect( btnClose, TQ_SIGNAL( clicked() ), this, TQ_SLOT( reject() ) ); + + exec(); +} + +SynchronizeDialog::~SynchronizeDialog() +{ + krConfig->writeEntry("Confirm overwrites", cbOverwrite->isChecked() ); +} + +void SynchronizeDialog::startSynchronization() +{ + btnStart->setEnabled( false ); + btnPause->setEnabled( syncStarted = true ); + connect( synchronizer, TQ_SIGNAL( synchronizationFinished() ), this, TQ_SLOT( synchronizationFinished() ) ); + connect( synchronizer, TQ_SIGNAL( processedSizes( int, TDEIO::filesize_t, int, TDEIO::filesize_t, int, TDEIO::filesize_t ) ), + this, TQ_SLOT( processedSizes( int, TDEIO::filesize_t, int, TDEIO::filesize_t, int, TDEIO::filesize_t) ) ); + connect( synchronizer, TQ_SIGNAL( pauseAccepted() ), this, TQ_SLOT( pauseAccepted() ) ); + + if( !cbRightToLeft->isChecked() ) leftCopySize = 0; + if( !cbLeftToRight->isChecked() ) rightCopySize = 0; + if( !cbDeletable->isChecked() ) deleteSize = 0; + + synchronizer->synchronize( this, cbRightToLeft->isChecked(), cbLeftToRight->isChecked(), + cbDeletable->isChecked(), !cbOverwrite->isChecked(), parallelThreads ); +} + +void SynchronizeDialog::synchronizationFinished() +{ + TQDialog::reject(); +} + +void SynchronizeDialog::processedSizes( int leftNr, TDEIO::filesize_t leftSize, int rightNr, + TDEIO::filesize_t rightSize, int delNr, TDEIO::filesize_t delSize ) +{ + lbRightToLeft->setText( i18n( "\tReady: %1/%2 files, %3/%4" ).arg( leftNr ).arg( leftCopyNr ) + .arg( KRpermHandler::parseSize( leftSize ).stripWhiteSpace() ) + .arg( KRpermHandler::parseSize( leftCopySize ).stripWhiteSpace() ) ); + lbLeftToRight->setText( i18n( "\tReady: %1/%2 files, %3/%4" ).arg( rightNr ).arg( rightCopyNr ) + .arg( KRpermHandler::parseSize( rightSize ).stripWhiteSpace() ) + .arg( KRpermHandler::parseSize( rightCopySize ).stripWhiteSpace() ) ); + lbDeletable->setText ( i18n( "\tReady: %1/%2 files, %3/%4" ).arg( delNr ).arg( deleteNr ) + .arg( KRpermHandler::parseSize( delSize ).stripWhiteSpace() ) + .arg( KRpermHandler::parseSize( deleteSize ).stripWhiteSpace() ) ); + + TDEIO::filesize_t totalSum = leftCopySize + rightCopySize + deleteSize; + TDEIO::filesize_t processedSum = leftSize + rightSize + delSize; + + if( totalSum == 0 ) + totalSum++; + + progress->setProgress( (int)(((double)processedSum / (double)totalSum )*1000) ); +} + +void SynchronizeDialog::pauseOrResume() +{ + if( isPause ) + { + btnPause->setEnabled( false ); + synchronizer->pause(); + } + else + { + btnPause->setText( i18n( "Pause" ) ); + synchronizer->resume(); + isPause = true; + } +} + +void SynchronizeDialog::pauseAccepted() +{ + btnPause->setText( i18n( "Resume" ) ); + btnPause->setEnabled( true ); + isPause = false; +} + +#include "synchronizedialog.moc" diff --git a/src/app/Synchronizer/synchronizedialog.h b/src/app/Synchronizer/synchronizedialog.h new file mode 100644 index 0000000..9d5a16c --- /dev/null +++ b/src/app/Synchronizer/synchronizedialog.h @@ -0,0 +1,92 @@ +/*************************************************************************** + synchronizedialog.h - description + ------------------- + copyright : (C) 2003 + 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 + + H e a d e r 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. * + * * + ***************************************************************************/ + +#ifndef __SYNCHRONIZE_DIALOG__ +#define __SYNCHRONIZE_DIALOG__ + +#include "../VFS/vfs.h" +#include "synchronizer.h" +#include <tqdialog.h> +#include <tqpushbutton.h> +#include <tqcheckbox.h> +#include <tqlabel.h> +#include <tqprogressbar.h> + +class SynchronizeDialog : TQDialog +{ + TQ_OBJECT + + + public: + SynchronizeDialog( TQWidget*, const char*, bool, WFlags, Synchronizer *sync, + int, TDEIO::filesize_t, int, TDEIO::filesize_t, int, TDEIO::filesize_t, int); + ~SynchronizeDialog(); + + inline bool wasSyncronizationStarted() { return syncStarted; } + + public slots: + void startSynchronization(); + void synchronizationFinished(); + void processedSizes( int, TDEIO::filesize_t, int, TDEIO::filesize_t, int, TDEIO::filesize_t); + void pauseOrResume(); + void pauseAccepted(); + + private: + TQProgressBar *progress; + + TQCheckBox *cbRightToLeft; + TQCheckBox *cbLeftToRight; + TQCheckBox *cbDeletable; + + TQLabel *lbRightToLeft; + TQLabel *lbLeftToRight; + TQLabel *lbDeletable; + + TQCheckBox *cbOverwrite; + + TQPushButton *btnStart; + TQPushButton *btnPause; + + Synchronizer *synchronizer; + + int leftCopyNr; + TDEIO::filesize_t leftCopySize; + int rightCopyNr; + TDEIO::filesize_t rightCopySize; + int deleteNr; + TDEIO::filesize_t deleteSize; + + int parallelThreads; + + bool isPause; + bool syncStarted; +}; + +#endif /* __SYNCHRONIZE_DIALOG__ */ diff --git a/src/app/Synchronizer/synchronizer.cpp b/src/app/Synchronizer/synchronizer.cpp new file mode 100644 index 0000000..612f756 --- /dev/null +++ b/src/app/Synchronizer/synchronizer.cpp @@ -0,0 +1,1493 @@ +/*************************************************************************** + synchronizer.cpp - description + ------------------- + copyright : (C) 2003 + 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 "synchronizer.h" +#include "synchronizerdirlist.h" +#include "../krusader.h" +#include "../krservices.h" +#include "../VFS/vfs.h" +#include "../VFS/krquery.h" +#include "config.h" +#include <kurl.h> +#include <tdemessagebox.h> +#include <tdelocale.h> +#include <tqapplication.h> +#include <tqregexp.h> +#include <tqdir.h> +#include <tqtimer.h> +#include <tdeio/job.h> +#include <kdialogbase.h> +#include <tdeio/observer.h> +#include <tdeio/renamedlg.h> +#include <tdeio/skipdlg.h> +#include <unistd.h> +#include <tqeventloop.h> +#include <tqpushbutton.h> +#include <tqdatetime.h> +#include <kprocess.h> +#include <kdialogbase.h> +#include <kprogress.h> +#include <tqlayout.h> +#include <kurlcompletion.h> + +#include <sys/types.h> +#include <sys/time.h> +#include <utime.h> +#include <pwd.h> +#include <grp.h> +#include <tqlabel.h> + + + +#if KDE_IS_VERSION(3,5,0) && defined( HAVE_POSIX_ACL ) +#include <sys/acl.h> +#ifdef HAVE_NON_POSIX_ACL_EXTENSIONS +#include <acl/libacl.h> +#endif +#endif + + +#define DISPLAY_UPDATE_PERIOD 2 + +Synchronizer::Synchronizer() : displayUpdateCount( 0 ), markEquals( true ), + markDiffers ( true ), markCopyToLeft( true ), markCopyToRight( true ), markDeletable( true ), + stack(), jobMap(), receivedMap(), parentWidget( 0 ) +{ + resultList.setAutoDelete( true ); + stack.setAutoDelete( true ); +} + +void Synchronizer::reset() +{ + displayUpdateCount = 0; + markEquals = markDiffers = markCopyToLeft = markCopyToRight = markDeletable = true; + stopped = false; + recurseSubDirs = followSymLinks = ignoreDate = asymmetric = cmpByContent = ignoreCase = autoScroll = false; + markEquals = markDiffers = markCopyToLeft = markCopyToRight = markDeletable = markDuplicates = markSingles = false; + leftCopyEnabled = rightCopyEnabled = deleteEnabled = overWrite = autoSkip = paused = false; + leftCopyNr = rightCopyNr = deleteNr = 0; + leftCopySize = rightCopySize = deleteSize = 0; + comparedDirs = fileCount = 0; + leftBaseDir = rightBaseDir = TQString(); + resultList.clear(); + temporaryList.clear(); + stack.clear(); +} + +int Synchronizer::compare( TQString leftURL, TQString rightURL, KRQuery *query, bool subDirs, + bool symLinks, bool igDate, bool asymm, bool cmpByCnt, bool igCase, + bool autoSc, TQStringList &selFiles, int equThres, int timeOffs, int parThreads, bool hiddenFiles ) +{ + resultList.clear(); + temporaryList.clear(); + + recurseSubDirs = subDirs; + followSymLinks = symLinks; + ignoreDate = igDate; + asymmetric = asymm; + cmpByContent = cmpByCnt; + autoScroll = autoSc; + ignoreCase = igCase; + selectedFiles = selFiles; + equalsThreshold= equThres; + timeOffset = timeOffs; + parallelThreads= parThreads; + ignoreHidden = hiddenFiles; + + stopped = false; + + this->query = query; + + leftURL = KURLCompletion::replacedPath( leftURL, true, true ); + rightURL = KURLCompletion::replacedPath( rightURL, true, true ); + + if( !leftURL.endsWith("/" )) leftURL+="/"; + if( !rightURL.endsWith("/" )) rightURL+="/"; + + excludedPaths = query->dontSearchInDirs().toStringList(); + for( unsigned i = 0; i != excludedPaths.count(); i++ ) + if( excludedPaths[ i ].endsWith( "/" ) ) + excludedPaths[ i ].truncate( excludedPaths[ i ].length() - 1 ); + + comparedDirs = fileCount = 0; + + stack.append( new CompareTask( 0, leftBaseDir = leftURL, rightBaseDir = rightURL, "", "", ignoreHidden ) ); + compareLoop(); + + SynchronizerFileItem *item = temporaryList.first(); + while( item ) + { + if( item->isTemporary() ) + delete item; + item = temporaryList.next(); + } + temporaryList.clear(); + + + if( !autoScroll ) + refresh( true ); + + emit statusInfo( i18n( "Number of files: %1" ).arg( fileCount ) ); + return fileCount; +} + +void Synchronizer::compareLoop() { + while( !stopped && !stack.isEmpty() ) { + for( int thread=0; thread < (int)stack.count() && thread < parallelThreads; thread++ ) { + SynchronizerTask * entry = stack.at( thread ); + + if( entry->state() == ST_STATE_NEW ) + entry->start( parentWidget ); + + if( entry->inherits("CompareTask") ) { + if( entry->state() == ST_STATE_READY ) { + CompareTask *ctentry = (CompareTask *) entry; + if( ctentry->isDuplicate() ) + compareDirectory( ctentry->parent(), ctentry->leftDirList(), ctentry->rightDirList(), + ctentry->leftDir(), ctentry->rightDir() ); + else + addSingleDirectory( ctentry->parent(), ctentry->dirList(), ctentry->dir(), + ctentry->isLeft() ); + } + if( entry->state() == ST_STATE_READY || entry->state() == ST_STATE_ERROR ) + comparedDirs++; + } + switch( entry->state() ) { + case ST_STATE_STATUS: + emit statusInfo( entry->status() ); + break; + case ST_STATE_READY: + case ST_STATE_ERROR: + emit statusInfo( i18n( "Number of compared directories: %1" ).arg( comparedDirs ) ); + stack.removeRef( entry ); + continue; + default: + break; + } + } + if( !stack.isEmpty() ) + tqApp->processEvents(); + } + stack.clear(); +} + +void Synchronizer::compareDirectory( SynchronizerFileItem *parent, SynchronizerDirList * left_directory, + SynchronizerDirList * right_directory, const TQString &leftDir, + const TQString &rightDir ) +{ + const TQString &leftURL = left_directory->url(); + const TQString &rightURL = right_directory->url(); + vfile * left_file; + vfile * right_file; + + TQString file_name; + bool checkIfSelected = false; + + if( leftDir.isEmpty() && rightDir.isEmpty() && selectedFiles.count() ) + checkIfSelected = true; + + /* walking through in the left directory */ + for( left_file=left_directory->first(); left_file != 0 && !stopped ; + left_file=left_directory->next() ) + { + if ( isDir( left_file ) ) + continue; + + file_name = left_file->vfile_getName(); + + if( checkIfSelected && !selectedFiles.contains( file_name ) ) + continue; + + if( !query->match( left_file ) ) + continue; + + if( (right_file = right_directory->search( file_name, ignoreCase )) == 0 ) + addLeftOnlyItem( parent, file_name, leftDir, left_file->vfile_getSize(), left_file->vfile_getTime_t(), + readLink( left_file ), left_file->vfile_getOwner(), left_file->vfile_getGroup(), + left_file->vfile_getMode(), left_file->vfile_getACL() ); + else + { + if( isDir( right_file ) ) + continue; + + addDuplicateItem( parent, file_name, right_file->vfile_getName(), leftDir, rightDir, left_file->vfile_getSize(), right_file->vfile_getSize(), + left_file->vfile_getTime_t(), right_file->vfile_getTime_t(), readLink( left_file ), + readLink( right_file ), left_file->vfile_getOwner(), right_file->vfile_getOwner(), + left_file->vfile_getGroup(), right_file->vfile_getGroup(), + left_file->vfile_getMode(), right_file->vfile_getMode(), + left_file->vfile_getACL(), right_file->vfile_getACL() ); + } + } + + /* walking through in the right directory */ + for( right_file=right_directory->first(); right_file != 0 && !stopped ; + right_file=right_directory->next() ) + { + if( isDir( right_file ) ) + continue; + + file_name = right_file->vfile_getName(); + + if( checkIfSelected && !selectedFiles.contains( file_name ) ) + continue; + + if( !query->match( right_file ) ) + continue; + + if( left_directory->search( file_name, ignoreCase ) == 0 ) + addRightOnlyItem( parent, file_name, rightDir, right_file->vfile_getSize(), right_file->vfile_getTime_t(), + readLink( right_file ), right_file->vfile_getOwner(), right_file->vfile_getGroup(), + right_file->vfile_getMode(), right_file->vfile_getACL() ); + } + + /* walking through the subdirectories */ + if( recurseSubDirs ) + { + for( left_file=left_directory->first(); left_file != 0 && !stopped ; + left_file=left_directory->next() ) + { + if ( left_file->vfile_isDir() && ( followSymLinks || !left_file->vfile_isSymLink()) ) + { + TQString left_file_name = left_file->vfile_getName(); + + if( checkIfSelected && !selectedFiles.contains( left_file_name ) ) + continue; + + if( excludedPaths.contains( leftDir.isEmpty() ? left_file_name : leftDir+"/"+left_file_name ) ) + continue; + + if( !query->matchDirName( left_file_name ) ) + continue; + + if( (right_file = right_directory->search( left_file_name, ignoreCase )) == 0 ) + { + SynchronizerFileItem *me = addLeftOnlyItem( parent, left_file_name, leftDir, 0, + left_file->vfile_getTime_t(), readLink( left_file ), + left_file->vfile_getOwner(), left_file->vfile_getGroup(), + left_file->vfile_getMode(), left_file->vfile_getACL(), + true, !query->match( left_file ) ); + stack.append( new CompareTask( me, leftURL+left_file_name+"/", + leftDir.isEmpty() ? left_file_name : leftDir+"/"+left_file_name, true, ignoreHidden ) ); + } else { + TQString right_file_name = right_file->vfile_getName(); + SynchronizerFileItem *me = addDuplicateItem( parent, left_file_name, right_file_name, + leftDir, rightDir, 0, 0, + left_file->vfile_getTime_t(), right_file->vfile_getTime_t(), + readLink( left_file ), readLink( right_file ), + left_file->vfile_getOwner(), right_file->vfile_getOwner(), + left_file->vfile_getGroup(), right_file->vfile_getGroup(), + left_file->vfile_getMode(), right_file->vfile_getMode(), + left_file->vfile_getACL(), right_file->vfile_getACL(), + true, !query->match( left_file ) ); + stack.append( new CompareTask( me, leftURL+left_file_name+"/", rightURL+right_file_name+"/", + leftDir.isEmpty() ? left_file_name : leftDir+"/"+left_file_name, + rightDir.isEmpty() ? right_file_name : rightDir+"/"+right_file_name, ignoreHidden ) ); + } + } + } + + /* walking through the the right side subdirectories */ + for( right_file=right_directory->first(); right_file != 0 && !stopped ; + right_file=right_directory->next() ) + { + if ( right_file->vfile_isDir() && (followSymLinks || !right_file->vfile_isSymLink()) ) + { + file_name = right_file->vfile_getName(); + + if( checkIfSelected && !selectedFiles.contains( file_name ) ) + continue; + + if( excludedPaths.contains( rightDir.isEmpty() ? file_name : rightDir+"/"+file_name ) ) + continue; + + if( !query->matchDirName( file_name ) ) + continue; + + if( left_directory->search( file_name, ignoreCase ) == 0 ) + { + SynchronizerFileItem *me = addRightOnlyItem( parent, file_name, rightDir, 0, + right_file->vfile_getTime_t(), readLink( right_file ), + right_file->vfile_getOwner(), right_file->vfile_getGroup(), + right_file->vfile_getMode(), right_file->vfile_getACL(), + true, !query->match( right_file ) ); + stack.append( new CompareTask( me, rightURL+file_name+"/", + rightDir.isEmpty() ? file_name : rightDir+"/"+file_name, false, ignoreHidden ) ); + } + } + } + } +} + +TQString Synchronizer::getTaskTypeName( TaskType taskType ) +{ + static TQString names[] = {"=","!=","<-","->","DEL","?","?","?","?","?"}; + + return names[taskType]; +} + +SynchronizerFileItem * Synchronizer::addItem( SynchronizerFileItem *parent, const TQString &leftFile, + const TQString &rightFile, const TQString &leftDir, + const TQString &rightDir, bool existsLeft, bool existsRight, + TDEIO::filesize_t leftSize, TDEIO::filesize_t rightSize, + time_t leftDate, time_t rightDate, const TQString &leftLink, + const TQString &rightLink, const TQString &leftOwner, + const TQString &rightOwner, const TQString &leftGroup, + const TQString &rightGroup, mode_t leftMode, mode_t rightMode, + const TQString &leftACL, const TQString &rightACL, TaskType tsk, + bool isDir, bool isTemp ) +{ + bool marked = autoScroll ? !isTemp && isMarked( tsk, existsLeft && existsRight ) : false; + SynchronizerFileItem *item = new SynchronizerFileItem( leftFile, rightFile, leftDir, rightDir, marked, + existsLeft, existsRight, leftSize, rightSize, leftDate, rightDate, leftLink, rightLink, + leftOwner, rightOwner, leftGroup, rightGroup, leftMode, rightMode, leftACL, rightACL, tsk, isDir, + isTemp, parent ); + + if( !isTemp ) + { + while( parent && parent->isTemporary() ) + setPermanent( parent ); + + bool doRefresh = false; + + if( marked ) + { + fileCount++; + if( autoScroll && markParentDirectories( item ) ) + doRefresh = true; + } + + resultList.append( item ); + emit comparedFileData( item ); + + if( doRefresh ) + refresh( true ); + + if( marked && (displayUpdateCount++ % DISPLAY_UPDATE_PERIOD == (DISPLAY_UPDATE_PERIOD-1) ) ) + tqApp->processEvents(); + } + else + temporaryList.append( item ); + + return item; +} + +void Synchronizer::compareContentResult( SynchronizerFileItem * item, bool res ) { + item->compareContentResult( res ); + bool marked = autoScroll ? isMarked( item->task(), item->existsInLeft() && item->existsInRight() ) : false; + item->setMarked( marked ); + if( marked ) { + markParentDirectories( item ); + fileCount++; + emit markChanged( item, true ); + } +} + +void Synchronizer::setPermanent( SynchronizerFileItem *item ) +{ + if( item->parent() && item->parent()->isTemporary() ) + setPermanent( item->parent() ); + + item->setPermanent(); + resultList.append( item ); + emit comparedFileData( item ); +} + +SynchronizerFileItem * Synchronizer::addLeftOnlyItem( SynchronizerFileItem *parent, + const TQString &file_name, const TQString &dir, TDEIO::filesize_t size, + time_t date, const TQString &link, const TQString &owner, + const TQString &group, mode_t mode, const TQString &acl, bool isDir, + bool isTemp ) +{ + return addItem( parent, file_name, file_name, dir, dir, true, false, size, 0, date, 0, link, TQString(), + owner, TQString(), group, TQString(), mode, (mode_t)-1, acl, TQString(), + asymmetric ? TT_DELETE : TT_COPY_TO_RIGHT, isDir, isTemp ); +} + +SynchronizerFileItem * Synchronizer::addRightOnlyItem( SynchronizerFileItem *parent, + const TQString &file_name, const TQString &dir, TDEIO::filesize_t size, + time_t date, const TQString &link, const TQString &owner, + const TQString &group, mode_t mode, const TQString &acl, bool isDir, + bool isTemp ) +{ + return addItem( parent, file_name, file_name, dir, dir, false, true, 0, size, 0, date, TQString(), link, + TQString(), owner, TQString(), group, (mode_t)-1, mode, TQString(), acl, + TT_COPY_TO_LEFT, isDir, isTemp ); +} + +SynchronizerFileItem * Synchronizer::addDuplicateItem( SynchronizerFileItem *parent, + const TQString &leftName, const TQString &rightName, + const TQString &leftDir, const TQString &rightDir, + TDEIO::filesize_t leftSize, TDEIO::filesize_t rightSize, time_t leftDate, time_t rightDate, + const TQString &leftLink, const TQString &rightLink, + const TQString &leftOwner, const TQString &rightOwner, + const TQString &leftGroup, const TQString &rightGroup, + mode_t leftMode, mode_t rightMode, + const TQString &leftACL, const TQString &rightACL, + bool isDir, bool isTemp ) +{ + TaskType task; + + int checkedRightDate = rightDate - timeOffset; + int uncertain = 0; + + do + { + if( isDir ) + { + task = TT_EQUALS; + break; + } + if( leftSize == rightSize ) + { + if( !leftLink.isNull() || !rightLink.isNull() ) { + if( leftLink == rightLink ) { + task = TT_EQUALS; + break; + } + } else if( cmpByContent ) + uncertain = TT_UNKNOWN; + else { + if( ignoreDate || leftDate == checkedRightDate ) { + task = TT_EQUALS; + break; + } + time_t diff = ( leftDate > checkedRightDate ) ? leftDate - checkedRightDate : checkedRightDate - leftDate; + if( diff <= equalsThreshold ) { + task = TT_EQUALS; + break; + } + } + } + + if( asymmetric ) + task = TT_COPY_TO_LEFT; + else if( ignoreDate ) + task = TT_DIFFERS; + else if( leftDate > checkedRightDate ) + task = TT_COPY_TO_RIGHT; + else if( leftDate < checkedRightDate ) + task = TT_COPY_TO_LEFT; + else + task = TT_DIFFERS; + + }while( false ); + + SynchronizerFileItem * item = addItem( parent, leftName, rightName, leftDir, rightDir, true, true, + leftSize, rightSize, leftDate, rightDate, leftLink, rightLink, + leftOwner, rightOwner, leftGroup, rightGroup, + leftMode, rightMode, leftACL, rightACL, + (TaskType)(task + uncertain), isDir, isTemp ); + + if( uncertain == TT_UNKNOWN ) { + KURL leftURL = vfs::fromPathOrURL( leftDir.isEmpty() ? leftBaseDir + leftName : leftBaseDir + leftDir + "/" + leftName ); + KURL rightURL = vfs::fromPathOrURL( rightDir.isEmpty() ? rightBaseDir + rightName : rightBaseDir + rightDir + "/" + rightName ); + stack.append( new CompareContentTask( this, item, leftURL, rightURL, leftSize ) ); + } + + return item; +} + +void Synchronizer::addSingleDirectory( SynchronizerFileItem *parent, SynchronizerDirList *directory, + const TQString &dirName, bool isLeft ) +{ + const TQString &url = directory->url(); + vfile * file; + TQString file_name; + + /* walking through the directory files */ + for( file=directory->first(); file != 0 && !stopped; file = directory->next() ) + { + if ( isDir( file ) ) + continue; + + file_name = file->vfile_getName(); + + if( !query->match( file ) ) + continue; + + if( isLeft ) + addLeftOnlyItem( parent, file_name, dirName, file->vfile_getSize(), file->vfile_getTime_t(), readLink( file ), + file->vfile_getOwner(), file->vfile_getGroup(), file->vfile_getMode(), file->vfile_getACL() ); + else + addRightOnlyItem( parent, file_name, dirName, file->vfile_getSize(), file->vfile_getTime_t(), readLink( file ), + file->vfile_getOwner(), file->vfile_getGroup(), file->vfile_getMode(), file->vfile_getACL() ); + } + + /* walking through the subdirectories */ + for( file=directory->first(); file != 0 && !stopped; file=directory->next() ) + { + if ( file->vfile_isDir() && (followSymLinks || !file->vfile_isSymLink()) ) + { + file_name = file->vfile_getName(); + + if( excludedPaths.contains( dirName.isEmpty() ? file_name : dirName+"/"+file_name ) ) + continue; + + if( !query->matchDirName( file_name ) ) + continue; + + SynchronizerFileItem *me; + + if( isLeft ) + me = addLeftOnlyItem( parent, file_name, dirName, 0, file->vfile_getTime_t(), readLink( file ), + file->vfile_getOwner(), file->vfile_getGroup(), file->vfile_getMode(), + file->vfile_getACL(), true, !query->match( file ) ); + else + me = addRightOnlyItem( parent, file_name, dirName, 0, file->vfile_getTime_t(), readLink( file ), + file->vfile_getOwner(), file->vfile_getGroup(), file->vfile_getMode(), + file->vfile_getACL(), true, !query->match( file ) ); + stack.append( new CompareTask( me, url+file_name+"/", + dirName.isEmpty() ? file_name : dirName+"/"+file_name, isLeft, ignoreHidden ) ); + } + } +} + +void Synchronizer::setMarkFlags( bool left, bool equal, bool differs, bool right, bool dup, bool sing, + bool del ) +{ + markEquals = equal; + markDiffers = differs; + markCopyToLeft = left; + markCopyToRight = right; + markDeletable = del; + markDuplicates = dup; + markSingles = sing; +} + +bool Synchronizer::isMarked( TaskType task, bool isDuplicate ) +{ + if( (isDuplicate && !markDuplicates) || (!isDuplicate && !markSingles) ) + return false; + + switch( task ) + { + case TT_EQUALS: + return markEquals; + case TT_DIFFERS: + return markDiffers; + case TT_COPY_TO_LEFT: + return markCopyToLeft; + case TT_COPY_TO_RIGHT: + return markCopyToRight; + case TT_DELETE: + return markDeletable; + default: + return false; + } +} + +bool Synchronizer::markParentDirectories( SynchronizerFileItem *item ) +{ + if( item->parent() == 0 || item->parent()->isMarked() ) + return false; + + markParentDirectories( item->parent() ); + + item->parent()->setMarked( true ); + + fileCount++; + emit markChanged( item->parent(), false ); + return true; +} + +int Synchronizer::refresh(bool nostatus) +{ + fileCount = 0; + + SynchronizerFileItem *item = resultList.first(); + + while( item ) + { + bool marked = isMarked( item->task(), item->existsInLeft() && item->existsInRight() ); + item->setMarked( marked ); + + if( marked ) + { + markParentDirectories( item ); + fileCount++; + } + + item = resultList.next(); + } + + item = resultList.first(); + while( item ) + { + emit markChanged( item, false ); + item = resultList.next(); + } + + if( !nostatus ) + emit statusInfo( i18n( "Number of files: %1" ).arg( fileCount ) ); + + return fileCount; +} + +void Synchronizer::operate( SynchronizerFileItem *item, + void (*executeOperation)(SynchronizerFileItem *) ) +{ + executeOperation( item ); + + if( item->isDir() ) + { + TQString leftDirName = ( item->leftDirectory() == "" ) ? + item->leftName() : item->leftDirectory() + "/" + item->leftName() ; + TQString rightDirName = ( item->rightDirectory() == "" ) ? + item->rightName() : item->rightDirectory() + "/" + item->rightName() ; + + item = resultList.first(); + while( item ) + { + if( item->leftDirectory() == leftDirName || item->leftDirectory().startsWith( leftDirName + "/" ) || + item->rightDirectory() == rightDirName || item->rightDirectory().startsWith( rightDirName + "/" ) ) + executeOperation( item ); + + item = resultList.next(); + } + } +} + +void Synchronizer::excludeOperation( SynchronizerFileItem *item ) +{ + item->setTask( TT_DIFFERS ); +} + +void Synchronizer::exclude( SynchronizerFileItem *item ) +{ + if( !item->parent() || item->parent()->task() != TT_DELETE ) + operate( item, excludeOperation ); /* exclude only if the parent task is not DEL */ +} + +void Synchronizer::restoreOperation( SynchronizerFileItem *item ) +{ + item->restoreOriginalTask(); +} + +void Synchronizer::restore( SynchronizerFileItem *item ) +{ + operate( item, restoreOperation ); + + while( ( item = item->parent() ) != 0 ) /* in case of restore, the parent directories */ + { /* must be changed for being consistent */ + if( item->task() != TT_DIFFERS ) + break; + + if( item->originalTask() == TT_DELETE ) /* if the parent original task is delete */ + break; /* don't touch it */ + + item->restoreOriginalTask(); /* restore */ + } +} + +void Synchronizer::reverseDirectionOperation( SynchronizerFileItem *item ) +{ + if( item->existsInRight() && item->existsInLeft() ) + { + if( item->task() == TT_COPY_TO_LEFT ) + item->setTask( TT_COPY_TO_RIGHT ); + else if( item->task() == TT_COPY_TO_RIGHT ) + item->setTask( TT_COPY_TO_LEFT ); + } +} + +void Synchronizer::reverseDirection( SynchronizerFileItem *item ) +{ + operate( item, reverseDirectionOperation ); +} + +void Synchronizer::deleteLeftOperation( SynchronizerFileItem *item ) +{ + if( !item->existsInRight() && item->existsInLeft() ) + item->setTask( TT_DELETE ); +} + +void Synchronizer::deleteLeft( SynchronizerFileItem *item ) +{ + operate( item, deleteLeftOperation ); +} + +void Synchronizer::copyToLeftOperation( SynchronizerFileItem *item ) +{ + if( item->existsInRight() ) + { + if( !item->isDir() ) + item->setTask( TT_COPY_TO_LEFT ); + else + { + if( item->existsInLeft() && item->existsInRight() ) + item->setTask( TT_EQUALS ); + else if( !item->existsInLeft() && item->existsInRight() ) + item->setTask( TT_COPY_TO_LEFT ); + } + } +} + +void Synchronizer::copyToLeft( SynchronizerFileItem *item ) +{ + operate( item, copyToLeftOperation ); + + while( ( item = item->parent() ) != 0 ) + { + if( item->task() != TT_DIFFERS ) + break; + + if( item->existsInLeft() && item->existsInRight() ) + item->setTask( TT_EQUALS ); + else if( !item->existsInLeft() && item->existsInRight() ) + item->setTask( TT_COPY_TO_LEFT ); + } +} + +void Synchronizer::copyToRightOperation( SynchronizerFileItem *item ) +{ + if( item->existsInLeft() ) + { + if( !item->isDir() ) + item->setTask( TT_COPY_TO_RIGHT ); + else + { + if( item->existsInLeft() && item->existsInRight() ) + item->setTask( TT_EQUALS ); + else if( item->existsInLeft() && !item->existsInRight() ) + item->setTask( TT_COPY_TO_RIGHT ); + } + } +} + +void Synchronizer::copyToRight( SynchronizerFileItem *item ) +{ + operate( item, copyToRightOperation ); + + while( ( item = item->parent() ) != 0 ) + { + if( item->task() != TT_DIFFERS && item->task() != TT_DELETE ) + break; + + if( item->existsInLeft() && item->existsInRight() ) + item->setTask( TT_EQUALS ); + else if( item->existsInLeft() && !item->existsInRight() ) + item->setTask( TT_COPY_TO_RIGHT ); + } +} + +bool Synchronizer::totalSizes( int * leftCopyNr, TDEIO::filesize_t *leftCopySize, int * rightCopyNr, + TDEIO::filesize_t *rightCopySize, int *deleteNr, TDEIO::filesize_t *deletableSize ) +{ + bool hasAnythingToDo = false; + + *leftCopySize = *rightCopySize = *deletableSize = 0; + *leftCopyNr = *rightCopyNr = *deleteNr = 0; + + SynchronizerFileItem *item = resultList.first(); + + while( item ) + { + if( item->isMarked() ) + { + switch( item->task() ) + { + case TT_COPY_TO_LEFT: + *leftCopySize += item->rightSize(); + (*leftCopyNr)++; + hasAnythingToDo = true; + break; + case TT_COPY_TO_RIGHT: + *rightCopySize += item->leftSize(); + (*rightCopyNr)++; + hasAnythingToDo = true; + break; + case TT_DELETE: + *deletableSize += item->leftSize(); + (*deleteNr)++; + hasAnythingToDo = true; + break; + default: + break; + } + } + item = resultList.next(); + } + + return hasAnythingToDo; +} + +void Synchronizer::swapSides() +{ + TQString leftTmp = leftBaseDir; + leftBaseDir = rightBaseDir; + rightBaseDir = leftTmp; + + SynchronizerFileItem *item = resultList.first(); + + while( item ) + { + item->swap( asymmetric ); + item = resultList.next(); + } +} + +void Synchronizer::setScrolling( bool scroll ) +{ + if( autoScroll = scroll ) + { + int oldFileCount = fileCount; + refresh( true ); + fileCount = oldFileCount; + } +} + +void Synchronizer::synchronize( TQWidget *syncWdg, bool leftCopyEnabled, bool rightCopyEnabled, + bool deleteEnabled, bool overWrite, int parThreads ) +{ + this->leftCopyEnabled = leftCopyEnabled; + this->rightCopyEnabled = rightCopyEnabled; + this->deleteEnabled = deleteEnabled; + this->overWrite = overWrite; + this->parallelThreads = parThreads; + this->syncDlgWidget = syncWdg; + + autoSkip = paused = disableNewTasks = false; + + leftCopyNr = rightCopyNr = deleteNr = 0; + leftCopySize = rightCopySize = deleteSize = 0; + + inTaskFinished = 0; + lastTask = 0; + + jobMap.clear(); + receivedMap.clear(); + + resultList.first(); + synchronizeLoop(); +} + +void Synchronizer::synchronizeLoop() { + if( disableNewTasks ) { + if( resultList.current() == 0 && jobMap.count() == 0 ) + emit synchronizationFinished(); + return; + } + + while( (int)jobMap.count() < parallelThreads ) { + SynchronizerFileItem *task = getNextTask(); + if( task == 0 ) { + if( jobMap.count() == 0 ) + emit synchronizationFinished(); + return; + } + executeTask( task ); + if( disableNewTasks ) + break; + } +} + +SynchronizerFileItem * Synchronizer::getNextTask() { + TaskType task; + SynchronizerFileItem * currentTask = resultList.current(); + + do { + if( currentTask == 0 ) + return 0; + + if( currentTask->isMarked() ) + { + task = currentTask->task(); + + if( leftCopyEnabled && task == TT_COPY_TO_LEFT ) + break; + else if( rightCopyEnabled && task == TT_COPY_TO_RIGHT ) + break; + else if( deleteEnabled && task == TT_DELETE ) + break; + } + + currentTask = resultList.next(); + }while( true ); + + resultList.next(); + return lastTask = currentTask; +} + + +void Synchronizer::executeTask( SynchronizerFileItem * task ) +{ + TQString leftDirName = task->leftDirectory(); + if( !leftDirName.isEmpty() ) + leftDirName += "/"; + TQString rightDirName = task->rightDirectory(); + if( !rightDirName.isEmpty() ) + rightDirName += "/"; + + KURL leftURL = vfs::fromPathOrURL( leftBaseDir + leftDirName + task->leftName() ); + KURL rightURL = vfs::fromPathOrURL( rightBaseDir + rightDirName + task->rightName() ); + + switch( task->task() ) + { + case TT_COPY_TO_LEFT: + if( task->isDir() ) + { + TDEIO::SimpleJob *job = TDEIO::mkdir( leftURL ); + connect(job,TQ_SIGNAL(result(TDEIO::Job*)),this,TQ_SLOT(slotTaskFinished(TDEIO::Job*))); + jobMap[ job ] = task; + disableNewTasks = true; + } + else + { + KURL destURL( leftURL ); + if( !task->destination().isNull() ) + destURL = vfs::fromPathOrURL( task->destination() ); + + if( task->rightLink().isNull() ) { + TDEIO::FileCopyJob *job = TDEIO::file_copy(rightURL, destURL, -1, + overWrite || task->overWrite(), false, false ); + connect(job,TQ_SIGNAL(processedSize (TDEIO::Job *, TDEIO::filesize_t )), this, + TQ_SLOT (slotProcessedSize (TDEIO::Job *, TDEIO::filesize_t ))); + connect(job,TQ_SIGNAL(result(TDEIO::Job*)),this,TQ_SLOT(slotTaskFinished(TDEIO::Job*))); + jobMap[ job ] = task; + } else { + TDEIO::SimpleJob *job = TDEIO::symlink( task->rightLink(), destURL, + overWrite || task->overWrite(), false ); + connect(job,TQ_SIGNAL(result(TDEIO::Job*)),this,TQ_SLOT(slotTaskFinished(TDEIO::Job*))); + jobMap[ job ] = task; + } + } + break; + case TT_COPY_TO_RIGHT: + if( task->isDir() ) + { + TDEIO::SimpleJob *job = TDEIO::mkdir( rightURL ); + connect(job,TQ_SIGNAL(result(TDEIO::Job*)),this,TQ_SLOT(slotTaskFinished(TDEIO::Job*))); + jobMap[ job ] = task; + disableNewTasks = true; + } + else + { + KURL destURL( rightURL ); + if( !task->destination().isNull() ) + destURL = vfs::fromPathOrURL( task->destination() ); + + if( task->leftLink().isNull() ) { + TDEIO::FileCopyJob *job = TDEIO::file_copy(leftURL, destURL, -1, + overWrite || task->overWrite(), false, false ); + connect(job,TQ_SIGNAL(processedSize (TDEIO::Job *, TDEIO::filesize_t )), this, + TQ_SLOT (slotProcessedSize (TDEIO::Job *, TDEIO::filesize_t ))); + connect(job,TQ_SIGNAL(result(TDEIO::Job*)),this,TQ_SLOT(slotTaskFinished(TDEIO::Job*))); + jobMap[ job ] = task; + } else { + TDEIO::SimpleJob *job = TDEIO::symlink( task->leftLink(), destURL, + overWrite || task->overWrite(), false ); + connect(job,TQ_SIGNAL(result(TDEIO::Job*)),this,TQ_SLOT(slotTaskFinished(TDEIO::Job*))); + jobMap[ job ] = task; + } + } + break; + case TT_DELETE: + { + TDEIO::DeleteJob *job = TDEIO::del( leftURL, false ); + connect(job,TQ_SIGNAL(result(TDEIO::Job*)),this,TQ_SLOT(slotTaskFinished(TDEIO::Job*))); + jobMap[ job ] = task; + } + break; + default: + break; + } +} + +void Synchronizer::slotTaskFinished(TDEIO::Job *job ) +{ + inTaskFinished++; + + SynchronizerFileItem * item = jobMap[ job ]; + jobMap.remove( job ); + + TDEIO::filesize_t receivedSize = 0; + + if( receivedMap.contains( job ) ) { + receivedSize = receivedMap[ job ]; + receivedMap.remove( job ); + } + + if( disableNewTasks && item == lastTask ) + disableNewTasks = false; // the blocker task finished + + TQString leftDirName = item->leftDirectory().isEmpty() ? "" : item->leftDirectory() + "/"; + TQString rightDirName = item->rightDirectory().isEmpty() ? "" : item->rightDirectory() + "/"; + KURL leftURL = vfs::fromPathOrURL( leftBaseDir + leftDirName + item->leftName() ); + KURL rightURL = vfs::fromPathOrURL( rightBaseDir + rightDirName + item->rightName() ); + + do { + if( !job->error() ) + { + switch( item->task() ) + { + case TT_COPY_TO_LEFT: + if( leftURL.isLocalFile() ) + { + struct utimbuf timestamp; + + timestamp.actime = time( 0 ); + timestamp.modtime = item->rightDate() - timeOffset; + + utime( (const char *)( leftURL.path( -1 ).local8Bit() ), ×tamp ); + + uid_t newOwnerID = (uid_t)-1; // chown(2) : -1 means no change + if ( !item->rightOwner().isEmpty() ) + { + struct passwd* pw = getpwnam(TQFile::encodeName(item->rightOwner())); + if ( pw != 0L ) + newOwnerID = pw->pw_uid; + } + gid_t newGroupID = (gid_t)-1; // chown(2) : -1 means no change + if ( !item->rightGroup().isEmpty() ) + { + struct group* g = getgrnam(TQFile::encodeName(item->rightGroup())); + if ( g != 0L ) + newGroupID = g->gr_gid; + } + chown( (const char *)( leftURL.path( -1 ).local8Bit() ), newOwnerID, (gid_t)-1 ); + chown( (const char *)( leftURL.path( -1 ).local8Bit() ), (uid_t)-1, newGroupID ); + + chmod( (const char *)( leftURL.path( -1 ).local8Bit() ), item->rightMode() & 07777 ); + +#if KDE_IS_VERSION(3,5,0) && defined( HAVE_POSIX_ACL ) + if( !item->rightACL().isNull() ) + { + acl_t acl = acl_from_text( item->rightACL().latin1() ); + if( acl && !acl_valid( acl ) ) + acl_set_file( leftURL.path( -1 ).local8Bit(), ACL_TYPE_ACCESS, acl ); + if( acl ) + acl_free( acl ); + } +#endif + } + break; + case TT_COPY_TO_RIGHT: + if( rightURL.isLocalFile() ) + { + struct utimbuf timestamp; + + timestamp.actime = time( 0 ); + timestamp.modtime = item->leftDate() + timeOffset; + + utime( (const char *)( rightURL.path( -1 ).local8Bit() ), ×tamp ); + + uid_t newOwnerID = (uid_t)-1; // chown(2) : -1 means no change + if ( !item->leftOwner().isEmpty() ) + { + struct passwd* pw = getpwnam(TQFile::encodeName(item->leftOwner())); + if ( pw != 0L ) + newOwnerID = pw->pw_uid; + } + gid_t newGroupID = (gid_t)-1; // chown(2) : -1 means no change + if ( !item->leftGroup().isEmpty() ) + { + struct group* g = getgrnam(TQFile::encodeName(item->leftGroup())); + if ( g != 0L ) + newGroupID = g->gr_gid; + } + chown( (const char *)( rightURL.path( -1 ).local8Bit() ), newOwnerID, (uid_t)-1 ); + chown( (const char *)( rightURL.path( -1 ).local8Bit() ), (uid_t)-1, newGroupID ); + + chmod( (const char *)( rightURL.path( -1 ).local8Bit() ), item->leftMode() & 07777 ); + +#if KDE_IS_VERSION(3,5,0) && defined( HAVE_POSIX_ACL ) + if( !item->leftACL().isNull() ) + { + acl_t acl = acl_from_text( item->leftACL().latin1() ); + if( acl && !acl_valid( acl ) ) + acl_set_file( rightURL.path( -1 ).local8Bit(), ACL_TYPE_ACCESS, acl ); + if( acl ) + acl_free( acl ); + } +#endif + } + break; + default: + break; + } + } + else + { + if( job->error() == TDEIO::ERR_FILE_ALREADY_EXIST && item->task() != TT_DELETE ) + { + TDEIO::RenameDlg_Result result; + TQString newDest; + + if( autoSkip ) + break; + + if ( item->task() == TT_COPY_TO_LEFT ) + { + TQWidget *mainWidget = tqApp->mainWidget(); // WORKAROUND, don't give focus to the main widget + tqApp->setMainWidget( syncDlgWidget ); + + result = Observer::self()->open_RenameDlg ( job, i18n("File Already Exists"), + vfs::pathOrURL( rightURL ), vfs::pathOrURL( leftURL ), + (TDEIO::RenameDlg_Mode)( TDEIO::M_OVERWRITE | TDEIO::M_SKIP | TDEIO::M_MULTI ), newDest, + item->rightSize(), item->leftSize(), (time_t)-1, (time_t)-1, + item->rightDate(), item->leftDate()); + + tqApp->setMainWidget( mainWidget ); + } + else + { + TQWidget *mainWidget = tqApp->mainWidget(); // WORKAROUND, don't give focus to the main widget + tqApp->setMainWidget( syncDlgWidget ); + + result = Observer::self()->open_RenameDlg ( job, i18n("File Already Exists"), + vfs::pathOrURL( leftURL ), vfs::pathOrURL( rightURL ), + (TDEIO::RenameDlg_Mode)( TDEIO::M_OVERWRITE | TDEIO::M_SKIP | TDEIO::M_MULTI ), newDest, + item->leftSize(), item->rightSize(), (time_t)-1, (time_t)-1, + item->leftDate(), item->rightDate()); + + tqApp->setMainWidget( mainWidget ); + } + + switch ( result ) + { + case TDEIO::R_RENAME: + item->setDestination( newDest ); + executeTask( item ); + inTaskFinished--; + return; + case TDEIO::R_OVERWRITE: + item->setOverWrite(); + executeTask( item ); + inTaskFinished--; + return; + case TDEIO::R_OVERWRITE_ALL: + overWrite = true; + executeTask( item ); + inTaskFinished--; + return; + case TDEIO::R_AUTO_SKIP: + autoSkip = true; + case TDEIO::R_SKIP: + default: + break; + } + break; + } + + if( job->error() != TDEIO::ERR_DOES_NOT_EXIST || item->task() != TT_DELETE ) + { + if( autoSkip ) + break; + + TQString error; + + switch( item->task() ) + { + case TT_COPY_TO_LEFT: + error = i18n("Error at copying file %1 to %2!") + .arg( vfs::pathOrURL( rightURL ) ) + .arg( vfs::pathOrURL( leftURL ) ); + break; + case TT_COPY_TO_RIGHT: + error = i18n("Error at copying file %1 to %2!") + .arg( vfs::pathOrURL( leftURL ) ) + .arg( vfs::pathOrURL( rightURL ) ); + break; + case TT_DELETE: + error = i18n("Error at deleting file %1!").arg( vfs::pathOrURL( leftURL ) ); + break; + default: + break; + } + + TQWidget *mainWidget = tqApp->mainWidget(); // WORKAROUND, don't give focus to the main widget + tqApp->setMainWidget( syncDlgWidget ); + + TDEIO::SkipDlg_Result result = Observer::self()->open_SkipDlg( job, true, error ); + + tqApp->setMainWidget( mainWidget ); + + switch( result ) + { + case TDEIO::S_CANCEL: + executeTask( item ); /* simply retry */ + inTaskFinished--; + return; + case TDEIO::S_AUTO_SKIP: + autoSkip = true; + default: + break; + } + } + } + }while( false ); + + switch( item->task() ) + { + case TT_COPY_TO_LEFT: + leftCopyNr++; + leftCopySize += item->rightSize() - receivedSize; + break; + case TT_COPY_TO_RIGHT: + rightCopyNr++; + rightCopySize += item->leftSize() - receivedSize; + break; + case TT_DELETE: + deleteNr++; + deleteSize += item->leftSize() - receivedSize; + break; + default: + break; + } + + emit processedSizes( leftCopyNr, leftCopySize, rightCopyNr, rightCopySize, deleteNr, deleteSize ); + + if( --inTaskFinished == 0 ) { + if( paused ) + emit pauseAccepted(); + else + synchronizeLoop(); + } +} + +void Synchronizer::slotProcessedSize( TDEIO::Job * job , TDEIO::filesize_t size) +{ + TDEIO::filesize_t dl = 0, dr = 0, dd = 0; + SynchronizerFileItem * item = jobMap[ job ]; + + TDEIO::filesize_t lastProcessedSize = 0; + if( receivedMap.contains( job ) ) + lastProcessedSize = receivedMap[ job ]; + + receivedMap[ job ] = size; + + switch( item->task() ) + { + case TT_COPY_TO_LEFT: + dl = size - lastProcessedSize; + break; + case TT_COPY_TO_RIGHT: + dr = size - lastProcessedSize; + break; + case TT_DELETE: + dd = size - lastProcessedSize; + break; + default: + break; + } + + emit processedSizes( leftCopyNr, leftCopySize+=dl, rightCopyNr, rightCopySize+=dr, deleteNr, deleteSize+=dd ); +} + +void Synchronizer::pause() +{ + paused = true; +} + +void Synchronizer::resume() +{ + paused = false; + synchronizeLoop(); +} + +TQString Synchronizer::leftBaseDirectory() +{ + return leftBaseDir; +} + +TQString Synchronizer::rightBaseDirectory() +{ + return rightBaseDir; +} + +class KgetProgressDialog : public KDialogBase +{ +public: + KgetProgressDialog( TQWidget *parent=0, const char *name=0, const TQString &caption=TQString(), + const TQString &text=TQString(), bool modal=false) : KDialogBase( KDialogBase::Plain, + caption, KDialogBase::User1 | KDialogBase::Cancel, KDialogBase::Cancel, parent, name, modal ) + { + showButton(KDialogBase::Close, false); + + TQFrame* mainWidget = plainPage(); + TQVBoxLayout* layout = new TQVBoxLayout(mainWidget, 10); + + TQLabel *mLabel = new TQLabel(text, mainWidget); + layout->addWidget(mLabel); + + mProgressBar = new KProgress(mainWidget); + layout->addWidget(mProgressBar); + + setButtonText( KDialogBase::User1, i18n( "Pause" ) ); + + mCancelled = mPaused = false; + } + + KProgress *progressBar() { return mProgressBar; } + + void slotUser1() + { + if( ( mPaused = !mPaused ) == false ) + setButtonText( KDialogBase::User1, i18n( "Pause" ) ); + else + setButtonText( KDialogBase::User1, i18n( "Resume" ) ); + } + + void slotCancel() + { + mCancelled = true; + + KDialogBase::slotCancel(); + } + + bool wasCancelled() { return mCancelled; } + bool isPaused() { return mPaused; } + +private: + KProgress *mProgressBar; + bool mCancelled; + bool mPaused; +}; + + +void Synchronizer::synchronizeWithKGet() +{ + bool isLeftLocal = vfs::fromPathOrURL( leftBaseDirectory() ).isLocalFile(); + KgetProgressDialog *progDlg = 0; + int processedCount = 0, totalCount = 0; + + SynchronizerFileItem *item = resultList.first(); + for(; item; item = resultList.next() ) + if( item->isMarked() ) + totalCount++; + + item = resultList.first(); + while( item ) + { + if( item->isMarked() ) + { + KURL downloadURL, destURL; + TQString leftDirName = item->leftDirectory().isEmpty() ? "" : item->leftDirectory() + "/"; + TQString rightDirName = item->rightDirectory().isEmpty() ? "" : item->rightDirectory() + "/"; + TQString destDir; + + if( progDlg == 0 ) + { + progDlg = new KgetProgressDialog( krApp, "Synchronizer Progress Dlg", i18n("Krusader::Synchronizer"), + i18n( "Feeding the URLs to Kget" ), true ); + progDlg->progressBar()->setTotalSteps( totalCount ); + progDlg->show(); + tqApp->processEvents(); + } + + if( item->task() == TT_COPY_TO_RIGHT && !isLeftLocal ) + { + downloadURL = vfs::fromPathOrURL( leftBaseDirectory() + leftDirName + item->leftName() ); + destDir = rightBaseDirectory() + rightDirName; + destURL = vfs::fromPathOrURL( destDir + item->rightName() ); + + if( item->isDir() ) + destDir += item->leftName(); + } + if( item->task() == TT_COPY_TO_LEFT && isLeftLocal ) + { + downloadURL = vfs::fromPathOrURL( rightBaseDirectory() + rightDirName + item->rightName() ); + destDir = leftBaseDirectory() + leftDirName; + destURL = vfs::fromPathOrURL( destDir + item->leftName() ); + + if( item->isDir() ) + destDir += item->rightName(); + } + + // creating the directory system + for( int i=0; i >= 0 ; i= destDir.find('/',i+1) ) + if( !TQDir( destDir.left(i) ).exists() ) + TQDir().mkdir( destDir.left(i) ); + + if( !item->isDir() && !downloadURL.isEmpty() ) + { + if( TQFile( destURL.path() ).exists() ) + TQFile( destURL.path() ).remove(); + + TQString source = downloadURL.prettyURL(); + if( source.contains( '@' ) >= 2 ) /* is this an ftp proxy URL? */ + { + int lastAt = source.findRev( '@' ); + TQString startString = source.left( lastAt ); + TQString endString = source.mid( lastAt ); + startString.replace( "@", "%40" ); + source = startString+endString; + } + + TDEProcess p; + + p << KrServices::fullPathName( "kget" ) << source << destURL.path(); + if (!p.start(TDEProcess::Block)) + KMessageBox::error(parentWidget,i18n("Error executing ")+KrServices::fullPathName( "kget" )+" !"); + else + p.detach(); + } + + progDlg->progressBar()->setProgress( ++processedCount ); + + do + { + tqApp->processEvents(); + + if( progDlg->wasCancelled() ) + break; + + if( progDlg->isPaused() ) + usleep( 100000 ); + + }while( progDlg->isPaused() ); + + if( progDlg->wasCancelled() ) + break; + } + item = resultList.next(); + } + + if( progDlg ) + delete progDlg; +} + +bool Synchronizer::isDir( const vfile * file ) { + if( followSymLinks ) { + return file->vfile_isDir(); + } + else { + return file->vfile_isDir() && !file->vfile_isSymLink(); + } +} + +TQString Synchronizer::readLink( const vfile * file ) { + if( file->vfile_isSymLink() ) + return file->vfile_getSymDest(); + else + return TQString(); +} + +#include "synchronizer.moc" diff --git a/src/app/Synchronizer/synchronizer.h b/src/app/Synchronizer/synchronizer.h new file mode 100644 index 0000000..01f85ec --- /dev/null +++ b/src/app/Synchronizer/synchronizer.h @@ -0,0 +1,205 @@ +/*************************************************************************** + synchronizer.h - description + ------------------- + copyright : (C) 2003 + 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 + + H e a d e r 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. * + * * + ***************************************************************************/ + +#ifndef __SYNCHRONIZER_H__ +#define __SYNCHRONIZER_H__ + +#include "synchronizertask.h" +#include "synchronizerfileitem.h" +#include <tqobject.h> +#include <tqptrvector.h> +#include <tqmap.h> +#include <tqcolor.h> +#include <tdeio/job.h> + +class KRQuery; +class vfile; + +#define DECLARE_COLOR_NAME_ARRAY TQString COLOR_NAMES[] = { "Equals", "Differs", "LeftCopy", "RightCopy", "Delete", \ + "Equals", "Equals", "Equals", "Equals", "Equals" } +#define DECLARE_BACKGROUND_DFLTS TQColor BCKG_DFLTS[] = { TQColor(), TQColor(), TQColor(), TQColor(), TQt::red, \ + TQColor(), TQColor(), TQColor(), TQColor(), TQColor() } +#define DECLARE_FOREGROUND_DFLTS TQColor FORE_DFLTS[] = { TQt::black, TQt::red, TQt::blue, TQt::darkGreen, TQt::white, \ + TQt::black, TQt::black, TQt::black, TQt::black, TQt::black } + +class Synchronizer : public TQObject +{ + TQ_OBJECT + + + private: + int displayUpdateCount; // the display is refreshed after every x-th change + + public: + Synchronizer(); + int compare( TQString leftURL, TQString rightURL, KRQuery *query, bool subDirs, bool symLinks, + bool igDate, bool asymm, bool cmpByCnt, bool igCase, bool autoSc, TQStringList &selFiles, + int equThres, int timeOffs, int parThreads, bool hiddenFiles ); + void stop() {stopped = true;} + void setMarkFlags( bool left, bool equal, bool differs, bool right, bool dup, bool sing, bool del ); + int refresh( bool nostatus=false ); + bool totalSizes( int *, TDEIO::filesize_t *, int *, TDEIO::filesize_t *, int *, TDEIO::filesize_t * ); + void synchronize( TQWidget *,bool leftCopyEnabled, bool rightCopyEnabled, bool deleteEnabled, + bool overWrite, int parThreads ); + void synchronizeWithKGet(); + void setScrolling( bool scroll ); + void pause(); + void resume(); + void swapSides(); + void reset(); + + void exclude( SynchronizerFileItem * ); + void restore( SynchronizerFileItem * ); + void reverseDirection( SynchronizerFileItem * ); + void copyToLeft( SynchronizerFileItem * ); + void copyToRight( SynchronizerFileItem * ); + void deleteLeft( SynchronizerFileItem * ); + + TQString leftBaseDirectory(); + TQString rightBaseDirectory(); + static TQString getTaskTypeName( TaskType taskType ); + + SynchronizerFileItem *getItemAt( unsigned ndx ) {return resultList.at(ndx);} + + void setParentWidget( TQWidget * widget ) {parentWidget = widget;} + void compareContentResult( SynchronizerFileItem * item, bool result ); + + signals: + void comparedFileData( SynchronizerFileItem * ); + void markChanged( SynchronizerFileItem *, bool ); + void synchronizationFinished(); + void processedSizes( int, TDEIO::filesize_t, int, TDEIO::filesize_t, int, TDEIO::filesize_t ); + void pauseAccepted(); + void statusInfo( TQString ); + + public slots: + void slotTaskFinished(TDEIO::Job*); + void slotProcessedSize( TDEIO::Job * , TDEIO::filesize_t ); + + private: + bool isDir( const vfile * file ); + TQString readLink( const vfile * file ); + + void compareDirectory( SynchronizerFileItem *,SynchronizerDirList *, SynchronizerDirList *, + const TQString &leftDir, const TQString &rightDir ); + void addSingleDirectory( SynchronizerFileItem *, SynchronizerDirList *, const TQString &, bool ); + SynchronizerFileItem * addItem( SynchronizerFileItem *, const TQString &, const TQString &, + const TQString &, const TQString &, bool, bool, TDEIO::filesize_t, + TDEIO::filesize_t, time_t, time_t, const TQString &, const TQString &, + const TQString &, const TQString &, const TQString &, const TQString &, + mode_t, mode_t, const TQString &, const TQString &, TaskType, bool, bool); + SynchronizerFileItem * addLeftOnlyItem( SynchronizerFileItem *, const TQString &, const TQString &, + TDEIO::filesize_t, time_t, const TQString &, const TQString &, + const TQString &, mode_t, const TQString &, bool isDir = false, bool isTemp = false ); + SynchronizerFileItem * addRightOnlyItem( SynchronizerFileItem *, const TQString &, const TQString &, + TDEIO::filesize_t, time_t, const TQString &, const TQString &, + const TQString &, mode_t, const TQString &, bool isDir = false, bool isTemp = false ); + SynchronizerFileItem * addDuplicateItem( SynchronizerFileItem *, const TQString &, const TQString &, + const TQString &, const TQString &, TDEIO::filesize_t, + TDEIO::filesize_t, time_t, time_t, const TQString &, + const TQString &, const TQString &, const TQString &, + const TQString &, const TQString &, mode_t, mode_t, const TQString &, + const TQString &, bool isDir = false, bool isTemp = false ); + bool isMarked( TaskType task, bool dupl ); + bool markParentDirectories( SynchronizerFileItem * ); + void synchronizeLoop(); + SynchronizerFileItem * getNextTask(); + void executeTask( SynchronizerFileItem * task ); + void setPermanent( SynchronizerFileItem * ); + void operate( SynchronizerFileItem *item, void (*)(SynchronizerFileItem *) ); + void compareLoop(); + + static void excludeOperation( SynchronizerFileItem *item ); + static void restoreOperation( SynchronizerFileItem *item ); + static void reverseDirectionOperation( SynchronizerFileItem *item ); + static void copyToLeftOperation( SynchronizerFileItem *item ); + static void copyToRightOperation( SynchronizerFileItem *item ); + static void deleteLeftOperation( SynchronizerFileItem *item ); + + protected: + bool recurseSubDirs; // walk through subdirectories also + bool followSymLinks; // follow the symbolic links + bool ignoreDate; // don't use date info at comparing + bool asymmetric; // asymmetric directory update + bool cmpByContent; // compare the files by content + bool ignoreCase; // case insensitive synchronization for Windows fs + bool autoScroll; // automatic update of the directory + TQPtrList<SynchronizerFileItem> resultList; // the found files + TQPtrList<SynchronizerFileItem> temporaryList; // temporary files + TQString leftBaseDir; // the left-side base directory + TQString rightBaseDir; // the right-side base directory + TQStringList excludedPaths; // list of the excluded paths + KRQuery *query; // the filter used for the query + bool stopped; // 'Stop' button was pressed + + int equalsThreshold;// threshold to treat files equal + int timeOffset; // time offset between the left and right sides + bool ignoreHidden; // ignores the hidden files + + bool markEquals; // show the equal files + bool markDiffers; // show the different files + bool markCopyToLeft; // show the files to copy from right to left + bool markCopyToRight;// show the files to copy from left to right + bool markDeletable; // show the files to be deleted + bool markDuplicates; // show the duplicated items + bool markSingles; // show the single items + + bool leftCopyEnabled;// copy to left is enabled at synchronize + bool rightCopyEnabled;// copy to right is enabled at synchronize + bool deleteEnabled; // delete is enabled at synchronize + bool overWrite; // overwrite or query each modification + bool autoSkip; // automatic skipping + bool paused; // pause flag + bool disableNewTasks;// at mkdir the further task creation is disabled + + int leftCopyNr; // the file number copied to left + int rightCopyNr; // the file number copied to right + int deleteNr; // the number of the deleted files + int parallelThreads;// the number of the parallel procesing threads + TDEIO::filesize_t leftCopySize; // the total size copied to left + TDEIO::filesize_t rightCopySize; // the total size copied to right + TDEIO::filesize_t deleteSize; // the size of the deleted files + + int comparedDirs; // the number of the compared directories + int fileCount; // the number of counted files + + private: + TQPtrList<SynchronizerTask> stack; // stack for comparing + TQMap<TDEIO::Job *,SynchronizerFileItem *> jobMap; // job maps + TQMap<TDEIO::Job *,TDEIO::filesize_t> receivedMap; // the received file size + SynchronizerFileItem *lastTask; // reference to the last stack + int inTaskFinished; // counter of quasy 'threads' in slotTaskFinished + + TQStringList selectedFiles; // the selected files to compare + TQWidget *parentWidget; // the parent widget + TQWidget *syncDlgWidget; // the synchronizer dialog widget +}; + +#endif /* __SYNCHRONIZER_H__ */ diff --git a/src/app/Synchronizer/synchronizerdirlist.cpp b/src/app/Synchronizer/synchronizerdirlist.cpp new file mode 100644 index 0000000..95bc89a --- /dev/null +++ b/src/app/Synchronizer/synchronizerdirlist.cpp @@ -0,0 +1,216 @@ +/*************************************************************************** + synchronizerdirlist.cpp - description + ------------------- + copyright : (C) 2006 + 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 + + H e a d e r 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 "synchronizerdirlist.h" +#include "../VFS/vfs.h" +#include "../VFS/krpermhandler.h" +#include <dirent.h> +#include <tdelocale.h> +#include <tdemessagebox.h> +#include <tdefileitem.h> +#include <klargefile.h> +#include <tqapplication.h> +#include <tqdir.h> +#include <tdeversion.h> + + +#if KDE_IS_VERSION(3,5,0) && defined( HAVE_POSIX_ACL ) +#include <sys/acl.h> +#ifdef HAVE_NON_POSIX_ACL_EXTENSIONS +#include <acl/libacl.h> +#endif +#endif + +SynchronizerDirList::SynchronizerDirList( TQWidget *w, bool hidden ) : TQObject(), TQDict<vfile>(), fileIterator( 0 ), + parentWidget( w ), busy( false ), result( false ), ignoreHidden( hidden ), currentUrl() { + setAutoDelete( true ); +} + +SynchronizerDirList::~SynchronizerDirList() { + if( fileIterator ) + delete fileIterator; +} + +vfile * SynchronizerDirList::search( const TQString &name, bool ignoreCase ) { + if( !ignoreCase ) + return (*this)[ name ]; + + vfile *item = first(); + TQString file = name.lower(); + + while( item ) + { + if( file == item->vfile_getName().lower() ) + return item; + item = next(); + } + return 0; +} + +vfile * SynchronizerDirList::first() { + return fileIterator->toFirst(); +} + +vfile * SynchronizerDirList::next() { + return ++(*fileIterator); +} + +bool SynchronizerDirList::load( const TQString &urlIn, bool wait ) { + if( busy ) + return false; + + currentUrl = urlIn; + KURL url = vfs::fromPathOrURL( urlIn ); + + if( fileIterator == 0 ) + fileIterator = new TQDictIterator<vfile> ( *this ); + + clear(); + + if( url.isLocalFile() ) { + TQString path = url.path( -1 ); + DIR* dir = opendir(path.local8Bit()); + if(!dir) { + KMessageBox::error(parentWidget, i18n("Can't open the %1 directory!").arg( path ), i18n("Error")); + emit finished( result = false ); + return false; + } + + struct dirent* dirEnt; + TQString name; + + while( (dirEnt=readdir(dir)) != NULL ){ + name = TQString::fromLocal8Bit(dirEnt->d_name); + + if (name=="." || name == "..") continue; + if (ignoreHidden && name.startsWith( "." ) ) continue; + + TQString fullName = path + "/" + name; + + KDE_struct_stat stat_p; + KDE_lstat(fullName.local8Bit(),&stat_p); + + TQString perm = KRpermHandler::mode2TQString(stat_p.st_mode); + + bool symLink= S_ISLNK(stat_p.st_mode); + TQString symlinkDest; + + if( symLink ){ // who the link is pointing to ? + char symDest[256]; + bzero(symDest,256); + int endOfName=0; + endOfName=readlink(fullName.local8Bit(),symDest,256); + if ( endOfName != -1 ) { + TQString absSymDest = symlinkDest = TQString::fromLocal8Bit( symDest ); + + if( !absSymDest.startsWith( "/" ) ) + absSymDest = TQDir::cleanDirPath( path + "/" + absSymDest ); + + if ( TQDir( absSymDest ).exists() ) + perm[0] = 'd'; + } + } + + TQString mime = TQString(); + + KURL fileURL = KURL::fromPathOrURL( fullName ); + + vfile* item=new vfile(name,stat_p.st_size,perm,stat_p.st_mtime,symLink,stat_p.st_uid, + stat_p.st_gid,mime,symlinkDest,stat_p.st_mode); + item->vfile_setUrl( fileURL ); + + insert( name, item ); + } + + closedir( dir ); + emit finished( result = true ); + return true; + } else { + TDEIO::Job *job = TDEIO::listDir( url, false, true ); + connect( job, TQ_SIGNAL( entries( TDEIO::Job*, const TDEIO::UDSEntryList& ) ), + this, TQ_SLOT( slotEntries( TDEIO::Job*, const TDEIO::UDSEntryList& ) ) ); + connect( job, TQ_SIGNAL( result( TDEIO::Job* ) ), + this, TQ_SLOT( slotListResult( TDEIO::Job* ) ) ); + busy = true; + + if( !wait ) + return true; + + while( busy ) + tqApp->processEvents(); + return result; + } +} + +void SynchronizerDirList::slotEntries( TDEIO::Job * job, const TDEIO::UDSEntryList& entries ) +{ + TDEIO::UDSEntryListConstIterator it = entries.begin(); + TDEIO::UDSEntryListConstIterator end = entries.end(); + + int rwx = -1; + TQString prot = (( TDEIO::ListJob *)job )->url().protocol(); + + if( prot == "krarc" || prot == "tar" || prot == "zip" ) + rwx = PERM_ALL; + + while( it != end ) + { + KFileItem kfi( *it, (( TDEIO::ListJob *)job )->url(), true, true ); + TQString key = kfi.text(); + if( key != "." && key != ".." && (!ignoreHidden || !key.startsWith(".") ) ) { + mode_t mode = kfi.mode() | kfi.permissions(); + TQString perm = KRpermHandler::mode2TQString( mode ); + if ( kfi.isDir() ) + perm[ 0 ] = 'd'; + + vfile *item = new vfile( kfi.text(), kfi.size(), perm, kfi.time( TDEIO::UDS_MODIFICATION_TIME ), + kfi.isLink(), kfi.user(), kfi.group(), kfi.user(), + kfi.mimetype(), kfi.linkDest(), mode, rwx +#if KDE_IS_VERSION(3,5,0) && defined( HAVE_POSIX_ACL ) + , kfi.ACL().asString() +#endif + ); + insert( key, item ); + } + ++it; + } +} + +void SynchronizerDirList::slotListResult( TDEIO::Job *job ) { + busy = false; + if ( job && job->error() ) { + job->showErrorDialog( parentWidget ); + emit finished( result = false ); + return; + } + emit finished( result = true ); +} + +#include "synchronizerdirlist.moc" diff --git a/src/app/Synchronizer/synchronizerdirlist.h b/src/app/Synchronizer/synchronizerdirlist.h new file mode 100644 index 0000000..9361a89 --- /dev/null +++ b/src/app/Synchronizer/synchronizerdirlist.h @@ -0,0 +1,73 @@ +/*************************************************************************** + synchronizerdirlist.h - description + ------------------- + copyright : (C) 2006 + 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 + + H e a d e r 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. * + * * + ***************************************************************************/ + +#ifndef __SYNCHRONIZER_DIR_LIST_H__ +#define __SYNCHRONIZER_DIR_LIST_H__ + +#include <tqobject.h> +#include <tqdict.h> +#include "../VFS/vfile.h" +#include <tdeio/job.h> + + +class SynchronizerDirList : public TQObject, public TQDict<vfile> +{ + TQ_OBJECT + + +public: + SynchronizerDirList( TQWidget *w, bool ignoreHidden ); + ~SynchronizerDirList(); + + vfile * search( const TQString &name, bool ignoreCase = false ); + vfile * first(); + vfile * next(); + + inline const TQString & url() { return currentUrl; } + bool load( const TQString &urlIn, bool wait=false ); + +public slots: + + void slotEntries( TDEIO::Job * job, const TDEIO::UDSEntryList& entries ); + void slotListResult( TDEIO::Job *job ); + +signals: + void finished( bool err ); + +private: + TQDictIterator<vfile> *fileIterator; //< Point to a dictionary of virtual files (vfile). + TQWidget *parentWidget; + bool busy; + bool result; + bool ignoreHidden; + TQString currentUrl; +}; + +#endif /* __SYNCHRONIZER_DIR_LIST_H__ */ diff --git a/src/app/Synchronizer/synchronizerfileitem.h b/src/app/Synchronizer/synchronizerfileitem.h new file mode 100644 index 0000000..715fcc5 --- /dev/null +++ b/src/app/Synchronizer/synchronizerfileitem.h @@ -0,0 +1,170 @@ +/*************************************************************************** + synchronizerfileitem.h - description + ------------------- + copyright : (C) 2006 + 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 + + H e a d e r 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. * + * * + ***************************************************************************/ + +#ifndef __SYNCHRONIZER_FILE_ITEM_H__ +#define __SYNCHRONIZER_FILE_ITEM_H__ + +#include <tqstring.h> +#include <tdeio/global.h> + +typedef enum +{ + TT_EQUALS = 0, // the files are equals -> do nothing + TT_DIFFERS = 1, // the files are differents -> don't know what to do + TT_COPY_TO_LEFT = 2, // the right file is newer -> copy from right to left + TT_COPY_TO_RIGHT = 3, // the left file is newer -> copy from left to right + TT_DELETE = 4, // the left file is single -> delete it + TT_UNKNOWN = 5, // (5-9) the type of the task is not yet known + TT_MAX = 10 // the maximum number of task types +} TaskType; + +#define SWAP( A, B, TYPE ) {TYPE TMP = A; A = B; B = TMP;} +#define REVERSE_TASK( A, asym ) {switch( A ) \ + { \ + case TT_COPY_TO_LEFT: \ + if( asym ) \ + A = !m_existsRight ? TT_DELETE : TT_COPY_TO_LEFT; \ + else \ + A = TT_COPY_TO_RIGHT; \ + break; \ + case TT_COPY_TO_RIGHT: \ + case TT_DELETE: \ + A = TT_COPY_TO_LEFT; \ + default: \ + break; \ + }}; + +class SynchronizerFileItem +{ + private: + TQString m_leftName; // the left file name + TQString m_rightName; // the right file name + TQString m_leftDirectory;// the left relative directory path from the base + TQString m_rightDirectory;// the left relative directory path from the base + bool m_marked; // flag, indicates to show the file + bool m_existsLeft; // flag, the file exists in the left directory + bool m_existsRight; // flag, the file exists in the right directory + TDEIO::filesize_t m_leftSize; // the file size at the left directory + TDEIO::filesize_t m_rightSize; // the file size at the right directory + time_t m_leftDate; // the file date at the left directory + time_t m_rightDate; // the file date at the left directory + TQString m_leftLink; // the left file's symbolic link destination + TQString m_rightLink; // the right file's symbolic link destination + TQString m_leftOwner; // the left file's owner + TQString m_rightOwner; // the right file's owner + TQString m_leftGroup; // the left file's group + TQString m_rightGroup; // the right file's group + mode_t m_leftMode; // mode for left + mode_t m_rightMode; // mode for right + TQString m_leftACL; // ACL of the left file + TQString m_rightACL; // ACL of the right file + TaskType m_task; // the task with the file + bool m_isDir; // flag, indicates that the file is a directory + SynchronizerFileItem *m_parent; // pointer to the parent directory item or 0 + void *m_userData; // user data + bool m_overWrite; // overwrite flag + TQString m_destination; // the destination URL at rename + bool m_temporary; // flag indicates temporary directory + TaskType m_originalTask; // the original task type + + public: + SynchronizerFileItem(const TQString &leftNam, const TQString &rightNam, const TQString &leftDir, + const TQString &rightDir, bool mark, bool exL, bool exR, TDEIO::filesize_t leftSize, + TDEIO::filesize_t rightSize, time_t leftDate, time_t rightDate, + const TQString &leftLink, const TQString &rightLink, const TQString &leftOwner, + const TQString &rightOwner, const TQString &leftGroup, const TQString &rightGroup, + mode_t leftMode, mode_t rightMode, const TQString &leftACL, const TQString &rightACL, + TaskType tsk, bool isDir, bool tmp, SynchronizerFileItem *parent ) : + m_leftName( leftNam ), m_rightName( rightNam ), m_leftDirectory( leftDir ), m_rightDirectory( rightDir ), + m_marked( mark ), m_existsLeft( exL ), m_existsRight( exR ), m_leftSize( leftSize ), + m_rightSize( rightSize ), m_leftDate( leftDate ), m_rightDate( rightDate ), + m_leftLink( leftLink ), m_rightLink( rightLink ), m_leftOwner( leftOwner ), + m_rightOwner( rightOwner ), m_leftGroup( leftGroup ), m_rightGroup( rightGroup ), + m_leftMode( leftMode ), m_rightMode( rightMode ), m_leftACL( leftACL ), + m_rightACL( rightACL ), m_task( tsk ), m_isDir( isDir ), m_parent(parent), + m_userData( 0 ), m_overWrite( false ), m_destination( TQString() ), + m_temporary( tmp ), m_originalTask( tsk ) {} + + inline bool isMarked() {return m_marked;} + inline void setMarked( bool flag ) {m_marked = flag;} + inline const TQString & leftName() {return m_leftName;} + inline const TQString & rightName() {return m_rightName;} + inline const TQString & leftDirectory() {return m_leftDirectory;} + inline const TQString & rightDirectory() {return m_rightDirectory;} + inline bool existsInLeft() {return m_existsLeft;} + inline bool existsInRight() {return m_existsRight;} + inline bool overWrite() {return m_overWrite;} + inline TDEIO::filesize_t leftSize() {return m_leftSize;} + inline TDEIO::filesize_t rightSize() {return m_rightSize;} + inline time_t leftDate() {return m_leftDate;} + inline time_t rightDate() {return m_rightDate;} + inline const TQString & leftLink() {return m_leftLink;} + inline const TQString & rightLink() {return m_rightLink;} + inline const TQString & leftOwner() {return m_leftOwner;} + inline const TQString & rightOwner() {return m_rightOwner;} + inline const TQString & leftGroup() {return m_leftGroup;} + inline const TQString & rightGroup() {return m_rightGroup;} + inline mode_t leftMode() {return m_leftMode;} + inline mode_t rightMode() {return m_rightMode;} + inline const TQString & leftACL() {return m_leftACL;} + inline const TQString & rightACL() {return m_rightACL;} + inline TaskType task() {return m_task;} + inline void compareContentResult( bool res ) + {if( res == true ) + m_task = m_originalTask = TT_EQUALS; + else if( m_originalTask >= TT_UNKNOWN ) + m_task = m_originalTask = (TaskType)(m_originalTask - TT_UNKNOWN); + } + inline bool isDir() {return m_isDir;} + inline SynchronizerFileItem * parent() {return m_parent;} + inline void * userData() {return m_userData;} + inline void setUserData( void *ud) {m_userData = ud;} + inline void setOverWrite() {m_overWrite = true;} + inline const TQString & destination() {return m_destination;} + inline void setDestination(TQString d) {m_destination = d;} + inline bool isTemporary() {return m_temporary;} + inline void setPermanent() {m_temporary = false;} + inline TaskType originalTask() {return m_originalTask;} + inline void restoreOriginalTask() {m_task = m_originalTask;} + inline void setTask( TaskType t ) {m_task = t;} + inline void swap( bool asym=false ) {SWAP( m_existsLeft, m_existsRight, bool ); + SWAP( m_leftName, m_rightName, TQString ); + SWAP( m_leftDirectory, m_rightDirectory, TQString ); + SWAP( m_leftSize, m_rightSize, TDEIO::filesize_t ); + SWAP( m_leftDate, m_rightDate, time_t ); + SWAP( m_leftLink, m_rightLink, TQString ); + SWAP( m_leftOwner, m_rightOwner, TQString ); + SWAP( m_leftGroup, m_rightGroup, TQString ); + SWAP( m_leftACL, m_rightACL, TQString ); + REVERSE_TASK( m_originalTask, asym ); + REVERSE_TASK( m_task, asym );} +}; + +#endif /* __SYNCHRONIZER_FILE_ITEM_H__ */ diff --git a/src/app/Synchronizer/synchronizergui.cpp b/src/app/Synchronizer/synchronizergui.cpp new file mode 100644 index 0000000..3a0d2b4 --- /dev/null +++ b/src/app/Synchronizer/synchronizergui.cpp @@ -0,0 +1,2478 @@ +/*************************************************************************** + synchronizergui.cpp - description + ------------------- + copyright : (C) 2003 + 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 "synchronizergui.h" +#include "../krusader.h" +#include "../defaults.h" +#include "../VFS/krpermhandler.h" +#include "../KViewer/krviewer.h" +#include "../Dialogs/krspwidgets.h" +#include "../VFS/krquery.h" +#include "../krservices.h" +#include "../krslots.h" +#include "../kicons.h" +#include "synchronizedialog.h" +#include "feedtolistboxdialog.h" +#include <tqlayout.h> +#include <kurlrequester.h> +#include <tdelocale.h> +#include <tqgrid.h> +#include <tdepopupmenu.h> +#include <tqcursor.h> +#include <time.h> +#include <tdemessagebox.h> +#include <tdeio/netaccess.h> +#include <tqeventloop.h> +#include <tqwhatsthis.h> +#include <tqregexp.h> +#include <tqheader.h> +#include <tqspinbox.h> +#include <kinputdialog.h> +#include <kurldrag.h> +#include <tqclipboard.h> + +static const char * const right_arrow_button_data[] = { +"18 18 97 2", +" c None", +". c #000000", +"+ c #030D03", +"@ c #184F16", +"# c #5DB45A", +"$ c #2E6C2A", +"% c #90D28D", +"& c #9CD59A", +"* c #32732E", +"= c #92CF8F", +"- c #BDE9BB", +"; c #C4E5C3", +"> c #447F41", +", c #108F08", +"' c #0F8E08", +") c #108E08", +"! c #14970B", +"~ c #8DD289", +"{ c #87DF7F", +"] c #D6F1D3", +"^ c #C3E1C1", +"/ c #488844", +"( c #73D56C", +"_ c #D1F4D0", +": c #F3FCF3", +"< c #F7FEF7", +"[ c #EFFCEF", +"} c #DCF6DB", +"| c #B4EAB0", +"1 c #70D965", +"2 c #2AC71B", +"3 c #68D85D", +"4 c #CFF1CB", +"5 c #DCEFDB", +"6 c #589955", +"7 c #74D46D", +"8 c #9DDF98", +"9 c #ABE8A5", +"0 c #B8EEB4", +"a c #9EE797", +"b c #74DD6A", +"c c #62D758", +"d c #23C512", +"e c #15BC07", +"f c #27C519", +"g c #73DC69", +"h c #BAEDB6", +"i c #B8E7B6", +"j c #499145", +"k c #77D671", +"l c #7BD874", +"m c #3AC72C", +"n c #42C437", +"o c #34C526", +"p c #1FC40F", +"q c #24C516", +"r c #1AB70E", +"s c #1ABC0D", +"t c #20C411", +"u c #5AD94B", +"v c #5DE24A", +"w c #36C229", +"x c #177B11", +"y c #7DDA75", +"z c #84E07B", +"A c #2BC519", +"B c #2FBF1F", +"C c #33C623", +"D c #28C716", +"E c #22CC11", +"F c #20C511", +"G c #23CC13", +"H c #31D81C", +"I c #4FE03B", +"J c #34C725", +"K c #137F0D", +"L c #157C0E", +"M c #126B0F", +"N c #126A0E", +"O c #116C0C", +"P c #13760E", +"Q c #179A0E", +"R c #37DC22", +"S c #4DDF38", +"T c #2AB71D", +"U c #12720D", +"V c #010C00", +"W c #28C715", +"X c #47DF32", +"Y c #2DBD1F", +"Z c #116B0D", +"` c #2CB122", +" . c #23AD18", +".. c #10620C", +"+. c #289023", +"@. c #125B0E", +"#. c #094706", +" ", +" . + ", +" . @ . ", +" . # $ . ", +" . % & * . ", +" . . . . . . . . = - ; > . ", +" . , ' ' ' ) , ! ~ { ] ^ / . ", +" . ( _ : < [ } | 1 2 3 4 5 6 . ", +" . 7 8 9 0 a b c d e f g h i j . ", +" . k l m n o p q r s t u v w x . ", +" . y z A B C D E F G H I J K . ", +" . L M N M O P Q p R S T U . ", +" V . . . . . . . W X Y Z . ", +" . ` .... ", +" . +.@.. ", +" . #.. ", +" . . ", +" "}; + +static const char * const equals_button_data[] = { +"18 18 5 1", +" c None", +". c #414100", +"+ c #E0E0E0", +"@ c #A8A8A8", +"# c #808080", +" ", +" ", +" ", +" .............. ", +" .++++++++++++. ", +" .@@@@@@@@@@@@. ", +" .############. ", +" .............. ", +" ", +" .............. ", +" .++++++++++++. ", +" .@@@@@@@@@@@@. ", +" .############. ", +" .............. ", +" ", +" ", +" ", +" "}; + +static const char * const differents_button_data[] = { +"18 18 5 1", +" c None", +". c #FF0000", +"+ c #FFC0C0", +"@ c #FF8080", +"# c #FF4040", +" ", +" ... ", +" ... ", +" .............. ", +" .+++++++...++. ", +" .@@@@@@...@@@. ", +" .######...###. ", +" .............. ", +" ... ", +" .............. ", +" .++++...+++++. ", +" .@@@...@@@@@@. ", +" .###...######. ", +" .............. ", +" ... ", +" ... ", +" ... ", +" "}; + +static const char * const left_arrow_button_data[] = { +"18 18 137 2", +" c None", +". c #03090E", +"+ c #0D3A57", +"@ c #041F2B", +"# c #073347", +"$ c #0D3C5A", +"% c #051C26", +"& c #0F455C", +"* c #237191", +"= c #104363", +"- c #04121A", +"; c #0C4A62", +"> c #198AAD", +", c #2291B2", +"' c #104564", +") c #062332", +"! c #0D506B", +"~ c #209FBD", +"{ c #33CBDF", +"] c #16ACC8", +"^ c #0C4968", +"/ c #061F2D", +"( c #031721", +"_ c #041621", +": c #051721", +"< c #021621", +"[ c #031B27", +"} c #01090D", +"| c #04151E", +"1 c #0D5672", +"2 c #1E99B8", +"3 c #39CEDF", +"4 c #22C5DC", +"5 c #10A1C4", +"6 c #0E799B", +"7 c #0E5976", +"8 c #0D516D", +"9 c #0F4E6B", +"0 c #0F4D6A", +"a c #0F607D", +"b c #031D25", +"c c #052837", +"d c #0D617F", +"e c #25ABC7", +"f c #3BD0E1", +"g c #1DC0D9", +"h c #14A8CC", +"i c #11A3C5", +"j c #11ABCC", +"k c #17AAC8", +"l c #23ACC6", +"m c #1FA8C0", +"n c #1AAAC5", +"o c #7CCDE1", +"p c #76C4DB", +"q c #032832", +"r c #061D28", +"s c #125F7C", +"t c #29A6C3", +"u c #4BD4E3", +"v c #4BC5DA", +"w c #129FC4", +"x c #0D95BC", +"y c #0F90B7", +"z c #16A2C5", +"A c #0FA3C4", +"B c #26A8C5", +"C c #37A8C4", +"D c #2DA9C7", +"E c #75C1D9", +"F c #71BED6", +"G c #0A212C", +"H c #467B92", +"I c #B6D9E8", +"J c #B6E2ED", +"K c #69C7DC", +"L c #19A2C5", +"M c #0796BC", +"N c #13A5C5", +"O c #59BBD7", +"P c #6BC5DD", +"Q c #98D8E8", +"R c #B4E2EE", +"S c #A6DCE9", +"T c #98CFDF", +"U c #6DBCD4", +"V c #143341", +"W c #56859A", +"X c #DCEAF0", +"Y c #CCEAF2", +"Z c #5EC2D9", +"` c #1BA7C8", +" . c #66C4DA", +".. c #B1DBEB", +"+. c #DBEEF6", +"@. c #EFF6FC", +"#. c #F7FAFE", +"$. c #F3F8FC", +"%. c #D0EAF4", +"&. c #6CBCD5", +"*. c #091A21", +"=. c #457589", +"-. c #C2D8E2", +";. c #D4ECF2", +">. c #80CCDF", +",. c #8ABFD3", +"'. c #0C7497", +"). c #086E90", +"!. c #086C8E", +"~. c #086B8E", +"{. c #086D90", +"]. c #021E27", +"^. c #0D2B38", +"/. c #426D80", +"(. c #C3DAE5", +"_. c #BCDCEA", +":. c #90BDD0", +"<. c #144361", +"[. c #002745", +"}. c #00213F", +"|. c #001F3E", +"1. c #00203F", +"2. c #002643", +"3. c #000B13", +"4. c #03161D", +"5. c #2F5F73", +"6. c #9AC3D5", +"7. c #8EBED3", +"8. c #1A4A68", +"9. c #0C222B", +"0. c #2B5A6D", +"a. c #5A98B4", +"b. c #164867", +"c. c #0F2731", +"d. c #163E50", +"e. c #0E3E5C", +"f. c #0C3652", +" ", +" . f. ", +" c.d.e. ", +" 9.0.a.b. ", +" 4.5.6.7.8. ", +" ^./.(._.:.<.[.}.|.|.1.2.3. ", +" *.=.-.;.>.,.'.).!.~.~.~.{.]. ", +" V W X Y Z ` ...+.@.#.$.%.&.q ", +" G H I J K L M N O P Q R S T U q ", +" r s t u v w x y z A B C D E F q ", +" c d e f g h i j k l m n o p q ", +" | 1 2 3 4 5 6 7 8 9 0 9 a b ", +" ) ! ~ { ] ^ / ( _ : < [ } ", +" - ; > , ' ", +" % & * = ", +" @ # $ ", +" . + ", +" "}; + +static const char * const trash_button_data[] = { +"18 18 140 2", +" c None", +". c #BFBFBF", +"+ c #BABAB9", +"@ c #AEAEAE", +"# c #A2A2A3", +"$ c #959595", +"% c #8B8B8C", +"& c #868687", +"* c #D3D5D5", +"= c #E1E1E1", +"- c #CCCCCD", +"; c #BDBEBD", +"> c #B1B2B1", +", c #A3A2A2", +"' c #959597", +") c #8E8E8F", +"! c #818282", +"~ c #727171", +"{ c #838384", +"] c #D1D1D1", +"^ c #F3F3F3", +"/ c #C6C7C6", +"( c #B8B9B9", +"_ c #ABABAB", +": c #9F9FA0", +"< c #949394", +"[ c #8E8E8E", +"} c #7E8080", +"| c #717071", +"1 c #5C5C5B", +"2 c #555556", +"3 c #A7A7A7", +"4 c #FAFAFA", +"5 c #CACACA", +"6 c #BABBBB", +"7 c #B5B6B6", +"8 c #A9A9AA", +"9 c #9E9E9D", +"0 c #929293", +"a c #8E8C8D", +"b c #7F7F7F", +"c c #6F6F70", +"d c #525151", +"e c #414141", +"f c #A1A2A2", +"g c #C3C3C2", +"h c #D5D4D4", +"i c #ECECEC", +"j c #E7E7E7", +"k c #D6D6D6", +"l c #C5C5C6", +"m c #B0B0B0", +"n c #AAAAAA", +"o c #989898", +"p c #6D6D6E", +"q c #494949", +"r c #9E9E9E", +"s c #C0C1C1", +"t c #BABABA", +"u c #B2B2B2", +"v c #AEAEAD", +"w c #A4A4A4", +"x c #9B9B9B", +"y c #8E8F8F", +"z c #888888", +"A c #767676", +"B c #616161", +"C c #B3B3B3", +"D c #B9B9BA", +"E c #A4A5A4", +"F c #979797", +"G c #888788", +"H c #6D6D6D", +"I c #4D4D4D", +"J c #4B4A4B", +"K c #F6F6F6", +"L c #B1B1B1", +"M c #A7A8A7", +"N c #939394", +"O c #8D8D8E", +"P c #727272", +"Q c #505050", +"R c #484848", +"S c #EEEEEE", +"T c #EBEBEB", +"U c #9D9D9C", +"V c #919292", +"W c #8C8C8C", +"X c #808080", +"Y c #6C6B6C", +"Z c #E5E5E5", +"` c #AFAFAF", +" . c #A6A6A6", +".. c #8F908F", +"+. c #888989", +"@. c #7B7B7B", +"#. c #676667", +"$. c #4F4F4F", +"%. c #AFB0AF", +"&. c #D8D8D8", +"*. c #D4D4D4", +"=. c #A5A5A4", +"-. c #9A9A9A", +";. c #8D8D8D", +">. c #777777", +",. c #5F5F5F", +"'. c #4B4B4B", +"). c #B0AFAF", +"!. c #D3D2D2", +"~. c #CDCDCD", +"{. c #A4A5A5", +"]. c #8D8D8B", +"^. c #868685", +"/. c #747474", +"(. c #5D5D5D", +"_. c #AEAFAE", +":. c #C4C4C4", +"<. c #BEBEBE", +"[. c #A3A4A3", +"}. c #8B8A8A", +"|. c #838282", +"1. c #707070", +"2. c #565656", +"3. c #444444", +"4. c #000000", +"5. c #B2B1B1", +"6. c #ADADAD", +"7. c #A3A3A3", +"8. c #979697", +"9. c #6C6C6C", +"0. c #403F3F", +"a. c #B1B2B2", +"b. c #9F9F9F", +"c. c #A6A6A7", +"d. c #9E9F9F", +"e. c #949494", +"f. c #828282", +"g. c #787979", +"h. c #3D3D3C", +"i. c #2F2F2F", +" ", +" . + @ # $ % & % ", +" * = - ; > , ' ) ! ~ { ", +" ] ^ / ; ( _ : < [ } | 1 2 ", +" 3 4 5 6 7 8 9 0 a b c d e ", +" f g h i j k l m n o p q e ", +" r s t u v w x y z A B e 2 ", +" [ C D C E F G b H I J ", +" C K ^ L M r N O P Q R ", +" L S T m 3 U V W X Y R ", +" m Z = ` .x ..+.@.#.$. ", +" %.&.*.@ =.-.;.& >.,.'. ", +" ).!.~.@ {.-.].^./.(.R ", +" _.:.<.@ [.o }.|.1.2.3.4.4.4. ", +" @ D 5.6.7.8.z b 9.Q 0.4.4.4.4. ", +" a.b.c.3 d.e.f.g.(.h.i.4.4.4.4. ", +" 4.4.4.4.4.4.4.4. ", +" "}; + +static const char * const file_data[] = { +"16 16 42 1", +" c None", +". c #D0D0DF", +"+ c #9C9CB6", +"@ c #FFFFFF", +"# c #F9F9FE", +"$ c #F5F5FC", +"% c #E9E9F2", +"& c #EBEBF4", +"* c #FCFCFF", +"= c #F8F8FE", +"- c #ECECF4", +"; c #D3D3E1", +"> c #EFEFF6", +", c #FDFDFF", +"' c #F1F1F8", +") c #E6E6F0", +"! c #D7D7E5", +"~ c #C9C9DA", +"{ c #FEFEFF", +"] c #F2F2F9", +"^ c #EEEEF5", +"/ c #DADAE7", +"( c #CECEDD", +"_ c #CCCCDB", +": c #F3F3F9", +"< c #D5D5E4", +"[ c #D2D2E0", +"} c #E7E7F0", +"| c #E0E0EC", +"1 c #DCDCE9", +"2 c #DBDBE8", +"3 c #D8D8E6", +"4 c #F6F6FD", +"5 c #E5E5EF", +"6 c #DEDEEB", +"7 c #F0F0F7", +"8 c #EAEAF3", +"9 c #E8E8F1", +"0 c #E1E1ED", +"a c #F4F4FA", +"b c #E4E4EE", +"c c #FAFAFF", +" ........+ ", +" .@@@#$%&.+ ", +" .@@@*=-&.;+ ", +" .@@@*#>&++++ ", +" .@@@,#'&)!~+ ", +" .@@@{*]^/(_+ ", +" .@@@@*:&<[.+ ", +" .@@{#$}|123+ ", +" .@{,4^)5|61+ ", +" .@@#7^8950|+ ", +" .@,a'>&8)b|+ ", +" .@c:'>&8}50+ ", +" .@$:'7^8}50+ ", +" .@:]7>-8)50+ ", +" .*::'>&8}50+ ", +" ++++++++++++ "}; + +static const char * const folder_data[] = { +"16 16 132 2", +" c None", +". c #2C87EF", +"+ c #64A6F7", +"@ c #357CE3", +"# c #D9E1F8", +"$ c #B1BADE", +"% c #8BA2D9", +"& c #4392E3", +"* c #B8D9F8", +"= c #4F9BED", +"- c #126EE0", +"; c #0A43A8", +"> c #C6CBDA", +", c #FFFFFF", +"' c #F1F0F6", +") c #80ADE2", +"! c #4F95E4", +"~ c #1876DF", +"{ c #0C6ADF", +"] c #0C4CB9", +"^ c #CCCFDA", +"/ c #F8F4F7", +"( c #89B7E7", +"_ c #78ACE4", +": c #B4D8F8", +"< c #97CAFF", +"[ c #6FAEFC", +"} c #3175D8", +"| c #0E51B4", +"1 c #002374", +"2 c #D0D0D7", +"3 c #8EC1F0", +"4 c #85BBED", +"5 c #DAF0F9", +"6 c #BDE2FB", +"7 c #9CCCF8", +"8 c #84BBF8", +"9 c #6FAAF4", +"0 c #4780D4", +"a c #0851AA", +"b c #0035A9", +"c c #CFD0D4", +"d c #51A2E9", +"e c #FFFFFE", +"f c #EEFCFD", +"g c #CEECFB", +"h c #B1D9F9", +"i c #9AC9F9", +"j c #7EB3F2", +"k c #568CDA", +"l c #1156BA", +"m c #004595", +"n c #003293", +"o c #EFEFEE", +"p c #84BCEE", +"q c #E2F8FC", +"r c #C9E8FB", +"s c #B0D8FA", +"t c #90C0F3", +"u c #6B9FE5", +"v c #3375CC", +"w c #2A71C7", +"x c #003B96", +"y c #0651AE", +"z c #0E3DAC", +"A c #E5E3E0", +"B c #DFD8D5", +"C c #FFF7F2", +"D c #DEEFFE", +"E c #BEDCF6", +"F c #E5FCFD", +"G c #C4E6FB", +"H c #A8D4F8", +"I c #85B6EC", +"J c #437DCE", +"K c #2170C9", +"L c #397CC8", +"M c #A3B6D4", +"N c #E3D3D2", +"O c #295BC3", +"P c #4AACFF", +"Q c #74A7D5", +"R c #CBC7CE", +"S c #7EB0E7", +"T c #F5FFFF", +"U c #C1E7FE", +"V c #9AC8F3", +"W c #4B84D3", +"X c #5490D9", +"Y c #B3C7E3", +"Z c #E9DFDF", +"` c #D3CED8", +" . c #D7CFD3", +".. c #7488C1", +"+. c #002A95", +"@. c #6FCDFF", +"#. c #CBEAFF", +"$. c #D9F9FF", +"%. c #70AAE1", +"&. c #C7E0EE", +"*. c #9DCBF1", +"=. c #84AEE4", +"-. c #D0E1F4", +";. c #FFF9F4", +">. c #EEE9EB", +",. c #E6E2E5", +"'. c #D9D1D6", +"). c #637DC0", +"!. c #2D63D3", +"~. c #001251", +"{. c #439FF0", +"]. c #B4DBF9", +"^. c #D6F8FF", +"/. c #75ACE3", +"(. c #F0FAFF", +"_. c #FCF9F8", +":. c #91A5D4", +"<. c #2A5FCE", +"[. c #002B91", +"}. c #3E9DEF", +"|. c #A4CEF4", +"1. c #77AFE8", +"2. c #E1EBFC", +"3. c #3F73D7", +"4. c #043BAE", +"5. c #3188DE", +"6. c #75A9E3", +"7. c #A8C6EC", +"8. c #6195E7", +"9. c #1450C5", +"0. c #7AB0FB", +"a. c #155ED2", +" ", +" . + @ ", +" # $ % & * = - ; ", +" > , , ' ) ! ~ { ] ", +" ^ , / ( _ : < [ } | 1 ", +" 2 , 3 4 5 6 7 8 9 0 a b ", +" c , d e f g h i j k l m n ", +"o , , p , q r s t u v w x y z ", +"A B C D E F G H I J K L M N O ", +" P Q R S T U V W X Y Z ` ...+.", +" @.#.$.%.&.*.=.-.;.>.,.'.).!.~.", +" {.].^./.(., , _.C :.<.[. ", +" }.|.1., , , 2.3.4. ", +" 5.6.7., 8.9. ", +" 0.a. ", +" "}; + +static const char * const swap_sides_data[] = { +"27 20 228 2", +" c None", +". c #03090E", +"+ c #0C3652", +"@ c #000000", +"# c #030D03", +"$ c #0F2731", +"% c #163E50", +"& c #0E3E5C", +"* c #184F16", +"= c #0C222B", +"- c #2B5A6D", +"; c #5A98B4", +"> c #164867", +", c #5DB45A", +"' c #2E6C2A", +") c #03161D", +"! c #2F5F73", +"~ c #9AC3D5", +"{ c #8EBED3", +"] c #1A4A68", +"^ c #90D28D", +"/ c #9CD59A", +"( c #32732E", +"_ c #0D2B38", +": c #426D80", +"< c #C3DAE5", +"[ c #BCDCEA", +"} c #90BDD0", +"| c #144361", +"1 c #002745", +"2 c #00213F", +"3 c #001F3E", +"4 c #00203F", +"5 c #002643", +"6 c #92CF8F", +"7 c #BDE9BB", +"8 c #C4E5C3", +"9 c #447F41", +"0 c #091A21", +"a c #457589", +"b c #C2D8E2", +"c c #D4ECF2", +"d c #80CCDF", +"e c #8ABFD3", +"f c #0C7497", +"g c #086E90", +"h c #086C8E", +"i c #086B8E", +"j c #086D90", +"k c #108F08", +"l c #0F8E08", +"m c #108E08", +"n c #14970B", +"o c #8DD289", +"p c #87DF7F", +"q c #D6F1D3", +"r c #C3E1C1", +"s c #488844", +"t c #143341", +"u c #56859A", +"v c #DCEAF0", +"w c #CCEAF2", +"x c #5EC2D9", +"y c #1BA7C8", +"z c #66C4DA", +"A c #B1DBEB", +"B c #DBEEF6", +"C c #EFF6FC", +"D c #F7FAFE", +"E c #F3F8FC", +"F c #D0EAF4", +"G c #6CBCD5", +"H c #73D56C", +"I c #D1F4D0", +"J c #F3FCF3", +"K c #F7FEF7", +"L c #EFFCEF", +"M c #DCF6DB", +"N c #B4EAB0", +"O c #70D965", +"P c #2AC71B", +"Q c #68D85D", +"R c #CFF1CB", +"S c #DCEFDB", +"T c #589955", +"U c #0A212C", +"V c #467B92", +"W c #B6D9E8", +"X c #B6E2ED", +"Y c #69C7DC", +"Z c #19A2C5", +"` c #0796BC", +" . c #13A5C5", +".. c #59BBD7", +"+. c #6BC5DD", +"@. c #98D8E8", +"#. c #B4E2EE", +"$. c #A6DCE9", +"%. c #98CFDF", +"&. c #6DBCD4", +"*. c #74D46D", +"=. c #9DDF98", +"-. c #ABE8A5", +";. c #B8EEB4", +">. c #9EE797", +",. c #74DD6A", +"'. c #62D758", +"). c #23C512", +"!. c #15BC07", +"~. c #27C519", +"{. c #73DC69", +"]. c #BAEDB6", +"^. c #B8E7B6", +"/. c #499145", +"(. c #061D28", +"_. c #125F7C", +":. c #29A6C3", +"<. c #4BD4E3", +"[. c #4BC5DA", +"}. c #129FC4", +"|. c #0D95BC", +"1. c #0F90B7", +"2. c #16A2C5", +"3. c #0FA3C4", +"4. c #26A8C5", +"5. c #37A8C4", +"6. c #2DA9C7", +"7. c #75C1D9", +"8. c #71BED6", +"9. c #77D671", +"0. c #7BD874", +"a. c #3AC72C", +"b. c #42C437", +"c. c #34C526", +"d. c #1FC40F", +"e. c #24C516", +"f. c #1AB70E", +"g. c #1ABC0D", +"h. c #20C411", +"i. c #5AD94B", +"j. c #5DE24A", +"k. c #36C229", +"l. c #177B11", +"m. c #052837", +"n. c #0D617F", +"o. c #25ABC7", +"p. c #3BD0E1", +"q. c #1DC0D9", +"r. c #14A8CC", +"s. c #11A3C5", +"t. c #11ABCC", +"u. c #17AAC8", +"v. c #23ACC6", +"w. c #1FA8C0", +"x. c #1AAAC5", +"y. c #7CCDE1", +"z. c #76C4DB", +"A. c #7DDA75", +"B. c #84E07B", +"C. c #2BC519", +"D. c #2FBF1F", +"E. c #33C623", +"F. c #28C716", +"G. c #22CC11", +"H. c #20C511", +"I. c #23CC13", +"J. c #31D81C", +"K. c #4FE03B", +"L. c #34C725", +"M. c #137F0D", +"N. c #04151E", +"O. c #0D5672", +"P. c #1E99B8", +"Q. c #39CEDF", +"R. c #22C5DC", +"S. c #10A1C4", +"T. c #0E799B", +"U. c #0E5976", +"V. c #0D516D", +"W. c #0F4E6B", +"X. c #0F4D6A", +"Y. c #0F607D", +"Z. c #157C0E", +"`. c #126B0F", +" + c #126A0E", +".+ c #116C0C", +"++ c #13760E", +"@+ c #179A0E", +"#+ c #37DC22", +"$+ c #4DDF38", +"%+ c #2AB71D", +"&+ c #12720D", +"*+ c #062332", +"=+ c #0D506B", +"-+ c #209FBD", +";+ c #33CBDF", +">+ c #16ACC8", +",+ c #0C4968", +"'+ c #061F2D", +")+ c #031721", +"!+ c #041621", +"~+ c #051721", +"{+ c #021621", +"]+ c #031B27", +"^+ c #010C00", +"/+ c #28C715", +"(+ c #47DF32", +"_+ c #2DBD1F", +":+ c #116B0D", +"<+ c #04121A", +"[+ c #0C4A62", +"}+ c #198AAD", +"|+ c #2291B2", +"1+ c #104564", +"2+ c #2CB122", +"3+ c #23AD18", +"4+ c #10620C", +"5+ c #051C26", +"6+ c #0F455C", +"7+ c #237191", +"8+ c #104363", +"9+ c #289023", +"0+ c #125B0E", +"a+ c #041F2B", +"b+ c #073347", +"c+ c #0D3C5A", +"d+ c #094706", +"e+ c #0D3A57", +" ", +" ", +" . + @ # ", +" $ % & @ * @ ", +" = - ; > @ , ' @ ", +" ) ! ~ { ] @ ^ / ( @ ", +" _ : < [ } | 1 3 4 5 @ @ @ @ @ @ 6 7 8 9 @ ", +" 0 a b c d e f g i i j @ k l l k n o p q r s @ ", +" t u v w x y z A B E F G @ H I K M N O P Q R S T @ ", +"U V W X Y Z ` ...+.$.%.&.@ *.=.;.,.'.).!.~.{.].^./.@ ", +"(._.:.<.[.}.|.1.2.3.6.7.8.@ 9.0.b.d.e.f.g.h.i.j.k.l.@ ", +" m.n.o.p.q.r.s.t.u.x.y.z.@ A.B.D.F.G.H.I.J.K.L.M.@ ", +" N.O.P.Q.R.S.T.U.X.W.Y.@ Z.`.`.++@+d.#+$+%+&+@ ", +" *+=+-+;+>+,+'+~+{+]+^+@ @ @ @ @ /+(+_+:+@ ", +" <+[+}+|+1+ @ 2+3+4+@ ", +" 5+6+7+8+ @ 9+0+@ ", +" a+b+c+ @ d+@ ", +" . e+ @ @ ", +" ", +" "}; + +class SynchronizerListView : public TQListView +{ +private: + Synchronizer *synchronizer; + bool isLeft; + +public: + SynchronizerListView( Synchronizer * sync, TQWidget * parent ) : TQListView( parent ), synchronizer( sync ) + { + } + + void contentsMouseMoveEvent ( TQMouseEvent * e ) + { + isLeft = (( e->state() & ShiftButton ) == 0 ); + TQListView::contentsMouseMoveEvent( e ); + } + void startDrag() + { + KURL::List urls; + + unsigned ndx = 0; + SynchronizerFileItem *currentItem; + + while( ( currentItem = synchronizer->getItemAt( ndx++ ) ) != 0 ) + { + SynchronizerGUI::SyncViewItem *viewItem = (SynchronizerGUI::SyncViewItem *)currentItem->userData(); + + if( !viewItem || !viewItem->isSelected() || !viewItem->isVisible() ) + continue; + + SynchronizerFileItem *item = viewItem->synchronizerItemRef(); + if( item ) + { + if( isLeft && item->existsInLeft() ) + { + TQString leftDirName = item->leftDirectory().isEmpty() ? "" : item->leftDirectory() + "/"; + KURL leftURL = vfs::fromPathOrURL( synchronizer->leftBaseDirectory() + leftDirName + item->leftName() ); + urls.push_back( leftURL ); + } + else if( !isLeft && item->existsInRight() ) + { + TQString rightDirName = item->rightDirectory().isEmpty() ? "" : item->rightDirectory() + "/"; + KURL rightURL = vfs::fromPathOrURL( synchronizer->rightBaseDirectory() + rightDirName + item->rightName() ); + urls.push_back( rightURL ); + } + } + } + + if( urls.count() == 0 ) + return; + + KURLDrag *d = new KURLDrag(urls, this); + d->setPixmap( FL_LOADICON( isLeft ? "2leftarrow" : "2rightarrow" ), TQPoint( -7, 0 ) ); + d->dragCopy(); + } +}; + +SynchronizerGUI::SynchronizerGUI(TQWidget* parent, KURL leftURL, KURL rightURL, TQStringList selList ) : + TQDialog( parent, "Krusader::SynchronizerGUI", false, 0 ) { + initGUI( parent, TQString(), leftURL, rightURL, selList ); +} + +SynchronizerGUI::SynchronizerGUI(TQWidget* parent, TQString profile ) : + TQDialog( parent, "Krusader::SynchronizerGUI", false, 0 ) { + initGUI( parent, profile, KURL(), KURL(), TQStringList() ); +} + +void SynchronizerGUI::initGUI(TQWidget* /* parent */, TQString profileName, KURL leftURL, KURL rightURL, TQStringList selList) { + selectedFiles = selList; + isComparing = wasClosed = wasSync = false; + firstResize = true; + sizeX = sizeY = -1; + + hasSelectedFiles = ( selectedFiles.count() != 0 ); + + if( leftURL.isEmpty() ) + leftURL = KURL("/"); + if( rightURL.isEmpty() ) + rightURL = KURL("/"); + + setCaption( i18n("Krusader::Synchronize Directories") ); + TQGridLayout *synchGrid = new TQGridLayout( this ); + synchGrid->setSpacing( 6 ); + synchGrid->setMargin( 11 ); + + folderIcon = TQPixmap( ( const char** ) folder_data ); + fileIcon = TQPixmap( ( const char** ) file_data ); + + synchronizerTabs = new TQTabWidget( this, "synchronizerTabs" ); + + /* ============================== Compare groupbox ============================== */ + + TQWidget *synchronizerTab = new TQWidget( this, "syncronizerTab" ); + TQGridLayout *synchronizerGrid = new TQGridLayout( synchronizerTab ); + synchronizerGrid->setSpacing( 6 ); + synchronizerGrid->setMargin( 11 ); + + TQGroupBox *compareDirs = new TQGroupBox( synchronizerTab, "SyncCompareDirectories" ); + compareDirs->setSizePolicy( TQSizePolicy::Expanding, TQSizePolicy::Fixed); + compareDirs->setTitle( i18n( "Directory Comparison" ) ); + compareDirs->setColumnLayout(0, TQt::Vertical ); + compareDirs->layout()->setSpacing( 0 ); + compareDirs->layout()->setMargin( 0 ); + + TQGridLayout *grid = new TQGridLayout( compareDirs->layout() ); + grid->setSpacing( 6 ); + grid->setMargin( 11 ); + + leftDirLabel = new TQLabel( compareDirs, "leftDirLabel" ); + leftDirLabel->setAlignment( TQt::AlignHCenter ); + grid->addWidget( leftDirLabel, 0 ,0 ); + + TQLabel *filterLabel = new TQLabel( compareDirs, "filterLabel" ); + filterLabel->setText( i18n( "File &Filter:" ) ); + filterLabel->setAlignment( TQt::AlignHCenter ); + grid->addWidget( filterLabel, 0 ,1 ); + + rightDirLabel = new TQLabel( compareDirs, "rightDirLabel" ); + rightDirLabel->setAlignment( TQt::AlignHCenter ); + grid->addWidget( rightDirLabel, 0 ,2 ); + + krConfig->setGroup("Synchronize"); + + leftLocation = new KHistoryCombo(false, compareDirs, "SynchronizerHistoryLeft"); + leftLocation->setMaxCount(25); // remember 25 items + leftLocation->setDuplicatesEnabled( false ); + leftLocation->setEditable( true ); + leftLocation->setSizePolicy(TQSizePolicy::Ignored,TQSizePolicy::Fixed); + TQStringList list = krConfig->readListEntry("Left Directory History"); + leftLocation->setHistoryItems(list); + KURLRequester *leftUrlReq = new KURLRequester( leftLocation, compareDirs, "LeftDirectory" ); + leftUrlReq->setURL( vfs::pathOrURL( leftURL ) ); + leftUrlReq->setMode( KFile::Directory ); + leftUrlReq->setMinimumWidth( 250 ); + grid->addWidget( leftUrlReq, 1 ,0 ); + TQWhatsThis::add( leftLocation, i18n( "The left base directory used during the synchronisation process." ) ); + leftUrlReq->setEnabled( !hasSelectedFiles ); + leftLocation->setEnabled( !hasSelectedFiles ); + leftDirLabel->setBuddy( leftLocation ); + + fileFilter = new KHistoryCombo(false, compareDirs, "SynchronizerFilter"); + fileFilter->setMaxCount(25); // remember 25 items + fileFilter->setDuplicatesEnabled( false ); + fileFilter->setMinimumWidth( 100 ); + fileFilter->setMaximumWidth( 100 ); + fileFilter->setSizePolicy(TQSizePolicy::Fixed,TQSizePolicy::Fixed); + list = krConfig->readListEntry("File Filter"); + fileFilter->setHistoryItems(list); + fileFilter->setEditText("*"); + grid->addWidget( fileFilter, 1 ,1 ); + filterLabel->setBuddy( fileFilter ); + + TQString wtFilter = "<p><img src='toolbar|find'></p>" + i18n("<p>The filename filtering criteria is defined here.</p><p>You can make use of wildcards. Multiple patterns are separated by space (means logical OR) and patterns are excluded from the search using the pipe symbol.</p><p>If the pattern is ended with a slash (<code>*pattern*/</code>), that means that pattern relates to recursive search of directories.<ul><li><code>pattern</code> - means to search those files/directories that name is <code>pattern</code>, recursive search goes through all subdirectories independently of the value of <code>pattern</code></li><li><code>pattern/</code> - means to search all files/directories, but recursive search goes through/excludes the directories that name is <code>pattern</code></li></ul><p></p><p>It's allowed to use quotation marks for names that contain space. Filter <code>\"Program Files\"</code> searches out those files/directories that name is <code>Program Files</code>.</p><p>Examples:<ul><code><li>*.o</li><li>*.h *.c\?\?</li><li>*.cpp *.h | *.moc.cpp</li><li>* | CVS/ .svn/</li></code></ul><b>Note</b>: the search term '<code>text</code>' is equivalent to '<code>*text*</code>'.</p>"); + TQWhatsThis::add(fileFilter, wtFilter); + TQWhatsThis::add(filterLabel, wtFilter); + + rightLocation = new KHistoryCombo(compareDirs, "SynchronizerHistoryRight"); + rightLocation->setMaxCount(25); // remember 25 items + rightLocation->setDuplicatesEnabled( false ); + rightLocation->setEditable( true ); + rightLocation->setSizePolicy(TQSizePolicy::Ignored,TQSizePolicy::Fixed); + list = krConfig->readListEntry("Right Directory History"); + rightLocation->setHistoryItems(list); + KURLRequester *rightUrlReq = new KURLRequester( rightLocation, compareDirs, "RightDirectory" ); + rightUrlReq->setURL( vfs::pathOrURL( rightURL ) ); + rightUrlReq->setMode( KFile::Directory ); + rightUrlReq->setMinimumWidth( 250 ); + grid->addWidget( rightUrlReq, 1 ,2 ); + TQWhatsThis::add( rightLocation, i18n( "The right base directory used during the synchronisation process." ) ); + rightUrlReq->setEnabled( !hasSelectedFiles ); + rightLocation->setEnabled( !hasSelectedFiles ); + rightDirLabel->setBuddy( rightLocation ); + + TQHBox *optionBox = new TQHBox( compareDirs ); + TQGrid *optionGrid = new TQGrid( 3, optionBox ); + cbSubdirs = new TQCheckBox( i18n( "Recurse subdirectories" ), optionGrid, "cbSubdirs" ); + cbSubdirs->setChecked( krConfig->readBoolEntry( "Recurse Subdirectories", _RecurseSubdirs ) ); + TQWhatsThis::add( cbSubdirs, i18n( "Compare not only the base directories but their subdirectories as well." ) ); + cbSymlinks = new TQCheckBox( i18n( "Follow symlinks" ), optionGrid, "cbSymlinks" ); + cbSymlinks->setChecked( krConfig->readBoolEntry( "Follow Symlinks", _FollowSymlinks ) ); + cbSymlinks->setEnabled( cbSubdirs->isChecked() ); + TQWhatsThis::add( cbSymlinks, i18n( "Follow symbolic links during the compare process." ) ); + cbByContent = new TQCheckBox( i18n( "Compare by content" ), optionGrid, "cbByContent" ); + cbByContent->setChecked( krConfig->readBoolEntry( "Compare By Content", _CompareByContent ) ); + TQWhatsThis::add( cbByContent, i18n( "Compare duplicated files with same size by content." ) ); + cbIgnoreDate = new TQCheckBox( i18n( "Ignore Date" ), optionGrid, "cbIgnoreDate" ); + cbIgnoreDate->setChecked( krConfig->readBoolEntry( "Ignore Date", _IgnoreDate ) ); + TQWhatsThis::add( cbIgnoreDate, i18n( "<p>Ignore date information during the compare process.</p><p><b>Note</b>: useful if the files are located on network filesystems or in archives.</p>" ) ); + cbAsymmetric = new TQCheckBox( i18n( "Asymmetric" ), optionGrid, "cbAsymmetric" ); + cbAsymmetric->setChecked( krConfig->readBoolEntry( "Asymmetric", _Asymmetric ) ); + TQWhatsThis::add( cbAsymmetric, i18n( "<p><b>Asymmetric mode</b></p><p>The left side is the destination, the right is the source directory. Files existing only in the left directory will be deleted, the other differing ones will be copied from right to left.</p><p><b>Note</b>: useful when updating a directory from a file server.</p>" ) ); + cbIgnoreCase = new TQCheckBox( i18n( "Ignore Case" ), optionGrid, "cbIgnoreCase" ); + cbIgnoreCase->setChecked( krConfig->readBoolEntry( "Ignore Case", _IgnoreCase ) ); + TQWhatsThis::add( cbIgnoreCase, i18n( "<p>Case insensitive filename compare.</p><p><b>Note</b>: useful when synchronizing Windows filesystems.</p>" ) ); + + /* =========================== Show options groupbox ============================= */ + + TQGroupBox *showOptions = new TQGroupBox( optionBox, "SyncOptionBox" ); + showOptions->setTitle( i18n( "S&how options" ) ); + showOptions->setSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed); + showOptions->setColumnLayout(0, TQt::Vertical ); + showOptions->layout()->setSpacing( 0 ); + showOptions->layout()->setMargin( 0 ); + TQGridLayout *showOptionsLayout = new TQGridLayout( showOptions->layout() ); + showOptionsLayout->setSpacing( 6 ); + showOptionsLayout->setMargin( 11 ); + + TQPixmap showLeftToRight( ( const char** ) right_arrow_button_data ); + TQPixmap showEquals ( ( const char** ) equals_button_data ); + TQPixmap showDifferents ( ( const char** ) differents_button_data ); + TQPixmap showRightToLeft( ( const char** ) left_arrow_button_data ); + TQPixmap showDeletable ( ( const char** ) trash_button_data ); + + btnLeftToRight = new TQPushButton( showOptions, "btnLeftToRight" ); + btnLeftToRight->setText( "" ); + btnLeftToRight->setPixmap( showLeftToRight ); + btnLeftToRight->setToggleButton( true ); + btnLeftToRight->setOn( krConfig->readBoolEntry( "LeftToRight Button", _BtnLeftToRight ) ); + btnLeftToRight->setAccel( CTRL + Key_L ); + TQWhatsThis::add( btnLeftToRight, i18n( "Show files marked to <i>Copy from left to right</i> (CTRL+L)." ) ); + showOptionsLayout->addWidget( btnLeftToRight, 0, 0); + + btnEquals = new TQPushButton( showOptions, "btnEquals" ); + btnEquals->setText( "" ); + btnEquals->setPixmap( showEquals ); + btnEquals->setToggleButton( true ); + btnEquals->setOn( krConfig->readBoolEntry( "Equals Button", _BtnEquals ) ); + btnEquals->setAccel( CTRL + Key_E ); + TQWhatsThis::add( btnEquals, i18n( "Show files considered to be identical (CTRL+E)." ) ); + showOptionsLayout->addWidget( btnEquals, 0, 1); + + btnDifferents = new TQPushButton( showOptions, "btnDifferents" ); + btnDifferents->setText( "" ); + btnDifferents->setPixmap( showDifferents ); + btnDifferents->setToggleButton( true ); + btnDifferents->setOn( krConfig->readBoolEntry( "Differents Button", _BtnDifferents ) ); + btnDifferents->setAccel( CTRL + Key_D ); + TQWhatsThis::add( btnDifferents, i18n( "Show excluded files (CTRL+D)." ) ); + showOptionsLayout->addWidget( btnDifferents, 0, 2); + + btnRightToLeft = new TQPushButton( showOptions, "btnRightToLeft" ); + btnRightToLeft->setText( "" ); + btnRightToLeft->setPixmap( showRightToLeft ); + btnRightToLeft->setToggleButton( true ); + btnRightToLeft->setOn( krConfig->readBoolEntry( "RightToLeft Button", _BtnRightToLeft ) ); + btnRightToLeft->setAccel( CTRL + Key_R ); + TQWhatsThis::add( btnRightToLeft, i18n( "Show files marked to <i>Copy from right to left</i> (CTRL+R)." ) ); + showOptionsLayout->addWidget( btnRightToLeft, 0, 3); + + btnDeletable = new TQPushButton( showOptions, "btnDeletable" ); + btnDeletable->setText( "" ); + btnDeletable->setPixmap( showDeletable ); + btnDeletable->setToggleButton( true ); + btnDeletable->setOn( krConfig->readBoolEntry( "Deletable Button", _BtnDeletable ) ); + btnDeletable->setAccel( CTRL + Key_T ); + TQWhatsThis::add( btnDeletable, i18n( "Show files marked to delete. (CTRL+T)" ) ); + showOptionsLayout->addWidget( btnDeletable, 0, 4); + + btnDuplicates = new TQPushButton( showOptions, "btnDuplicates" ); + btnDuplicates->setText( i18n("Duplicates") ); + btnDuplicates->setMinimumHeight( btnLeftToRight->height() ); + btnDuplicates->setToggleButton( true ); + btnDuplicates->setOn( krConfig->readBoolEntry( "Duplicates Button", _BtnDuplicates ) ); + TQWhatsThis::add( btnDuplicates, i18n( "Show files that exist on both sides." ) ); + showOptionsLayout->addWidget( btnDuplicates, 0, 5); + + btnSingles = new TQPushButton( showOptions, "btnSingles" ); + btnSingles->setText( i18n("Singles") ); + btnSingles->setMinimumHeight( btnLeftToRight->height() ); + btnSingles->setToggleButton( true ); + btnSingles->setOn( krConfig->readBoolEntry( "Singles Button", _BtnSingles ) ); + TQWhatsThis::add( btnSingles, i18n( "Show files that exist on one side only." ) ); + showOptionsLayout->addWidget( btnSingles, 0, 6); + + grid->addMultiCellWidget( optionBox, 2, 2, 0, 2 ); + + synchronizerGrid->addWidget( compareDirs, 0, 0 ); + + /* ========================= Synchronization list view ========================== */ + syncList=new SynchronizerListView( &synchronizer, synchronizerTab ); // create the main container + TQWhatsThis::add( syncList, i18n( "The compare results of the synchronizer (CTRL+M)." ) ); + + krConfig->setGroup("Look&Feel"); + syncList->setFont(krConfig->readFontEntry("Filelist Font",_FilelistFont)); + + syncList->setAllColumnsShowFocus(true); + syncList->setMultiSelection(true); + syncList->setSelectionMode(TQListView::Extended); + syncList->setVScrollBarMode(TQScrollView::Auto); + syncList->setHScrollBarMode(TQScrollView::Auto); + syncList->setShowSortIndicator(false); + syncList->setSorting(-1); + syncList->setRootIsDecorated( true ); + syncList->setTreeStepSize( 10 ); + int i=TQFontMetrics(syncList->font()).width("W"); + int j=TQFontMetrics(syncList->font()).width("0"); + j=(i>j ? i : j); + int typeWidth = j*7/2; + + krConfig->setGroup("Synchronize"); + + int leftNameWidth = krConfig->readNumEntry("Left Name Width", 9*typeWidth/2 ); + int leftSizeWidth = krConfig->readNumEntry("Left Size Width", 2*typeWidth ); + int leftDateWidth = krConfig->readNumEntry("Left Date Width", 3*typeWidth ); + int taskTypeWidth = krConfig->readNumEntry("Task Type Width", typeWidth ); + int rightDateWidth = krConfig->readNumEntry("Right Date Width", 3*typeWidth ); + int rightSizeWidth = krConfig->readNumEntry("Right Size Width", 2*typeWidth ); + int rightNameWidth = krConfig->readNumEntry("Right Name Width", 4*typeWidth ); + + syncList->addColumn(i18n("Name"),leftNameWidth); + syncList->addColumn(i18n("Size"),leftSizeWidth); + syncList->addColumn(i18n("Date"),leftDateWidth); + syncList->addColumn(i18n("<=>") ,taskTypeWidth); + syncList->addColumn(i18n("Date"),rightDateWidth); + syncList->addColumn(i18n("Size"),rightSizeWidth); + syncList->addColumn(i18n("Name"),rightNameWidth); + syncList->setColumnWidthMode(0,TQListView::Manual); + syncList->setColumnWidthMode(1,TQListView::Manual); + syncList->setColumnWidthMode(2,TQListView::Manual); + syncList->setColumnWidthMode(3,TQListView::Manual); + syncList->setColumnWidthMode(4,TQListView::Manual); + syncList->setColumnWidthMode(5,TQListView::Manual); + syncList->setColumnWidthMode(6,TQListView::Manual); + syncList->setColumnAlignment(1, TQt::AlignRight ); + syncList->setColumnAlignment(3, TQt::AlignHCenter ); + syncList->setColumnAlignment(5, TQt::AlignRight ); + + syncList->header()->setStretchEnabled( true, 0 ); + + synchronizerGrid->addWidget(syncList,1,0); + + synchronizerTabs->insertTab( synchronizerTab, i18n( "&Synchronizer" ) ); + synchGrid->addWidget( synchronizerTabs, 0, 0 ); + + filterTabs = FilterTabs::addTo( synchronizerTabs, FilterTabs::HasDontSearchIn ); + generalFilter = (GeneralFilter *)filterTabs->get( "GeneralFilter" ); + generalFilter->searchFor->setEditText( fileFilter->currentText() ); + generalFilter->searchForCase->setChecked( true ); + + // creating the time shift, equality threshold, hidden files options + + TQGroupBox *optionsGroup = new TQGroupBox( generalFilter, "options" ); + optionsGroup->setTitle( i18n( "&Options" ) ); + optionsGroup->setColumnLayout(0, TQt::Vertical ); + optionsGroup->layout()->setSpacing( 0 ); + optionsGroup->layout()->setMargin( 0 ); + TQGridLayout *optionsLayout = new TQGridLayout( optionsGroup->layout() ); + optionsLayout->setAlignment( TQt::AlignTop ); + optionsLayout->setSpacing( 6 ); + optionsLayout->setMargin( 11 ); + + TQLabel * parallelThreadsLabel = new TQLabel( i18n( "Parallel threads:" ), optionsGroup ); + optionsLayout->addWidget( parallelThreadsLabel, 0, 0 ); + parallelThreadsSpinBox = new TQSpinBox( optionsGroup, "parallelThreadsSpinBox" ); + parallelThreadsSpinBox->setMinValue( 1 ); + parallelThreadsSpinBox->setMaxValue( 15 ); + krConfig->setGroup( "Synchronize" ); + int parThreads = krConfig->readNumEntry( "Parallel Threads", 1 ); + parallelThreadsSpinBox->setValue( parThreads ); + + optionsLayout->addWidget( parallelThreadsSpinBox, 0, 1 ); + + TQLabel * equalityLabel = new TQLabel( i18n( "Equality threshold:" ), optionsGroup ); + optionsLayout->addWidget( equalityLabel, 1, 0 ); + + equalitySpinBox = new TQSpinBox( optionsGroup, "equalitySpinBox" ); + equalitySpinBox->setMaxValue( 9999 ); + optionsLayout->addWidget( equalitySpinBox, 1, 1 ); + + equalityUnitCombo = new TQComboBox( optionsGroup, "equalityUnitCombo" ); + equalityUnitCombo->insertItem( i18n( "sec" ) ); + equalityUnitCombo->insertItem( i18n( "min" ) ); + equalityUnitCombo->insertItem( i18n( "hour" ) ); + equalityUnitCombo->insertItem( i18n( "day" ) ); + optionsLayout->addWidget( equalityUnitCombo, 1, 2 ); + + TQLabel * timeShiftLabel = new TQLabel( i18n( "Time shift (right-left):" ), optionsGroup ); + optionsLayout->addWidget( timeShiftLabel, 2, 0 ); + + timeShiftSpinBox = new TQSpinBox( optionsGroup, "timeShiftSpinBox" ); + timeShiftSpinBox->setMinValue( -9999 ); + timeShiftSpinBox->setMaxValue( 9999 ); + optionsLayout->addWidget( timeShiftSpinBox, 2, 1 ); + + timeShiftUnitCombo = new TQComboBox( optionsGroup, "timeShiftUnitCombo" ); + timeShiftUnitCombo->insertItem( i18n( "sec" ) ); + timeShiftUnitCombo->insertItem( i18n( "min" ) ); + timeShiftUnitCombo->insertItem( i18n( "hour" ) ); + timeShiftUnitCombo->insertItem( i18n( "day" ) ); + optionsLayout->addWidget( timeShiftUnitCombo, 2, 2 ); + + TQFrame *line = new TQFrame( optionsGroup ); + line->setFrameStyle( TQFrame::HLine | TQFrame::Sunken ); + optionsLayout->addMultiCellWidget( line, 3, 3, 0, 2 ); + + ignoreHiddenFilesCB = new TQCheckBox( i18n( "Ignore hidden files" ), optionsGroup ); + optionsLayout->addMultiCellWidget( ignoreHiddenFilesCB, 4, 4, 0, 2 ); + + generalFilter->middleLayout->addWidget( optionsGroup ); + + + /* ================================== Buttons =================================== */ + + TQHBoxLayout *buttons = new TQHBoxLayout; + buttons->setSpacing( 6 ); + buttons->setMargin( 0 ); + + profileManager = new ProfileManager( "SynchronizerProfile", this, "profileManager" ); + profileManager->setAccel( CTRL + Key_P ); + TQWhatsThis::add( profileManager, i18n( "Profile manager (Ctrl+P)." ) ); + buttons->addWidget( profileManager ); + + TQPixmap swapSides( ( const char** ) swap_sides_data ); + btnSwapSides = new TQPushButton( this, "btnSwapSides" ); + btnSwapSides->setPixmap( swapSides ); + btnSwapSides->setAccel( CTRL + Key_S ); + TQWhatsThis::add( btnSwapSides, i18n( "Swap sides (Ctrl+S)." ) ); + buttons->addWidget( btnSwapSides ); + + statusLabel = new TQLabel( this, "statusLabel" ); + buttons->addWidget( statusLabel ); + + TQSpacerItem* spacer = new TQSpacerItem( 20, 20, TQSizePolicy::Expanding, TQSizePolicy::Minimum ); + buttons->addItem( spacer ); + + btnCompareDirs = new TQPushButton( this, "btnCompareDirs" ); + btnCompareDirs->setText( i18n( "Compare" ) ); + btnCompareDirs->setDefault(true); + buttons->addWidget( btnCompareDirs ); + + krConfig->setGroup("Synchronize"); + btnScrollResults = new TQPushButton( this, "btnSynchronize" ); + btnScrollResults->setToggleButton( true ); + btnScrollResults->setOn( krConfig->readBoolEntry( "Scroll Results", _ScrollResults ) ); + btnScrollResults->hide(); + if( btnScrollResults->isOn() ) + btnScrollResults->setText( i18n( "Quiet" ) ); + else + btnScrollResults->setText( i18n( "Scroll Results" ) ); + buttons->addWidget( btnScrollResults ); + + btnStopComparing = new TQPushButton( this, "btnStopComparing" ); + btnStopComparing->setText( i18n( "Stop" ) ); + btnStopComparing->setEnabled(false); + buttons->addWidget( btnStopComparing ); + + btnFeedToListBox = new TQPushButton( this, "btnFeedToListBox" ); + btnFeedToListBox->setText( i18n( "Feed to listbox" ) ); + btnFeedToListBox->setEnabled(false); + btnFeedToListBox->hide(); + buttons->addWidget( btnFeedToListBox ); + + btnSynchronize = new TQPushButton( this, "btnSynchronize" ); + btnSynchronize->setText( i18n( "Synchronize" ) ); + btnSynchronize->setEnabled(false); + buttons->addWidget( btnSynchronize ); + + TQPushButton *btnCloseSync = new TQPushButton( this, "btnCloseSync" ); + btnCloseSync->setText( i18n( "Close" ) ); + buttons->addWidget( btnCloseSync ); + + synchGrid->addLayout( buttons, 1, 0 ); + + /* =============================== Connect table ================================ */ + + connect( syncList,TQ_SIGNAL(rightButtonPressed(TQListViewItem *, const TQPoint &, int)), + this, TQ_SLOT(rightMouseClicked(TQListViewItem *))); + connect( syncList,TQ_SIGNAL(doubleClicked(TQListViewItem *, const TQPoint &, int)), + this, TQ_SLOT(doubleClicked(TQListViewItem *))); + + connect( syncList,TQ_SIGNAL(contextMenuRequested(TQListViewItem *, const TQPoint &, int)), + this, TQ_SLOT(rightMouseClicked(TQListViewItem *))); + + connect( profileManager, TQ_SIGNAL( loadFromProfile( TQString ) ), this, TQ_SLOT( loadFromProfile( TQString ) ) ); + connect( profileManager, TQ_SIGNAL( saveToProfile( TQString ) ), this, TQ_SLOT( saveToProfile( TQString ) ) ); + + connect( btnSwapSides, TQ_SIGNAL( clicked() ), this, TQ_SLOT( swapSides() ) ); + connect( btnCompareDirs, TQ_SIGNAL( clicked() ), this, TQ_SLOT( compare() ) ); + connect( btnStopComparing, TQ_SIGNAL( clicked() ), this, TQ_SLOT( stop() ) ); + connect( btnFeedToListBox, TQ_SIGNAL( clicked() ), this, TQ_SLOT( feedToListBox() ) ); + connect( btnSynchronize, TQ_SIGNAL( clicked() ), this, TQ_SLOT( synchronize() ) ); + connect( btnScrollResults, TQ_SIGNAL( toggled(bool) ), this, TQ_SLOT( setScrolling(bool) ) ); + connect( btnCloseSync, TQ_SIGNAL( clicked() ), this, TQ_SLOT( closeDialog() ) ); + + connect( cbSubdirs, TQ_SIGNAL( toggled(bool) ), this, TQ_SLOT( subdirsChecked( bool ) ) ); + connect( cbAsymmetric, TQ_SIGNAL( toggled(bool) ), this, TQ_SLOT( setPanelLabels() ) ); + + connect( &synchronizer, TQ_SIGNAL( comparedFileData( SynchronizerFileItem * ) ), this, + TQ_SLOT( addFile( SynchronizerFileItem * ) ) ); + connect( &synchronizer, TQ_SIGNAL( markChanged( SynchronizerFileItem *, bool ) ), this, + TQ_SLOT( markChanged( SynchronizerFileItem *, bool ) ) ); + connect( &synchronizer, TQ_SIGNAL( statusInfo( TQString ) ), this, TQ_SLOT( statusInfo( TQString ) ) ); + + connect( btnLeftToRight, TQ_SIGNAL( toggled(bool) ), this, TQ_SLOT( refresh() ) ); + connect( btnEquals, TQ_SIGNAL( toggled(bool) ), this, TQ_SLOT( refresh() ) ); + connect( btnDifferents, TQ_SIGNAL( toggled(bool) ), this, TQ_SLOT( refresh() ) ); + connect( btnRightToLeft, TQ_SIGNAL( toggled(bool) ), this, TQ_SLOT( refresh() ) ); + connect( btnDeletable, TQ_SIGNAL( toggled(bool) ), this, TQ_SLOT( refresh() ) ); + connect( btnDuplicates, TQ_SIGNAL( toggled(bool) ), this, TQ_SLOT( refresh() ) ); + connect( btnSingles, TQ_SIGNAL( toggled(bool) ), this, TQ_SLOT( refresh() ) ); + + connect( fileFilter, TQ_SIGNAL( textChanged( const TQString & ) ), this, TQ_SLOT( connectFilters( const TQString & ) ) ); + connect( generalFilter->searchFor, TQ_SIGNAL( textChanged( const TQString & ) ), this, TQ_SLOT( connectFilters( const TQString & ) ) ); + connect( generalFilter->searchFor, TQ_SIGNAL( textChanged( const TQString & ) ), this, TQ_SLOT( setCompletion() ) ); + connect( generalFilter->dontSearchIn, TQ_SIGNAL( checkValidity( TQString &, TQString & ) ), + this, TQ_SLOT( checkExcludeURLValidity( TQString &, TQString & ) ) ); + + connect( profileManager, TQ_SIGNAL( loadFromProfile( TQString ) ), filterTabs, TQ_SLOT( loadFromProfile( TQString ) ) ); + connect( profileManager, TQ_SIGNAL( saveToProfile( TQString ) ), filterTabs, TQ_SLOT( saveToProfile( TQString ) ) ); + + setPanelLabels(); + setCompletion(); + + /* =============================== Loading the colors ================================ */ + + krConfig->setGroup("Colors"); + + DECLARE_COLOR_NAME_ARRAY; + DECLARE_BACKGROUND_DFLTS; + DECLARE_FOREGROUND_DFLTS; + + for( int clr = 0; clr != TT_MAX; clr ++ ) { + TQString foreEntry = TQString( "Synchronizer " ) + COLOR_NAMES[ clr ] + TQString( " Foreground" ); + TQString bckgEntry = TQString( "Synchronizer " ) + COLOR_NAMES[ clr ] + TQString( " Background" ); + + if( krConfig->readEntry( foreEntry ) == "KDE default" ) + foreGrounds[ clr ] = TQColor(); + else + foreGrounds[ clr ] = krConfig->readColorEntry( foreEntry, &FORE_DFLTS[ clr ] ); + + if( krConfig->readEntry( bckgEntry ) == "KDE default" ) + backGrounds[ clr ] = TQColor(); + else + backGrounds[ clr ] = krConfig->readColorEntry( bckgEntry, &BCKG_DFLTS[ clr ] ); + } + if( backGrounds[ TT_EQUALS ].isValid() ) + syncList->setPaletteBackgroundColor( backGrounds[ TT_EQUALS ] ); + + krConfig->setGroup("Synchronize"); + int sx = krConfig->readNumEntry( "Window Width", -1 ); + int sy = krConfig->readNumEntry( "Window Height", -1 ); + + if( sx != -1 && sy != -1 ) + resize( sx, sy ); + + if( krConfig->readBoolEntry( "Window Maximized", false ) ) + showMaximized(); + else + show(); + + if( !profileName.isNull() ) + profileManager->loadProfile( profileName ); + + synchronizer.setParentWidget( this ); +} + +SynchronizerGUI::~SynchronizerGUI() +{ + syncList->clear(); // for sanity: deletes the references to the synchronizer list +} + +void SynchronizerGUI::setPanelLabels() +{ + if( hasSelectedFiles && cbAsymmetric->isChecked() ) + { + leftDirLabel->setText( i18n( "Selected files from targ&et directory:" ) ); + rightDirLabel->setText( i18n( "Selected files from sou&rce directory:" ) ); + } + else if( hasSelectedFiles && !cbAsymmetric->isChecked() ) + { + leftDirLabel->setText( i18n( "Selected files from &left directory:" ) ); + rightDirLabel->setText( i18n( "Selected files from &right directory:" ) ); + } + else if( cbAsymmetric->isChecked() ) + { + leftDirLabel->setText( i18n( "Targ&et directory:" ) ); + rightDirLabel->setText( i18n( "Sou&rce directory:" ) ); + } + else + { + leftDirLabel->setText( i18n( "&Left directory:" ) ); + rightDirLabel->setText( i18n( "&Right directory:" ) ); + } +} + +void SynchronizerGUI::setCompletion() +{ + generalFilter->dontSearchIn->setCompletionDir( rightLocation->currentText() ); +} + +void SynchronizerGUI::checkExcludeURLValidity( TQString &text, TQString &error ) +{ + KURL url = vfs::fromPathOrURL( text ); + if( KURL::isRelativeURL( url.url() ) ) + return; + + TQString leftBase = leftLocation->currentText(); + if( !leftBase.endsWith( "/" ) ) + leftBase += "/"; + KURL leftBaseURL = vfs::fromPathOrURL( leftBase ); + if( leftBaseURL.isParentOf( url ) && !url.isParentOf( leftBaseURL) ) + { + text = KURL::relativeURL( leftBaseURL, url ); + return; + } + + TQString rightBase = rightLocation->currentText(); + if( !rightBase.endsWith( "/" ) ) + rightBase += "/"; + KURL rightBaseURL = vfs::fromPathOrURL( rightBase ); + if( rightBaseURL.isParentOf( url ) && !url.isParentOf( rightBaseURL ) ) + { + text = KURL::relativeURL( rightBaseURL, url ); + return; + } + + error = i18n("URL must be the descendant of either the left or the right base URL!"); +} + +void SynchronizerGUI::doubleClicked(TQListViewItem *itemIn) +{ + if (!itemIn) + return; + + SyncViewItem *syncItem = (SyncViewItem *)itemIn; + SynchronizerFileItem *item = syncItem->synchronizerItemRef(); + if( item && item->existsInLeft() && item->existsInRight() && !item->isDir() ) + { + TQString leftDirName = item->leftDirectory().isEmpty() ? "" : item->leftDirectory() + "/"; + TQString rightDirName = item->rightDirectory().isEmpty() ? "" : item->rightDirectory() + "/"; + KURL leftURL = vfs::fromPathOrURL( synchronizer.leftBaseDirectory() + leftDirName + item->leftName() ); + KURL rightURL = vfs::fromPathOrURL( synchronizer.rightBaseDirectory() + rightDirName + item->rightName() ); + + SLOTS->compareContent( leftURL, rightURL ); + } +} + +void SynchronizerGUI::rightMouseClicked(TQListViewItem *itemIn) +{ + // these are the values that will exist in the menu + #define EXCLUDE_ID 90 + #define RESTORE_ID 91 + #define COPY_TO_LEFT_ID 92 + #define COPY_TO_RIGHT_ID 93 + #define REVERSE_DIR_ID 94 + #define DELETE_ID 95 + #define VIEW_LEFT_FILE_ID 96 + #define VIEW_RIGHT_FILE_ID 97 + #define COMPARE_FILES_ID 98 + #define SELECT_ITEMS_ID 99 + #define DESELECT_ITEMS_ID 100 + #define INVERT_SELECTION_ID 101 + #define SYNCH_WITH_KGET_ID 102 + #define COPY_CLPBD_LEFT_ID 103 + #define COPY_CLPBD_RIGHT_ID 104 + ////////////////////////////////////////////////////////// + if (!itemIn) + return; + + SyncViewItem *syncItem = (SyncViewItem *)itemIn; + if( syncItem == 0 ) + return; + + SynchronizerFileItem *item = syncItem->synchronizerItemRef(); + + bool isDuplicate = item->existsInLeft() && item->existsInRight(); + bool isDir = item->isDir(); + TQString leftDirName = item->leftDirectory().isEmpty() ? "" : item->leftDirectory() + "/"; + TQString rightDirName = item->rightDirectory().isEmpty() ? "" : item->rightDirectory() + "/"; + + KURL leftURL = vfs::fromPathOrURL( synchronizer.leftBaseDirectory() + leftDirName + item->leftName() ); + KURL rightURL = vfs::fromPathOrURL( synchronizer.rightBaseDirectory() + rightDirName + item->rightName() ); + + // create the menu + TDEPopupMenu popup; + popup.insertTitle(i18n("Synchronize Directories")); + + popup.insertItem(i18n("E&xclude"),EXCLUDE_ID); + popup.setItemEnabled(EXCLUDE_ID, true ); + popup.insertItem(i18n("Restore ori&ginal operation"),RESTORE_ID); + popup.setItemEnabled(RESTORE_ID, true ); + popup.insertItem(i18n("Re&verse direction"),REVERSE_DIR_ID); + popup.setItemEnabled(REVERSE_DIR_ID, true ); + popup.insertItem(i18n("Copy from &right to left"),COPY_TO_LEFT_ID); + popup.setItemEnabled(COPY_TO_LEFT_ID, true ); + popup.insertItem(i18n("Copy from &left to right"),COPY_TO_RIGHT_ID); + popup.setItemEnabled(COPY_TO_RIGHT_ID, true ); + popup.insertItem(i18n("&Delete (left single)"),DELETE_ID); + popup.setItemEnabled(DELETE_ID, true ); + + popup.insertSeparator(); + + popup.insertItem(i18n("V&iew left file"),VIEW_LEFT_FILE_ID); + popup.setItemEnabled(VIEW_LEFT_FILE_ID, !isDir && item->existsInLeft() ); + popup.insertItem(i18n("Vi&ew right file"),VIEW_RIGHT_FILE_ID); + popup.setItemEnabled(VIEW_RIGHT_FILE_ID, !isDir && item->existsInRight() ); + popup.insertItem(i18n("&Compare Files"),COMPARE_FILES_ID); + popup.setItemEnabled(COMPARE_FILES_ID, !isDir && isDuplicate ); + + popup.insertSeparator(); + + popup.insertItem(i18n("C&opy selected to clipboard (left)"),COPY_CLPBD_LEFT_ID); + popup.insertItem(i18n("Co&py selected to clipboard (right)"),COPY_CLPBD_RIGHT_ID); + + popup.insertSeparator(); + + popup.insertItem(i18n("&Select items"),SELECT_ITEMS_ID); + popup.setItemEnabled(SELECT_ITEMS_ID, true ); + popup.insertItem(i18n("Deselec&t items"),DESELECT_ITEMS_ID); + popup.setItemEnabled(DESELECT_ITEMS_ID, true ); + popup.insertItem(i18n("I&nvert selection"),INVERT_SELECTION_ID); + popup.setItemEnabled(INVERT_SELECTION_ID, true ); + + KURL leftBDir = vfs::fromPathOrURL( synchronizer.leftBaseDirectory() ); + KURL rightBDir = vfs::fromPathOrURL( synchronizer.rightBaseDirectory() ); + + if( KrServices::cmdExist( "kget" ) && + ( ( !leftBDir.isLocalFile() && rightBDir.isLocalFile() && btnLeftToRight->isOn() ) || + ( leftBDir.isLocalFile() && !rightBDir.isLocalFile() && btnRightToLeft->isOn() ) ) ) + { + popup.insertSeparator(); + popup.insertItem(i18n("Synchronize with &KGet"),SYNCH_WITH_KGET_ID); + popup.setItemEnabled(SYNCH_WITH_KGET_ID, true ); + } + + int result=popup.exec(TQCursor::pos()); + + // check out the user's option + switch (result) + { + case EXCLUDE_ID: + case RESTORE_ID: + case COPY_TO_LEFT_ID: + case COPY_TO_RIGHT_ID: + case REVERSE_DIR_ID: + case DELETE_ID: + { + unsigned ndx = 0; + SynchronizerFileItem *currentItem; + + while( ( currentItem = synchronizer.getItemAt( ndx++ ) ) != 0 ) + { + SyncViewItem *viewItem = (SyncViewItem *)currentItem->userData(); + + if( !viewItem || !viewItem->isSelected() || !viewItem->isVisible() ) + continue; + + switch( result ) + { + case EXCLUDE_ID: + synchronizer.exclude( viewItem->synchronizerItemRef() ); + break; + case RESTORE_ID: + synchronizer.restore( viewItem->synchronizerItemRef() ); + break; + case REVERSE_DIR_ID: + synchronizer.reverseDirection( viewItem->synchronizerItemRef() ); + break; + case COPY_TO_LEFT_ID: + synchronizer.copyToLeft( viewItem->synchronizerItemRef() ); + break; + case COPY_TO_RIGHT_ID: + synchronizer.copyToRight( viewItem->synchronizerItemRef() ); + break; + case DELETE_ID: + synchronizer.deleteLeft( viewItem->synchronizerItemRef() ); + break; + } + } + + refresh(); + } + break; + case VIEW_LEFT_FILE_ID: + KrViewer::view( leftURL, this ); // view the file + break; + case VIEW_RIGHT_FILE_ID: + KrViewer::view( rightURL, this ); // view the file + break; + case COMPARE_FILES_ID: + SLOTS->compareContent( leftURL, rightURL ); + break; + case SELECT_ITEMS_ID: + case DESELECT_ITEMS_ID: + { + KRQuery query = KRSpWidgets::getMask( ( result == SELECT_ITEMS_ID ? i18n("Select items") : + i18n( "Deselect items" ) ), true ); + if( query.isNull() ) + break; + + unsigned ndx = 0; + SynchronizerFileItem *currentItem; + + while( ( currentItem = synchronizer.getItemAt( ndx++ ) ) != 0 ) + { + SyncViewItem *viewItem = (SyncViewItem *)currentItem->userData(); + + if( !viewItem || !viewItem->isVisible() ) + continue; + + if( query.match( currentItem->leftName() ) || + query.match( currentItem->rightName() ) ) + syncList->setSelected( viewItem, result == SELECT_ITEMS_ID ); + } + } + break; + case INVERT_SELECTION_ID: + syncList->invertSelection(); + break; + case SYNCH_WITH_KGET_ID: + synchronizer.synchronizeWithKGet(); + closeDialog(); + break; + case COPY_CLPBD_LEFT_ID: + copyToClipboard( true ); + break; + case COPY_CLPBD_RIGHT_ID: + copyToClipboard( false ); + break; + case -1 : return; // the user clicked outside of the menu + } +} + +void SynchronizerGUI::closeDialog() +{ + if( isComparing ) + { + stop(); + wasClosed = true; + return; + } + + TQStringList list = leftLocation->historyItems(); + krConfig->setGroup("Synchronize"); + krConfig->writeEntry("Left Directory History", list); + list = rightLocation->historyItems(); + krConfig->writeEntry("Right Directory History", list); + list = fileFilter->historyItems(); + krConfig->writeEntry("File Filter", list); + + krConfig->writeEntry("Recurse Subdirectories", cbSubdirs->isChecked() ); + krConfig->writeEntry("Follow Symlinks", cbSymlinks->isChecked() ); + krConfig->writeEntry("Compare By Content", cbByContent->isChecked() ); + krConfig->writeEntry("Ignore Date", cbIgnoreDate->isChecked() ); + krConfig->writeEntry("Asymmetric", cbAsymmetric->isChecked() ); + krConfig->writeEntry("Ignore Case", cbIgnoreCase->isChecked() ); + krConfig->writeEntry("LeftToRight Button", btnLeftToRight->isOn() ); + krConfig->writeEntry("Equals Button", btnEquals->isOn() ); + krConfig->writeEntry("Differents Button", btnDifferents->isOn() ); + krConfig->writeEntry("RightToLeft Button", btnRightToLeft->isOn() ); + krConfig->writeEntry("Deletable Button", btnDeletable->isOn() ); + krConfig->writeEntry("Duplicates Button", btnDuplicates->isOn() ); + krConfig->writeEntry("Singles Button", btnSingles->isOn() ); + + krConfig->writeEntry("Scroll Results", btnScrollResults->isOn() ); + + krConfig->writeEntry("Parallel Threads", parallelThreadsSpinBox->value() ); + + krConfig->writeEntry("Window Width", sizeX ); + krConfig->writeEntry("Window Height", sizeY ); + krConfig->writeEntry("Window Maximized", isMaximized() ); + + krConfig->writeEntry("Left Name Width", syncList->columnWidth( 0 ) ); + krConfig->writeEntry("Left Size Width", syncList->columnWidth( 1 ) ); + krConfig->writeEntry("Left Date Width", syncList->columnWidth( 2 ) ); + krConfig->writeEntry("Task Type Width", syncList->columnWidth( 3 ) ); + krConfig->writeEntry("Right Date Width", syncList->columnWidth( 4 ) ); + krConfig->writeEntry("Right Size Width", syncList->columnWidth( 5 ) ); + krConfig->writeEntry("Right Name Width", syncList->columnWidth( 6 ) ); + + TQDialog::reject(); + + this->deleteLater(); + + if( wasSync ) + { + ListPanel *p=ACTIVE_PANEL; + MAIN_VIEW->left->func->refresh(); + MAIN_VIEW->right->func->refresh(); + p->slotFocusOnMe(); + } +} + +void SynchronizerGUI::compare() +{ + KRQuery query; + + if( !filterTabs->fillQuery( &query ) ) + return; + + query.setNameFilter( fileFilter->currentText(), query.isCaseSensitive() ); + synchronizerTabs->setCurrentPage(0); + + syncList->clear(); + lastItem = 0; + + leftLocation->addToHistory(leftLocation->currentText()); + rightLocation->addToHistory(rightLocation->currentText()); + fileFilter->addToHistory(fileFilter->currentText()); + + setMarkFlags(); + + btnCompareDirs->setEnabled( false ); + profileManager->setEnabled( false ); + btnSwapSides->setEnabled( false ); + btnStopComparing->setEnabled( isComparing = true ); + btnStopComparing->show(); + btnFeedToListBox->setEnabled( false ); + btnFeedToListBox->hide(); + btnSynchronize->setEnabled( false ); + btnCompareDirs->hide(); + btnScrollResults->show(); + disableMarkButtons(); + + int fileCount = synchronizer.compare(leftLocation->currentText(), rightLocation->currentText(), + &query, cbSubdirs->isChecked(), cbSymlinks->isChecked(), + cbIgnoreDate->isChecked(), cbAsymmetric->isChecked(), cbByContent->isChecked(), + cbIgnoreCase->isChecked(), btnScrollResults->isOn(), selectedFiles, + convertToSeconds( equalitySpinBox->value(), equalityUnitCombo->currentItem() ), + convertToSeconds( timeShiftSpinBox->value(), timeShiftUnitCombo->currentItem() ), + parallelThreadsSpinBox->value(), ignoreHiddenFilesCB->isChecked() ); + enableMarkButtons(); + btnStopComparing->setEnabled( isComparing = false ); + btnStopComparing->hide(); + btnFeedToListBox->show(); + btnCompareDirs->setEnabled( true ); + profileManager->setEnabled( true ); + btnSwapSides->setEnabled( true ); + btnCompareDirs->show(); + btnScrollResults->hide(); + if( fileCount ) { + btnSynchronize->setEnabled( true ); + btnFeedToListBox->setEnabled( true ); + } + + syncList->setFocus(); + + if( wasClosed ) + closeDialog(); +} + +void SynchronizerGUI::stop() +{ + synchronizer.stop(); +} + +void SynchronizerGUI::feedToListBox() +{ + FeedToListBoxDialog listBox( this, "feedToListBoxDialog", &synchronizer, syncList, btnEquals->isOn() ); + if( listBox.isAccepted() ) + closeDialog(); +} + +void SynchronizerGUI::reject() +{ + closeDialog(); +} + +void SynchronizerGUI::addFile( SynchronizerFileItem *item ) +{ + TQString leftName="", rightName="", leftDate="", rightDate="", leftSize="", rightSize=""; + bool isDir = item->isDir(); + + TQColor textColor = foreGrounds[ item->task() ]; + TQColor baseColor = backGrounds[ item->task() ]; + + if( item->existsInLeft() ) + { + leftName = item->leftName(); + leftSize = isDir ? i18n("<DIR>")+" " : KRpermHandler::parseSize( item->leftSize() ); + leftDate = SynchronizerGUI::convertTime( item->leftDate() ); + } + + if( item->existsInRight() ) + { + rightName = item->rightName(); + rightSize = isDir ? i18n("<DIR>")+" " : KRpermHandler::parseSize( item->rightSize() ); + rightDate = SynchronizerGUI::convertTime( item->rightDate() ); + } + + SyncViewItem *listItem = 0; + SyncViewItem *dirItem; + + if( item->parent() == 0 ) + { + listItem = new SyncViewItem(item, textColor, baseColor, syncList, lastItem, leftName, leftSize, + leftDate, Synchronizer::getTaskTypeName( item->task() ), rightDate, + rightSize, rightName ); + lastItem = listItem; + } + else + { + dirItem = (SyncViewItem *)item->parent()->userData(); + if( dirItem ) + { + dirItem->setOpen( true ); + listItem = new SyncViewItem(item, textColor, baseColor, dirItem, dirItem->lastItem(), leftName, + leftSize, leftDate, Synchronizer::getTaskTypeName( item->task() ), + rightDate, rightSize, rightName ); + + dirItem->setLastItem( listItem ); + } + } + + if( listItem ) + { + listItem->setPixmap(0, isDir ? folderIcon : fileIcon); + if( !item->isMarked() ) + listItem->setVisible( false ); + else + syncList->ensureItemVisible( listItem ); + } +} + +void SynchronizerGUI::markChanged( SynchronizerFileItem *item, bool ensureVisible ) +{ + SyncViewItem *listItem = (SyncViewItem *)item->userData(); + if( listItem ) + { + if( !item->isMarked() ) { + listItem->setVisible( false ); + } else { + TQString leftName="", rightName="", leftDate="", rightDate="", leftSize="", rightSize=""; + bool isDir = item->isDir(); + + if( item->existsInLeft() ) + { + leftName = item->leftName(); + leftSize = isDir ? i18n("<DIR>")+" " : KRpermHandler::parseSize( item->leftSize() ); + leftDate = SynchronizerGUI::convertTime( item->leftDate() ); + } + + if( item->existsInRight() ) + { + rightName = item->rightName(); + rightSize = isDir ? i18n("<DIR>")+" " : KRpermHandler::parseSize( item->rightSize() ); + rightDate = SynchronizerGUI::convertTime( item->rightDate() ); + } + + listItem->setVisible( true ); + listItem->setText( 0, leftName ); + listItem->setText( 1, leftSize ); + listItem->setText( 2, leftDate ); + listItem->setColors( foreGrounds[ item->task() ], backGrounds[ item->task() ] ); + listItem->setText( 3, Synchronizer::getTaskTypeName( item->task() ) ); + listItem->setText( 4, rightDate ); + listItem->setText( 5, rightSize ); + listItem->setText( 6, rightName ); + + if( ensureVisible ) + syncList->ensureItemVisible( listItem ); + } + } +} + +void SynchronizerGUI::subdirsChecked( bool isOn ) +{ + cbSymlinks->setEnabled( isOn ); +} + +void SynchronizerGUI::disableMarkButtons() +{ + btnLeftToRight->setEnabled( false ); + btnEquals->setEnabled( false ); + btnDifferents->setEnabled( false ); + btnRightToLeft->setEnabled( false ); + btnDeletable->setEnabled( false ); + btnDuplicates->setEnabled( false ); + btnSingles->setEnabled( false ); +} + +void SynchronizerGUI::enableMarkButtons() +{ + btnLeftToRight->setEnabled( true ); + btnEquals->setEnabled( true ); + btnDifferents->setEnabled( true ); + btnRightToLeft->setEnabled( true ); + btnDeletable->setEnabled( true ); + btnDuplicates->setEnabled( true ); + btnSingles->setEnabled( true ); +} + +TQString SynchronizerGUI::convertTime(time_t time) const +{ + // convert the time_t to struct tm + struct tm* t=localtime((time_t *)&time); + + TQDateTime tmp(TQDate(t->tm_year+1900, t->tm_mon+1, t->tm_mday), TQTime(t->tm_hour, t->tm_min)); + return TDEGlobal::locale()->formatDateTime(tmp); +} + +void SynchronizerGUI::setMarkFlags() +{ + synchronizer.setMarkFlags( btnRightToLeft->isOn(), btnEquals->isOn(), btnDifferents->isOn(), + btnLeftToRight->isOn(), btnDuplicates->isOn(), btnSingles->isOn(), + btnDeletable->isOn() ); +} + +void SynchronizerGUI::refresh() +{ + if( !isComparing ) + { + syncList->clearSelection(); + setMarkFlags(); + btnCompareDirs->setEnabled( false ); + profileManager->setEnabled( false ); + btnSwapSides->setEnabled( false ); + btnSynchronize->setEnabled( false ); + btnFeedToListBox->setEnabled( false ); + disableMarkButtons(); + int fileCount = synchronizer.refresh(); + enableMarkButtons(); + btnCompareDirs->setEnabled( true ); + profileManager->setEnabled( true ); + btnSwapSides->setEnabled( true ); + if( fileCount ) { + btnFeedToListBox->setEnabled( true ); + btnSynchronize->setEnabled( true ); + } + } +} + +void SynchronizerGUI::synchronize() +{ + int copyToLeftNr, copyToRightNr, deleteNr; + TDEIO::filesize_t copyToLeftSize, copyToRightSize, deleteSize; + + if( !synchronizer.totalSizes( ©ToLeftNr, ©ToLeftSize, ©ToRightNr, ©ToRightSize, + &deleteNr, &deleteSize ) ) + { + KMessageBox::sorry(parentWidget(), i18n("Synchronizer has nothing to do!")); + return; + } + + SynchronizeDialog *sd = new SynchronizeDialog( this, "SychDialog", true, 0, &synchronizer, + copyToLeftNr, copyToLeftSize, copyToRightNr, + copyToRightSize, deleteNr, deleteSize, + parallelThreadsSpinBox->value() ); + + wasSync = sd->wasSyncronizationStarted(); + delete sd; + + if( wasSync ) + closeDialog(); +} + +void SynchronizerGUI::resizeEvent( TQResizeEvent *e ) +{ + if( !isMaximized() ) + { + sizeX = e->size().width(); + sizeY = e->size().height(); + } + + if( !firstResize ) + { + int delta = e->size().width() - e->oldSize().width() + (e->size().width() & 1 ); + int newSize = syncList->header()->sectionSize( 6 ) + delta/2; + + if( newSize > 20 ) + syncList->header()->resizeSection( 6, newSize ); + + syncList->header()->adjustHeaderSize(); + } + firstResize = false; + TQDialog::resizeEvent( e ); +} + +void SynchronizerGUI::statusInfo( TQString info ) +{ + statusLabel->setText( info ); + tqApp->processEvents(); +} + +void SynchronizerGUI::swapSides() +{ + if( btnCompareDirs->isEnabled() ) + { + TQString leftCurrent = leftLocation->currentText(); + leftLocation->setCurrentText( rightLocation->currentText() ); + rightLocation->setCurrentText( leftCurrent ); + synchronizer.swapSides(); + refresh(); + } +} + +void SynchronizerGUI::keyPressEvent( TQKeyEvent *e ) +{ + switch ( e->key() ) + { + case Key_M : + { + if( e->state() == ControlButton ) + { + syncList->setFocus(); + e->accept(); + } + break; + } + case Key_F3 : + case Key_F4 : + { + e->accept(); + TQListViewItem *listItem = syncList->currentItem(); + if( listItem == 0 ) + break; + + bool isedit = e->key() == Key_F4; + + SynchronizerFileItem *item = ((SyncViewItem *)listItem)->synchronizerItemRef(); + TQString leftDirName = item->leftDirectory().isEmpty() ? "" : item->leftDirectory() + "/"; + TQString rightDirName = item->rightDirectory().isEmpty() ? "" : item->rightDirectory() + "/"; + + if( item->isDir() ) + return; + + if ( e->state() == ShiftButton && item->existsInRight() ) + { + KURL rightURL = vfs::fromPathOrURL( synchronizer.rightBaseDirectory() + rightDirName + item->rightName() ); + if( isedit ) + KrViewer::edit( rightURL, this ); // view the file + else + KrViewer::view( rightURL, this ); // view the file + return; + } + else if ( e->state() == 0 && item->existsInLeft() ) + { + KURL leftURL = vfs::fromPathOrURL( synchronizer.leftBaseDirectory() + leftDirName + item->leftName() ); + if( isedit ) + KrViewer::edit( leftURL, this ); // view the file + else + KrViewer::view( leftURL, this ); // view the file + return; + } + } + break; + case Key_U : + if( e->state() != ControlButton ) + break; + e->accept(); + swapSides(); + return; + case Key_Enter: + case Key_Return: + if( syncList->hasFocus() ) + { + e->accept(); + + TQListViewItem *listItem = syncList->currentItem(); + if( listItem == 0 || !listItem->isVisible() ) + return; + + SynchronizerFileItem *item = ((SyncViewItem *)listItem)->synchronizerItemRef(); + if( item->isDir() ) { + listItem->setOpen( !listItem->isOpen() ); + return; + } + + if( !item->existsInLeft() || !item->existsInRight() ) + return; + // call compare + doubleClicked( listItem ); + return; + } + break; + case Key_Escape: + if( btnStopComparing->isShown() && btnStopComparing->isEnabled() ) // is it comparing? + { + e->accept(); + btnStopComparing->animateClick(); // just click the stop button + } + else + { + e->accept(); + if( syncList->childCount() != 0 ) + { + int result = KMessageBox::warningYesNo(this, i18n( "The synchronizer window contains data from a previous compare. If you exit, this data will be lost. Do you really want to exit?" ), + i18n("Krusader::Synchronize Directories"), + KStdGuiItem::yes(), KStdGuiItem::no(), "syncGUIexit" ); + if( result != KMessageBox::Yes ) + return; + } + TQDialog::reject(); + } + return; + } + + TQDialog::keyPressEvent( e ); +} + +void SynchronizerGUI::loadFromProfile( TQString profile ) +{ + syncList->clear(); + synchronizer.reset(); + isComparing = wasClosed = false; + btnSynchronize->setEnabled( false ); + btnFeedToListBox->setEnabled( false ); + + krConfig->setGroup( profile ); + + if( !hasSelectedFiles ) + { + leftLocation->setCurrentText( krConfig->readEntry( "Left Location" ) ); + rightLocation->setCurrentText( krConfig->readEntry( "Right Location" ) ); + } + fileFilter->setCurrentText( krConfig->readEntry( "Search For" ) ); + + cbSubdirs-> setChecked( krConfig->readBoolEntry( "Recurse Subdirectories", true ) ); + cbSymlinks-> setChecked( krConfig->readBoolEntry( "Follow Symlinks", false ) ); + cbByContent-> setChecked( krConfig->readBoolEntry( "Compare By Content", false ) ); + cbIgnoreDate->setChecked( krConfig->readBoolEntry( "Ignore Date", false ) ); + cbAsymmetric->setChecked( krConfig->readBoolEntry( "Asymmetric", false ) ); + cbIgnoreCase->setChecked( krConfig->readBoolEntry( "Ignore Case", false ) ); + + btnScrollResults->setOn( krConfig->readBoolEntry( "Scroll Results", false ) ); + + btnLeftToRight->setOn( krConfig->readBoolEntry( "Show Left To Right", true ) ); + btnEquals ->setOn( krConfig->readBoolEntry( "Show Equals", true ) ); + btnDifferents ->setOn( krConfig->readBoolEntry( "Show Differents", true ) ); + btnRightToLeft->setOn( krConfig->readBoolEntry( "Show Right To Left", true ) ); + btnDeletable ->setOn( krConfig->readBoolEntry( "Show Deletable", true ) ); + btnDuplicates ->setOn( krConfig->readBoolEntry( "Show Duplicates", true ) ); + btnSingles ->setOn( krConfig->readBoolEntry( "Show Singles", true ) ); + + int equalityThreshold = krConfig->readNumEntry( "Equality Threshold", 0 ); + int equalityCombo = 0; + convertFromSeconds( equalityThreshold, equalityCombo, equalityThreshold ); + equalitySpinBox->setValue( equalityThreshold ); + equalityUnitCombo->setCurrentItem( equalityCombo ); + + int timeShift = krConfig->readNumEntry( "Time Shift", 0 ); + int timeShiftCombo = 0; + convertFromSeconds( timeShift, timeShiftCombo, timeShift ); + timeShiftSpinBox->setValue( timeShift ); + timeShiftUnitCombo->setCurrentItem( timeShiftCombo ); + + int parallelThreads = krConfig->readNumEntry( "Parallel Threads", 1 ); + parallelThreadsSpinBox->setValue( parallelThreads ); + + bool ignoreHidden = krConfig->readBoolEntry( "Ignore Hidden Files", false ); + ignoreHiddenFilesCB->setChecked( ignoreHidden ); + + refresh(); +} + +void SynchronizerGUI::saveToProfile( TQString profile ) +{ + krConfig->setGroup( profile ); + + krConfig->writeEntry( "Left Location", leftLocation->currentText() ); + krConfig->writeEntry( "Search For", fileFilter->currentText() ); + krConfig->writeEntry( "Right Location", rightLocation->currentText() ); + + krConfig->writeEntry( "Recurse Subdirectories", cbSubdirs->isChecked() ); + krConfig->writeEntry( "Follow Symlinks", cbSymlinks->isChecked() ); + krConfig->writeEntry( "Compare By Content", cbByContent->isChecked() ); + krConfig->writeEntry( "Ignore Date", cbIgnoreDate->isChecked() ); + krConfig->writeEntry( "Asymmetric", cbAsymmetric->isChecked() ); + krConfig->writeEntry( "Ignore Case", cbIgnoreCase->isChecked() ); + + krConfig->writeEntry( "Scroll Results", btnScrollResults->isOn() ); + + krConfig->writeEntry( "Show Left To Right", btnLeftToRight->isOn() ); + krConfig->writeEntry( "Show Equals", btnEquals->isOn() ); + krConfig->writeEntry( "Show Differents", btnDifferents->isOn() ); + krConfig->writeEntry( "Show Right To Left", btnRightToLeft->isOn() ); + krConfig->writeEntry( "Show Deletable", btnDeletable->isOn() ); + krConfig->writeEntry( "Show Duplicates", btnDuplicates->isOn() ); + krConfig->writeEntry( "Show Singles", btnSingles->isOn() ); + + krConfig->writeEntry( "Equality Threshold", convertToSeconds( equalitySpinBox->value(), equalityUnitCombo->currentItem() ) ); + krConfig->writeEntry( "Time Shift", convertToSeconds( timeShiftSpinBox->value(), timeShiftUnitCombo->currentItem() ) ); + krConfig->writeEntry( "Parallel Threads", parallelThreadsSpinBox->value() ); + + krConfig->writeEntry( "Ignore Hidden Files", ignoreHiddenFilesCB->isChecked() ); +} + +void SynchronizerGUI::connectFilters( const TQString &newString ) +{ + if( synchronizerTabs->currentPageIndex() ) + fileFilter->setEditText( newString ); + else + generalFilter->searchFor->setEditText( newString ); +} + +void SynchronizerGUI::setScrolling( bool isOn ) +{ + if( isOn ) + btnScrollResults->setText( i18n( "Quiet" ) ); + else + btnScrollResults->setText( i18n( "Scroll Results" ) ); + + synchronizer.setScrolling( isOn ); +} + +int SynchronizerGUI::convertToSeconds( int time, int unit ) { + switch( unit ) { + case 1: + return time * 60; + case 2: + return time * 3600; + case 3: + return time * 86400; + default: + return time; + } +} + +void SynchronizerGUI::convertFromSeconds( int &time, int &unit, int second ) { + unit = 0; + time = second; + int absTime = (time < 0 ) ? -time: time; + + if( absTime >= 86400 && ( absTime % 86400 ) == 0 ) { + time /= 86400; + unit = 3; + } else if( absTime >= 3600 && ( absTime % 3600 ) == 0 ) { + time /= 3600; + unit = 2; + } else if( absTime >= 60 && ( absTime % 60 ) == 0 ) { + time /= 60; + unit = 1; + } +} + +void SynchronizerGUI::copyToClipboard( bool isLeft ) +{ + KURL::List urls; + + unsigned ndx = 0; + SynchronizerFileItem *currentItem; + + while( ( currentItem = synchronizer.getItemAt( ndx++ ) ) != 0 ) + { + SynchronizerGUI::SyncViewItem *viewItem = (SynchronizerGUI::SyncViewItem *)currentItem->userData(); + + if( !viewItem || !viewItem->isSelected() || !viewItem->isVisible() ) + continue; + + SynchronizerFileItem *item = viewItem->synchronizerItemRef(); + if( item ) + { + if( isLeft && item->existsInLeft() ) + { + TQString leftDirName = item->leftDirectory().isEmpty() ? "" : item->leftDirectory() + "/"; + KURL leftURL = vfs::fromPathOrURL( synchronizer.leftBaseDirectory() + leftDirName + item->leftName() ); + urls.push_back( leftURL ); + } + else if( !isLeft && item->existsInRight() ) + { + TQString rightDirName = item->rightDirectory().isEmpty() ? "" : item->rightDirectory() + "/"; + KURL rightURL = vfs::fromPathOrURL( synchronizer.rightBaseDirectory() + rightDirName + item->rightName() ); + urls.push_back( rightURL ); + } + } + } + + if( urls.count() == 0 ) + return; + + KURLDrag *d = new KURLDrag(urls, this); + d->setPixmap( FL_LOADICON( isLeft ? "2leftarrow" : "2rightarrow" ), TQPoint( -7, 0 ) ); + TQApplication::clipboard()->setData( d ); +} + +#include "synchronizergui.moc" diff --git a/src/app/Synchronizer/synchronizergui.h b/src/app/Synchronizer/synchronizergui.h new file mode 100644 index 0000000..c442b80 --- /dev/null +++ b/src/app/Synchronizer/synchronizergui.h @@ -0,0 +1,225 @@ +/*************************************************************************** + synchronizergui.h - description + ------------------- + copyright : (C) 2003 + 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 + + H e a d e r 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. * + * * + ***************************************************************************/ + +#ifndef __SYNCHRONIZERGUI_H__ +#define __SYNCHRONIZERGUI_H__ + +#include "synchronizer.h" +#include "../GUI/profilemanager.h" +#include "../Filter/filtertabs.h" +#include "../Filter/generalfilter.h" +#include <tqdialog.h> +#include <tqlistview.h> +#include <kcombobox.h> +#include <tqpixmap.h> +#include <tqcheckbox.h> +#include <tqmap.h> +#include <tqlabel.h> +#include <tqtabwidget.h> + +class TQSpinBox; + +class SynchronizerGUI : TQDialog +{ + TQ_OBJECT + + +public: + class SyncViewItem : public TQListViewItem + { + private: + SynchronizerFileItem *syncItemRef; + SyncViewItem *lastItemRef; + TQColor textColor; + TQColor baseColor; + + public: + SyncViewItem( SynchronizerFileItem *item, TQColor txt, TQColor base, TQListView * parent, TQListViewItem *after, TQString label1, + TQString label2 = TQString(), TQString label3 = TQString(), TQString label4 = TQString(), + TQString label5 = TQString(), TQString label6 = TQString(), + TQString label7 = TQString(), TQString label8 = TQString() ) : + TQListViewItem( parent, after, label1, label2, label3, label4, label5, label6, + label7, label8 ), syncItemRef( item ), lastItemRef( 0 ), textColor( txt ), baseColor( base ) + { + item->setUserData( (void *)this ); + setDragEnabled( true ); + } + + SyncViewItem( SynchronizerFileItem *item, TQColor txt, TQColor base, TQListViewItem * parent, TQListViewItem *after, TQString label1, + TQString label2 = TQString(), TQString label3 = TQString(), TQString label4 = TQString(), + TQString label5 = TQString(), TQString label6 = TQString(), + TQString label7 = TQString(), TQString label8 = TQString() ) : + TQListViewItem( parent, after, label1, label2, label3, label4, label5, label6, + label7, label8 ), syncItemRef( item ), lastItemRef( 0 ), textColor( txt ), baseColor( base ) + { + item->setUserData( (void *)this ); + setDragEnabled( true ); + } + + ~SyncViewItem() + { + syncItemRef->setUserData( 0 ); + } + + inline SynchronizerFileItem * synchronizerItemRef() {return syncItemRef;} + inline SyncViewItem * lastItem() {return lastItemRef;} + inline void setLastItem(SyncViewItem*s) {lastItemRef = s;} + + void setColors( TQColor fore, TQColor back ) { + textColor = fore; + baseColor = back; + } + + void paintCell(TQPainter *p, const TQColorGroup &cg, int column, int width, int align) + { + TQColorGroup _cg = cg; + if( textColor.isValid() ) + _cg.setColor(TQColorGroup::Text, textColor ); + if( baseColor.isValid() ) + _cg.setColor(TQColorGroup::Base, baseColor ); + TQListViewItem::paintCell( p, _cg, column, width, align ); + }; + }; + +public: + // if rightDirectory is null, leftDirectory is actually the profile name to load + SynchronizerGUI(TQWidget* parent, KURL leftDirectory, KURL rightDirectory = TQString(), TQStringList selList = TQStringList() ); + SynchronizerGUI(TQWidget* parent, TQString profile ); + ~SynchronizerGUI(); + + inline bool wasSynchronization() {return wasSync;} + +public slots: + void rightMouseClicked(TQListViewItem *); + void doubleClicked(TQListViewItem *); + void compare(); + void synchronize(); + void stop(); + void feedToListBox(); + void closeDialog(); + void refresh(); + void swapSides(); + void loadFromProfile( TQString ); + void saveToProfile( TQString ); + +protected slots: + void reject(); + void addFile( SynchronizerFileItem * ); + void markChanged( SynchronizerFileItem *, bool ); + void setScrolling( bool ); + void statusInfo( TQString ); + void subdirsChecked( bool ); + void setPanelLabels(); + void setCompletion(); + void checkExcludeURLValidity( TQString &text, TQString &error ); + void connectFilters( const TQString & ); + +private: + void initGUI(TQWidget* parent, TQString profile, KURL leftURL, KURL rightURL, TQStringList selList); + + TQString convertTime(time_t time) const; + void setMarkFlags(); + void disableMarkButtons(); + void enableMarkButtons(); + void copyToClipboard( bool isLeft ); + + int convertToSeconds( int time, int unit ); + void convertFromSeconds( int &time, int &unit, int second ); + +protected: + virtual void keyPressEvent( TQKeyEvent * ); + virtual void resizeEvent( TQResizeEvent *e ); + + ProfileManager *profileManager; + FilterTabs *filterTabs; + GeneralFilter *generalFilter; + + TQTabWidget *synchronizerTabs; + + KHistoryCombo *leftLocation; + KHistoryCombo *rightLocation; + KHistoryCombo *fileFilter; + + TQListView *syncList; + Synchronizer synchronizer; + + TQCheckBox *cbSubdirs; + TQCheckBox *cbSymlinks; + TQCheckBox *cbByContent; + TQCheckBox *cbIgnoreDate; + TQCheckBox *cbAsymmetric; + TQCheckBox *cbIgnoreCase; + + TQPushButton *btnSwapSides; + TQPushButton *btnCompareDirs; + TQPushButton *btnStopComparing; + TQPushButton *btnSynchronize; + TQPushButton *btnFeedToListBox; + TQPushButton *btnScrollResults; + + TQPushButton *btnLeftToRight; + TQPushButton *btnEquals; + TQPushButton *btnDifferents; + TQPushButton *btnRightToLeft; + TQPushButton *btnDeletable; + TQPushButton *btnDuplicates; + TQPushButton *btnSingles; + + TQLabel *statusLabel; + TQLabel *leftDirLabel; + TQLabel *rightDirLabel; + + TQStringList selectedFiles; + + TQSpinBox *parallelThreadsSpinBox; + TQSpinBox *equalitySpinBox; + TQComboBox *equalityUnitCombo; + TQSpinBox *timeShiftSpinBox; + TQComboBox *timeShiftUnitCombo; + TQCheckBox *ignoreHiddenFilesCB; + +private: + TQPixmap fileIcon; + TQPixmap folderIcon; + bool isComparing; + bool wasClosed; + bool wasSync; + bool firstResize; + bool hasSelectedFiles; + SyncViewItem *lastItem; + + int sizeX; + int sizeY; + + TQColor foreGrounds[ TT_MAX ]; + TQColor backGrounds[ TT_MAX ]; +}; + +#endif /* __SYNCHRONIZERGUI_H__ */ diff --git a/src/app/Synchronizer/synchronizertask.cpp b/src/app/Synchronizer/synchronizertask.cpp new file mode 100644 index 0000000..9a27584 --- /dev/null +++ b/src/app/Synchronizer/synchronizertask.cpp @@ -0,0 +1,343 @@ +/*************************************************************************** + synchronizertask.cpp - description + ------------------- + copyright : (C) 2006 + 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 "synchronizer.h" +#include "synchronizertask.h" +#include "synchronizerfileitem.h" +#include "synchronizerdirlist.h" +#include <tqtimer.h> +#include <tqfile.h> +#include <tdelocale.h> +#include <tdemessagebox.h> +#include "../VFS/vfs.h" + +CompareTask::CompareTask( SynchronizerFileItem *parentIn, const TQString &leftURL, + const TQString &rightURL, const TQString &leftDir, + const TQString &rightDir, bool hidden ) : SynchronizerTask (), m_parent( parentIn ), + m_url( leftURL ), m_dir( leftDir ), m_otherUrl( rightURL ), + m_otherDir( rightDir ), m_duplicate( true ), + m_dirList( 0 ), m_otherDirList( 0 ) { + ignoreHidden = hidden; +} + +CompareTask::CompareTask( SynchronizerFileItem *parentIn, const TQString &urlIn, + const TQString &dirIn, bool isLeftIn, bool hidden ) : SynchronizerTask (), + m_parent( parentIn ), m_url( urlIn ), m_dir( dirIn ), + m_isLeft( isLeftIn ), m_duplicate( false ), + m_dirList( 0 ), m_otherDirList( 0 ) { + ignoreHidden = hidden; +} + +CompareTask::~CompareTask() { + if( m_dirList ) { + delete m_dirList; + m_dirList = 0; + } + if( m_otherDirList ) { + delete m_otherDirList; + m_otherDirList = 0; + } +} + +void CompareTask::start() { + if( m_state == ST_STATE_NEW ) { + m_state = ST_STATE_PENDING; + m_loadFinished = m_otherLoadFinished = false; + + m_dirList = new SynchronizerDirList( parentWidget, ignoreHidden ); + connect( m_dirList, TQ_SIGNAL( finished( bool ) ), this, TQ_SLOT( slotFinished( bool ) )); + m_dirList->load( m_url, false ); + + if( m_duplicate ) { + m_otherDirList = new SynchronizerDirList( parentWidget, ignoreHidden ); + connect( m_otherDirList, TQ_SIGNAL( finished( bool ) ), this, TQ_SLOT( slotOtherFinished( bool ) )); + m_otherDirList->load( m_otherUrl, false ); + } + } +} + +void CompareTask::slotFinished( bool result ) { + if( !result ) { + m_state = ST_STATE_ERROR; + return; + } + m_loadFinished = true; + + if( m_otherLoadFinished || !m_duplicate ) + m_state = ST_STATE_READY; +} + + +void CompareTask::slotOtherFinished( bool result ) { + if( !result ) { + m_state = ST_STATE_ERROR; + return; + } + m_otherLoadFinished = true; + + if( m_loadFinished ) + m_state = ST_STATE_READY; +} + +CompareContentTask::CompareContentTask( Synchronizer *syn, SynchronizerFileItem *itemIn, const KURL &leftURLIn, + const KURL &rightURLIn, TDEIO::filesize_t sizeIn ) : SynchronizerTask(), + leftURL( leftURLIn ), rightURL( rightURLIn ), + size( sizeIn ), errorPrinted(false), leftReadJob( 0 ), + rightReadJob( 0 ), compareArray(), item( itemIn ), timer( 0 ), + leftFile( 0 ), rightFile( 0 ), received( 0 ), sync( syn ) { +} + +CompareContentTask::~CompareContentTask() { + abortContentComparing(); + + if( timer ) + delete timer; + if( leftFile ) + delete leftFile; + if( rightFile ) + delete rightFile; +} + +void CompareContentTask::start() { + m_state = ST_STATE_PENDING; + + if( leftURL.isLocalFile() && rightURL.isLocalFile() ) { + leftFile = new TQFile( leftURL.path() ); + if( !leftFile->open( IO_ReadOnly ) ) { + KMessageBox::error(parentWidget, i18n("Error at opening %1!").arg( leftURL.path() )); + m_state = ST_STATE_ERROR; + return; + } + + rightFile = new TQFile( rightURL.path() ); + if( !rightFile->open( IO_ReadOnly ) ) { + KMessageBox::error(parentWidget, i18n("Error at opening %1!").arg( rightURL.path() )); + m_state = ST_STATE_ERROR; + return; + } + + timer = new TQTimer( this ); + connect( timer, TQ_SIGNAL(timeout()), this, TQ_SLOT(sendStatusMessage()) ); + timer->start( 1000, true ); + + localFileCompareCycle(); + } else { + leftReadJob = TDEIO::get( leftURL, false, false ); + rightReadJob = TDEIO::get( rightURL, false, false ); + + connect(leftReadJob, TQ_SIGNAL(data(TDEIO::Job *, const TQByteArray &)), + this, TQ_SLOT(slotDataReceived(TDEIO::Job *, const TQByteArray &))); + connect(rightReadJob, TQ_SIGNAL(data(TDEIO::Job *, const TQByteArray &)), + this, TQ_SLOT(slotDataReceived(TDEIO::Job *, const TQByteArray &))); + connect(leftReadJob, TQ_SIGNAL(result(TDEIO::Job*)), + this, TQ_SLOT(slotFinished(TDEIO::Job *))); + connect(rightReadJob, TQ_SIGNAL(result(TDEIO::Job*)), + this, TQ_SLOT(slotFinished(TDEIO::Job *))); + + rightReadJob->suspend(); + + timer = new TQTimer( this ); + connect( timer, TQ_SIGNAL(timeout()), this, TQ_SLOT(sendStatusMessage()) ); + timer->start( 1000, true ); + } +} + +void CompareContentTask::localFileCompareCycle() { + + bool different = false; + + char leftBuffer[ 1440 ]; + char rightBuffer[ 1440 ]; + + TQTime timer; + timer.start(); + + int cnt = 0; + + while ( !leftFile->atEnd() && !rightFile->atEnd() ) + { + int leftBytes = leftFile->readBlock( leftBuffer, sizeof( leftBuffer ) ); + int rightBytes = rightFile->readBlock( rightBuffer, sizeof( rightBuffer ) ); + + if( leftBytes != rightBytes ) { + different = true; + break; + } + + if( leftBytes <= 0 ) + break; + + received += leftBytes; + + if( memcmp( leftBuffer, rightBuffer, leftBytes ) ) { + different = true; + break; + } + + if( (++cnt % 16) == 0 && timer.elapsed() >= 250 ) + break; + } + + if( different ) { + sync->compareContentResult( item, false ); + m_state = ST_STATE_READY; + return; + } + + if( leftFile->atEnd() && rightFile->atEnd() ) { + sync->compareContentResult( item, true ); + m_state = ST_STATE_READY; + return; + } + + TQTimer::singleShot( 0, this, TQ_SLOT( localFileCompareCycle() ) ); +} + + +void CompareContentTask::slotDataReceived(TDEIO::Job *job, const TQByteArray &data) +{ + int bufferLen = compareArray.size(); + int dataLen = data.size(); + + if( job == leftReadJob ) + received += dataLen; + + do + { + if( bufferLen == 0 ) + { + compareArray.duplicate( data.data(), dataLen ); + break; + } + + int minSize = ( dataLen < bufferLen ) ? dataLen : bufferLen; + + for( int i = 0; i != minSize; i++ ) + if( data[i] != compareArray[i] ) + { + abortContentComparing(); + return; + } + + if( minSize == bufferLen ) + { + compareArray.duplicate( data.data() + bufferLen, dataLen - bufferLen ); + if( dataLen == bufferLen ) + return; + break; + } + else + { + compareArray.duplicate( compareArray.data() + dataLen, bufferLen - dataLen ); + return; + } + + }while ( false ); + + TDEIO::TransferJob *otherJob = ( job == leftReadJob ) ? rightReadJob : leftReadJob; + + if( otherJob == 0 ) + { + if( compareArray.size() ) + abortContentComparing(); + } + else + { + if( !((TDEIO::TransferJob *)job)->isSuspended() ) + { + ((TDEIO::TransferJob *)job)->suspend(); + otherJob->resume(); + } + } +} + +void CompareContentTask::slotFinished(TDEIO::Job *job) +{ + TDEIO::TransferJob *otherJob = ( job == leftReadJob ) ? rightReadJob : leftReadJob; + + if( job == leftReadJob ) + leftReadJob = 0; + else + rightReadJob = 0; + + if( otherJob ) + otherJob->resume(); + + if( job->error() ) + { + timer->stop(); + abortContentComparing(); + } + + if( job->error() && job->error() != TDEIO::ERR_USER_CANCELED && !errorPrinted ) + { + errorPrinted = true; + KMessageBox::error(parentWidget, i18n("IO error at comparing file %1 with %2!") + .arg( vfs::pathOrURL( leftURL ) ) + .arg( vfs::pathOrURL( rightURL ) ) ); + } + + if( leftReadJob == 0 && rightReadJob == 0 ) + { + if( !compareArray.size() ) + sync->compareContentResult( item, true ); + else + sync->compareContentResult( item, false ); + + m_state = ST_STATE_READY; + } +} + +void CompareContentTask::abortContentComparing() +{ + if( timer ) + timer->stop(); + + if( leftReadJob ) + leftReadJob->kill( false ); + if( rightReadJob ) + rightReadJob->kill( false ); + + if( item->task() >= TT_UNKNOWN ) + sync->compareContentResult( item, false ); + + m_state = ST_STATE_READY; +} + +void CompareContentTask::sendStatusMessage() +{ + double perc = (size == 0) ? 1. : (double)received / (double)size; + int percent = (int)(perc * 10000. + 0.5); + TQString statstr = TQString( "%1.%2%3" ).arg( percent / 100 ).arg( ( percent / 10 )%10 ).arg( percent % 10 ) + "%"; + setStatusMessage( i18n( "Comparing file %1 (%2)..." ).arg( leftURL.fileName() ).arg( statstr ) ); + timer->start( 500, true ); +} + +#include "synchronizertask.moc" diff --git a/src/app/Synchronizer/synchronizertask.h b/src/app/Synchronizer/synchronizertask.h new file mode 100644 index 0000000..2241a04 --- /dev/null +++ b/src/app/Synchronizer/synchronizertask.h @@ -0,0 +1,170 @@ +/*************************************************************************** + synchronizertask.h - description + ------------------- + copyright : (C) 2006 + 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 + + H e a d e r 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. * + * * + ***************************************************************************/ + +#ifndef __SYNCHRONIZER_TASK_H__ +#define __SYNCHRONIZER_TASK_H__ + +#include <tqobject.h> +#include <tdeio/job.h> + +class Synchronizer; +class SynchronizerDirList; +class SynchronizerFileItem; +class TQProgressDialog; +class TQTimer; +class TQFile; + +#define ST_STATE_NEW 0 +#define ST_STATE_PENDING 1 +#define ST_STATE_STATUS 2 +#define ST_STATE_READY 3 +#define ST_STATE_ERROR 4 + +class SynchronizerTask : public TQObject { + TQ_OBJECT + + +public: + SynchronizerTask() : TQObject(), m_state( ST_STATE_NEW ), m_statusMessage( TQString() ) {} + virtual ~SynchronizerTask() {}; + + inline int start( TQWidget *parentWidget ) { this->parentWidget = parentWidget; start(); return state(); } + + inline int state() { return m_state; } + + void setStatusMessage( const TQString & statMsg ) { + if( m_state == ST_STATE_PENDING || m_state == ST_STATE_STATUS ) + m_state = ST_STATE_STATUS; + m_statusMessage = statMsg; + } + + TQString status() { + if( m_state == ST_STATE_STATUS ) { + m_state = ST_STATE_PENDING; + return m_statusMessage; + } + return TQString(); + } + +protected: + virtual void start() {}; + int m_state; + TQString m_statusMessage; + TQWidget *parentWidget; +}; + + +class CompareTask : public SynchronizerTask { + TQ_OBJECT + + +public: + CompareTask( SynchronizerFileItem *parentIn, const TQString &leftURL, + const TQString &rightURL, const TQString &leftDir, + const TQString &rightDir, bool ignoreHidden ); + CompareTask( SynchronizerFileItem *parentIn, const TQString &urlIn, + const TQString &dirIn, bool isLeftIn, bool ignoreHidden ); + virtual ~CompareTask(); + + inline bool isDuplicate() { return m_duplicate; } + inline bool isLeft() { return !m_duplicate && m_isLeft; } + inline const TQString & leftURL() { return m_url; } + inline const TQString & rightURL() { return m_otherUrl; } + inline const TQString & leftDir() { return m_dir; } + inline const TQString & rightDir() { return m_otherDir; } + inline const TQString & url() { return m_url; } + inline const TQString & dir() { return m_dir; } + inline SynchronizerFileItem * parent() { return m_parent; } + inline SynchronizerDirList * leftDirList() { return m_dirList; } + inline SynchronizerDirList * rightDirList() { return m_otherDirList; } + inline SynchronizerDirList * dirList() { return m_dirList; } + +protected slots: + virtual void start(); + void slotFinished( bool result ); + void slotOtherFinished( bool result ); + +private: + SynchronizerFileItem * m_parent; + TQString m_url; + TQString m_dir; + TQString m_otherUrl; + TQString m_otherDir; + bool m_isLeft; + bool m_duplicate; + SynchronizerDirList * m_dirList; + SynchronizerDirList * m_otherDirList; + bool m_loadFinished; + bool m_otherLoadFinished; + bool ignoreHidden; +}; + + +class CompareContentTask : public SynchronizerTask { + TQ_OBJECT + + +public: + CompareContentTask( Synchronizer *, SynchronizerFileItem *, const KURL &, const KURL &, TDEIO::filesize_t ); + virtual ~CompareContentTask(); + +public slots: + void slotDataReceived(TDEIO::Job *job, const TQByteArray &data); + void slotFinished(TDEIO::Job *job); + void sendStatusMessage(); + +protected: + virtual void start(); + +protected slots: + void localFileCompareCycle(); + +private: + void abortContentComparing(); + + KURL leftURL; // the currently processed URL (left) + KURL rightURL; // the currently processed URL (right) + TDEIO::filesize_t size; // the size of the compared files + + bool errorPrinted; // flag indicates error + TDEIO::TransferJob *leftReadJob; // compare left read job + TDEIO::TransferJob *rightReadJob; // compare right read job + TQByteArray compareArray; // the array for comparing + SynchronizerFileItem *item; // the item for content compare + TQTimer *timer; // timer to show the process dialog at compare by content + + TQFile *leftFile; // the left side local file + TQFile *rightFile; // the right side local file + + TDEIO::filesize_t received; // the received size + Synchronizer *sync; +}; + +#endif /* __SYNCHRONIZER_TASK_H__ */ |