akabeierror.cpp 4.93 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
/* This file is part of the Chakra project

   Copyright (C) 2010 Dario Freddi <drf@chakra-project.org>

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.
*/

11
#include <akabeierror.h>
Lisa's avatar
Lisa committed
12 13 14 15 16
#include <QQueue>
#include <QMap>
#include <QMetaType>
#include <QDebug>
#include <QReadWriteLock>
17

18 19
namespace Akabei
{
20

Lisa's avatar
Lisa committed
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
class ErrorHandler
{
public:
    ErrorHandler(QObject* receiver, const char* handler)
        : m_receiver(receiver)
        , m_slot(handler)
    {}
    
    QObject* receiver() const
    {
        return m_receiver;
    }
    
    const char* slot() const
    {
        return m_slot;
    }
    
private:
    QObject* m_receiver;
    const char* m_slot;
};
    
class ErrorQueue::Private
{
public:
    Private() : mutex(new QReadWriteLock(QReadWriteLock::Recursive))
    {}
    
    ~Private()
    {
    }
    
    QQueue<Error> errorQueue;
    QMultiMap< Error::Type, ErrorHandler* > errorSlots;
    QReadWriteLock * mutex;
};
    
class ErrorQueueHelper
{
public:
    ErrorQueueHelper()
63
      : q( nullptr )
Lisa's avatar
Lisa committed
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
    {}

    virtual ~ErrorQueueHelper()
    {
        delete q;
    }

    ErrorQueue* q;
};
Q_GLOBAL_STATIC(ErrorQueueHelper, s_globalErrorQueue)

ErrorQueue::ErrorQueue()
    : d( new Private )
{
    Q_ASSERT(!s_globalErrorQueue()->q);
    qRegisterMetaType<Error::Type>("Error::Type");    
    s_globalErrorQueue()->q = this;
}

ErrorQueue::~ErrorQueue()
{
    delete d;
}

ErrorQueue* ErrorQueue::instance()
{
    if (!s_globalErrorQueue()->q) {
        new ErrorQueue;
    }
    
    return s_globalErrorQueue()->q;
}

void ErrorQueue::registerForErrorType(Error::Type t, QObject* receiver, const char* slot)
{
    QWriteLocker locker(d->mutex);
    d->errorSlots.insertMulti(t, new ErrorHandler(receiver, slot));
}

void ErrorQueue::registerForAllErrors(QObject* receiver, const char* slot)
{
    QWriteLocker locker(d->mutex);
106
    auto  h = new ErrorHandler(receiver, slot);
Lisa's avatar
Lisa committed
107 108 109 110 111 112 113 114 115 116 117 118 119 120
    
    for (int t = Error::UnknownError; t <= Error::FilesystemError; t++) {
        d->errorSlots.insertMulti((Error::Type)t, h);
    }
    
    d->errorSlots.insertMulti(Error::GenericError, h);
    d->errorSlots.insertMulti(Error::AkabeiInternalError, h);
}

void ErrorQueue::appendError(const Error& error)
{
    QWriteLocker locker(d->mutex);
    d->errorQueue.enqueue(error);
    
121 122
    for (auto it = d->errorSlots.constFind( error.type() ), end = d->errorSlots.constEnd(); it != end && it.key() == error.type(); ++it ) {
        ErrorHandler* registeredHandler = it.value();
Lisa's avatar
Lisa committed
123 124
        QMetaObject::invokeMethod(registeredHandler->receiver(), registeredHandler->slot(), Qt::QueuedConnection);
    }
125

Lisa's avatar
Lisa committed
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
}

void ErrorQueue::appendErrors(const Error::List& errors)
{
    QWriteLocker locker(d->mutex);
    foreach (const Error& error, errors) {
        appendError(error);
    }
}

bool ErrorQueue::isEmpty() const
{
    QReadLocker locker(d->mutex);
    return d->errorQueue.isEmpty();
}

Error ErrorQueue::takeError()
{
    QReadLocker locker(d->mutex);
    return d->errorQueue.dequeue();
}

Error::Type ErrorQueue::headType() const
{
    QReadLocker locker(d->mutex);
    return d->errorQueue.first().type();
}
    
154 155 156 157 158 159 160
/**
 * @class Error::Private
 * @brief Class for operation errors.
 * 
 * It covers an operation, and includes the type of error occurred, as well as a
 * description of the error and the list of affected packages.
 */
Lukas Appelhans's avatar
Lukas Appelhans committed
161
class Error::Private : public QSharedData
162 163
{
    public:
164
        Private(Error::Type type, QString const& description, Operation* operation)
Lukas Appelhans's avatar
Lukas Appelhans committed
165 166 167 168 169 170 171 172 173 174 175 176 177 178
          : type( type )
          , description( description )
          , operation( operation )
        {
        }

        Private(const Private &d)
          : QSharedData()
          , type(d.type)
          , description(d.description)
          , operation(d.operation)
          , packages(d.packages)
        {
        }
179 180

        virtual ~Private()
Lukas Appelhans's avatar
Lukas Appelhans committed
181 182
        {
        }
183 184

        Type type;
185 186
        QString description;
        Operation* operation;
187
        Package::List packages;
188 189
};

Lukas Appelhans's avatar
Lukas Appelhans committed
190 191
Error::Error(const Error &error)
    : d(error.d)
192 193 194
{
}

195 196
Error::Error(Error::Type type, const QString& description, Operation* operation)
    : d( new Private(type, description, operation) )
197 198 199 200 201
{
}

Error::~Error()
{
Lukas Appelhans's avatar
Lukas Appelhans committed
202 203 204 205 206 207
}

Error& Error::operator=(const Error &other)
{
    d = other.d;
    return *this;
208 209 210 211
}

QString Error::description() const
{
212
    return d->description;
213 214 215 216
}

Operation* Error::operation()
{
217
    return d->operation;
218 219
}

220 221 222 223 224
void Error::setType(Error::Type type)
{
    d->type = type;
}

225 226
void Error::setDescription(const QString& description)
{
227
    d->description = description;
228 229
}

230
void Error::setOperation(Operation* operation)
231
{
232
    d->operation = operation;
233 234
}

235
void Error::setTargets(Package::List const& targets)
236 237 238 239
{
    d->packages = targets;
}

240
Package::List Error::targets() const
241 242 243 244 245 246 247 248 249
{
    return d->packages;
}

Error::Type Error::type() const
{
    return d->type;
}

250
}