[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