[SCM] Kaboom - Debian KDE 3->4 migration tool branch, master, updated. ae3f1a6f9e4dfcc14e6747ac88656d6e85ee0d4b

George Kiagiadakis gkiagia-guest at alioth.debian.org
Sat Mar 7 00:28:21 UTC 2009


The following commit has been merged in the master branch:
commit 736cfbfdde794dd14666b9e6181a937c9d8ead2f
Author: George Kiagiadakis <gkiagia at users.sourceforge.net>
Date:   Sat Mar 7 01:54:32 2009 +0200

    Use threads for DirOperations...
    This provides the following features:
    1) The ui is not sluggish anymore when an operation is running.
    2) It is possible to do an operation asynchronously.
    The old API is left untouched for source compatibility.

diff --git a/diroperations/diroperations.cpp b/diroperations/diroperations.cpp
index 179636c..92abbaf 100644
--- a/diroperations/diroperations.cpp
+++ b/diroperations/diroperations.cpp
@@ -15,15 +15,15 @@
     You should have received a copy of the GNU Lesser General Public License
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
-#define _FILE_OFFSET_BITS 64
-#include <sys/statvfs.h> // for statvfs for calculating free space
 #include "diroperations.h"
-#include <QDir>
-#include <QFileInfo>
-#include <QStack>
-#include <QDebug>
+#include "recursivedirjob.h"
+#include <QtCore/QFile>
+#include <QtCore/QEventLoop>
+#include <QtCore/QVariant>
+#include <QtCore/QDebug>
 #include <climits> //for PATH_MAX
-
+#define _FILE_OFFSET_BITS 64
+#include <sys/statvfs.h> // for statvfs for calculating free space
 
 namespace DirOperations {
 
@@ -63,7 +63,7 @@ quint64 freeDirSpace(const QString & dir)
     }
     qDebug() << "freeDirSpace" << dir << info.f_bsize*info.f_bavail;
     return info.f_bsize*info.f_bavail;
-  
+
 }
 
 quint64 totalPartitionSize(const QString & dir)
@@ -77,253 +77,51 @@ quint64 totalPartitionSize(const QString & dir)
     }
     qDebug() << "totalPartitionSize" << dir << info.f_bsize*info.f_blocks;
     return info.f_frsize*info.f_blocks;
-  
+
 }
 
-qint64 calculateDirSize(const QString & dir, ProgressDialogInterface *pd)
+quint64 calculateDirSize(const QString & dir, ProgressDialogInterface *pd)
 {
-    QDir currentDir(dir);
-    if ( !currentDir.exists() )
-        throw Exception(Exception::NoSuchFileOrDirectory, dir);
-
-    QDir::Filters filters = QDir::AllEntries | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System | QDir::CaseSensitive;
-    QFileInfoList currentList = currentDir.entryInfoList( filters, QDir::DirsLast );
-    QFileInfo currentItem;
-    QStack<QFileInfoList> stack;
-    qint64 totalSize = 0;
-    int refreshCounter = 0;
-
-    while(1){
-        if ( !currentList.isEmpty() ){
-            currentItem = currentList.takeFirst();
-            totalSize += currentItem.size();
-
-            if ( currentItem.isDir() && !currentItem.isSymLink() ) {
-                if ( !currentDir.cd(currentItem.fileName()) )
-                    throw Exception(Exception::AccessDenied, currentItem.absoluteFilePath());
-                stack.push(currentList);
-                currentList = currentDir.entryInfoList( filters, QDir::DirsLast );
-            }
-
-            if ( pd && (++refreshCounter % 100 == 0) ) {
-                pd->setLabelText(QObject::tr("Calculating... %1 bytes").arg(totalSize));
-                pd->processEvents();
-                if (pd->wasCanceled())
-                    throw Exception(Exception::OperationCanceled);
-            }
-
-        } else { // list is empty
-            if ( !stack.isEmpty() ){
-                currentList = stack.pop();
-                currentDir.cdUp();
-            } else
-                break;
-        }
-    }
-
-    totalSize += QFileInfo(dir).size();
-    return totalSize;
+    QEventLoop loop;
+    RecursiveDirJob *j = RecursiveDirJob::calculateDirSize(dir);
+    j->setProgressDialogInterface(pd);
+    //we will start the thread as soon as we are in the event loop, because if the thread
+    //finishes too early (before the event loop starts), quit() will not work and we will stay
+    //in this event loop forever.
+    QMetaObject::invokeMethod(j, "start", Qt::QueuedConnection);
+    QObject::connect(j, SIGNAL(finished()), &loop, SLOT(quit()) );
+    loop.exec();
+    j->deleteLater();
+    if ( j->hasError() )
+        throw j->lastError();
+    return qvariant_cast<quint64>(j->result());
 }
 
