Commit 15fce6f5 authored by Raphael Kubo da Costa's avatar Raphael Kubo da Costa
Browse files

Get rid of the Observer class.

I have never understood why this class was added in the first place,
and digging through the old commit history does not help much in this
regard.  It was mostly used as another way of doing signals and slots.

 * The calls in ArchiveInterface that called each observer method now
   just emit the signals declared in ReadOnlyArchiveInterface, and the
   observer methods in the Job classes are now slots.
 * ReadOnlyArchiveInterface::removeObserver() has been replaced with
   QObject::disconnect().

All the (few) unit tests we have still pass.
parent 3e7d49fb
/*
* Copyright (c) 2007 Henrique Pinto <henrique.pinto@kdemail.net>
* Copyright (c) 2008-2009 Harald Hvaal <haraldhv@stud.ntnu.no>
* Copyright (c) 2009-2012 Raphael Kubo da Costa <rakuco@FreeBSD.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
......@@ -25,7 +26,6 @@
*/
#include "archiveinterface.h"
#include "observer.h"
#include <kdebug.h>
#include <kfileitem.h>
......@@ -70,48 +70,6 @@ QString ReadOnlyArchiveInterface::password() const
return m_password;
}
void ReadOnlyArchiveInterface::error(const QString & message, const QString & details)
{
foreach(ArchiveObserver *observer, m_observers) {
observer->onError(message, details);
}
}
void ReadOnlyArchiveInterface::entry(const ArchiveEntry & archiveEntry)
{
foreach(ArchiveObserver *observer, m_observers) {
observer->onEntry(archiveEntry);
}
}
void ReadOnlyArchiveInterface::entryRemoved(const QString & path)
{
foreach(ArchiveObserver *observer, m_observers) {
observer->onEntryRemoved(path);
}
}
void ReadOnlyArchiveInterface::progress(double p)
{
foreach(ArchiveObserver *observer, m_observers) {
observer->onProgress(p);
}
}
void ReadOnlyArchiveInterface::info(const QString& info)
{
foreach(ArchiveObserver *observer, m_observers) {
observer->onInfo(info);
}
}
void ReadOnlyArchiveInterface::finished(bool result)
{
foreach(ArchiveObserver *observer, m_observers) {
observer->onFinished(result);
}
}
bool ReadOnlyArchiveInterface::doKill()
{
//default implementation
......@@ -130,23 +88,6 @@ bool ReadOnlyArchiveInterface::doResume()
return false;
}
void ReadOnlyArchiveInterface::userQuery(Query *query)
{
foreach(ArchiveObserver *observer, m_observers) {
observer->onUserQuery(query);
}
}
void ReadOnlyArchiveInterface::registerObserver(ArchiveObserver *observer)
{
m_observers.append(observer);
}
void ReadOnlyArchiveInterface::removeObserver(ArchiveObserver *observer)
{
m_observers.removeAll(observer);
}
ReadWriteArchiveInterface::ReadWriteArchiveInterface(QObject *parent, const QVariantList & args)
: ReadOnlyArchiveInterface(parent, args)
{
......
/*
* Copyright (c) 2007 Henrique Pinto <henrique.pinto@kdemail.net>
* Copyright (c) 2008-2009 Harald Hvaal <haraldhv@stud.ntnu.no>
* Copyright (c) 2009-2012 Raphael Kubo da Costa <rakuco@FreeBSD.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
......@@ -37,7 +38,6 @@
namespace Kerfuffle
{
class ArchiveObserver;
class Query;
class KERFUFFLE_EXPORT ReadOnlyArchiveInterface: public QObject
......@@ -60,9 +60,6 @@ public:
*/
virtual bool isReadOnly() const;
void KDE_NO_EXPORT registerObserver(ArchiveObserver *observer);
void KDE_NO_EXPORT removeObserver(ArchiveObserver *observer);
virtual bool open();
/**
......@@ -71,7 +68,7 @@ public:
* When subclassing, you can block as long as you need, the function runs
* in its own thread.
* @returns whether the listing succeeded.
* @note If returning false, make sure to call error() beforewards to notify
* @note If returning false, make sure to emit the error() signal beforewards to notify
* the user of the error condition.
*/
virtual bool list() = 0;
......@@ -85,37 +82,28 @@ public:
* When subclassing, you can block as long as you need, the function runs
* in its own thread.
* @returns whether the listing succeeded.
* @note If returning false, make sure to call error() beforewards to notify
* @note If returning false, make sure to emit the error() signal beforewards to notify
* the user of the error condition.
*/
virtual bool copyFiles(const QList<QVariant> & files, const QString & destinationDirectory, ExtractionOptions options) = 0;
bool waitForFinishedSignal();
void finished(bool result);
virtual bool doKill();
virtual bool doSuspend();
virtual bool doResume();
protected:
/**
* Communicate an error.
* Sets message of error for user to read and understand. It will be
* displayed once the job has returned false.
*/
void error(const QString & message, const QString & details = QString());
signals:
void error(const QString &message, const QString &details = QString());
void entry(const ArchiveEntry &archiveEntry);
void entryRemoved(const QString &path);
void progress(double progress);
void info(const QString &info);
void finished(bool result);
void userQuery(Query *query);
/**
* Notify observers of a new archive entry.
* The interface should call this function whenever a new archive entry
* is read. @note Remember that directories should have filename ending with /.
*/
void entry(const ArchiveEntry & archiveEntry);
void progress(double);
void info(const QString& info);
void entryRemoved(const QString& path);
protected:
QString password() const;
void userQuery(Query*);
/**
* Setting this option to true will not exit the thread with the
* exit of the various functions, but rather when finished(bool) is
......@@ -125,7 +113,6 @@ protected:
void setWaitForFinishedSignal(bool value);
private:
QList<ArchiveObserver*> m_observers;
QString m_filename;
QString m_password;
bool m_waitForFinishedSignal;
......
......@@ -150,7 +150,7 @@ bool CliInterface::copyFiles(const QList<QVariant> & files, const QString & dest
kDebug() << "Password hint enabled, querying user";
Kerfuffle::PasswordNeededQuery query(filename());
userQuery(&query);
emit userQuery(&query);
query.waitForResponse();
if (query.responseCancelled()) {
......@@ -322,7 +322,7 @@ bool CliInterface::runProcess(const QString& programName, const QStringList& arg
{
const QString programPath(KStandardDirs::findExe(programName));
if (programPath.isEmpty()) {
error(i18nc("@info", "Failed to locate program <filename>%1</filename> in PATH.", programName));
emit error(i18nc("@info", "Failed to locate program <filename>%1</filename> in PATH.", programName));
return false;
}
......@@ -379,14 +379,14 @@ void CliInterface::processFinished(int exitCode, QProcess::ExitStatus exitStatus
if (m_operationMode == Delete) {
foreach(const QVariant& v, m_removedFiles) {
entryRemoved(v.toString());
emit entryRemoved(v.toString());
}
}
//handle all the remaining data in the process
readStdout(true);
progress(1.0);
emit progress(1.0);
if (m_operationMode == Add) {
list();
......@@ -394,7 +394,7 @@ void CliInterface::processFinished(int exitCode, QProcess::ExitStatus exitStatus
}
//and we're finished
finished(true);
emit finished(true);
}
void CliInterface::failOperation()
......@@ -403,7 +403,7 @@ void CliInterface::failOperation()
doKill();
finished(false);
emit finished(false);
}
void CliInterface::readStdout(bool handleAll)
......@@ -486,7 +486,7 @@ void CliInterface::handleLine(const QString& line)
int pos = line.indexOf(QLatin1Char( '%' ));
if (pos != -1 && pos > 1) {
int percentage = line.mid(pos - 2, 2).toInt();
progress(float(percentage) / 100);
emit progress(float(percentage) / 100);
return;
}
}
......@@ -496,7 +496,7 @@ void CliInterface::handleLine(const QString& line)
kDebug() << "Found a password prompt";
Kerfuffle::PasswordNeededQuery query(filename());
userQuery(&query);
emit userQuery(&query);
query.waitForResponse();
if (query.responseCancelled()) {
......@@ -514,14 +514,14 @@ void CliInterface::handleLine(const QString& line)
if (checkForErrorMessage(line, WrongPasswordPatterns)) {
kDebug() << "Wrong password!";
error(i18n("Incorrect password."));
emit error(i18n("Incorrect password."));
failOperation();
return;
}
if (checkForErrorMessage(line, ExtractionFailedPatterns)) {
kDebug() << "Error in extraction!!";
error(i18n("Extraction failed because of an unexpected error."));
emit error(i18n("Extraction failed because of an unexpected error."));
failOperation();
return;
}
......@@ -536,7 +536,7 @@ void CliInterface::handleLine(const QString& line)
kDebug() << "Found a password prompt";
Kerfuffle::PasswordNeededQuery query(filename());
userQuery(&query);
emit userQuery(&query);
query.waitForResponse();
if (query.responseCancelled()) {
......@@ -554,14 +554,14 @@ void CliInterface::handleLine(const QString& line)
if (checkForErrorMessage(line, WrongPasswordPatterns)) {
kDebug() << "Wrong password!";
error(i18n("Incorrect password."));
emit error(i18n("Incorrect password."));
failOperation();
return;
}
if (checkForErrorMessage(line, ExtractionFailedPatterns)) {
kDebug() << "Error in extraction!!";
error(i18n("Extraction failed because of an unexpected error."));
emit error(i18n("Extraction failed because of an unexpected error."));
failOperation();
return;
}
......@@ -616,7 +616,7 @@ bool CliInterface::handleFileExistsMessage(const QString& line)
Kerfuffle::OverwriteQuery query(QDir::current().path() + QLatin1Char( '/' ) + filename);
query.setNoRenameMode(true);
userQuery(&query);
emit userQuery(&query);
kDebug() << "Waiting response";
query.waitForResponse();
......
/*
* Copyright (c) 2007 Henrique Pinto <henrique.pinto@kdemail.net>
* Copyright (c) 2008-2009 Harald Hvaal <haraldhv@stud.ntnu.no>
* Copyright (c) 2009-2010 Raphael Kubo da Costa <rakuco@FreeBSD.org>
* Copyright (c) 2009-2012 Raphael Kubo da Costa <rakuco@FreeBSD.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
......@@ -112,6 +112,17 @@ void Job::emitResult()
KJob::emitResult();
}
void Job::connectToArchiveInterfaceSignals()
{
connect(archiveInterface(), SIGNAL(error(QString,QString)), SLOT(onError(QString,QString)));
connect(archiveInterface(), SIGNAL(entry(ArchiveEntry)), SLOT(onEntry(ArchiveEntry)));
connect(archiveInterface(), SIGNAL(entryRemoved(QString)), SLOT(onEntryRemoved(QString)));
connect(archiveInterface(), SIGNAL(progress(double)), SLOT(onProgress(double)));
connect(archiveInterface(), SIGNAL(info(QString)), SLOT(onInfo(QString)));
connect(archiveInterface(), SIGNAL(finished(bool)), SLOT(onFinished(bool)));
connect(archiveInterface(), SIGNAL(userQuery(Query*)), SLOT(onUserQuery(Query*)));
}
void Job::onError(const QString & message, const QString & details)
{
Q_UNUSED(details)
......@@ -144,7 +155,7 @@ void Job::onFinished(bool result)
{
kDebug() << result;
archiveInterface()->removeObserver(this);
archiveInterface()->disconnect(this);
emitResult();
}
......@@ -177,11 +188,11 @@ ListJob::ListJob(ReadOnlyArchiveInterface *interface, QObject *parent)
void ListJob::doWork()
{
emit description(this, i18n("Loading archive..."));
archiveInterface()->registerObserver(this);
connectToArchiveInterfaceSignals();
bool ret = archiveInterface()->list();
if (!archiveInterface()->waitForFinishedSignal()) {
archiveInterface()->finished(ret);
onFinished(ret);
}
}
......@@ -245,7 +256,7 @@ void ExtractJob::doWork()
}
emit description(this, desc);
archiveInterface()->registerObserver(this);
connectToArchiveInterfaceSignals();
kDebug() << "Starting extraction with selected files:"
<< m_files
......@@ -255,7 +266,7 @@ void ExtractJob::doWork()
bool ret = archiveInterface()->copyFiles(m_files, m_destinationDir, m_options);
if (!archiveInterface()->waitForFinishedSignal()) {
archiveInterface()->finished(ret);
onFinished(ret);
}
}
......@@ -299,11 +310,11 @@ void AddJob::doWork()
Q_ASSERT(m_writeInterface);
m_writeInterface->registerObserver(this);
connectToArchiveInterfaceSignals();
bool ret = m_writeInterface->addFiles(m_files, m_options);
if (!archiveInterface()->waitForFinishedSignal()) {
archiveInterface()->finished(ret);
onFinished(ret);
}
}
......@@ -322,11 +333,11 @@ void DeleteJob::doWork()
Q_ASSERT(m_writeInterface);
m_writeInterface->registerObserver(this);
connectToArchiveInterfaceSignals();
int ret = m_writeInterface->deleteFiles(m_files);
if (!archiveInterface()->waitForFinishedSignal()) {
archiveInterface()->finished(ret);
onFinished(ret);
}
}
......
/*
* Copyright (c) 2007 Henrique Pinto <henrique.pinto@kdemail.net>
* Copyright (c) 2008-2009 Harald Hvaal <haraldhv@stud.ntnu.no>
* Copyright (c) 2009-2010 Raphael Kubo da Costa <rakuco@FreeBSD.org>
* Copyright (c) 2009-2012 Raphael Kubo da Costa <rakuco@FreeBSD.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
......@@ -32,7 +32,6 @@
#include "archiveinterface.h"
#include "archive.h"
#include "queries.h"
#include "observer.h"
#include <KJob>
#include <QList>
......@@ -44,22 +43,13 @@ namespace Kerfuffle
class ThreadExecution;
class KERFUFFLE_EXPORT Job : public KJob, public ArchiveObserver
class KERFUFFLE_EXPORT Job : public KJob
{
Q_OBJECT
public:
void start();
//abstract implemented methods from observer
virtual void onError(const QString & message, const QString & details);
virtual void onInfo(const QString & info);
virtual void onEntry(const ArchiveEntry & archiveEntry);
virtual void onProgress(double);
virtual void onEntryRemoved(const QString & path);
virtual void onFinished(bool result);
virtual void onUserQuery(class Query *query);
bool isRunning() const;
protected:
......@@ -70,9 +60,20 @@ protected:
ReadOnlyArchiveInterface *archiveInterface();
void connectToArchiveInterfaceSignals();
public slots:
virtual void doWork() = 0;
protected slots:
virtual void onError(const QString &message, const QString &details);
virtual void onInfo(const QString &info);
virtual void onEntry(const ArchiveEntry &archiveEntry);
virtual void onProgress(double progress);
virtual void onEntryRemoved(const QString &path);
virtual void onFinished(bool result);
virtual void onUserQuery(Query *query);
signals:
void entryRemoved(const QString & entry);
void error(const QString& errorMessage, const QString& details);
......
/*
* ark -- archiver for the KDE project
*
* Copyright (C) 2007 Henrique Pinto <henrique.pinto@kdemail.net>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ( INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef OBSERVER_H
#define OBSERVER_H
#include "archive.h"
namespace Kerfuffle
{
class ArchiveObserver
{
public:
ArchiveObserver() {}
virtual ~ArchiveObserver() {}
virtual void onError(const QString & message, const QString & details) = 0;
virtual void onEntry(const ArchiveEntry & archiveEntry) = 0;
virtual void onProgress(double) = 0;
virtual void onInfo(const QString& message) = 0;
virtual void onEntryRemoved(const QString & path) = 0;
virtual void onFinished(bool result) = 0;
virtual void onUserQuery(class Query *query) = 0;
};
} // namespace Kerfuffle
#endif // OBSERVER_H
......@@ -43,7 +43,7 @@ bool JSONArchiveInterface::list()
{
JSONParser::JSONArchive::const_iterator it = m_archive.constBegin();
for (; it != m_archive.constEnd(); ++it) {
entry(*it);
emit entry(*it);
}
return true;
......@@ -99,7 +99,7 @@ bool JSONArchiveInterface::deleteFiles(const QList<QVariant>& files)
const QString fileName = file.toString();
if (m_archive.contains(fileName)) {
m_archive.remove(fileName);
entryRemoved(fileName);
emit entryRemoved(fileName);
}
}
......
......@@ -166,7 +166,7 @@ bool CliPlugin::readListLine(const QString& line)
m_currentArchiveEntry[ IsPasswordProtected ] = (line.at(12) == QLatin1Char( '+' ));
} else if (line.startsWith(QLatin1String("Block = "))) {
if (m_currentArchiveEntry.contains(FileName)) {
entry(m_currentArchiveEntry);
emit entry(m_currentArchiveEntry);
}
}
break;
......
......@@ -114,7 +114,7 @@ bool CliPlugin::readListLine(const QString &line)
QDate::fromString(entryList[6], QLatin1String("yyyy-MM-dd")),
QTime::fromString(entryList[7], QLatin1String("HH:mm:ss")));
e[Timestamp] = timestamp;
entry(e);
emit entry(e);
}
else if (entryList.count() == 10) { // All info is available
const QStringList ownerList = entryList[1].split(QLatin1Char('/')); // Separate uid from gui
......@@ -130,7 +130,7 @@ bool CliPlugin::readListLine(const QString &line)
QDate::fromString(entryList[7], QLatin1String("yyyy-MM-dd")),
QTime::fromString(entryList[8], QLatin1String("HH:mm:ss")));
e[Timestamp] = timestamp;
entry(e);
emit entry(e);
}
m_firstLine = true;
......
......@@ -140,7 +140,7 @@ bool CliPlugin::readListLine(const QString &line)
e[ IsPasswordProtected] = m_isPasswordProtected;
kDebug() << "Added entry: " << e;
entry(e);
emit entry(e);
m_isFirstLine = true;
return true;
}
......
......@@ -247,7 +247,7 @@ bool CliPlugin::readListLine(const QString &line)
e[IsPasswordProtected] = m_isPasswordProtected;
kDebug() << "Added entry: " << e;
entry(e);
emit entry(e);
// #243273: unrar-free does not output the third file entry line,
// skip directly to parsing a new entry.
......
......@@ -131,7 +131,7 @@ bool CliPlugin::readListLine(const QString &line)
e[Timestamp] = ts;
e[FileName] = e[InternalID] = entryPattern.cap(10);
entry(e);
emit entry(e);
}
break;
}
......
......@@ -62,7 +62,7 @@ bool KArchiveInterface::list()
{
kDebug();
if (!archive()->isOpen() && !archive()->open(QIODevice::ReadOnly)) {
error(i18nc("@info", "Could not open the archive <filename>%1</filename> for reading", filename()));
emit error(i18nc("@info", "Could not open the archive <filename>%1</filename> for reading", filename()));
return false;
} else {
return browseArchive(archive());
......@@ -89,7 +89,7 @@ bool KArchiveInterface::copyFiles(const QList<QVariant> &files, const QString &d
const KArchiveDirectory *dir = archive()->directory();
if (!archive()->isOpen() && !archive()->open(QIODevice::ReadOnly)) {
error(i18nc("@info", "Could not open the archive <filename>%1</filename> for reading", filename()));
emit error(i18nc("@info", "Could not open the archive <filename>%1</filename> for reading", filename()));
return false;
}
......@@ -105,7 +105,7 @@ bool KArchiveInterface::copyFiles(const QList<QVariant> &files, const QString &d
QString realDestination = destinationDirectory;
const KArchiveEntry *archiveEntry = dir->entry(file.toString());
if (!archiveEntry) {
error(i18nc("@info", "File <filename>%1</filename> not found in the archive" , file.toString()));
emit error(i18nc("@info", "File <filename>%1</filename> not found in the archive" , file.toString()));
return false;
}
......@@ -115,7 +115,7 @@ bool KArchiveInterface::copyFiles(const QList<QVariant> &files, const QString &d
QString filepath = archiveEntry->isDirectory() ? fi.filePath() : fi.path();
if (!dirCache.contains(filepath)) {
if (!dest.mkpath(filepath)) {
error(i18nc("@info", "Error creating directory <filename>%1</filename>", filepath);
emit error(i18nc("@info", "Error creating directory <filename>%1</filename>", filepath));
return false;
}
dirCache << filepath;
......@@ -158,7 +158,7 @@ int KArchiveInterface::handleFileExistsMessage(const QString &dir, const QString
{
Kerfuffle::OverwriteQuery query(dir + QLatin1Char('/') + fileName);
query.setNoRenameMode(true);
userQuery(&query);
emit userQuery(&query);
query.waitForResponse();
if (query.responseOverwrite()) {
......@@ -216,7 +216,7 @@ void KArchiveInterface::createEntryFor(const KArchiveEntry *aentry, const QStrin