File indexing completed on 2024-04-21 15:42:51

0001 /***************************************************************************
0002     This file contains private helper classes for the Smb4KSynchronizer 
0003     class.
0004                              -------------------
0005     begin                : Fr Okt 24 2008
0006     copyright            : (C) 2008-2019 by Alexander Reinholdt
0007     email                : alexander.reinholdt@kdemail.net
0008  ***************************************************************************/
0009 
0010 /***************************************************************************
0011  *   This program is free software; you can redistribute it and/or modify  *
0012  *   it under the terms of the GNU General Public License as published by  *
0013  *   the Free Software Foundation; either version 2 of the License, or     *
0014  *   (at your option) any later version.                                   *
0015  *                                                                         *
0016  *   This program is distributed in the hope that it will be useful, but   *
0017  *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
0018  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
0019  *   General Public License for more details.                              *
0020  *                                                                         *
0021  *   You should have received a copy of the GNU General Public License     *
0022  *   along with this program; if not, write to the                         *
0023  *   Free Software Foundation, Inc., 51 Franklin Street, Suite 500, Boston,*
0024  *   MA 02110-1335, USA                                                    *
0025  ***************************************************************************/
0026 
0027 #ifdef HAVE_CONFIG_H
0028 #include <config.h>
0029 #endif
0030 
0031 // application specific includes
0032 #include "smb4ksynchronizer_p.h"
0033 #include "smb4knotification.h"
0034 #include "smb4ksettings.h"
0035 #include "smb4kglobal.h"
0036 #include "smb4kshare.h"
0037 
0038 // Qt includes
0039 #include <QTimer>
0040 #include <QPointer>
0041 #include <QStandardPaths>
0042 #include <QGridLayout>
0043 #include <QLabel>
0044 #include <QDialogButtonBox>
0045 #include <QWindow>
0046 #include <QApplication>
0047 
0048 // KDE includes
0049 #define TRANSLATION_DOMAIN "smb4k-core"
0050 #include <KCompletion/KLineEdit>
0051 #include <KIOWidgets/KUrlCompletion>
0052 #include <KI18n/KLocalizedString>
0053 #include <KIconThemes/KIconLoader>
0054 #include <KConfigGui/KWindowConfig>
0055 
0056 using namespace Smb4KGlobal;
0057 
0058 
0059 Smb4KSyncJob::Smb4KSyncJob(QObject *parent) 
0060 : KJob(parent), m_share(0), m_process(0)
0061 {
0062   setCapabilities(KJob::Killable);
0063   m_job_tracker = new KUiServerJobTracker(this);
0064 }
0065 
0066 
0067 Smb4KSyncJob::~Smb4KSyncJob()
0068 {
0069 }
0070 
0071 
0072 void Smb4KSyncJob::start()
0073 {
0074   QTimer::singleShot(0, this, SLOT(slotStartSynchronization()));
0075 }
0076 
0077 
0078 void Smb4KSyncJob::setupSynchronization(const SharePtr &share)
0079 {
0080   if (share)
0081   {
0082     m_share = share;
0083   }
0084 }
0085 
0086 
0087 bool Smb4KSyncJob::doKill()
0088 {
0089   if (m_process && m_process->state() != KProcess::NotRunning)
0090   {
0091     m_process->terminate();
0092   }
0093   
0094   return KJob::doKill();
0095 }
0096 
0097 
0098 void Smb4KSyncJob::slotStartSynchronization()
0099 {
0100   //
0101   // Find the shell command
0102   //
0103   QString rsync = QStandardPaths::findExecutable("rsync");
0104 
0105   if (rsync.isEmpty())
0106   {
0107     Smb4KNotification::commandNotFound("rsync");
0108     emitResult();
0109     return;
0110   }
0111   else
0112   {
0113     // Go ahead
0114   }
0115   
0116   //
0117   // The synchronization dialog
0118   //
0119   if (m_share)
0120   {
0121     // Show the user an URL input dialog.
0122     QPointer<Smb4KSynchronizationDialog> dlg = new Smb4KSynchronizationDialog(m_share, QApplication::activeWindow());
0123 
0124     if (dlg->exec() == QDialog::Accepted)
0125     {
0126       // Create the destination directory if it does not already exits.
0127       QDir syncDir(dlg->destination().path());
0128       
0129       if (!syncDir.exists())
0130       {
0131         if (!QDir().mkpath(syncDir.path()))
0132         {
0133           Smb4KNotification::mkdirFailed(syncDir);
0134           emitResult();
0135           return;
0136         }
0137       }
0138       
0139       // Make sure that we have got the trailing slash present.
0140       // rsync is very picky regarding it.
0141       m_src = dlg->source();
0142       m_dest = dlg->destination();
0143 
0144       delete dlg;
0145     }
0146     else
0147     {
0148       delete dlg;
0149       emitResult();
0150       return;
0151     }
0152   }
0153   else
0154   {
0155     emitResult();
0156     return;
0157   }
0158   
0159   //
0160   // The command
0161   //
0162   QStringList command;
0163   command << rsync;
0164   command << "--progress";
0165   
0166   // 
0167   // Basic settings
0168   // 
0169   if (Smb4KSettings::archiveMode())
0170   {
0171     command << "--archive";
0172   }
0173   else
0174   {
0175     if (Smb4KSettings::recurseIntoDirectories())
0176     {
0177       command << "--recursive";
0178     }
0179 
0180     if (Smb4KSettings::preserveSymlinks())
0181     {
0182       command << "--links";
0183     }
0184 
0185     if (Smb4KSettings::preservePermissions())
0186     {
0187       command << "--perms";
0188     }
0189 
0190     if (Smb4KSettings::preserveTimes())
0191     {
0192       command << "--times";
0193     }
0194 
0195     if (Smb4KSettings::preserveGroup())
0196     {
0197       command << "--group";
0198     }
0199 
0200     if (Smb4KSettings::preserveOwner())
0201     {
0202       command << "--owner";
0203     }
0204 
0205     if (Smb4KSettings::preserveDevicesAndSpecials())
0206     {
0207       // Alias -D
0208       command << "--devices";
0209       command << "--specials";
0210     }
0211   }
0212   
0213   if (Smb4KSettings::relativePathNames())
0214   {
0215     command << "--relative";
0216   }
0217   
0218   if (Smb4KSettings::noImpliedDirectories())
0219   {
0220     command << "--no-implied-dirs";
0221   }
0222   
0223   if (Smb4KSettings::transferDirectories())
0224   {
0225     command << "--dirs";
0226   }
0227   
0228   if (Smb4KSettings::makeBackups())
0229   {
0230     command << "--backup";
0231 
0232     if (Smb4KSettings::useBackupDirectory())
0233     {
0234       command << QString("--backup-dir=%1").arg(Smb4KSettings::backupDirectory().path());
0235     }
0236 
0237     if (Smb4KSettings::useBackupSuffix())
0238     {
0239       command << QString("--suffix=%1").arg(Smb4KSettings::backupSuffix());
0240     }
0241   }
0242   
0243   //
0244   // File handling
0245   // 
0246   if (Smb4KSettings::updateTarget())
0247   {
0248     command << "--update";
0249   }
0250   
0251   if (Smb4KSettings::updateInPlace())
0252   {
0253     command << "--inplace";
0254   }
0255   
0256   if (Smb4KSettings::efficientSparseFileHandling())
0257   {
0258     command << "--sparse";
0259   }
0260   
0261   if (Smb4KSettings::copyFilesWhole())
0262   {
0263     command << "--whole-file";
0264   }
0265   
0266   if (Smb4KSettings::updateExisting())
0267   {
0268     command << "--existing";
0269   }
0270 
0271   if (Smb4KSettings::ignoreExisting())
0272   {
0273     command << "--ignore-existing";
0274   }
0275   
0276   if (Smb4KSettings::transformSymlinks())
0277   {
0278     command << "--copy-links";
0279   }
0280   
0281   if (Smb4KSettings::transformUnsafeSymlinks())
0282   {
0283     command << "--copy-unsafe-links";
0284   }
0285   
0286   if (Smb4KSettings::ignoreUnsafeSymlinks())
0287   {
0288     command << "--safe-links";
0289   }
0290   
0291   if (Smb4KSettings::mungeSymlinks())
0292   {
0293     command << "--munge-links";
0294   }
0295   
0296   if (Smb4KSettings::preserveHardLinks())
0297   {
0298     command << "--hard-links";
0299   }
0300   
0301   if (Smb4KSettings::copyDirectorySymlinks())
0302   {
0303     command << "--copy-dirlinks";
0304   }
0305 
0306   if (Smb4KSettings::keepDirectorySymlinks())
0307   {
0308     command << "--keep-dirlinks";
0309   }
0310 
0311   if (Smb4KSettings::omitDirectoryTimes())
0312   {
0313     command << "--omit-dir-times";
0314   }
0315   
0316   //
0317   // File transfer
0318   //
0319   if (Smb4KSettings::compressData())
0320   {
0321     command << "--compress";
0322   
0323     if (Smb4KSettings::useCompressionLevel())
0324     {
0325       command << QString("--compress-level=%1").arg(Smb4KSettings::compressionLevel());
0326     }
0327     
0328     if (Smb4KSettings::useSkipCompression())
0329     {
0330       command << QString("--skip-compress=%1").arg(Smb4KSettings::skipCompression());
0331     }
0332   }
0333   
0334   if (Smb4KSettings::self()->useMaximalTransferSize())
0335   {
0336     command << QString("--max-size=%1K").arg(Smb4KSettings::self()->maximalTransferSize());
0337   }
0338   
0339   if (Smb4KSettings::self()->useMinimalTransferSize())
0340   {
0341     command << QString("--min-size=%1K").arg(Smb4KSettings::self()->minimalTransferSize());
0342   }
0343   
0344   if (Smb4KSettings::keepPartial())
0345   {
0346     command << " --partial";
0347     
0348     if (Smb4KSettings::usePartialDirectory())
0349     {
0350       command << QString("--partial-dir=%1").arg(Smb4KSettings::partialDirectory().path());
0351     }
0352   }
0353   
0354   if (Smb4KSettings::useBandwidthLimit())
0355   {
0356     command << QString("--bwlimit=%1K").arg(Smb4KSettings::bandwidthLimit());
0357   }
0358   
0359   //
0360   // File deletion
0361   //
0362   if (Smb4KSettings::removeSourceFiles())
0363   {
0364     command << "--remove-source-files";
0365   }
0366 
0367   if (Smb4KSettings::deleteExtraneous())
0368   {
0369     command << "--delete";
0370   }
0371 
0372   if (Smb4KSettings::deleteBefore())
0373   {
0374     command << "--delete-before";
0375   }
0376 
0377   if (Smb4KSettings::deleteDuring())
0378   {
0379     command << "--delete-during";
0380   }
0381   
0382   if (Smb4KSettings::deleteAfter())
0383   {
0384     command << "--delete-after";
0385   }
0386 
0387   if (Smb4KSettings::deleteExcluded())
0388   {
0389     command << "--delete-excluded";
0390   }
0391 
0392   if (Smb4KSettings::ignoreErrors())
0393   {
0394     command << "--ignore-errors";
0395   }
0396 
0397   if (Smb4KSettings::forceDirectoryDeletion())
0398   {
0399     command << "--force";
0400   }
0401   
0402   if (Smb4KSettings::useMaximumDelete())
0403   {
0404     command << QString("--max-delete=%1").arg(Smb4KSettings::maximumDeleteValue());
0405   }
0406   
0407   //
0408   // Filtering
0409   // 
0410   if (Smb4KSettings::useCVSExclude())
0411   {
0412     command << "--cvs-exclude";
0413   }
0414   
0415   if (Smb4KSettings::useExcludePattern())
0416   {
0417     command << QString("--exclude=%1").arg(Smb4KSettings::excludePattern());
0418   }
0419 
0420   if (Smb4KSettings::useExcludeFrom())
0421   {
0422     command << QString("--exclude-from=%1").arg(Smb4KSettings::excludeFrom().path());
0423   }
0424   
0425   if (Smb4KSettings::useIncludePattern())
0426   {
0427     command << QString("--include=%1").arg(Smb4KSettings::includePattern());
0428   }
0429 
0430   if (Smb4KSettings::useIncludeFrom())
0431   {
0432     command << QString("--include-from=%1").arg(Smb4KSettings::includeFrom().path());
0433   }
0434   
0435   if (!Smb4KSettings::customFilteringRules().isEmpty())
0436   {
0437     qDebug() << "Do we need to spilt the filtering rules into a list?";
0438     command << Smb4KSettings::customFilteringRules();
0439   }
0440   
0441   if (Smb4KSettings::useFFilterRule())
0442   {
0443     command << "-F";
0444   }
0445 
0446   if (Smb4KSettings::useFFFilterRule())
0447   {
0448     command << "-F";
0449     command << "-F";
0450   }
0451   
0452   //
0453   // Miscellaneous
0454   // 
0455   if (Smb4KSettings::useBlockSize())
0456   {
0457     command << QString("--block-size=%1").arg(Smb4KSettings::blockSize());
0458   }
0459 
0460   if (Smb4KSettings::useChecksumSeed())
0461   {
0462     command << QString("--checksum-seed=%1").arg(Smb4KSettings::checksumSeed());
0463   }
0464   
0465   if (Smb4KSettings::useChecksum())
0466   {
0467     command << "--checksum";
0468   }
0469 
0470   if (Smb4KSettings::oneFileSystem())
0471   {
0472     command << "--one-file-system";
0473   }
0474   
0475   if (Smb4KSettings::delayUpdates())
0476   {
0477     command << "--delay-updates";
0478   }
0479   
0480   // Make sure that the trailing slash is present. rsync is very 
0481   // picky regarding it.
0482   QString source = m_src.path() + (!m_src.path().endsWith('/') ? "/" : "");
0483   QString destination = m_dest.path() + (!m_dest.path().endsWith('/') ? "/" : "");
0484     
0485   command << source;
0486   command << destination;
0487   
0488   //
0489   // The job tracker
0490   //
0491   m_job_tracker->registerJob(this);
0492   connect(this, SIGNAL(result(KJob*)), m_job_tracker, SLOT(unregisterJob(KJob*)));
0493 
0494   //
0495   // The process
0496   //
0497   m_process = new KProcess(this);
0498   m_process->setEnv("LANG", "en_US.UTF-8");
0499   m_process->setOutputChannelMode(KProcess::SeparateChannels);
0500   m_process->setProgram(command);
0501   
0502   connect(m_process, SIGNAL(readyReadStandardOutput()), SLOT(slotReadStandardOutput()));
0503   connect(m_process, SIGNAL(readyReadStandardError()),  SLOT(slotReadStandardError()));
0504   connect(m_process, SIGNAL(finished(int,QProcess::ExitStatus)), SLOT(slotProcessFinished(int,QProcess::ExitStatus)));
0505   
0506   // Start the synchronization process
0507   emit aboutToStart(m_dest.path()); 
0508 
0509   // Send description to the GUI
0510   emit description(this, i18n("Synchronizing"),
0511                    qMakePair(i18n("Source"), source),
0512                    qMakePair(i18n("Destination"), destination));
0513      
0514   // Dummy to show 0 %
0515   emitPercent(0, 100);
0516   
0517   m_process->start();
0518 }
0519 
0520 
0521 void Smb4KSyncJob::slotReadStandardOutput()
0522 {
0523   QStringList stdOut = QString::fromUtf8(m_process->readAllStandardOutput(), -1).split('\n', QString::SkipEmptyParts);
0524 
0525   for (int i = 0; i < stdOut.size(); ++i)
0526   {
0527     if (stdOut.at(i)[0].isSpace())
0528     {
0529       // Get the overall transfer progress
0530       if (stdOut.at(i).contains(" to-check="))
0531       {
0532         QString tmp = stdOut.at(i).section(" to-check=", 1, 1).section(')', 0, 0).trimmed();
0533 
0534         bool success1 = true;
0535         bool success2 = true;
0536 
0537         qulonglong files = tmp.section('/', 0, 0).trimmed().toLongLong(&success1);
0538         qulonglong total = tmp.section('/', 1, 1).trimmed().toLongLong(&success2);
0539 
0540         if (success1 && success2)
0541         {
0542           setProcessedAmount(KJob::Files, total - files);
0543           setTotalAmount(KJob::Files, total);
0544           emitPercent(total - files, total);
0545         }
0546       }
0547       else if (stdOut.at(i).contains(" to-chk="))
0548       {
0549         // Make Smb4K work with rsync >= 3.1.
0550         QString tmp = stdOut.at(i).section(" to-chk=", 1, 1).section(')', 0, 0).trimmed();
0551 
0552         bool success1 = true;
0553         bool success2 = true;
0554 
0555         qulonglong files = tmp.section('/', 0, 0).trimmed().toLongLong(&success1);
0556         qulonglong total = tmp.section('/', 1, 1).trimmed().toLongLong(&success2);
0557 
0558         if (success1 && success2)
0559         {
0560           setProcessedAmount(KJob::Files, total - files);
0561           setTotalAmount(KJob::Files, total);
0562           emitPercent(total - files, total);
0563         }
0564       }
0565       else if (stdOut.at(i).contains(" ir-chk="))
0566       {
0567         // Make Smb4K work with rsync >= 3.1.
0568         QString tmp = stdOut.at(i).section(" ir-chk=", 1, 1).section(')', 0, 0).trimmed();
0569 
0570         bool success1 = true;
0571         bool success2 = true;
0572 
0573         qulonglong files = tmp.section('/', 0, 0).trimmed().toLongLong(&success1);
0574         qulonglong total = tmp.section('/', 1, 1).trimmed().toLongLong(&success2);
0575 
0576         if (success1 && success2)
0577         {
0578           setProcessedAmount(KJob::Files, total - files);
0579           setTotalAmount(KJob::Files, total);
0580           emitPercent(total - files, total);
0581         }
0582       }
0583 
0584       // Get transfer rate
0585       if (stdOut.at(i).contains("/s ", Qt::CaseSensitive))
0586       {
0587         bool success = true;
0588         
0589         double tmp_speed = stdOut.at(i).section(QRegExp("../s"), 0, 0).section(' ', -1 -1).trimmed().toDouble(&success);
0590 
0591         if (success)
0592         {
0593           // MB == 1000000 B and kB == 1000 B per definition!
0594           if (stdOut.at(i).contains("MB/s"))
0595           {
0596             tmp_speed *= 1e6;
0597           }
0598           else if (stdOut.at(i).contains("kB/s"))
0599           {
0600             tmp_speed *= 1e3;
0601           }
0602 
0603           ulong speed = (ulong)tmp_speed;
0604           emitSpeed(speed /* B/s */);
0605         }
0606       }
0607     }
0608     else if (!stdOut.at(i).contains("sending incremental file list"))
0609     {
0610       QString file = stdOut.at(i).trimmed();
0611 
0612       QUrl src_url = m_src;
0613       src_url.setPath(QDir::cleanPath(src_url.path() + '/' + file));
0614 
0615       QUrl dest_url = m_dest;
0616       dest_url.setPath(QDir::cleanPath(dest_url.path() + '/' + file));
0617       
0618       // Send description to the GUI
0619       emit description(this, i18n("Synchronizing"),
0620                        qMakePair(i18n("Source"), src_url.path()),
0621                        qMakePair(i18n("Destination"), dest_url.path()));
0622     }
0623   }
0624 }
0625 
0626 
0627 void Smb4KSyncJob::slotReadStandardError()
0628 {
0629   //
0630   // Get the error message
0631   // 
0632   QString stdErr = QString::fromUtf8(m_process->readAllStandardError(), -1).trimmed();
0633   
0634   //
0635   // Make sure the process is terminated
0636   // 
0637   if (m_process->state() != KProcess::NotRunning)
0638   {
0639     m_process->terminate();
0640   }
0641   
0642   //
0643   // Report an error if the process was not terminated
0644   // 
0645   if (!(stdErr.contains("rsync error") && stdErr.contains("(code 20)")))
0646   {
0647     Smb4KNotification::synchronizationFailed(m_src, m_dest, stdErr);
0648   }
0649 }
0650 
0651 
0652 void Smb4KSyncJob::slotProcessFinished(int, QProcess::ExitStatus status)
0653 {
0654   // Dummy to show 100 %
0655   emitPercent(100, 100);
0656   
0657   // Handle error.
0658   switch (status)
0659   {
0660     case QProcess::CrashExit:
0661     {
0662       Smb4KNotification::processError(m_process->error());
0663       break;
0664     }
0665     default:
0666     {
0667       break;
0668     }
0669   }
0670 
0671   // Finish job
0672   emitResult();
0673   emit finished(m_dest.path());
0674 }
0675 
0676 
0677 
0678 Smb4KSynchronizationDialog::Smb4KSynchronizationDialog(const SharePtr &share, QWidget *parent)
0679 : QDialog(parent), m_share(share)
0680 {
0681   setWindowTitle(i18n("Synchronization"));
0682   
0683   QDialogButtonBox *buttonBox = new QDialogButtonBox(Qt::Horizontal, this);
0684   m_swap_button = buttonBox->addButton(i18n("Swap Paths"), QDialogButtonBox::ActionRole);
0685   m_swap_button->setToolTip(i18n("Swap source and destination"));
0686   m_synchronize_button = buttonBox->addButton(i18n("Synchronize"), QDialogButtonBox::ActionRole);
0687   m_synchronize_button->setToolTip(i18n("Synchronize the destination with the source"));
0688   m_cancel_button = buttonBox->addButton(QDialogButtonBox::Cancel);
0689   
0690   m_cancel_button->setShortcut(Qt::Key_Escape);
0691   
0692   m_synchronize_button->setDefault(true);
0693 
0694   QGridLayout *layout = new QGridLayout(this);
0695   layout->setSpacing(5);
0696 
0697   QLabel *pixmap = new QLabel(this);
0698   QPixmap sync_pix = KDE::icon("folder-sync").pixmap(KIconLoader::SizeHuge);
0699   pixmap->setPixmap(sync_pix);
0700   pixmap->setAlignment(Qt::AlignBottom);
0701 
0702   QLabel *description = new QLabel(i18n("Please provide the source and destination "
0703                                         "directory for the synchronization."), this);
0704   description->setWordWrap(true);
0705   description->setAlignment(Qt::AlignBottom);
0706 
0707   QUrl src_url  = QUrl(QDir::cleanPath(m_share->path()));
0708   QUrl dest_url = QUrl(QDir::cleanPath(QString("%1/%2/%3").arg(Smb4KSettings::rsyncPrefix().path())
0709                        .arg(m_share->hostName()).arg(m_share->shareName())));
0710 
0711   QLabel *source_label = new QLabel(i18n("Source:"), this);
0712   m_source = new KUrlRequester(this);
0713   m_source->setUrl(src_url);
0714   m_source->setMode(KFile::Directory | KFile::LocalOnly);
0715   m_source->lineEdit()->setSqueezedTextEnabled(true);
0716   m_source->completionObject()->setCompletionMode(KCompletion::CompletionPopupAuto);
0717   m_source->completionObject()->setMode(KUrlCompletion::FileCompletion);
0718   m_source->setWhatsThis(i18n("This is the source directory. The data that it contains is to be written "
0719     "to the destination directory."));
0720 
0721   QLabel *destination_label = new QLabel(i18n("Destination:"), this);
0722   m_destination = new KUrlRequester(this);
0723   m_destination->setUrl(dest_url);
0724   m_destination->setMode(KFile::Directory | KFile::LocalOnly);
0725   m_destination->lineEdit()->setSqueezedTextEnabled(true);
0726   m_destination->completionObject()->setCompletionMode(KCompletion::CompletionPopupAuto);
0727   m_destination->completionObject()->setMode(KUrlCompletion::FileCompletion);
0728   m_destination->setWhatsThis(i18n("This is the destination directory. It will be updated with the data "
0729     "from the source directory."));
0730 
0731   layout->addWidget(pixmap, 0, 0, 0);
0732   layout->addWidget(description, 0, 1, Qt::AlignBottom);
0733   layout->addWidget(source_label, 1, 0, 0);
0734   layout->addWidget(m_source, 1, 1, 0);
0735   layout->addWidget(destination_label, 2, 0, 0);
0736   layout->addWidget(m_destination, 2, 1, 0);
0737   layout->addWidget(buttonBox, 3, 0, 1, 2, 0);
0738 
0739   // 
0740   // Connections
0741   // 
0742   connect(m_cancel_button, SIGNAL(clicked()), SLOT(slotCancelClicked()));
0743   connect(m_synchronize_button, SIGNAL(clicked()), SLOT(slotSynchronizeClicked()));
0744   connect(m_swap_button, SIGNAL(clicked()), SLOT(slotSwapPathsClicked()));
0745 
0746   //
0747   // Set the dialog size
0748   // 
0749   create();
0750 
0751   KConfigGroup group(Smb4KSettings::self()->config(), "SynchronizationDialog");
0752   QSize dialogSize;
0753   
0754   if (group.exists())
0755   {
0756     KWindowConfig::restoreWindowSize(windowHandle(), group);
0757     dialogSize = windowHandle()->size();
0758   }
0759   else
0760   {
0761     dialogSize = sizeHint();
0762   }
0763   
0764   resize(dialogSize); // workaround for QTBUG-40584  
0765 }
0766 
0767 
0768 Smb4KSynchronizationDialog::~Smb4KSynchronizationDialog()
0769 {
0770 }
0771 
0772 
0773 const QUrl Smb4KSynchronizationDialog::source()
0774 {
0775   return m_source->url();
0776 }
0777 
0778 
0779 const QUrl Smb4KSynchronizationDialog::destination()
0780 {
0781   return m_destination->url();
0782 }
0783 
0784 
0785 /////////////////////////////////////////////////////////////////////////////
0786 //   SLOT IMPLEMENTATIONS
0787 /////////////////////////////////////////////////////////////////////////////
0788 
0789 
0790 void Smb4KSynchronizationDialog::slotCancelClicked()
0791 {
0792   reject();
0793 }
0794 
0795 
0796 void Smb4KSynchronizationDialog::slotSynchronizeClicked()
0797 {
0798   KConfigGroup group(Smb4KSettings::self()->config(), "SynchronizationDialog");
0799   KWindowConfig::saveWindowSize(windowHandle(), group);
0800   accept();
0801 }
0802 
0803 
0804 void Smb4KSynchronizationDialog::slotSwapPathsClicked()
0805 {
0806   // Swap URLs.
0807   QString sourceURL = m_source->url().path();
0808   QString destinationURL = m_destination->url().path();
0809 
0810   m_source->setUrl(QUrl(destinationURL));
0811   m_destination->setUrl(QUrl(sourceURL));
0812 }
0813