File indexing completed on 2023-10-03 07:53:59

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