1
<?xml version="1.0" encoding="UTF-8"?>
2
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en_US" lang="en_US">
5
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
6
<title>Qt 4.7: mainwindow.cpp Example File (network/torrent/mainwindow.cpp)</title>
7
<link rel="stylesheet" type="text/css" href="style/style.css" />
8
<script src="scripts/jquery.js" type="text/javascript"></script>
9
<script src="scripts/functions.js" type="text/javascript"></script>
11
<body class="offline narrow creator">
12
<div class="header" id="qtdocheader">
15
<a href="index.html">Home</a></div>
16
<a href="index.html" class="qtref"><span>Qt Reference Documentation</span></a>
17
<div id="nav-topright">
19
<li class="nav-topright-home"><a href="http://qt.nokia.com/">Qt HOME</a></li>
20
<li class="nav-topright-dev"><a href="http://developer.qt.nokia.com/">DEV</a></li>
21
<li class="nav-topright-labs"><a href="http://labs.qt.nokia.com/blogs/">LABS</a></li>
22
<li class="nav-topright-doc nav-topright-doc-active"><a href="http://doc.qt.nokia.com/">
24
<li class="nav-topright-blog"><a href="http://blog.qt.nokia.com/">BLOG</a></li>
29
<li class="shortCut-topleft-inactive"><span><a href="index.html">Qt 4.7</a></span></li>
30
<li class="shortCut-topleft-active"><a href="http://doc.qt.nokia.com">ALL VERSIONS </a></li>
33
<ul class="sf-menu sf-js-enabled sf-shadow" id="narrowmenu">
34
<li><a href="#">API Lookup</a>
36
<li><a href="classes.html">Class index</a></li>
37
<li><a href="functions.html">Function index</a></li>
38
<li><a href="modules.html">Modules</a></li>
39
<li><a href="namespaces.html">Namespaces</a></li>
40
<li><a href="qtglobal.html">Global Declarations</a></li>
41
<li><a href="licensing.html">Licenses and Credits</a></li>
44
<li><a href="#">Qt Topics</a>
45
<ul id="topmenuTopic">
46
<li><a href="qt-basic-concepts.html">Programming with Qt</a></li>
47
<li><a href="qtquick.html">Device UI's & Qt Quick</a></li>
48
<li><a href="qt-gui-concepts.html">UI Design with Qt</a></li>
49
<li><a href="developing-with-qt.html">Cross-platform and Platform-specific</a></li>
50
<li><a href="platform-specific.html">Platform-specific info</a></li>
51
<li><a href="technology-apis.html">Qt and Key Technologies</a></li>
52
<li><a href="best-practices.html">How-To's and Best Practices</a></li>
55
<li><a href="#">Examples</a>
56
<ul id="topmenuexample">
57
<li><a href="all-examples.html">Examples</a></li>
58
<li><a href="tutorials.html">Tutorials</a></li>
59
<li><a href="demos.html">Demos</a></li>
60
<li><a href="qdeclarativeexamples.html">QML Examples</a></li>
70
<div class="bd group">
72
<div class="searchlabel">
75
<form id="qtdocsearch" action="" onsubmit="return false;">
77
<input type="text" name="searchstring" id="pageType" value="" />
81
<div class="box first bottombar" id="lookup">
82
<h2 title="API Lookup"><span></span>
84
<div id="list001" class="list">
86
<li class="defaultLink"><a href="classes.html">Class index</a></li>
87
<li class="defaultLink"><a href="functions.html">Function index</a></li>
88
<li class="defaultLink"><a href="modules.html">Modules</a></li>
89
<li class="defaultLink"><a href="namespaces.html">Namespaces</a></li>
90
<li class="defaultLink"><a href="qtglobal.html">Global Declarations</a></li>
91
<li class="defaultLink"><a href="qdeclarativeelements.html">QML elements</a></li>
95
<div class="box bottombar" id="topics">
96
<h2 title="Qt Topics"><span></span>
98
<div id="list002" class="list">
100
<li class="defaultLink"><a href="qt-basic-concepts.html">Programming with Qt</a></li>
101
<li class="defaultLink"><a href="qtquick.html">Device UI's & Qt Quick</a></li>
102
<li class="defaultLink"><a href="qt-gui-concepts.html">UI Design with Qt</a></li>
103
<li class="defaultLink"><a href="developing-with-qt.html">Cross-platform and Platform-specific</a></li>
104
<li class="defaultLink"><a href="platform-specific.html">Platform-specific info</a></li>
105
<li class="defaultLink"><a href="technology-apis.html">Qt and Key Technologies</a></li>
106
<li class="defaultLink"><a href="best-practices.html">How-To's and Best Practices</a></li>
110
<div class="box" id="examples">
111
<h2 title="Examples"><span></span>
113
<div id="list003" class="list">
115
<li class="defaultLink"><a href="all-examples.html">Examples</a></li>
116
<li class="defaultLink"><a href="tutorials.html">Tutorials</a></li>
117
<li class="defaultLink"><a href="demos.html">Demos</a></li>
118
<li class="defaultLink"><a href="qdeclarativeexamples.html">QML Examples</a></li>
124
<div class="toolbar">
125
<div class="breadcrumb toolblock">
127
<li class="first"><a href="index.html">Home</a></li>
128
<!-- Bread crumbs goes here -->
131
<div class="toolbuttons toolblock">
133
<li id="smallA" class="t_button">A</li>
134
<li id="medA" class="t_button active">A</li>
135
<li id="bigA" class="t_button">A</li>
136
<li id="print" class="t_button"><a href="javascript:this.print();">
137
<span>Print</span></a></li>
141
<div class="content">
142
<h1 class="title">mainwindow.cpp Example File</h1>
143
<span class="small-subtitle">network/torrent/mainwindow.cpp</span>
144
<!-- $$$network/torrent/mainwindow.cpp-description -->
145
<div class="descr"> <a name="details"></a>
146
<pre class="highlightedCode brush: cpp"><span class="comment"> /****************************************************************************
148
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
149
** All rights reserved.
150
** Contact: Nokia Corporation (qt-info@nokia.com)
152
** This file is part of the examples of the Qt Toolkit.
154
** $QT_BEGIN_LICENSE:BSD$
155
** You may use this file under the terms of the BSD license as follows:
157
** "Redistribution and use in source and binary forms, with or without
158
** modification, are permitted provided that the following conditions are
160
** * Redistributions of source code must retain the above copyright
161
** notice, this list of conditions and the following disclaimer.
162
** * Redistributions in binary form must reproduce the above copyright
163
** notice, this list of conditions and the following disclaimer in
164
** the documentation and/or other materials provided with the
166
** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
167
** the names of its contributors may be used to endorse or promote
168
** products derived from this software without specific prior written
171
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
173
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
174
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
175
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
176
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
177
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
178
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
179
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
180
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
181
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
184
****************************************************************************/</span>
186
#include <QtGui>
188
#include "addtorrentdialog.h"
189
#include "mainwindow.h"
190
#include "ratecontroller.h"
191
#include "torrentclient.h"
193
<span class="comment"> // TorrentView extends QTreeWidget to allow drag and drop.</span>
194
class TorrentView : public QTreeWidget
198
TorrentView(QWidget *parent = 0);
201
void fileDropped(const QString &fileName);
204
void dragMoveEvent(QDragMoveEvent *event);
205
void dropEvent(QDropEvent *event);
208
<span class="comment"> // TorrentViewDelegate is used to draw the progress bars.</span>
209
class TorrentViewDelegate : public QItemDelegate
213
inline TorrentViewDelegate(MainWindow *mainWindow) : QItemDelegate(mainWindow) {}
215
inline void paint(QPainter *painter, const QStyleOptionViewItem &option,
216
const QModelIndex &index ) const
218
if (index.column() != 2) {
219
QItemDelegate::paint(painter, option, index);
223
<span class="comment">// Set up a QStyleOptionProgressBar to precisely mimic the</span>
224
<span class="comment">// environment of a progress bar.</span>
225
QStyleOptionProgressBar progressBarOption;
226
progressBarOption.state = QStyle::State_Enabled;
227
progressBarOption.direction = QApplication::layoutDirection();
228
progressBarOption.rect = option.rect;
229
progressBarOption.fontMetrics = QApplication::fontMetrics();
230
progressBarOption.minimum = 0;
231
progressBarOption.maximum = 100;
232
progressBarOption.textAlignment = Qt::AlignCenter;
233
progressBarOption.textVisible = true;
235
<span class="comment">// Set the progress and text values of the style option.</span>
236
int progress = qobject_cast<MainWindow *>(parent())->clientForRow(index.row())->progress();
237
progressBarOption.progress = progress < 0 ? 0 : progress;
238
progressBarOption.text = QString().sprintf("%d%%", progressBarOption.progress);
240
<span class="comment">// Draw the progress bar onto the view.</span>
241
QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, painter);
245
MainWindow::MainWindow(QWidget *parent)
246
: QMainWindow(parent), quitDialog(0), saveChanges(false)
248
<span class="comment">// Initialize some static strings</span>
250
headers << tr("Torrent") << tr("Peers/Seeds") << tr("Progress")
251
<< tr("Down rate") << tr("Up rate") << tr("Status");
253
<span class="comment">// Main torrent list</span>
254
torrentView = new TorrentView(this);
255
torrentView->setItemDelegate(new TorrentViewDelegate(this));
256
torrentView->setHeaderLabels(headers);
257
torrentView->setSelectionBehavior(QAbstractItemView::SelectRows);
258
torrentView->setAlternatingRowColors(true);
259
torrentView->setRootIsDecorated(false);
260
setCentralWidget(torrentView);
262
<span class="comment">// Set header resize modes and initial section sizes</span>
263
QFontMetrics fm = fontMetrics();
264
QHeaderView *header = torrentView->header();
265
header->resizeSection(0, fm.width("typical-name-for-a-torrent.torrent"));
266
header->resizeSection(1, fm.width(headers.at(1) + " "));
267
header->resizeSection(2, fm.width(headers.at(2) + " "));
268
header->resizeSection(3, qMax(fm.width(headers.at(3) + " "), fm.width(" 1234.0 KB/s ")));
269
header->resizeSection(4, qMax(fm.width(headers.at(4) + " "), fm.width(" 1234.0 KB/s ")));
270
header->resizeSection(5, qMax(fm.width(headers.at(5) + " "), fm.width(tr("Downloading") + " ")));
272
<span class="comment">// Create common actions</span>
273
QAction *newTorrentAction = new QAction(QIcon(":/icons/bottom.png"), tr("Add &new torrent"), this);
274
pauseTorrentAction = new QAction(QIcon(":/icons/player_pause.png"), tr("&Pause torrent"), this);
275
removeTorrentAction = new QAction(QIcon(":/icons/player_stop.png"), tr("&Remove torrent"), this);
277
<span class="comment">// File menu</span>
278
QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
279
fileMenu->addAction(newTorrentAction);
280
fileMenu->addAction(pauseTorrentAction);
281
fileMenu->addAction(removeTorrentAction);
282
fileMenu->addSeparator();
283
fileMenu->addAction(QIcon(":/icons/exit.png"), tr("E&xit"), this, SLOT(close()));
285
<span class="comment">// Help menu</span>
286
QMenu *helpMenu = menuBar()->addMenu(tr("&Help"));
287
helpMenu->addAction(tr("&About"), this, SLOT(about()));
288
helpMenu->addAction(tr("About &Qt"), qApp, SLOT(aboutQt()));
290
<span class="comment">// Top toolbar</span>
291
QToolBar *topBar = new QToolBar(tr("Tools"));
292
addToolBar(Qt::TopToolBarArea, topBar);
293
topBar->setMovable(false);
294
topBar->addAction(newTorrentAction);
295
topBar->addAction(removeTorrentAction);
296
topBar->addAction(pauseTorrentAction);
297
topBar->addSeparator();
298
downActionTool = topBar->addAction(QIcon(tr(":/icons/1downarrow.png")), tr("Move down"));
299
upActionTool = topBar->addAction(QIcon(tr(":/icons/1uparrow.png")), tr("Move up"));
301
<span class="comment">// Bottom toolbar</span>
302
QToolBar *bottomBar = new QToolBar(tr("Rate control"));
303
addToolBar(Qt::BottomToolBarArea, bottomBar);
304
bottomBar->setMovable(false);
305
downloadLimitSlider = new QSlider(Qt::Horizontal);
306
downloadLimitSlider->setRange(0, 1000);
307
bottomBar->addWidget(new QLabel(tr("Max download:")));
308
bottomBar->addWidget(downloadLimitSlider);
309
bottomBar->addWidget((downloadLimitLabel = new QLabel(tr("0 KB/s"))));
310
downloadLimitLabel->setFixedSize(QSize(fm.width(tr("99999 KB/s")), fm.lineSpacing()));
311
bottomBar->addSeparator();
312
uploadLimitSlider = new QSlider(Qt::Horizontal);
313
uploadLimitSlider->setRange(0, 1000);
314
bottomBar->addWidget(new QLabel(tr("Max upload:")));
315
bottomBar->addWidget(uploadLimitSlider);
316
bottomBar->addWidget((uploadLimitLabel = new QLabel(tr("0 KB/s"))));
317
uploadLimitLabel->setFixedSize(QSize(fm.width(tr("99999 KB/s")), fm.lineSpacing()));
319
<span class="comment">// Set up connections</span>
320
connect(torrentView, SIGNAL(itemSelectionChanged()),
321
this, SLOT(setActionsEnabled()));
322
connect(torrentView, SIGNAL(fileDropped(QString)),
323
this, SLOT(acceptFileDrop(QString)));
324
connect(uploadLimitSlider, SIGNAL(valueChanged(int)),
325
this, SLOT(setUploadLimit(int)));
326
connect(downloadLimitSlider, SIGNAL(valueChanged(int)),
327
this, SLOT(setDownloadLimit(int)));
328
connect(newTorrentAction, SIGNAL(triggered()),
329
this, SLOT(addTorrent()));
330
connect(pauseTorrentAction, SIGNAL(triggered()),
331
this, SLOT(pauseTorrent()));
332
connect(removeTorrentAction, SIGNAL(triggered()),
333
this, SLOT(removeTorrent()));
334
connect(upActionTool, SIGNAL(triggered(bool)),
335
this, SLOT(moveTorrentUp()));
336
connect(downActionTool, SIGNAL(triggered(bool)),
337
this, SLOT(moveTorrentDown()));
339
<span class="comment">// Load settings and start</span>
340
setWindowTitle(tr("Torrent Client"));
342
QMetaObject::invokeMethod(this, "loadSettings", Qt::QueuedConnection);
345
QSize MainWindow::sizeHint() const
347
const QHeaderView *header = torrentView->header();
349
<span class="comment">// Add up the sizes of all header sections. The last section is</span>
350
<span class="comment">// stretched, so its size is relative to the size of the width;</span>
351
<span class="comment">// instead of counting it, we count the size of its largest value.</span>
352
int width = fontMetrics().width(tr("Downloading") + " ");
353
for (int i = 0; i < header->count() - 1; ++i)
354
width += header->sectionSize(i);
356
return QSize(width, QMainWindow::sizeHint().height())
357
.expandedTo(QApplication::globalStrut());
360
const TorrentClient *MainWindow::clientForRow(int row) const
362
<span class="comment">// Return the client at the given row.</span>
363
return jobs.at(row).client;
366
int MainWindow::rowOfClient(TorrentClient *client) const
368
<span class="comment">// Return the row that displays this client's status, or -1 if the</span>
369
<span class="comment">// client is not known.</span>
371
foreach (Job job, jobs) {
372
if (job.client == client)
379
void MainWindow::loadSettings()
381
<span class="comment">// Load base settings (last working directory, upload/download limits).</span>
382
QSettings settings("Trolltech", "Torrent");
383
lastDirectory = settings.value("LastDirectory").toString();
384
if (lastDirectory.isEmpty())
385
lastDirectory = QDir::currentPath();
386
int up = settings.value("UploadLimit").toInt();
387
int down = settings.value("DownloadLimit").toInt();
388
uploadLimitSlider->setValue(up ? up : 170);
389
downloadLimitSlider->setValue(down ? down : 550);
391
<span class="comment">// Resume all previous downloads.</span>
392
int size = settings.beginReadArray("Torrents");
393
for (int i = 0; i < size; ++i) {
394
settings.setArrayIndex(i);
395
QByteArray resumeState = settings.value("resumeState").toByteArray();
396
QString fileName = settings.value("sourceFileName").toString();
397
QString dest = settings.value("destinationFolder").toString();
399
if (addTorrent(fileName, dest, resumeState)) {
400
TorrentClient *client = jobs.last().client;
401
client->setDownloadedBytes(settings.value("downloadedBytes").toLongLong());
402
client->setUploadedBytes(settings.value("uploadedBytes").toLongLong());
407
bool MainWindow::addTorrent()
409
<span class="comment">// Show the file dialog, let the user select what torrent to start downloading.</span>
410
QString fileName = QFileDialog::getOpenFileName(this, tr("Choose a torrent file"),
412
tr("Torrents (*.torrent);;"
413
" All files (*.*)"));
414
if (fileName.isEmpty())
416
lastDirectory = QFileInfo(fileName).absolutePath();
418
<span class="comment">// Show the "Add Torrent" dialog.</span>
419
AddTorrentDialog *addTorrentDialog = new AddTorrentDialog(this);
420
addTorrentDialog->setTorrent(fileName);
421
addTorrentDialog->deleteLater();
422
if (!addTorrentDialog->exec())
425
<span class="comment">// Add the torrent to our list of downloads</span>
426
addTorrent(fileName, addTorrentDialog->destinationFolder());
429
QTimer::singleShot(1000, this, SLOT(saveSettings()));
434
void MainWindow::removeTorrent()
436
<span class="comment">// Find the row of the current item, and find the torrent client</span>
437
<span class="comment">// for that row.</span>
438
int row = torrentView->indexOfTopLevelItem(torrentView->currentItem());
439
TorrentClient *client = jobs.at(row).client;
441
<span class="comment">// Stop the client.</span>
442
client->disconnect();
443
connect(client, SIGNAL(stopped()), this, SLOT(torrentStopped()));
446
<span class="comment">// Remove the row from the view.</span>
447
delete torrentView->takeTopLevelItem(row);
455
void MainWindow::torrentStopped()
457
<span class="comment">// Schedule the client for deletion.</span>
458
TorrentClient *client = qobject_cast<TorrentClient *>(sender());
459
client->deleteLater();
461
<span class="comment">// If the quit dialog is shown, update its progress.</span>
463
if (++jobsStopped == jobsToStop)
464
quitDialog->close();
468
void MainWindow::torrentError(TorrentClient::Error)
470
<span class="comment">// Delete the client.</span>
471
TorrentClient *client = qobject_cast<TorrentClient *>(sender());
472
int row = rowOfClient(client);
473
QString fileName = jobs.at(row).torrentFileName;
476
<span class="comment">// Display the warning.</span>
477
QMessageBox::warning(this, tr("Error"),
478
tr("An error occurred while downloading %0: %1")
480
.arg(client->errorString()));
482
delete torrentView->takeTopLevelItem(row);
483
client->deleteLater();
486
bool MainWindow::addTorrent(const QString &fileName, const QString &destinationFolder,
487
const QByteArray &resumeState)
489
<span class="comment">// Check if the torrent is already being downloaded.</span>
490
foreach (Job job, jobs) {
491
if (job.torrentFileName == fileName && job.destinationDirectory == destinationFolder) {
492
QMessageBox::warning(this, tr("Already downloading"),
493
tr("The torrent file %1 is "
494
"already being downloaded.").arg(fileName));
499
<span class="comment">// Create a new torrent client and attempt to parse the torrent data.</span>
500
TorrentClient *client = new TorrentClient(this);
501
if (!client->setTorrent(fileName)) {
502
QMessageBox::warning(this, tr("Error"),
503
tr("The torrent file %1 cannot not be opened/resumed.").arg(fileName));
507
client->setDestinationFolder(destinationFolder);
508
client->setDumpedState(resumeState);
510
<span class="comment">// Setup the client connections.</span>
511
connect(client, SIGNAL(stateChanged(TorrentClient::State)), this, SLOT(updateState(TorrentClient::State)));
512
connect(client, SIGNAL(peerInfoUpdated()), this, SLOT(updatePeerInfo()));
513
connect(client, SIGNAL(progressUpdated(int)), this, SLOT(updateProgress(int)));
514
connect(client, SIGNAL(downloadRateUpdated(int)), this, SLOT(updateDownloadRate(int)));
515
connect(client, SIGNAL(uploadRateUpdated(int)), this, SLOT(updateUploadRate(int)));
516
connect(client, SIGNAL(stopped()), this, SLOT(torrentStopped()));
517
connect(client, SIGNAL(error(TorrentClient::Error)), this, SLOT(torrentError(TorrentClient::Error)));
519
<span class="comment">// Add the client to the list of downloading jobs.</span>
522
job.torrentFileName = fileName;
523
job.destinationDirectory = destinationFolder;
526
<span class="comment">// Create and add a row in the torrent view for this download.</span>
527
QTreeWidgetItem *item = new QTreeWidgetItem(torrentView);
529
QString baseFileName = QFileInfo(fileName).fileName();
530
if (baseFileName.toLower().endsWith(".torrent"))
531
baseFileName.remove(baseFileName.size() - 8);
533
item->setText(0, baseFileName);
534
item->setToolTip(0, tr("Torrent: %1<br>Destination: %2")
535
.arg(baseFileName).arg(destinationFolder));
536
item->setText(1, tr("0/0"));
537
item->setText(2, "0");
538
item->setText(3, "0.0 KB/s");
539
item->setText(4, "0.0 KB/s");
540
item->setText(5, tr("Idle"));
541
item->setFlags(item->flags() & ~Qt::ItemIsEditable);
542
item->setTextAlignment(1, Qt::AlignHCenter);
546
QTimer::singleShot(5000, this, SLOT(saveSettings()));
552
void MainWindow::saveSettings()
558
<span class="comment">// Prepare and reset the settings</span>
559
QSettings settings("Trolltech", "Torrent");
562
settings.setValue("LastDirectory", lastDirectory);
563
settings.setValue("UploadLimit", uploadLimitSlider->value());
564
settings.setValue("DownloadLimit", downloadLimitSlider->value());
566
<span class="comment">// Store data on all known torrents</span>
567
settings.beginWriteArray("Torrents");
568
for (int i = 0; i < jobs.size(); ++i) {
569
settings.setArrayIndex(i);
570
settings.setValue("sourceFileName", jobs.at(i).torrentFileName);
571
settings.setValue("destinationFolder", jobs.at(i).destinationDirectory);
572
settings.setValue("uploadedBytes", jobs.at(i).client->uploadedBytes());
573
settings.setValue("downloadedBytes", jobs.at(i).client->downloadedBytes());
574
settings.setValue("resumeState", jobs.at(i).client->dumpedState());
580
void MainWindow::updateState(TorrentClient::State)
582
<span class="comment">// Update the state string whenever the client's state changes.</span>
583
TorrentClient *client = qobject_cast<TorrentClient *>(sender());
584
int row = rowOfClient(client);
585
QTreeWidgetItem *item = torrentView->topLevelItem(row);
587
item->setToolTip(0, tr("Torrent: %1<br>Destination: %2<br>State: %3")
588
.arg(jobs.at(row).torrentFileName)
589
.arg(jobs.at(row).destinationDirectory)
590
.arg(client->stateString()));
592
item->setText(5, client->stateString());
597
void MainWindow::updatePeerInfo()
599
<span class="comment">// Update the number of connected, visited, seed and leecher peers.</span>
600
TorrentClient *client = qobject_cast<TorrentClient *>(sender());
601
int row = rowOfClient(client);
603
QTreeWidgetItem *item = torrentView->topLevelItem(row);
604
item->setText(1, tr("%1/%2").arg(client->connectedPeerCount())
605
.arg(client->seedCount()));
608
void MainWindow::updateProgress(int percent)
610
TorrentClient *client = qobject_cast<TorrentClient *>(sender());
611
int row = rowOfClient(client);
613
<span class="comment">// Update the progressbar.</span>
614
QTreeWidgetItem *item = torrentView->topLevelItem(row);
616
item->setText(2, QString::number(percent));
619
void MainWindow::setActionsEnabled()
621
<span class="comment">// Find the view item and client for the current row, and update</span>
622
<span class="comment">// the states of the actions.</span>
623
QTreeWidgetItem *item = 0;
624
if (!torrentView->selectedItems().isEmpty())
625
item = torrentView->selectedItems().first();
626
TorrentClient *client = item ? jobs.at(torrentView->indexOfTopLevelItem(item)).client : 0;
627
bool pauseEnabled = client && ((client->state() == TorrentClient::Paused)
628
|| (client->state() > TorrentClient::Preparing));
630
removeTorrentAction->setEnabled(item != 0);
631
pauseTorrentAction->setEnabled(item != 0 && pauseEnabled);
633
if (client && client->state() == TorrentClient::Paused) {
634
pauseTorrentAction->setIcon(QIcon(":/icons/player_play.png"));
635
pauseTorrentAction->setText(tr("Resume torrent"));
637
pauseTorrentAction->setIcon(QIcon(":/icons/player_pause.png"));
638
pauseTorrentAction->setText(tr("Pause torrent"));
641
int row = torrentView->indexOfTopLevelItem(item);
642
upActionTool->setEnabled(item && row != 0);
643
downActionTool->setEnabled(item && row != jobs.size() - 1);
646
void MainWindow::updateDownloadRate(int bytesPerSecond)
648
<span class="comment">// Update the download rate.</span>
649
TorrentClient *client = qobject_cast<TorrentClient *>(sender());
650
int row = rowOfClient(client);
652
num.sprintf("%.1f KB/s", bytesPerSecond / 1024.0);
653
torrentView->topLevelItem(row)->setText(3, num);
657
QTimer::singleShot(5000, this, SLOT(saveSettings()));
661
void MainWindow::updateUploadRate(int bytesPerSecond)
663
<span class="comment">// Update the upload rate.</span>
664
TorrentClient *client = qobject_cast<TorrentClient *>(sender());
665
int row = rowOfClient(client);
667
num.sprintf("%.1f KB/s", bytesPerSecond / 1024.0);
668
torrentView->topLevelItem(row)->setText(4, num);
672
QTimer::singleShot(5000, this, SLOT(saveSettings()));
676
void MainWindow::pauseTorrent()
678
<span class="comment">// Pause or unpause the current torrent.</span>
679
int row = torrentView->indexOfTopLevelItem(torrentView->currentItem());
680
TorrentClient *client = jobs.at(row).client;
681
client->setPaused(client->state() != TorrentClient::Paused);
685
void MainWindow::moveTorrentUp()
687
QTreeWidgetItem *item = torrentView->currentItem();
688
int row = torrentView->indexOfTopLevelItem(item);
692
Job tmp = jobs.at(row - 1);
693
jobs[row - 1] = jobs[row];
696
QTreeWidgetItem *itemAbove = torrentView->takeTopLevelItem(row - 1);
697
torrentView->insertTopLevelItem(row, itemAbove);
701
void MainWindow::moveTorrentDown()
703
QTreeWidgetItem *item = torrentView->currentItem();
704
int row = torrentView->indexOfTopLevelItem(item);
705
if (row == jobs.size() - 1)
708
Job tmp = jobs.at(row + 1);
709
jobs[row + 1] = jobs[row];
712
QTreeWidgetItem *itemAbove = torrentView->takeTopLevelItem(row + 1);
713
torrentView->insertTopLevelItem(row, itemAbove);
717
static int rateFromValue(int value)
720
if (value >= 0 && value < 250) {
721
rate = 1 + int(value * 0.124);
722
} else if (value < 500) {
723
rate = 32 + int((value - 250) * 0.384);
724
} else if (value < 750) {
725
rate = 128 + int((value - 500) * 1.536);
727
rate = 512 + int((value - 750) * 6.1445);
732
void MainWindow::setUploadLimit(int value)
734
int rate = rateFromValue(value);
735
uploadLimitLabel->setText(tr("%1 KB/s").arg(QString().sprintf("%4d", rate)));
736
RateController::instance()->setUploadLimit(rate * 1024);
739
void MainWindow::setDownloadLimit(int value)
741
int rate = rateFromValue(value);
742
downloadLimitLabel->setText(tr("%1 KB/s").arg(QString().sprintf("%4d", rate)));
743
RateController::instance()->setDownloadLimit(rate * 1024);
746
void MainWindow::about()
748
QLabel *icon = new QLabel;
749
icon->setPixmap(QPixmap(":/icons/peertopeer.png"));
751
QLabel *text = new QLabel;
752
text->setWordWrap(true);
753
text->setText("<p>The <b>Torrent Client</b> example demonstrates how to"
754
" write a complete peer-to-peer file sharing"
755
" application using Qt's network and thread classes.</p>"
756
"<p>This feature complete client implementation of"
757
" the BitTorrent protocol can efficiently"
758
" maintain several hundred network connections"
759
" simultaneously.</p>");
761
QPushButton *quitButton = new QPushButton("OK");
763
QHBoxLayout *topLayout = new QHBoxLayout;
764
topLayout->setMargin(10);
765
topLayout->setSpacing(10);
766
topLayout->addWidget(icon);
767
topLayout->addWidget(text);
769
QHBoxLayout *bottomLayout = new QHBoxLayout;
770
bottomLayout->addStretch();
771
bottomLayout->addWidget(quitButton);
772
bottomLayout->addStretch();
774
QVBoxLayout *mainLayout = new QVBoxLayout;
775
mainLayout->addLayout(topLayout);
776
mainLayout->addLayout(bottomLayout);
779
about.setModal(true);
780
about.setWindowTitle(tr("About Torrent Client"));
781
about.setLayout(mainLayout);
783
connect(quitButton, SIGNAL(clicked()), &about, SLOT(close()));
788
void MainWindow::acceptFileDrop(const QString &fileName)
790
<span class="comment">// Create and show the "Add Torrent" dialog.</span>
791
AddTorrentDialog *addTorrentDialog = new AddTorrentDialog;
792
lastDirectory = QFileInfo(fileName).absolutePath();
793
addTorrentDialog->setTorrent(fileName);
794
addTorrentDialog->deleteLater();
795
if (!addTorrentDialog->exec())
798
<span class="comment">// Add the torrent to our list of downloads.</span>
799
addTorrent(fileName, addTorrentDialog->destinationFolder());
803
void MainWindow::closeEvent(QCloseEvent *)
808
<span class="comment">// Save upload / download numbers.</span>
812
quitDialog = new QProgressDialog(tr("Disconnecting from trackers"), tr("Abort"), 0, jobsToStop, this);
814
<span class="comment">// Stop all clients, remove the rows from the view and wait for</span>
815
<span class="comment">// them to signal that they have stopped.</span>
818
foreach (Job job, jobs) {
820
TorrentClient *client = job.client;
821
client->disconnect();
822
connect(client, SIGNAL(stopped()), this, SLOT(torrentStopped()));
824
delete torrentView->takeTopLevelItem(0);
827
if (jobsToStop > jobsStopped)
828
quitDialog->exec();
829
quitDialog->deleteLater();
833
TorrentView::TorrentView(QWidget *parent)
834
: QTreeWidget(parent)
836
setAcceptDrops(true);
839
void TorrentView::dragMoveEvent(QDragMoveEvent *event)
841
<span class="comment">// Accept file actions with a '.torrent' extension.</span>
842
QUrl url(event->mimeData()->text());
843
if (url.isValid() && url.scheme().toLower() == "file"
844
&& url.path().toLower().endsWith(".torrent"))
845
event->acceptProposedAction();
848
void TorrentView::dropEvent(QDropEvent *event)
850
<span class="comment">// Accept drops if the file has a '.torrent' extension and it</span>
851
<span class="comment">// exists.</span>
852
QString fileName = QUrl(event->mimeData()->text()).path();
853
if (QFile::exists(fileName) && fileName.toLower().endsWith(".torrent"))
854
emit fileDropped(fileName);
857
#include "mainwindow.moc"</pre>
859
<!-- @@@network/torrent/mainwindow.cpp -->
860
<div class="feedback t_button">
861
[+] Documentation Feedback</div>
871
<acronym title="Copyright">©</acronym> 2008-2010 Nokia Corporation and/or its
872
subsidiaries. Nokia, Qt and their respective logos are trademarks of Nokia Corporation
873
in Finland and/or other countries worldwide.</p>
875
All other trademarks are property of their respective owners. <a title="Privacy Policy"
876
href="http://qt.nokia.com/about/privacy-policy">Privacy Policy</a></p>
879
Licensees holding valid Qt Commercial licenses may use this document in accordance with the Qt Commercial License Agreement provided with the Software or, alternatively, in accordance with the terms contained in a written agreement between you and Nokia.</p>
881
Alternatively, this document may be used under the terms of the <a href="http://www.gnu.org/licenses/fdl.html">GNU
882
Free Documentation License version 1.3</a>
883
as published by the Free Software Foundation.</p>
885
<div id="feedbackBox">
886
<div id="feedcloseX" class="feedclose t_button">X</div>
887
<form id="feedform" action="http://doc.qt.nokia.com/docFeedbck/feedback.php" method="get">
888
<p id="noteHead">Thank you for giving your feedback.</p> <p class="note">Make sure it is related to this specific page. For more general bugs and
889
requests, please use the <a href="http://bugreports.qt.nokia.com/secure/Dashboard.jspa">Qt Bug Tracker</a>.</p>
890
<p><textarea id="feedbox" name="feedText" rows="5" cols="40"></textarea></p>
891
<p><input id="feedsubmit" class="feedclose" type="submit" name="feedback" /></p>