File indexing completed on 2024-04-14 04:51:58

0001 /* This file is part of the KDE project
0002 
0003    Copyright (C) 2005 Dario Massarin <nekkar@libero.it>
0004    Copyright (C) 2009 Lukas Appelhans <l.appelhans@gmx.de>
0005    Copyright (C) 2009 Matthias Fuchs <mat69@gmx.net>
0006 
0007    Based on:
0008        kmainwidget.{h,cpp}
0009        Copyright (C) 2002 by Patrick Charbonnier <pch@freeshell.org>
0010        that was based On Caitoo v.0.7.3 (c) 1998 - 2000, Matej Koss
0011 
0012    This program is free software; you can redistribute it and/or
0013    modify it under the terms of the GNU General Public
0014    License as published by the Free Software Foundation; either
0015    version 2 of the License, or (at your option) any later version.
0016 */
0017 
0018 #ifndef KGET_H
0019 #define KGET_H
0020 
0021 #include <KActionCollection>
0022 #include <KLocalizedString>
0023 #include <KNotification>
0024 #include <KPluginFactory>
0025 
0026 #include <QDomElement>
0027 #include <QNetworkInformation>
0028 
0029 #include "kget_export.h"
0030 #include "kuiserverjobs.h"
0031 #include "scheduler.h"
0032 #include "transfer.h"
0033 #include "transfergrouphandler.h"
0034 #include "transferhandler.h"
0035 
0036 class QDomElement;
0037 
0038 class TransferDataSource;
0039 class TransferGroup;
0040 class TransferFactory;
0041 class TransferTreeModel;
0042 class TransferTreeSelectionModel;
0043 class KGetPlugin;
0044 class MainWindow;
0045 class NewTransferDialog;
0046 class TransferGroupScheduler;
0047 class TransferHistoryStore;
0048 
0049 /**
0050  * This is our KGet class. This is where the user's transfers and searches are
0051  * stored and organized.
0052  * Use this class from the views to add or remove transfers or searches
0053  * In order to organize the transfers inside categories we have a TransferGroup
0054  * class. By definition, a transfer must always belong to a TransferGroup. If we
0055  * don't want it to be displayed by the gui inside a specific group, we will put
0056  * it in the group named "Not grouped" (better name?).
0057  **/
0058 
0059 class KGET_EXPORT KGet
0060 {
0061     friend class NewTransferDialog;
0062     friend class NewTransferDialogHandler;
0063     friend class GenericObserver;
0064     friend class TransferTreeModel;
0065     friend class UrlChecker;
0066 
0067 public:
0068     enum AfterFinishAction {
0069         Quit = 0,
0070         Shutdown = 1,
0071         Hibernate = 2,
0072         Suspend = 3,
0073     };
0074     enum DeleteMode {
0075         AutoDelete,
0076         DeleteFiles,
0077     };
0078     ~KGet();
0079 
0080     static KGet *self(MainWindow *mainWindow = nullptr);
0081 
0082     /**
0083      * Adds a new group to the KGet.
0084      *
0085      * @param groupName The name of the new group
0086      *
0087      * @returns true if the group has been successfully added, otherwise
0088      *          it returns false, probably because a group with that named
0089      *          already exists
0090      */
0091     static bool addGroup(const QString &groupName);
0092 
0093     /**
0094      * Removes a group from the KGet.
0095      *
0096      * @param group The name of the group to be deleted
0097      * @param askUser Whether to ask user about the deletion
0098      */
0099     static void delGroup(TransferGroupHandler *group, bool askUser = true);
0100 
0101     /**
0102      * Removes specific groups from the KGet.
0103      *
0104      * @param groups The names of the groups to be deleted.
0105      * @param askUser Whether to ask user about the deletion
0106      */
0107     static void delGroups(QList<TransferGroupHandler *> groups, bool askUser = true);
0108 
0109     /**
0110      * Changes the name of the group
0111      *
0112      * @param oldName the name of the group to be changed
0113      * @param newName the new name of the group
0114      */
0115     static void renameGroup(const QString &oldName, const QString &newName);
0116 
0117     /**
0118      * @returns the name of the available transfers groups
0119      */
0120     static QStringList transferGroupNames();
0121 
0122     /**
0123      * Adds a new transfer to the KGet
0124      *
0125      * @param srcUrl The url to be downloaded
0126      * @param destDir The destination directory. If empty we show a dialog
0127      * where the user can choose it.
0128      * @param suggestedFileName a suggestion of a simple filename to be saved in destDir
0129      * @param groupName The name of the group the new transfer will belong to
0130      * @param start Specifies if the newly added transfers should be started.
0131      * If the group queue is already in a running state, this flag does nothing
0132      */
0133     static TransferHandler *
0134     addTransfer(QUrl srcUrl, QString destDir = QString(), QString suggestedFileName = QString(), QString groupName = QString(), bool start = false);
0135 
0136     /**
0137      * Adds new transfers to the KGet, it is assumed that this takes place because of loading
0138      * that results in less checks for location etc.
0139      *
0140      * @param elements The dom elements of the transfers to add
0141      * @param groupName The name of the group the new transfer will belong to
0142      */
0143     static QList<TransferHandler *> addTransfers(const QList<QDomElement> &elements, const QString &groupName = QString());
0144 
0145     /**
0146      * Adds new transfers to the KGet
0147      *
0148      * @param srcUrls The urls to be downloaded
0149      * @param destDir The destination directory. If empty we show a dialog
0150      * where the user can choose it.
0151      * @param groupName The name of the group the new transfer will belong to
0152      * @param start Specifies if the newly added transfers should be started.
0153      * If the group queue is already in a running state, this flag does nothing
0154      */
0155     static const QList<TransferHandler *> addTransfer(QList<QUrl> srcUrls, QString destDir = QString(), QString groupName = QString(), bool start = false);
0156 
0157     /**
0158      * Removes a transfer from the KGet
0159      *
0160      * @param transfer The transfer to be removed
0161      * @param mode The deletion mode
0162      */
0163     static bool delTransfer(TransferHandler *transfer, DeleteMode mode = AutoDelete);
0164 
0165     /**
0166      * Removes multiple transfers from the KGet
0167      *
0168      * @param transfers The transfers to be removed
0169      * @param mode The deletion mode
0170      */
0171     static bool delTransfers(const QList<TransferHandler *> &transfers, DeleteMode mode = AutoDelete);
0172 
0173     /**
0174      * Moves a transfer to a new group
0175      *
0176      * @param transfer The transfer to be moved
0177      * @param groupName The name of the new transfer's group
0178      */
0179     static void moveTransfer(TransferHandler *transfer, const QString &groupName);
0180 
0181     /**
0182      * Redownload a transfer
0183      * @param transfer the transfer to redownload
0184      */
0185     static void redownloadTransfer(TransferHandler *transfer);
0186 
0187     /**
0188      * @returns the list of selected transfers
0189      */
0190     static QList<TransferHandler *> selectedTransfers();
0191 
0192     /**
0193      * @returns the list of the finished transfers
0194      */
0195     static QList<TransferHandler *> finishedTransfers();
0196 
0197     /**
0198      * @returns the list of selected groups
0199      */
0200     static QList<TransferGroupHandler *> selectedTransferGroups();
0201 
0202     /**
0203      * @returns a pointer to the TransferTreeModel object
0204      */
0205     static TransferTreeModel *model();
0206 
0207     /**
0208      * @returns a pointer to the QItemSelectionModel object
0209      */
0210     static TransferTreeSelectionModel *selectionModel();
0211 
0212     /**
0213      * Imports the transfers and groups included in the provided xml file
0214      *
0215      * @param filename the file name to
0216      */
0217     static void load(QString filename = QString());
0218 
0219     /**
0220      * Exports all the transfers and groups to the given file
0221      *
0222      * @param filename the file name
0223      * @param plain should list be in plain mode or kget mode
0224      */
0225     static void save(QString filename = QString(), bool plain = false);
0226 
0227     /**
0228      * @returns a list of all transferfactories
0229      */
0230     static QList<TransferFactory *> factories();
0231 
0232     /**
0233      * @returns a list of pluginInfos associated with all transferFactories
0234      */
0235     static QVector<KPluginMetaData> plugins();
0236 
0237     /**
0238      * @returns The factory of a given transfer
0239      *
0240      * @param transfer the transfer about which we want to have the factory
0241      */
0242     static TransferFactory *factory(TransferHandler *transfer);
0243 
0244     /**
0245      * @return a pointer to the KActionCollection objects
0246      */
0247     static KActionCollection *actionCollection();
0248 
0249     /**
0250      * if running == true starts the scheduler
0251      * if running == false stops the scheduler
0252      */
0253     static void setSchedulerRunning(bool running = true);
0254 
0255     /**
0256      * Returns true if the scheduler has running jobs.
0257      */
0258     static bool schedulerRunning();
0259 
0260     /**
0261      * true suspends the scheduler, any events that would result in a reschedule are ignored
0262      * false wakes up the scheduler, events result in reschedule again
0263      * NOTE this is a HACK for cases where the scheduler is the bottleneck, e.g. when stopping
0264      * a lot of running transfers, or starting a lot transfers
0265      */
0266     static void setSuspendScheduler(bool isSuspended);
0267 
0268     /**
0269      * Gets all transfers
0270      */
0271     static QList<TransferHandler *> allTransfers();
0272 
0273     /**
0274      * Gets all transfer-groups
0275      */
0276     static QList<TransferGroupHandler *> allTransferGroups();
0277 
0278     /**
0279      * Get the transfer with the given url
0280      * @param src the url
0281      */
0282     static TransferHandler *findTransfer(const QUrl &src);
0283 
0284     /**
0285      * Get the group with the given name
0286      * @param name the name
0287      */
0288     static TransferGroupHandler *findGroup(const QString &name);
0289 
0290     /**
0291      * Run this function for enabling the systemTray
0292      * (will be automatically done, if there is download running)
0293      */
0294     static void checkSystemTray();
0295 
0296     /**
0297      * This will be called when the settings have been changed
0298      */
0299     static void settingsChanged();
0300 
0301     /**
0302      * @return a list of the groups assigned to the filename of a transfer
0303      */
0304     static QList<TransferGroupHandler *> groupsFromExceptions(const QUrl &filename);
0305 
0306     /**
0307      * Returns @c true if sourceUrl matches any of the patterns
0308      */
0309     static bool matchesExceptions(const QUrl &sourceUrl, const QStringList &patterns);
0310 
0311     /**
0312      * Scans for all the available plugins and creates the proper
0313      * transfer DataSource object for transfers Containers
0314      *
0315      * @param src Source Url
0316      * @param type the type of the DataSource that should be created e.g. \<TransferDataSource type="search" /\>
0317      * this is only needed when creating a "special" TransferDataSource like the search for Urls
0318      * you can set additional information and the TransferDataSource will use it if it can
0319      * @param parent the parent QObject
0320      */
0321     static TransferDataSource *createTransferDataSource(const QUrl &src, const QDomElement &type = QDomElement(), QObject *parent = nullptr);
0322 
0323     /**
0324      * Sets the global download limit
0325      * @param limit the new global download limit
0326      */
0327     static void setGlobalDownloadLimit(int limit);
0328 
0329     /**
0330      * Sets the global upload limit
0331      * @param limit the new global upload limit
0332      */
0333     static void setGlobalUploadLimit(int limit);
0334 
0335     /**
0336      * Recalculates the global speedlimits
0337      */
0338     static void calculateGlobalSpeedLimits();
0339 
0340     /**
0341      * Recalculates the global download-limit
0342      */
0343     static void calculateGlobalDownloadLimit();
0344 
0345     /**
0346      * Recalculates the global upload-limit
0347      */
0348     static void calculateGlobalUploadLimit();
0349 
0350     /**
0351      * Shows a knotification
0352      * @param eventType Notification type
0353      * @param text Description of the information showed by the notification
0354      * @param icon Pixmap showed in the notification, by default 'dialog-error'
0355      * @param title Notification window title
0356      * @param flags Notification flags
0357      */
0358     static KNotification *showNotification(const QString &eventType,
0359                                            const QString &text,
0360                                            const QString &icon = QString("dialog-error"),
0361                                            const QString &title = i18n("KGet"),
0362                                            const KNotification::NotificationFlags &flags = KNotification::CloseOnTimeout);
0363 
0364     static void loadPlugins();
0365 
0366     /**
0367      * Returns a download directory
0368      * @param preferXDGDownloadDir if true the XDG_DOWNLOAD_DIR will be taken if it is not empty
0369      * @note depending if the directories exist it will return them in the following order:
0370      * (preferXDGDownloadDirectory >) lastDirectory > XDG_DOWNLOAD_DIR
0371      */
0372     static QString generalDestDir(bool preferXDGDownloadDir = false);
0373 
0374 private:
0375     KGet();
0376 
0377     class TransferData;
0378 
0379     /**
0380      * Scans for all the available plugins and creates the proper
0381      * transfer object for the given src url
0382      *
0383      * @param src the source url
0384      * @param dest the destination url
0385      * @param groupName the group name
0386      * @param start Specifies if the newly added transfers should be started.
0387      */
0388     static TransferHandler *
0389     createTransfer(const QUrl &src, const QUrl &dest, const QString &groupName = QString(), bool start = false, const QDomElement *e = nullptr);
0390 
0391     /**
0392      * Creates multiple transfers with transferData
0393      */
0394     static QList<TransferHandler *> createTransfers(const QList<TransferData> &transferData);
0395 
0396     static QUrl urlInputDialog();
0397     static QString destDirInputDialog();
0398     static QUrl destFileInputDialog(QString destDir = QString(), const QString &suggestedFileName = QString());
0399 
0400     static bool isValidSource(const QUrl &source);
0401     static bool isValidDestDirectory(const QString &destDir);
0402 
0403     static QUrl getValidDestUrl(const QUrl &destDir, const QUrl &srcUrl);
0404 
0405     // Plugin-related functions
0406     static KGetPlugin *loadPlugin(const KPluginMetaData &md);
0407 
0408     /**
0409      * Stops all downloads if there is no connection and also displays
0410      * a message.
0411      * If there is a connection, then the downloads will be started again
0412      */
0413     static void setHasNetworkConnection(bool hasConnection);
0414 
0415     /**
0416      * Deletes the given file, if possible.
0417      *
0418      * @param url The file to delete
0419      *
0420      * @return true if the file was successfully deleted: if the given url
0421      * is a directory or if it is not local it returns false and shows a
0422      * warning message.
0423      */
0424     static bool safeDeleteFile(const QUrl &url);
0425 
0426     // Interview models
0427     static TransferTreeModel *m_transferTreeModel;
0428     static TransferTreeSelectionModel *m_selectionModel;
0429 
0430     // Lists of available plugins
0431     static QVector<KPluginMetaData> m_pluginList;
0432     static QList<TransferFactory *> m_transferFactories;
0433 
0434     // pointer to the Main window
0435     static MainWindow *m_mainWindow;
0436 
0437     // Scheduler object
0438     static TransferGroupScheduler *m_scheduler;
0439 
0440     // pointer to the kget uiserver jobs manager
0441     static KUiServerJobs *m_jobManager;
0442 
0443     // pointer to the used TransferHistoryStore
0444     static TransferHistoryStore *m_store;
0445 
0446     static bool m_hasConnection;
0447 };
0448 
0449 class KGET_EXPORT KGet::TransferData
0450 {
0451 public:
0452     TransferData(const QUrl &src, const QUrl &dest, const QString &groupName = QString(), bool start = false, const QDomElement *e = nullptr);
0453 
0454     QUrl src;
0455     QUrl dest;
0456     QString groupName;
0457     bool start;
0458     const QDomElement *e;
0459 };
0460 
0461 class GenericObserver : public QObject
0462 {
0463     Q_OBJECT
0464 public:
0465     explicit GenericObserver(QObject *parent = nullptr);
0466     ~GenericObserver() override;
0467 
0468 public Q_SLOTS:
0469     void groupAddedEvent(TransferGroupHandler *handler);
0470     void groupRemovedEvent(TransferGroupHandler *handler);
0471     void transfersAddedEvent(const QList<TransferHandler *> &handlers);
0472     void transfersRemovedEvent(const QList<TransferHandler *> &handlers);
0473     void transfersChangedEvent(QMap<TransferHandler *, Transfer::ChangesFlags> transfers);
0474     void groupsChangedEvent(QMap<TransferGroupHandler *, TransferGroup::ChangesFlags> groups);
0475     void transferMovedEvent(TransferHandler *, TransferGroupHandler *);
0476 
0477 private Q_SLOTS:
0478     void slotSave();
0479     void slotAfterFinishAction();
0480     void slotAbortAfterFinishAction();
0481     void slotResolveTransferError();
0482     void slotNotificationClosed();
0483     void slotNetworkStatusChanged(QNetworkInformation::Reachability reachability);
0484 
0485 private:
0486     bool allTransfersFinished();
0487 
0488     void requestSave();
0489 
0490 private:
0491     QTimer *m_save;
0492     QTimer *m_finishAction;
0493     QHash<KNotification *, TransferHandler *> m_notifications;
0494 };
0495 #endif