-void recursiveCpDir(const QString & sourcePath, const QString & destPath, CopyOptions options, ProgressDialogInterface *pd)
+void recursiveCpDir(const QString & sourcePath, const QString & destPath,
+                    CopyOptions options, ProgressDialogInterface *pd)
 {
-    QDir source(sourcePath);
-    if ( !source.exists() )
-        throw Exception(Exception::NoSuchFileOrDirectory, sourcePath);
-
-    QDir dest(destPath);
-    if ( dest.exists() ) {
-        if ( options & RemoveDestination )
-            recursiveRmDir(destPath, pd);
-        else if ( !(options & OverWrite) )
-            throw Exception(Exception::FileOrDirectoryExists, destPath);
-    }
-
-    dest.mkdir(dest.absolutePath());
-
-    QDir::Filters filters = QDir::AllEntries | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System | QDir::CaseSensitive;
-    QFileInfoList currentList = source.entryInfoList( filters, QDir::DirsLast );
-    QFileInfo currentItem;
-    QStack<QFileInfoList> stack;
-    QString currentName;
-    qint64 bytesCopied = 0;
-
-    if ( pd ) {
-        qint64 dirSize = calculateDirSize(sourcePath, pd);
-        pd->setLabelText(QObject::tr("Copying files..."));
-        if (dirSize > 0) {
-            pd->setMaximum(dirSize);
-            //the directory special file is already (almost) copied in dest.mkdir() above
-            bytesCopied += QFileInfo(sourcePath).size();
-            pd->setValue(bytesCopied);
-        } else {
-            //no files to be copied, so set the progressbar to 100%
-            pd->setMaximum(1);
-            pd->setValue(1);
-        }
-    }
-
-    while(1)
-    {
-        if ( !currentList.isEmpty() )
-        {
-            currentItem = currentList.takeFirst();
-            currentName = currentItem.fileName();
-
-            if ( currentItem.isSymLink() )
-            {
-                if ( options & OverWrite ) {
-                    if ( QFile::exists(dest.absoluteFilePath(currentName)) &&
-                         !QFile::remove(dest.absoluteFilePath(currentName)) )
-                        throw Exception(Exception::RmFail, dest.absoluteFilePath(currentName));
-                }
-                if ( !QFile::link( relativeSymLinkTarget(source.absoluteFilePath(currentName)),
-                                    dest.absoluteFilePath(currentName) ) )
-                    throw Exception(Exception::CopyFail, source.absoluteFilePath(currentName));
-            }
-            else if ( currentItem.isDir() )
-            {
-                if ( !source.cd(currentName) )
-                    throw Exception(Exception::AccessDenied, source.absoluteFilePath(currentName));
-                if ( !dest.cd(currentName) ) {
-                    //if the target dir doesn't exist, create it and try again.
-                    if ( !dest.mkdir(currentName) )
-                        throw Exception(Exception::MkdirFail, dest.absoluteFilePath(currentName));
-                    if ( !dest.cd(currentName) )
-                        throw Exception(Exception::AccessDenied, dest.absoluteFilePath(currentName)); //quite impossible
-                }
-
-                stack.push(currentList);
-                currentList = source.entryInfoList( filters, QDir::DirsLast );
-            }
-            else if ( currentItem.isFile() )
-            {
-                if ( options & OverWrite ) {
-                    if ( QFile::exists(dest.absoluteFilePath(currentName)) &&
-                         !QFile::remove(dest.absoluteFilePath(currentName)) )
-                        throw Exception(Exception::RmFail, dest.absoluteFilePath(currentName));
-                }
-                if ( !QFile::copy( source.absoluteFilePath(currentName), dest.absoluteFilePath(currentName) ) )
-                    throw Exception(Exception::CopyFail, source.absoluteFilePath(currentName));
-            }
-            else
-            {
-                qDebug() << "Ignoring special file" << source.absoluteFilePath(currentName);
-            }
-
-            if ( pd ) {
-                bytesCopied += currentItem.size();
-                pd->setValue(bytesCopied);
-            }
-        }
-        else // list is empty
-        {
-            if ( !stack.isEmpty() )
-            {
-                currentList = stack.pop();
-                source.cdUp();
-                dest.cdUp();
-            }
-            else
-                break;
-        }
-
-        if ( pd ) {
-            pd->processEvents();
-            if (pd->wasCanceled())
-                throw Exception(Exception::OperationCanceled);
-        }
-    }
+    QEventLoop loop;
+    RecursiveDirJob *j = RecursiveDirJob::recursiveCpDir(sourcePath, destPath, options);
+    j->setProgressDialogInterface(pd);
+    QMetaObject::invokeMethod(j, "start", Qt::QueuedConnection);
+    QObject::connect(j, SIGNAL(finished()), &loop, SLOT(quit()) );
+    loop.exec();
+    j->deleteLater();
+    if ( j->hasError() )
+        throw j->lastError();
 }
 
 void recursiveRmDir(const QString & dir, ProgressDialogInterface *pd)
 {
-    QDir currentDir(dir);
-    if ( !currentDir.exists() ) {
-        qWarning() << "recursiveRmDir: trying to remove non-existent directory" << dir;
-        if (pd) {
-            //no files to be removed, so set the progressbar to 100%
-            pd->setMaximum(1);
-            pd->setValue(1);
-        }
-        return; // directory gone, no work to do
-    }
-
-    QDir::Filters filters = QDir::AllEntries | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System | QDir::CaseSensitive;
-    QFileInfoList currentList = currentDir.entryInfoList( filters, QDir::DirsLast );
-    QFileInfo currentItem;
-    QStack<QFileInfoList> stack;
-    qint64 bytesRemoved = 0;
-
-    if ( pd ) {
-        qint64 dirSize = calculateDirSize(dir, pd);
-        pd->setLabelText(QObject::tr("Removing files..."));
-        if (dirSize > 0) {
-            pd->setMaximum(dirSize);
-        } else {
-            //no files to be removed, so set the progressbar to 100%
-            pd->setMaximum(1);
-            pd->setValue(1);
-        }
-    }
-
-    while(1)
-    {
-        if ( !currentList.isEmpty() ){
-            currentItem = currentList.takeFirst();
-
-            if ( currentItem.isDir() && !currentItem.isSymLink() )
-            {
-                if ( !currentDir.cd(currentItem.fileName()) )
-                    throw Exception(Exception::AccessDenied, currentItem.absoluteFilePath());
-                stack.push(currentList);
-                currentList = currentDir.entryInfoList( filters, QDir::DirsLast );
-            }
-            else
-            {
-                if ( pd ) {
-                    bytesRemoved += currentItem.size();
-                    pd->setValue(bytesRemoved);
-                }
-
-                if ( !currentDir.remove(currentItem.fileName()) )
-                    throw Exception(Exception::RmFail, currentItem.absoluteFilePath());
-            }
-        }
-        else // list is empty
-        {
-            bool quit = false;
-            if ( !stack.isEmpty() )
-                currentList = stack.pop();
-            else
-                quit = true;
-
-            //if quit == true, we remove the original dir itself, now that it is empty for sure...
-            QString tmpname = currentDir.dirName();
-            currentDir.cdUp();
-
-            if ( pd ) {
-                //count the directory special file before it is removed
-                bytesRemoved += QFileInfo(currentDir, tmpname).size();
-                pd->setValue(bytesRemoved);
-                //if we are about to quit, process events before exiting the loop (to make the progressbar reach 100%)
-                if ( quit )
-                    pd->processEvents();
-            }
-
-            if ( !currentDir.rmdir(tmpname) )
-                throw Exception(Exception::RmFail, currentDir.absoluteFilePath(tmpname));
-
-            if ( quit )
-                break;
-        }
-
-        if ( pd ) {
-            pd->processEvents();
-            if (pd->wasCanceled())
-                throw Exception(Exception::OperationCanceled);
-        }
-    }
+    QEventLoop loop;
+    RecursiveDirJob *j = RecursiveDirJob::recursiveRmDir(dir);
+    j->setProgressDialogInterface(pd);
+    QMetaObject::invokeMethod(j, "start", Qt::QueuedConnection);
+    QObject::connect(j, SIGNAL(finished()), &loop, SLOT(quit()) );
+    loop.exec();
+    j->deleteLater();
+    if ( j->hasError() )
+        throw j->lastError();
 }
 
 } //namespace DirOperations
