KanoopTorrentQt 0.1.0
Qt6 wrapper library for libtorrent-rasterbar
Loading...
Searching...
No Matches
torrent.h
1#ifndef TORRENT_H
2#define TORRENT_H
3
4#include <Kanoop/torrent/kanooptorrent.h>
5#include <Kanoop/torrent/magnetlink.h>
6#include <Kanoop/torrent/peerinfo.h>
7#include <Kanoop/utility/loggingbaseclass.h>
8#include <QObject>
9
10/**
11 * @brief Represents a single torrent within a TorrentClient session.
12 *
13 * Torrent objects are created by TorrentClient::addTorrent() and provide
14 * a Qt-friendly interface over a libtorrent torrent handle. All state
15 * updates are driven by TorrentClient::processAlerts() and delivered
16 * as Qt signals.
17 *
18 * @note Do not construct Torrent objects directly; use TorrentClient::addTorrent().
19 */
20class LIBKANOOPTORRENT_EXPORT Torrent : public QObject,
21 public LoggingBaseClass
22{
23 Q_OBJECT
24public:
25 /**
26 * @brief Lifecycle state of a torrent.
27 */
28 enum State {
29 Idle, ///< Torrent is stopped or not yet started.
30 FetchingMetadata, ///< Downloading torrent metadata (magnet link resolution).
31 Checking, ///< Verifying existing data on disk.
32 Downloading, ///< Actively downloading pieces.
33 Seeding, ///< Download complete; uploading to peers.
34 Paused, ///< Explicitly paused by the user.
35 Error, ///< An unrecoverable error occurred.
36 };
37 Q_ENUM(State)
38
39 Torrent(QObject* parent = nullptr);
40 ~Torrent();
41
42 // ── Control ─────────────────────────────────────────────────────────
43
44 /** @brief Resume downloading/seeding. */
45 void start();
46 /** @brief Stop the torrent and reset state to Idle. */
47 void stop();
48 /** @brief Pause the torrent, keeping its state recoverable via resume(). */
49 void pause();
50 /** @brief Resume a paused torrent. */
51 void resume();
52
53 /** @brief Current lifecycle state. */
54 State state() const { return _state; }
55
56 // ── Info ────────────────────────────────────────────────────────────
57
58 /**
59 * @brief Human-readable torrent name.
60 *
61 * Returns the name from torrent metadata if available, otherwise
62 * falls back to the magnet link display name or a truncated info hash.
63 */
64 QString name() const;
65
66 /** @brief Raw 20-byte SHA-1 info hash. */
67 QByteArray infoHash() const { return _infoHash; }
68 /** @brief Info hash as a lowercase hex string (40 characters). */
69 QString infoHashHex() const { return QString::fromLatin1(_infoHash.toHex()); }
70
71 // ── Download progress ───────────────────────────────────────────────
72
73 /** @brief Download progress as a ratio from 0.0 to 1.0. */
74 double progress() const;
75 /** @brief Total bytes downloaded so far. */
76 qint64 bytesDownloaded() const;
77 /** @brief Total size of all selected files in bytes. */
78 qint64 totalSize() const;
79 /** @brief Number of currently connected peers. */
80 int connectedPeers() const;
81 /** @brief Current download rate in bytes/sec. */
82 qint64 downloadRate() const;
83
84 // ── Upload stats ────────────────────────────────────────────────────
85
86 /** @brief Current upload rate in bytes/sec. */
87 qint64 uploadRate() const;
88 /** @brief Total bytes uploaded over the lifetime of this torrent. */
89 qint64 totalUploaded() const;
90 /**
91 * @brief Share ratio (uploaded / downloaded).
92 * @return 0.0 if nothing has been downloaded yet.
93 */
94 double ratio() const;
95
96 // ── Piece info ──────────────────────────────────────────────────────
97
98 /** @brief Total number of pieces in this torrent. Requires metadata. */
99 int totalPieces() const;
100 /** @brief Number of pieces that have been downloaded and verified. */
101 int downloadedPieces() const;
102 /** @brief Size of each piece in bytes. Requires metadata. */
103 int pieceSize() const;
104
105 // ── ETA ─────────────────────────────────────────────────────────────
106
107 /**
108 * @brief Estimated seconds remaining until download completes.
109 * @return Seconds remaining, or -1 if the rate is zero or unknown.
110 */
111 int eta() const;
112
113 // ── Metadata ────────────────────────────────────────────────────────
114
115 /**
116 * @brief Whether torrent metadata has been received.
117 *
118 * File management methods require metadata. For magnet links, metadata
119 * is fetched from peers after the torrent is added.
120 */
121 bool hasMetadata() const { return _hasMetadata; }
122
123 // ── File management ─────────────────────────────────────────────────
124
125 /** @brief Number of files in the torrent. Requires metadata. */
126 int fileCount() const;
127
128 /**
129 * @brief Relative path of a file within the torrent.
130 * @param index Zero-based file index.
131 * @return Relative file path, or empty string if out of range.
132 */
133 QString fileName(int index) const;
134
135 /** @brief List of all file paths in the torrent. */
136 QStringList fileNames() const;
137
138 /**
139 * @brief Size of a file in bytes.
140 * @param index Zero-based file index.
141 * @return File size, or 0 if out of range or no metadata.
142 */
143 qint64 fileSize(int index) const;
144
145 /**
146 * @brief Set the download priority for a single file.
147 * @param index Zero-based file index.
148 * @param priority 0 = skip, 1 = low, 4 = normal, 7 = highest.
149 */
150 void setFilePriority(int index, int priority);
151
152 /**
153 * @brief Set the same download priority for every file.
154 * @param priority 0 = skip, 1 = low, 4 = normal, 7 = highest.
155 */
156 void setAllFilePriorities(int priority);
157
158 /**
159 * @brief Find a file by partial name (case-insensitive substring match).
160 * @param partialName Substring to search for.
161 * @return Zero-based file index, or -1 if not found.
162 */
163 int findFileByName(const QString& partialName) const;
164
165 /**
166 * @brief Get the current download priority for a file.
167 * @param index Zero-based file index.
168 * @return Priority value (0 = skip, 1 = low, 4 = normal, 7 = highest), or -1 if invalid.
169 */
170 int filePriority(int index) const;
171
172 /**
173 * @brief Get per-file download progress as a list of byte counts.
174 * @return A list with one entry per file containing bytes downloaded so far.
175 * Empty list if no metadata is available.
176 */
177 QList<qint64> fileProgress() const;
178
179 /**
180 * @brief Rename a file within the torrent.
181 *
182 * The rename is asynchronous. On completion, fileRenamed() is emitted;
183 * on failure, fileRenameError() is emitted.
184 * @param index Zero-based file index.
185 * @param newName New relative path for the file.
186 */
187 void renameFile(int index, const QString& newName);
188
189 // ── Paths ───────────────────────────────────────────────────────────
190
191 /** @brief The directory where this torrent's data is being saved. */
192 QString downloadDirectory() const { return _downloadDirectory; }
193
194 /**
195 * @brief Full output path (save_path + torrent name).
196 *
197 * For single-file torrents this is the file path; for multi-file
198 * torrents this is the containing directory.
199 */
200 QString outputPath() const;
201
202 /**
203 * @brief Move the torrent's data to a new directory.
204 *
205 * The move is asynchronous. On completion, storageMoved() is emitted;
206 * on failure, storageMoveError() is emitted.
207 * @param newPath Destination directory.
208 */
209 void moveStorage(const QString& newPath);
210
211 // ── Per-torrent options ─────────────────────────────────────────────
212
213 /** @brief Whether pieces are requested in sequential order. */
215 /**
216 * @brief Enable or disable sequential piece downloading.
217 *
218 * Useful for streaming: the first pieces arrive before later ones,
219 * so playback can begin before the download finishes.
220 */
221 void setSequentialDownload(bool enabled);
222
223 /** @brief Whether libtorrent auto-manages this torrent's queue position. */
224 bool isAutoManaged() const;
225 /** @brief Enable or disable libtorrent's auto-managed mode. */
226 void setAutoManaged(bool enabled);
227
228 /** @brief Per-torrent download rate limit in bytes/sec. 0 = unlimited. */
229 int downloadLimit() const;
230 /** @brief Set the per-torrent download rate limit. Pass 0 for unlimited. */
231 void setDownloadLimit(int bytesPerSecond);
232
233 /** @brief Per-torrent upload rate limit in bytes/sec. 0 = unlimited. */
234 int uploadLimit() const;
235 /** @brief Set the per-torrent upload rate limit. Pass 0 for unlimited. */
236 void setUploadLimit(int bytesPerSecond);
237
238 /** @brief Maximum number of peer connections for this torrent. */
239 int maxConnections() const;
240 /** @brief Set the maximum peer connections for this torrent. */
241 void setMaxConnections(int value);
242
243 /** @brief Maximum number of upload slots for this torrent. */
244 int maxUploads() const;
245 /** @brief Set the maximum upload slots for this torrent. */
246 void setMaxUploads(int value);
247
248 // ── Seed ratio limit ────────────────────────────────────────────────
249
250 /**
251 * @brief Target share ratio after which the torrent is auto-paused.
252 * @return 0.0 means no limit (seed indefinitely).
253 */
254 double seedRatioLimit() const { return _seedRatioLimit; }
255
256 /**
257 * @brief Set a share-ratio target; the torrent pauses when it is reached.
258 * @param ratio Target ratio (e.g. 1.0 = upload as much as downloaded). 0 = no limit.
259 */
260 void setSeedRatioLimit(double ratio);
261
262 // ── Tracker management ──────────────────────────────────────────────
263
264 /** @brief List of tracker URLs currently attached to this torrent. */
265 QStringList trackers() const;
266
267 /**
268 * @brief Append a tracker URL.
269 * @param url The tracker announce URL.
270 */
271 void addTracker(const QString& url);
272
273 /**
274 * @brief Remove a tracker by URL.
275 * @param url The tracker announce URL to remove.
276 */
277 void removeTracker(const QString& url);
278
279 /** @brief Force an immediate re-announce to all trackers. */
281
282 // ── Peer management ─────────────────────────────────────────────────
283
284 /**
285 * @brief Snapshot of all currently connected peers.
286 *
287 * Each PeerInfo captures identity, transfer rates, progress, and flags
288 * at the time of the call. The list is not updated automatically;
289 * call again to refresh.
290 * @return List of PeerInfo value objects.
291 */
292 QList<PeerInfo> peers() const;
293
294 /**
295 * @brief Ban a peer by IP address.
296 *
297 * Adds the address to the session IP filter with a deny rule and
298 * disconnects the peer if currently connected. The ban persists
299 * for the lifetime of the session.
300 * @param address The peer's IP address to ban.
301 */
302 void banPeer(const QHostAddress& address);
303
304 // ── Resume data ─────────────────────────────────────────────────────
305
306 /**
307 * @brief Request an asynchronous resume-data save.
308 *
309 * The result arrives via TorrentClient::resumeDataSaved() or
310 * TorrentClient::resumeDataFailed().
311 */
313
314 // ── Internal — used by TorrentClient ────────────────────────────────
315
316 /** @internal Set the underlying libtorrent handle (lt::torrent_handle*). */
317 void setHandle(void* handle);
318 /** @internal Get the underlying libtorrent handle. */
319 void* handle() const { return _handle; }
320 /** @internal Associate a magnet link with this torrent. */
321 void setMagnetLink(const MagnetLink& link) { _magnetLink = link; }
322 /** @internal Set the raw 20-byte info hash. */
323 void setInfoHash(const QByteArray& hash) { _infoHash = hash; }
324 /** @internal Set the download directory. */
325 void setDownloadDirectory(const QString& dir) { _downloadDirectory = dir; }
326 /** @internal Called by TorrentClient::processAlerts() to update state from libtorrent status. */
327 void updateFromStatus();
328 /** @internal Called after status update to auto-pause if seed ratio is reached. */
329 void checkSeedRatio();
330
331signals:
332 /** @brief Emitted when the torrent transitions to a new State. */
334 /** @brief Emitted periodically during download with the current progress ratio (0.0–1.0). */
335 void progressUpdated(double ratio);
336 /** @brief Emitted when an individual file finishes downloading. */
337 void fileCompleted(int fileIndex, const QString& filePath);
338 /** @brief Emitted once when the entire torrent download completes. */
340 /** @brief Emitted when metadata is received (magnet links only). */
342 /** @brief Emitted on torrent errors (tracker failures, I/O errors, etc.). */
343 void error(const QString& message);
344
345 /** @brief Emitted when a tracker announce succeeds. */
346 void trackerAnnounced(const QString& url);
347 /** @brief Emitted when a tracker announce fails. */
348 void trackerError(const QString& url, const QString& message);
349
350 /** @brief Emitted when moveStorage() completes successfully. */
351 void storageMoved(const QString& newPath);
352 /** @brief Emitted when moveStorage() fails. */
353 void storageMoveError(const QString& error);
354
355 /** @brief Emitted when renameFile() completes successfully. */
356 void fileRenamed(int fileIndex, const QString& newName);
357 /** @brief Emitted when renameFile() fails. */
358 void fileRenameError(int fileIndex, const QString& error);
359
360private:
361 void setState(State newState);
362
363 State _state = Idle;
364 MagnetLink _magnetLink;
365 QByteArray _infoHash;
366 QString _downloadDirectory;
367 bool _hasMetadata = false;
368 bool _downloadEmitted = false;
369 double _seedRatioLimit = 0.0; // 0 = no limit
370 void* _handle = nullptr; // lt::torrent_handle*
371};
372
373#endif // TORRENT_H
Represents a single torrent within a TorrentClient session.
Definition torrent.h:22
int filePriority(int index) const
Get the current download priority for a file.
qint64 uploadRate() const
Current upload rate in bytes/sec.
void storageMoved(const QString &newPath)
Emitted when moveStorage() completes successfully.
void setUploadLimit(int bytesPerSecond)
Set the per-torrent upload rate limit.
void forceReannounce()
Force an immediate re-announce to all trackers.
int eta() const
Estimated seconds remaining until download completes.
QByteArray infoHash() const
Raw 20-byte SHA-1 info hash.
Definition torrent.h:67
int maxUploads() const
Maximum number of upload slots for this torrent.
void setMaxConnections(int value)
Set the maximum peer connections for this torrent.
bool isAutoManaged() const
Whether libtorrent auto-manages this torrent's queue position.
QString outputPath() const
Full output path (save_path + torrent name).
bool hasMetadata() const
Whether torrent metadata has been received.
Definition torrent.h:121
QString infoHashHex() const
Info hash as a lowercase hex string (40 characters).
Definition torrent.h:69
void setDownloadLimit(int bytesPerSecond)
Set the per-torrent download rate limit.
void removeTracker(const QString &url)
Remove a tracker by URL.
State state() const
Current lifecycle state.
Definition torrent.h:54
void downloadComplete()
Emitted once when the entire torrent download completes.
void progressUpdated(double ratio)
Emitted periodically during download with the current progress ratio (0.0–1.0).
QList< PeerInfo > peers() const
Snapshot of all currently connected peers.
QString name() const
Human-readable torrent name.
void resume()
Resume a paused torrent.
qint64 bytesDownloaded() const
Total bytes downloaded so far.
int findFileByName(const QString &partialName) const
Find a file by partial name (case-insensitive substring match).
int totalPieces() const
Total number of pieces in this torrent.
int connectedPeers() const
Number of currently connected peers.
void banPeer(const QHostAddress &address)
Ban a peer by IP address.
void stateChanged(Torrent::State state)
Emitted when the torrent transitions to a new State.
qint64 fileSize(int index) const
Size of a file in bytes.
void stop()
Stop the torrent and reset state to Idle.
int fileCount() const
Number of files in the torrent.
int maxConnections() const
Maximum number of peer connections for this torrent.
QList< qint64 > fileProgress() const
Get per-file download progress as a list of byte counts.
void trackerAnnounced(const QString &url)
Emitted when a tracker announce succeeds.
void setAutoManaged(bool enabled)
Enable or disable libtorrent's auto-managed mode.
void setFilePriority(int index, int priority)
Set the download priority for a single file.
void fileRenamed(int fileIndex, const QString &newName)
Emitted when renameFile() completes successfully.
void start()
Resume downloading/seeding.
void saveResumeData()
Request an asynchronous resume-data save.
int downloadedPieces() const
Number of pieces that have been downloaded and verified.
void setAllFilePriorities(int priority)
Set the same download priority for every file.
void setSeedRatioLimit(double ratio)
Set a share-ratio target; the torrent pauses when it is reached.
qint64 totalUploaded() const
Total bytes uploaded over the lifetime of this torrent.
int downloadLimit() const
Per-torrent download rate limit in bytes/sec.
void metadataReceived()
Emitted when metadata is received (magnet links only).
void storageMoveError(const QString &error)
Emitted when moveStorage() fails.
void fileRenameError(int fileIndex, const QString &error)
Emitted when renameFile() fails.
void setMaxUploads(int value)
Set the maximum upload slots for this torrent.
QString downloadDirectory() const
The directory where this torrent's data is being saved.
Definition torrent.h:192
bool isSequentialDownload() const
Whether pieces are requested in sequential order.
void trackerError(const QString &url, const QString &message)
Emitted when a tracker announce fails.
void renameFile(int index, const QString &newName)
Rename a file within the torrent.
int pieceSize() const
Size of each piece in bytes.
int uploadLimit() const
Per-torrent upload rate limit in bytes/sec.
QString fileName(int index) const
Relative path of a file within the torrent.
qint64 downloadRate() const
Current download rate in bytes/sec.
double seedRatioLimit() const
Target share ratio after which the torrent is auto-paused.
Definition torrent.h:254
QStringList trackers() const
List of tracker URLs currently attached to this torrent.
double ratio() const
Share ratio (uploaded / downloaded).
void fileCompleted(int fileIndex, const QString &filePath)
Emitted when an individual file finishes downloading.
void error(const QString &message)
Emitted on torrent errors (tracker failures, I/O errors, etc.).
State
Lifecycle state of a torrent.
Definition torrent.h:28
@ Idle
Torrent is stopped or not yet started.
Definition torrent.h:29
@ Checking
Verifying existing data on disk.
Definition torrent.h:31
@ Downloading
Actively downloading pieces.
Definition torrent.h:32
@ Error
An unrecoverable error occurred.
Definition torrent.h:35
@ FetchingMetadata
Downloading torrent metadata (magnet link resolution).
Definition torrent.h:30
@ Paused
Explicitly paused by the user.
Definition torrent.h:34
@ Seeding
Download complete; uploading to peers.
Definition torrent.h:33
double progress() const
Download progress as a ratio from 0.0 to 1.0.
qint64 totalSize() const
Total size of all selected files in bytes.
void moveStorage(const QString &newPath)
Move the torrent's data to a new directory.
void pause()
Pause the torrent, keeping its state recoverable via resume().
void setSequentialDownload(bool enabled)
Enable or disable sequential piece downloading.
QStringList fileNames() const
List of all file paths in the torrent.
void addTracker(const QString &url)
Append a tracker URL.