File indexing completed on 2024-12-08 04:30:59

0001 /* This file is part of the KDE project
0002 
0003    Copyright (C) 2008 Manolo Valdes <nolis71cu@gmail.com>
0004 
0005    This program is free software; you can redistribute it and/or
0006    modify it under the terms of the GNU General Public
0007    License as published by the Free Software Foundation; either
0008    version 2 of the License, or (at your option) any later version.
0009 */
0010 
0011 #ifndef TRANSFERDATASOURCE_H
0012 #define TRANSFERDATASOURCE_H
0013 
0014 #include "kget_export.h"
0015 #include "transfer.h"
0016 
0017 #include <QObject>
0018 
0019 #include <KIO/Job>
0020 
0021 /**
0022  * This Class is an interface for inter-plugins data change.
0023  * allowing to use already implemented features from others plugins
0024  */
0025 class KGET_EXPORT TransferDataSource : public QObject
0026 {
0027     Q_OBJECT
0028 public:
0029     TransferDataSource(const QUrl &srcUrl, QObject *parent);
0030     ~TransferDataSource() override;
0031 
0032     /**
0033      * @enum Error
0034      * @brief Error type enum
0035      */
0036     enum Error { Unknown, WrongDownloadSize, NotResumeable };
0037 
0038     /**
0039      * Returns the capabilities this TransferDataSource supports
0040      */
0041     Transfer::Capabilities capabilities() const;
0042 
0043     virtual void start() = 0;
0044     virtual void stop() = 0;
0045 
0046     /**
0047      * Tries to find the filesize if this capability is supported,
0048      * if successful it emits foundFileSize(TransferDataSource*,KIO::filesize_t,QPair<int,int>)
0049      * and assigns all segments to itself
0050      * if not successful it will try to download the file nevertheless
0051      * @note if stop is called and no size is found yet then this is aborted, i.e. needs to be
0052      * called again if start is later called
0053      * @param segmentSize the segments should have
0054      */
0055     virtual void findFileSize(KIO::fileoffset_t segmentSize);
0056 
0057     /**
0058      * Adds multiple continuous segments that should be downloaded by this TransferDataSource
0059      * @param segmentSize first is always the general segmentSize, second the segmentSize
0060      * of the last segment in the range. If just one (the last) segment was assigned, then
0061      * first would not equal second, this is to ensure that first can be used to calculate the offset
0062      * TransferDataSources have to handle all that internally.
0063      * @param segmentRange first the beginning, second the end
0064      */
0065     virtual void addSegments(const QPair<KIO::fileoffset_t, KIO::fileoffset_t> &segmentSize, const QPair<int, int> &segmentRange) = 0;
0066 
0067     /**
0068      * Removes one connection, useful when setMaximumParallelDownloads was called with a lower number
0069      * @return the segments that are removed (unassigned) now
0070      *
0071      */
0072     virtual QPair<int, int> removeConnection();
0073 
0074     QUrl sourceUrl() const
0075     {
0076         return m_sourceUrl;
0077     } // TODO
0078 
0079     /**
0080      * returns the current speed of this data source
0081      * @return the speed
0082      */
0083     ulong currentSpeed() const
0084     {
0085         return m_speed;
0086     }
0087 
0088     /**
0089      * Set the size the server used for downloading should report
0090      * @param supposedSize the size the file should have
0091      */
0092     virtual void setSupposedSize(KIO::filesize_t supposedSize)
0093     {
0094         m_supposedSize = supposedSize;
0095     }
0096 
0097     /**
0098      * Returns the assignedSegments to this TransferDataSource
0099      * Each connection is represented by a QPair, where the first int is the beginning
0100      * segment and the last the ending segment
0101      * @note an empty list is returned by default, the elements can also be (-1, -1)
0102      */
0103     virtual QList<QPair<int, int>> assignedSegments() const;
0104 
0105     /**
0106      * Returns the number of unfinished Segments of the connection with the most
0107      * unfinished segments
0108      * Each TransferDataSource can have multiple connections and each connection
0109      * can have multiple segments assigned
0110      * @note default implementation returns 0
0111      */
0112     virtual int countUnfinishedSegments() const;
0113 
0114     /**
0115      * If a connection of this TransferDataSource is assigned multiple (continuous) segments, then
0116      * this method will split them (the unfinished ones) in half, it returns the beginning
0117      * and the end of the now unassigned segments; (-1, -1) if there are none
0118      * @note if only one segment is assigned to a connection split will also return (-1, -1)
0119      */
0120     virtual QPair<int, int> split(); // TODO should split also take the current running segment into account?
0121 
0122     // the following methods are used for managing the number of parallel connections
0123     // subclasses have to keep track of the currentSegments
0124     /**
0125      * @return the number of parallel segments this DataSource is allowed to use,
0126      * default is 1
0127      */
0128     virtual int parallelSegments() const;
0129 
0130     /**
0131      * Sets the number of parallel segments this DataSource is allowed to use
0132      */
0133     virtual void setParallelSegments(int parallelSegments);
0134 
0135     /**
0136      * @return the number of parallel segments this DataSources currently uses
0137      */
0138     virtual int currentSegments() const;
0139 
0140     /**
0141      * Returns the mismatch of parallelSegments() and currentSegments()
0142      * @return the number of segments to add/remove e.g. -1 means one segment to remove
0143      */
0144     virtual int changeNeeded() const;
0145 
0146 Q_SIGNALS:
0147     /**
0148      * Emitted after findFileSize is called successfully
0149      * @param source that found the filesize
0150      * @param fileSize that was found
0151      * @param segmentRange that was calculated based on the segmentSize and that was assigned to
0152      * source automatically
0153      */
0154     void foundFileSize(TransferDataSource *source, KIO::filesize_t fileSize, const QPair<int, int> &segmentRange);
0155 
0156     /**
0157      * Emitted when the capabilities of the TransferDataSource change
0158      */
0159     void capabilitiesChanged();
0160 
0161     /**
0162      * Emitted when the TransferDataSource finished the download on its own, e.g. when findFileSize
0163      * is being called but no fileSize is found and instead the download finishes
0164      * @param source the source that emitted this signal
0165      * @param fileSize the fileSize of the finished file (calculated by the downloaded bytes)
0166      */
0167     void finishedDownload(TransferDataSource *source, KIO::filesize_t fileSize);
0168 
0169     /**
0170      * Returns data in the forms of chucks
0171      * @note if the receiver set worked to wrong the TransferDataSource should cache the data
0172      * @param offset the offset in the file
0173      * @param data the downloaded data
0174      * @param worked if the receiver could handle the data, if not, the sender should cache the data
0175      */
0176     void data(KIO::fileoffset_t offset, const QByteArray &data, bool &worked);
0177 
0178     /**
0179      * Returns data in the forms of URL List
0180      * @param data in form of QUrl list
0181      */
0182     void data(const QList<QUrl> &data);
0183 
0184     /**
0185      * Returns found checksums with their type
0186      * @param type the type of the checksum
0187      * @param checksum the checksum
0188      */
0189     void data(const QString type, const QString checksum);
0190 
0191     /**
0192      * emitted when there is no more data
0193      */
0194     void finished();
0195 
0196     /**
0197      * emitted when an assigned segment finishes
0198      * @param source the source that emitted this signal
0199      * @param segmentNumber the number of the segment, to identify it
0200      * @param connectionFinished true if all segments of this connection have been finished,
0201      * if one segment (instead of a group of segments) has been assigned this is always true
0202      */
0203     void finishedSegment(TransferDataSource *source, int segmentNumber, bool connectionFinished = true);
0204 
0205     /**
0206      * Alert that datasource is no able to send any data
0207      * @param source the datasource, sending the signal
0208      * @param error the error type
0209      */
0210     void broken(TransferDataSource *source, TransferDataSource::Error error);
0211 
0212     /**
0213      * emitted when an assigned segment is broken
0214      * @param source the source that emitted this signal
0215      * @param segmentRange the range of the segments e.g. (1,1,) or (0, 10)
0216      */
0217     void brokenSegments(TransferDataSource *source, QPair<int, int> segmentRange);
0218 
0219     /**
0220      * The speed of the download
0221      * @param speed speed of the download
0222      */
0223     void speed(ulong speed);
0224 
0225     /**
0226      * Emitted when a Datasource itself decides to not download a specific segmentRange,
0227      * e.g. when there are too many connections for this TransferDataSource
0228      */
0229     void freeSegments(TransferDataSource *source, QPair<int, int> segmentRange);
0230 
0231     void log(const QString &message, Transfer::LogLevel logLevel);
0232 
0233     /**
0234      * Emitted when the filename of a url changes, e.g. when a link redirects
0235      */
0236     void urlChanged(const QUrl &old, const QUrl &newUrl);
0237 
0238 protected:
0239     /**
0240      * Sets the capabilities and automatically emits capabilitiesChanged
0241      */
0242     void setCapabilities(Transfer::Capabilities capabilities);
0243 
0244 private Q_SLOTS:
0245     virtual void slotSpeed(ulong speed)
0246     {
0247         Q_UNUSED(speed)
0248     }
0249 
0250 protected:
0251     QUrl m_sourceUrl;
0252     ulong m_speed;
0253     KIO::filesize_t m_supposedSize;
0254     int m_parallelSegments;
0255     int m_currentSegments;
0256 
0257 private:
0258     Transfer::Capabilities m_capabilities;
0259 };
0260 #endif