diff --git a/diroperations/diroperations.h b/diroperations/diroperations.h
index 9ed2e32..28231aa 100644
--- a/diroperations/diroperations.h
+++ b/diroperations/diroperations.h
@@ -18,7 +18,8 @@
 #ifndef DIROPERATIONS_H
 #define DIROPERATIONS_H
 
-#include <QString>
+#include <QtCore/QString>
+#include <QtCore/QMetaType>
 
 namespace DirOperations {
 
@@ -28,22 +29,21 @@ namespace DirOperations {
         virtual ~ProgressDialogInterface() {}
 
         virtual void setLabelText(const QString & text) = 0;
-        virtual bool wasCanceled() const = 0;
-        virtual void setMaximum(int max) = 0;
-        virtual void setValue(int value) = 0;
-        virtual void processEvents() = 0;
+        virtual void setMaximum(quint64 max) = 0;
+        virtual void setValue(quint64 value) = 0;
     };
 
     class Exception
     {
     public:
         enum Type { OperationCanceled, AccessDenied, NoSuchFileOrDirectory,
-                    FileOrDirectoryExists, CopyFail, MkdirFail, RmFail };
+                    FileOrDirectoryExists, CopyFail, MkdirFail, RmFail, NoError };
 
+        explicit Exception() : m_type(NoError) {}
         explicit Exception(Type type, const QString & extraInfo = QString())
                     : m_type(type), m_info(extraInfo) {}
 
-        Type exceptionType() const { return m_type; }
+        Type type() const { return m_type; }
         QString what() const;
 
     private:
@@ -53,7 +53,6 @@ namespace DirOperations {
 
     enum CopyOption { NoOptions = 0x0, RemoveDestination = 0x1, OverWrite = 0x2 };
     Q_DECLARE_FLAGS(CopyOptions, CopyOption);
-    Q_DECLARE_OPERATORS_FOR_FLAGS(CopyOptions);
 
     /*! Returns the target path of the symbolic link \a fileName .
      * The path returned is relative to the symlink. For example if
@@ -66,12 +65,12 @@ namespace DirOperations {
 
     /*! Calculates the free space in the partition of a dir */
     quint64 freeDirSpace(const QString & dir);
-    
+
     /*! Calculates the total space of a partition */
     quint64 totalPartitionSize(const QString & dir);
 
     /*! Calculates the size of a directory. Works like "du -hs". */
-    qint64 calculateDirSize(const QString & dir, ProgressDialogInterface *pd = 0);
+    quint64 calculateDirSize(const QString & dir, ProgressDialogInterface *pd = 0);
 
     /*! Copies directory \a sourcePath and all of its contents
      * to directory \a destPath . Works like "cp -r".
@@ -88,4 +87,7 @@ namespace DirOperations {
 
 } //namespace DirOperations
 
+Q_DECLARE_OPERATORS_FOR_FLAGS(DirOperations::CopyOptions)
+Q_DECLARE_METATYPE(DirOperations::CopyOptions)
+
 #endif
diff --git a/diroperations/progresswidget.cpp b/diroperations/progresswidget.cpp
index e9dd361..a173957 100644
--- a/diroperations/progresswidget.cpp
+++ b/diroperations/progresswidget.cpp
@@ -18,7 +18,6 @@
 #include <QVBoxLayout>
 #include <QLabel>
 #include <QProgressBar>
-#include <QApplication>
 
 ProgressWidget::ProgressWidget(QWidget *parent)
     : QWidget(parent)
@@ -37,22 +36,13 @@ void ProgressWidget::setLabelText(const QString & text)
     m_label->setText(text);
 }
 
-bool ProgressWidget::wasCanceled() const
-{
-    return false;
-}
-
-void ProgressWidget::setMaximum(int max)
+void ProgressWidget::setMaximum(quint64 max)
 {
     m_progressBar->setMaximum(max);
 }
 
-void ProgressWidget::setValue(int value)
+void ProgressWidget::setValue(quint64 value)
 {
     m_progressBar->setValue(value);
 }
 
-void ProgressWidget::processEvents()
-{
-    qApp->processEvents();
-}
diff --git a/diroperations/progresswidget.h b/diroperations/progresswidget.h
index 6cd327c..6491fcd 100644
--- a/diroperations/progresswidget.h
+++ b/diroperations/progresswidget.h
@@ -28,10 +28,8 @@ public:
     ProgressWidget(QWidget *parent = 0);
 
     virtual void setLabelText(const QString & text);
-    virtual bool wasCanceled() const;
-    virtual void setMaximum(int max);
-    virtual void setValue(int value);
-    virtual void processEvents();
+    virtual void setMaximum(quint64 max);
+    virtual void setValue(quint64 value);
 
 private:
     QLabel *m_label;
diff --git a/diroperations/diroperations.cpp b/diroperations/recursivedirjob.cpp
similarity index 58%
copy from diroperations/diroperations.cpp
copy to diroperations/recursivedirjob.cpp
index 179636c..f06cdd9 100644
--- a/diroperations/diroperations.cpp
+++ b/diroperations/recursivedirjob.cpp
@@ -15,82 +15,119 @@
     You should have received a copy of the GNU Lesser General Public License
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
-#define _FILE_OFFSET_BITS 64
-#include <sys/statvfs.h> // for statvfs for calculating free space
-#include "diroperations.h"
-#include <QDir>
-#include <QFileInfo>
-#include <QStack>
-#include <QDebug>
-#include <climits> //for PATH_MAX
+#include "recursivedirjob_p.h"
+#include <QtCore/QDir>
+#include <QtCore/QFileInfo>
+#include <QtCore/QStack>
+#include <QtCore/QDebug>
 
+using namespace DirOperations;
 
-namespace DirOperations {
+struct RecursiveDirJob::Private
+{
+    RecursiveDirJob::JobType m_jobType;
+    QVariantList m_args;
+    QVariant m_result;
+    Exception m_exception;
+};
+
+//static
+RecursiveDirJob* RecursiveDirJob::calculateDirSize(const QString & dir)
+{
+    return new RecursiveDirJob(CalculateDirSize, QVariantList() << QVariant(dir));
+}
 
-QString Exception::what() const
+//static
+RecursiveDirJob* RecursiveDirJob::recursiveCpDir(const QString & sourcePath,
+                                                const QString & destPath, CopyOptions options)
 {
-    switch (m_type) {
-        case OperationCanceled: return QObject::tr("User canceled the operation");
-        case AccessDenied: return QObject::tr("Access was denied to the file or directory %1").arg(m_info);
-        case NoSuchFileOrDirectory: return QObject::tr("%1: No such file or directory").arg(m_info);
-        case FileOrDirectoryExists: return QObject::tr("%1 already exists").arg(m_info);
-        case CopyFail: return QObject::tr("Could not copy %1").arg(m_info);
-        case MkdirFail: return QObject::tr("Could not create directory %1").arg(m_info);
-        case RmFail: return QObject::tr("Could not remove %1").arg(m_info);
-        default: return QObject::tr("Unknown error");
-    }
+    return new RecursiveDirJob(CpDir, QVariantList() << QVariant(sourcePath)
+                                << QVariant(destPath) << QVariant::fromValue<CopyOptions>(options));
 }
 
+//static
+RecursiveDirJob* RecursiveDirJob::recursiveRmDir(const QString & dir)
+{
+    return new RecursiveDirJob(RmDir, QVariantList() << QVariant(dir));
+}
 
-QString relativeSymLinkTarget(const QString & fileName)
+bool RecursiveDirJob::hasError() const
 {
-    char buff[PATH_MAX+1];
-    int len = readlink(QFile::encodeName(fileName), buff, PATH_MAX);
-    if ( len < 0 )
-        return QString();
-    buff[len] = '\0';
-    return QString(buff);
+    return (isFinished()) ? (d->m_exception.type() != Exception::NoError) : false;
 }
 
-quint64 freeDirSpace(const QString & dir)
+Exception RecursiveDirJob::lastError() const
 {
-    struct statvfs info;
-    int ret = statvfs(dir.toLocal8Bit(),&info);
-    if(ret < 0) {
-      qDebug() << "statvfs errors" << ret;
-      //error handling
-      return -1;
-    }
-    qDebug() << "freeDirSpace" << dir << info.f_bsize*info.f_bavail;
-    return info.f_bsize*info.f_bavail;
-  
+    return (isFinished()) ? d->m_exception : Exception();
 }
 
-quint64 totalPartitionSize(const QString & dir)
+QVariant RecursiveDirJob::result() const
 {
-    struct statvfs info;
-    int ret = statvfs(dir.toLocal8Bit(),&info);
-    if(ret < 0) {
-      qDebug() << "statvfs errors" << ret;
-      //error handling
-      return -1;
+    return (isFinished()) ? d->m_result : QVariant();
+}
+
+void RecursiveDirJob::setProgressDialogInterface(ProgressDialogInterface *pd)
+{
+    m_pd = pd;
+}
+
+RecursiveDirJob::RecursiveDirJob(JobType jtype, const QVariantList & arguments)
+    : QThread(), d(new Private), m_pd(NULL)
+{
+    d->m_jobType = jtype;
+    d->m_args = arguments;
+}
+
+RecursiveDirJob::~RecursiveDirJob()
+{
+    delete d;
+}
+
+void RecursiveDirJob::run()
+{
+    RecursiveDirJobHelper helper(m_pd != NULL); //report progress info if pd != NULL
+
+    connect(&helper, SIGNAL(setValue(quint64)),
+            this, SLOT(setValue(quint64)), Qt::QueuedConnection);
+    connect(&helper, SIGNAL(setMaximum(quint64)),
+            this, SLOT(setMaximum(quint64)), Qt::QueuedConnection);
+    connect(&helper, SIGNAL(setLabelText(QString)),
+            this, SLOT(setLabelText(QString)), Qt::QueuedConnection);
+
+    try {
+        switch( d->m_jobType ) {
+            case CalculateDirSize:
+                d->m_result = helper.calculateDirSize(d->m_args[0].toString());
+                break;
+            case CpDir:
+                helper.recursiveCpDir(d->m_args[0].toString(), d->m_args[1].toString(),
+                                        d->m_args[2].value<CopyOptions>());
+                break;
+            case RmDir:
+                helper.recursiveRmDir(d->m_args[0].toString());
+                break;
+            default:
+                Q_ASSERT(false);
+        }
+    } catch(const Exception & e) {
+        d->m_exception = e;
     }
-    qDebug() << "totalPartitionSize" << dir << info.f_bsize*info.f_blocks;
-    return info.f_frsize*info.f_blocks;
-  
 }
 
-qint64 calculateDirSize(const QString & dir, ProgressDialogInterface *pd)
+//constant defining the QDir filters that are used in the RecursiveDirJobHelper functions
+const QDir::Filters dirFilters = QDir::AllEntries | QDir::NoDotAndDotDot |
+                                 QDir::Hidden | QDir::System | QDir::CaseSensitive;
+
+quint64 RecursiveDirJobHelper::calculateDirSize(const QString & dir)
 {
     QDir currentDir(dir);
     if ( !currentDir.exists() )
         throw Exception(Exception::NoSuchFileOrDirectory, dir);
 
-    QDir::Filters filters = QDir::AllEntries | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System | QDir::CaseSensitive;
-    QFileInfoList currentList = currentDir.entryInfoList( filters, QDir::DirsLast );
+    QFileInfoList currentList = currentDir.entryInfoList(dirFilters);
     QFileInfo currentItem;
     QStack<QFileInfoList> stack;
-    qint64 totalSize = 0;
+    quint64 totalSize = 0;
     int refreshCounter = 0;
 
     while(1){
@@ -102,15 +139,11 @@ qint64 calculateDirSize(const QString & dir, ProgressDialogInterface *pd)
                 if ( !currentDir.cd(currentItem.fileName()) )
                     throw Exception(Exception::AccessDenied, currentItem.absoluteFilePath());
                 stack.push(currentList);
-                currentList = currentDir.entryInfoList( filters, QDir::DirsLast );
+                currentList = currentDir.entryInfoList(dirFilters);
             }
 
-            if ( pd && (++refreshCounter % 100 == 0) ) {
-                pd->setLabelText(QObject::tr("Calculating... %1 bytes").arg(totalSize));
-                pd->processEvents();
-                if (pd->wasCanceled())
-                    throw Exception(Exception::OperationCanceled);
-            }
+            if ( m_reportProgress && (++refreshCounter % 100 == 0) )
+                emit setLabelText(tr("Calculating... %1 bytes").arg(totalSize));
 
         } else { // list is empty
             if ( !stack.isEmpty() ){
@@ -125,7 +158,7 @@ qint64 calculateDirSize(const QString & dir, ProgressDialogInterface *pd)
     return totalSize;
 }
 
-void recursiveCpDir(const QString & sourcePath, const QString & destPath, CopyOptions options, ProgressDialogInterface *pd)
+void RecursiveDirJobHelper::recursiveCpDir(const QString & sourcePath, const QString & destPath, CopyOptions options)
 {
     QDir source(sourcePath);
     if ( !source.exists() )
@@ -133,33 +166,32 @@ void recursiveCpDir(const QString & sourcePath, const QString & destPath, CopyOp
 
     QDir dest(destPath);
     if ( dest.exists() ) {
-        if ( options & RemoveDestination )
-            recursiveRmDir(destPath, pd);
-        else if ( !(options & OverWrite) )
+        if ( options & DirOperations::RemoveDestination )
+            recursiveRmDir(destPath);
+        else if ( !(options & DirOperations::OverWrite) )
             throw Exception(Exception::FileOrDirectoryExists, destPath);
     }
 
     dest.mkdir(dest.absolutePath());
 
-    QDir::Filters filters = QDir::AllEntries | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System | QDir::CaseSensitive;
-    QFileInfoList currentList = source.entryInfoList( filters, QDir::DirsLast );
+    QFileInfoList currentList = source.entryInfoList(dirFilters);
     QFileInfo currentItem;
     QStack<QFileInfoList> stack;
     QString currentName;
-    qint64 bytesCopied = 0;
+    quint64 bytesCopied = 0;
 
-    if ( pd ) {
-        qint64 dirSize = calculateDirSize(sourcePath, pd);
-        pd->setLabelText(QObject::tr("Copying files..."));
+    if ( m_reportProgress ) {
+        quint64 dirSize = calculateDirSize(sourcePath);
+        emit setLabelText(tr("Copying files..."));
         if (dirSize > 0) {
-            pd->setMaximum(dirSize);
+            emit setMaximum(dirSize);
             //the directory special file is already (almost) copied in dest.mkdir() above
             bytesCopied += QFileInfo(sourcePath).size();
-            pd->setValue(bytesCopied);
+            emit setValue(bytesCopied);
         } else {
             //no files to be copied, so set the progressbar to 100%
-            pd->setMaximum(1);
-            pd->setValue(1);
+            emit setMaximum(1);
+            emit setValue(1);
         }
     }
 
@@ -194,7 +226,7 @@ void recursiveCpDir(const QString & sourcePath, const QString & destPath, CopyOp
                 }
 
                 stack.push(currentList);
-                currentList = source.entryInfoList( filters, QDir::DirsLast );
+                currentList = source.entryInfoList(dirFilters);
             }
             else if ( currentItem.isFile() )
             {
@@ -211,9 +243,9 @@ void recursiveCpDir(const QString & sourcePath, const QString & destPath, CopyOp
                 qDebug() << "Ignoring special file" << source.absoluteFilePath(currentName);
             }
 
-            if ( pd ) {
+            if ( m_reportProgress ) {
                 bytesCopied += currentItem.size();
-                pd->setValue(bytesCopied);
+                emit setValue(bytesCopied);
             }
         }
         else // list is empty
@@ -227,43 +259,36 @@ void recursiveCpDir(const QString & sourcePath, const QString & destPath, CopyOp
             else
                 break;
         }
-
-        if ( pd ) {
-            pd->processEvents();
-            if (pd->wasCanceled())
-                throw Exception(Exception::OperationCanceled);
-        }
     }
 }
 
-void recursiveRmDir(const QString & dir, ProgressDialogInterface *pd)
+void RecursiveDirJobHelper::recursiveRmDir(const QString & dir)
 {
     QDir currentDir(dir);
     if ( !currentDir.exists() ) {
         qWarning() << "recursiveRmDir: trying to remove non-existent directory" << dir;
-        if (pd) {
+        if (m_reportProgress) {
             //no files to be removed, so set the progressbar to 100%
-            pd->setMaximum(1);
-            pd->setValue(1);
+            emit setMaximum(1);
+            emit setValue(1);
         }
         return; // directory gone, no work to do
     }
 
-    QDir::Filters filters = QDir::AllEntries | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System | QDir::CaseSensitive;
-    QFileInfoList currentList = currentDir.entryInfoList( filters, QDir::DirsLast );
+    QFileInfoList currentList = currentDir.entryInfoList(dirFilters);
     QFileInfo currentItem;
     QStack<QFileInfoList> stack;
-    qint64 bytesRemoved = 0;
+    quint64 bytesRemoved = 0;
 
-    if ( pd ) {
-        qint64 dirSize = calculateDirSize(dir, pd);
-        pd->setLabelText(QObject::tr("Removing files..."));
+    if (m_reportProgress) {
+        quint64 dirSize = calculateDirSize(dir);
+        emit setLabelText(tr("Removing files..."));
         if (dirSize > 0) {
-            pd->setMaximum(dirSize);
+            emit setMaximum(dirSize);
         } else {
             //no files to be removed, so set the progressbar to 100%
-            pd->setMaximum(1);
-            pd->setValue(1);
+            emit setMaximum(1);
+            emit setValue(1);
         }
     }
 
@@ -277,13 +302,13 @@ void recursiveRmDir(const QString & dir, ProgressDialogInterface *pd)
                 if ( !currentDir.cd(currentItem.fileName()) )
                     throw Exception(Exception::AccessDenied, currentItem.absoluteFilePath());
                 stack.push(currentList);
-                currentList = currentDir.entryInfoList( filters, QDir::DirsLast );
+                currentList = currentDir.entryInfoList(dirFilters);
             }
             else
             {
-                if ( pd ) {
+                if ( m_reportProgress ) {
                     bytesRemoved += currentItem.size();
-                    pd->setValue(bytesRemoved);
+                    emit setValue(bytesRemoved);
                 }
 
                 if ( !currentDir.remove(currentItem.fileName()) )
@@ -302,13 +327,10 @@ void recursiveRmDir(const QString & dir, ProgressDialogInterface *pd)
             QString tmpname = currentDir.dirName();
             currentDir.cdUp();
 
-            if ( pd ) {
+            if ( m_reportProgress ) {
                 //count the directory special file before it is removed
                 bytesRemoved += QFileInfo(currentDir, tmpname).size();
-                pd->setValue(bytesRemoved);
-                //if we are about to quit, process events before exiting the loop (to make the progressbar reach 100%)
-                if ( quit )
-                    pd->processEvents();
+                emit setValue(bytesRemoved);
             }
 
             if ( !currentDir.rmdir(tmpname) )
@@ -317,13 +339,6 @@ void recursiveRmDir(const QString & dir, ProgressDialogInterface *pd)
             if ( quit )
                 break;
         }
-
-        if ( pd ) {
-            pd->processEvents();
-            if (pd->wasCanceled())
-                throw Exception(Exception::OperationCanceled);
-        }
     }
 }
 
-} //namespace DirOperations
diff --git a/diroperations/recursivedirjob.h b/diroperations/recursivedirjob.h
new file mode 100644
index 0000000..b67740a
--- /dev/null
+++ b/diroperations/recursivedirjob.h
@@ -0,0 +1,58 @@
+/*
+    Copyright (C) 2009  George Kiagiadakis <gkiagia at users.sourceforge.net>
+
+    This library is free software; you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published
+    by the Free Software Foundation; either version 2.1 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef RECURSIVEDIRJOB_H
+#define RECURSIVEDIRJOB_H
+
+#include "diroperations.h"
+#include <QtCore/QThread>
+#include <QtCore/QVariant>
+
+class RecursiveDirJob : public QThread
+{
+    Q_OBJECT
+public:
+    virtual ~RecursiveDirJob();
+
+    static RecursiveDirJob* calculateDirSize(const QString & dir);
+    static RecursiveDirJob* recursiveRmDir(const QString & dir);
+    static RecursiveDirJob* recursiveCpDir(const QString & sourcePath, const QString & destPath,
+                                           DirOperations::CopyOptions options = DirOperations::NoOptions);
+
+    void setProgressDialogInterface(DirOperations::ProgressDialogInterface *pd);
+
+    bool hasError() const;
+    DirOperations::Exception lastError() const;
+    QVariant result() const;
+
+protected:
+    enum JobType { CalculateDirSize, CpDir, RmDir };
+    RecursiveDirJob(JobType jtype, const QVariantList & arguments);
+
+    virtual void run();
+
+private:
+    struct Private;
+    Private *const d;
+    DirOperations::ProgressDialogInterface *m_pd;
+
+    //these will be called in the main thread.
+    Q_PRIVATE_SLOT(m_pd, void setValue(quint64));
+    Q_PRIVATE_SLOT(m_pd, void setMaximum(quint64));
+    Q_PRIVATE_SLOT(m_pd, void setLabelText(QString));
+};
+
+#endif
diff --git a/diroperations/progresswidget.h b/diroperations/recursivedirjob_p.h
similarity index 54%
copy from diroperations/progresswidget.h
copy to diroperations/recursivedirjob_p.h
index 6cd327c..105652f 100644
--- a/diroperations/progresswidget.h
+++ b/diroperations/recursivedirjob_p.h
@@ -14,28 +14,30 @@
     You should have received a copy of the GNU Lesser General Public License
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
-#ifndef PROGRESSWIDGET_H
-#define PROGRESSWIDGET_H
+#ifndef RECURSIVEDIRJOB_P_H
+#define RECURSIVEDIRJOB_P_H
 
-#include "diroperations.h"
-#include <QWidget>
-class QLabel;
-class QProgressBar;
+#include "recursivedirjob.h"
 
-class ProgressWidget : public QWidget, public DirOperations::ProgressDialogInterface
+class RecursiveDirJobHelper : public QObject
 {
+    Q_OBJECT
 public:
-    ProgressWidget(QWidget *parent = 0);
+    RecursiveDirJobHelper(bool reportProgress, QObject *parent = 0)
+        : QObject(parent), m_reportProgress(reportProgress) {}
 
-    virtual void setLabelText(const QString & text);
-    virtual bool wasCanceled() const;
-    virtual void setMaximum(int max);
-    virtual void setValue(int value);
-    virtual void processEvents();
+    quint64 calculateDirSize(const QString & dir);
+    void recursiveCpDir(const QString & sourcePath, const QString & destPath,
+                        DirOperations::CopyOptions options);
+    void recursiveRmDir(const QString & dir);
+
+signals:
+    void setValue(quint64 value);
+    void setMaximum(quint64 maxValue);
+    void setLabelText(QString text);
 
 private:
-    QLabel *m_label;
-    QProgressBar *m_progressBar;
+    bool m_reportProgress;
 };
 
 #endif
diff --git a/kaboom.pro b/kaboom.pro
index 13a029d..60045be 100644
--- a/kaboom.pro
+++ b/kaboom.pro
@@ -25,12 +25,14 @@ HEADERS += \
       migrationtool_p.h \
       warningpage.h \
       diroperations/diroperations.h \
+      diroperations/recursivedirjob.h \
+      diroperations/recursivedirjob_p.h \
       diroperations/progresswidget.h \
       richradiobutton.h
 
 
 SOURCES += \
-      kaboomsettings.cpp \ 
+      kaboomsettings.cpp \
       choicepage.cpp \
       intropage.cpp \
       main.cpp \
@@ -38,6 +40,7 @@ SOURCES += \
       migrationtool.cpp \
       warningpage.cpp \
       diroperations/diroperations.cpp \
+      diroperations/recursivedirjob.cpp \
       diroperations/progresswidget.cpp \
       richradiobutton.cpp
 

-- 
Kaboom - Debian KDE 3->4 migration tool



More information about the pkg-kde-commits mailing list