File indexing completed on 2024-05-05 04:48:15

0001 /****************************************************************************************
0002  * Copyright (c) 2010 Maximilian Kossick <maximilian.kossick@googlemail.com>            *
0003  *                                                                                      *
0004  * This program is free software; you can redistribute it and/or modify it under        *
0005  * the terms of the GNU General Public License as published by the Free Software        *
0006  * Foundation; either version 2 of the License, or (at your option) any later           *
0007  * version.                                                                             *
0008  *                                                                                      *
0009  * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
0010  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
0011  * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
0012  *                                                                                      *
0013  * You should have received a copy of the GNU General Public License along with         *
0014  * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
0015  ****************************************************************************************/
0016 
0017 #ifndef AMAROK_LOGGER_H
0018 #define AMAROK_LOGGER_H
0019 
0020 #include "core/amarokcore_export.h"
0021 
0022 #include <QMetaMethod>
0023 #include <QMutex>
0024 #include <QObject>
0025 
0026 #include <functional>
0027 
0028 
0029 class KJob;
0030 class QNetworkReply;
0031 struct ShortMessage;
0032 struct LongMessage;
0033 struct ProgressData;
0034 
0035 namespace Amarok
0036 {
0037     /**
0038       * This class provides methods that allow backend components to notify the user.
0039       * Users of this class may not make assumptions about the kind of notifications that
0040       * will be sent to the user.
0041       *
0042       * The class name is up for discussion btw.
0043       */
0044     class AMAROKCORE_EXPORT Logger
0045     {
0046     public:
0047         enum MessageType { Information, Warning, Error };
0048 
0049         Logger();
0050         virtual ~Logger();
0051 
0052         /**
0053           * Informs the user about the progress of a job, i.e. a download job.
0054           * At the very least, the user is notified about the start and end of the job.
0055           *
0056           * @param job The job whose progress should be monitored
0057           * @param text An additional text that will be part of the notification
0058           * @param obj The object that will be called if the user cancels the job. If not set, the job will not be cancellable
0059           * @param slot The slot on the given object that will be called if the user cancels the job. No slot will be called if not set.
0060           * The signal will be emitted from the GUI thread. The receiver may not make assumptions about the sender
0061           * @param type The Qt connection type to use for the connection to the receiving slot. Defaults to Qt::AutoConnection
0062           */
0063         template<class Object = QObject, class Func = void (QObject::*)()>
0064         static void newProgressOperation( KJob *job, const QString &text, Object *obj = nullptr, Func slot = nullptr, Qt::ConnectionType type = Qt::AutoConnection )
0065         {
0066             if( !job )
0067                 return;
0068 
0069             std::function<void ()> function = std::bind( slot, obj );
0070             addProgressOperation( job, nullptr, nullptr, QMetaMethod(), QMetaMethod(), text, 100, obj, obj ? function : nullptr, type );
0071         }
0072 
0073         /**
0074          * Informs the user about the progress of a job, i.e. a download job.
0075          * At the very least, the user is notified about the start and end of the job.
0076          *
0077          * @param job The job whose progress should be monitored
0078          * @param text An additional text that will be part of the notification
0079          * @param obj The object that will be called if the user cancels the job.
0080          * @param slot The slot on the given object that will be called if the user cancels the job.
0081          * The signal will be emitted from the GUI thread. The receiver may not make assumptions about the sender
0082          * @param type The Qt connection type to use for the connection to the receiving slot.
0083          * @param args Arguments given to the slot.
0084          */
0085         template<class Object = QObject, class Func = void (QObject::*)(), class... FuncArgs>
0086         static void newProgressOperation( KJob *job, const QString &text, Object *obj, Func slot, Qt::ConnectionType type, FuncArgs... args )
0087         {
0088             if( !job )
0089                 return;
0090 
0091             std::function<void ()> function = std::bind( slot, obj, args... );
0092             addProgressOperation( job, nullptr, nullptr, QMetaMethod(), QMetaMethod(), text, 100, obj, obj ? function : nullptr, type );
0093         }
0094 
0095         /**
0096           * Informs the user about the progress of a network request.
0097           * At the very least, the user is notified about the start and end of the request.
0098           *
0099           * @param reply The network reply object whose progress should be monitored
0100           * @param text An additional text that will be part of the notification
0101           * @param obj The object that will be called if the user cancels the network request. If not set, the progress will not be cancellable
0102           * @param slot The slot on the given object that will be called if the user cancels the network request. No slot will be called if not set.
0103           * The signal will be emitted from the GUI thread. The receiver may not make assumptions about the sender
0104           * @param type The Qt connection type to use for the connection to the receiving slot. Defaults to Qt::AutoConnection
0105           */
0106         template<class Object = QObject, class Func = void (QObject::*)()>
0107         static void newProgressOperation( QNetworkReply *reply, const QString &text, Object *obj = nullptr, Func slot = nullptr, Qt::ConnectionType type = Qt::AutoConnection )
0108         {
0109             if( !reply )
0110                 return;
0111 
0112             std::function<void ()> function = std::bind( slot, obj );
0113             addProgressOperation( nullptr, reply, nullptr, QMetaMethod(), QMetaMethod(), text, 100, obj, obj ? function : nullptr, type );
0114         }
0115 
0116         /**
0117          * Informs the user about the progress of a network request.
0118          * At the very least, the user is notified about the start and end of the request.
0119          *
0120          * @param reply The network reply object whose progress should be monitored
0121          * @param text An additional text that will be part of the notification
0122          * @param obj The object that will be called if the user cancels the network request.
0123          * @param slot The slot on the given object that will be called if the user cancels the network request.
0124          * The signal will be emitted from the GUI thread. The receiver may not make assumptions about the sender
0125          * @param type The Qt connection type to use for the connection to the receiving slot.
0126          * @param args Arguments given to the slot.
0127          */
0128         template<class Object = QObject, class Func = void (QObject::*)(), class... FuncArgs>
0129         static void newProgressOperation( QNetworkReply *reply, const QString &text, Object *obj, Func slot, Qt::ConnectionType type, FuncArgs... args )
0130         {
0131             if( !reply )
0132                 return;
0133 
0134             std::function<void ()> function = std::bind( slot, obj, args... );
0135             addProgressOperation( nullptr, reply, nullptr, QMetaMethod(), QMetaMethod(), text, 100, obj, obj ? function : nullptr, type );
0136         }
0137 
0138         /**
0139          * Informs the user about the progress of a generic QObject
0140          *
0141          * @param sender The object sending the required signals. This sender must Q_EMIT signals
0142          *        incrementProgress() and endProgressOperation() and optionally totalSteps().
0143          * @param text An additional text that will be part of the notification
0144          * @param maximum The maximum value of the progress operation
0145          * @param obj The object that will be called if the user cancels the network request. If not
0146          *        set, the progress will not be cancellable
0147          * @param slot The slot on the given object that will be called if the user cancels the
0148          *             network request. No slot will be called if not set.
0149          * The signal will be emitted from the GUI thread. The receiver may not make assumptions
0150          * about the sender
0151          * @param type The Qt connection type to use for the connection to the receiving slot.
0152          *             Defaults to Qt::AutoConnection
0153          */
0154         template<class Sender, class Object = QObject, class Func = void (QObject::*)()>
0155         static typename std::enable_if<!std::is_convertible<Sender*, KJob*>::value && !std::is_convertible<Sender*, QNetworkReply*>::value && std::is_convertible<Sender*, QObject*>::value>::type
0156         newProgressOperation( Sender *sender, const QString &text, int maximum = 100, Object *obj = nullptr, Func slot = nullptr, Qt::ConnectionType type = Qt::AutoConnection)
0157         {
0158             if( !sender )
0159                 return;
0160 
0161             auto increment = QMetaMethod::fromSignal( &Sender::incrementProgress );
0162             auto end = QMetaMethod::fromSignal( &Sender::endProgressOperation );
0163             std::function<void ()> function = std::bind( slot, obj );
0164             addProgressOperation( nullptr, nullptr, sender, increment, end, text, maximum, obj, obj ? function : nullptr, type );
0165         }
0166 
0167         /**
0168          * Informs the user about the progress of a generic QObject
0169          *
0170          * @param sender The object sending the required signals. This sender must Q_EMIT signals
0171          *        incrementProgress() and endProgressOperation() and optionally totalSteps().
0172          * @param text An additional text that will be part of the notification
0173          * @param maximum The maximum value of the progress operation
0174          * @param obj The object that will be called if the user cancels the network request.
0175          * @param slot The slot on the given object that will be called if the user cancels the
0176          *             network request.
0177          * The signal will be emitted from the GUI thread. The receiver may not make assumptions
0178          * about the sender
0179          * @param type The Qt connection type to use for the connection to the receiving slot.
0180          * @param args Arguments given to the slot.
0181          */
0182         template<class Sender, class Object = QObject, class Func = void (QObject::*)(), class... FuncArgs>
0183         static typename std::enable_if<!std::is_convertible<Sender*, KJob*>::value && !std::is_convertible<Sender*, QNetworkReply*>::value && std::is_convertible<Sender*, QObject*>::value>::type
0184         newProgressOperation( Sender *sender, const QString &text, int maximum, Object *obj, Func slot, Qt::ConnectionType type, FuncArgs... args )
0185         {
0186             if( !sender )
0187                 return;
0188 
0189             auto increment = QMetaMethod::fromSignal( &Sender::incrementProgress );
0190             auto end = QMetaMethod::fromSignal( &Sender::endProgressOperation );
0191             std::function<void ()> function = std::bind( slot, obj, args... );
0192             addProgressOperation( nullptr, nullptr, sender, increment, end, text, maximum, obj, obj ? function : nullptr, type );
0193         }
0194 
0195         /**
0196           * Sends a notification to the user.
0197           * This method will send a notification containing the given text to the user.
0198           *
0199           * @param text The text that the notification will contain
0200           */
0201         static void shortMessage( const QString &text );
0202 
0203         /**
0204           * Send a notification to the user with an additional context.
0205           * A notification will be send to the user containing the given text. Additionally, it will convey the context given by @p type.
0206           * @param text The text that the notification will contain
0207           * @param type The context of the notification
0208           */
0209         static void longMessage( const QString &text, MessageType type = Information );
0210 
0211     protected:
0212         virtual void newProgressOperationImpl( KJob *job, const QString &text, QObject *context, const std::function<void ()> &function, Qt::ConnectionType type ) = 0;
0213         virtual void newProgressOperationImpl( QNetworkReply *reply, const QString &text, QObject *context, const std::function<void ()> &function, Qt::ConnectionType type ) = 0;
0214         virtual void newProgressOperationImpl( QObject *sender, const QMetaMethod &increment, const QMetaMethod &end, const QString &text,
0215                                                int maximum, QObject *context, const std::function<void ()> &function, Qt::ConnectionType type ) = 0;
0216         virtual void longMessageImpl( const QString &text, MessageType type = Information ) = 0;
0217         virtual void shortMessageImpl( const QString &text ) = 0;
0218 
0219     private:
0220         static void addProgressOperation(KJob *job = nullptr, QNetworkReply *reply = nullptr, QObject *sender = nullptr, QMetaMethod increment = QMetaMethod(),
0221                                           const QMetaMethod &end = QMetaMethod(), const QString &text = QString(), int maximum = 100, QObject *context = nullptr,
0222                                           const std::function<void ()> &function = nullptr, Qt::ConnectionType type = Qt::AutoConnection );
0223         void loadExistingMessages();
0224 
0225         static QMutex s_mutex;
0226         static QList<Logger*> s_loggers;
0227         static QList<QString> s_shortMessageList;
0228         static QList<LongMessage> s_longMessageList;
0229         static QList<ProgressData> s_progressList;
0230     };
0231 }
0232 
0233 #endif