📄 mainwindow.cpp
字号:
connect(client, SIGNAL(peerInfoUpdated()), this, SLOT(updatePeerInfo()));
connect(client, SIGNAL(progressUpdated(int)), this, SLOT(updateProgress(int)));
connect(client, SIGNAL(downloadRateUpdated(int)), this, SLOT(updateDownloadRate(int)));
connect(client, SIGNAL(uploadRateUpdated(int)), this, SLOT(updateUploadRate(int)));
connect(client, SIGNAL(stopped()), this, SLOT(torrentStopped()));
connect(client, SIGNAL(error(TorrentClient::Error)), this, SLOT(torrentError(TorrentClient::Error)));
// Add the client to the list of downloading jobs.
Job job;
job.client = client;
job.torrentFileName = fileName;
job.destinationDirectory = destinationFolder;
jobs << job;
// Create and add a row in the torrent view for this download.
QTreeWidgetItem *item = new QTreeWidgetItem(torrentView);
QString baseFileName = QFileInfo(fileName).fileName();
if (baseFileName.toLower().endsWith(".torrent"))
baseFileName.remove(baseFileName.size() - 8);
item->setText(0, baseFileName);
item->setToolTip(0, tr("Torrent: %1<br>Destination: %2")
.arg(baseFileName).arg(destinationFolder));
item->setText(1, tr("0/0"));
item->setText(2, "0");
item->setText(3, "0.0 KB/s");
item->setText(4, "0.0 KB/s");
item->setText(5, tr("Idle"));
item->setFlags(item->flags() & ~Qt::ItemIsEditable);
item->setTextAlignment(1, Qt::AlignHCenter);
if (!saveChanges) {
saveChanges = true;
QTimer::singleShot(5000, this, SLOT(saveSettings()));
}
client->start();
return true;
}
void MainWindow::saveSettings()
{
if (!saveChanges)
return;
saveChanges = false;
// Prepare and reset the settings
QSettings settings("Trolltech", "Torrent");
settings.clear();
settings.setValue("LastDirectory", lastDirectory);
settings.setValue("UploadLimit", uploadLimitSlider->value());
settings.setValue("DownloadLimit", downloadLimitSlider->value());
// Store data on all known torrents
settings.beginWriteArray("Torrents");
for (int i = 0; i < jobs.size(); ++i) {
settings.setArrayIndex(i);
settings.setValue("sourceFileName", jobs.at(i).torrentFileName);
settings.setValue("destinationFolder", jobs.at(i).destinationDirectory);
settings.setValue("uploadedBytes", jobs.at(i).client->uploadedBytes());
settings.setValue("downloadedBytes", jobs.at(i).client->downloadedBytes());
settings.setValue("resumeState", jobs.at(i).client->dumpedState());
}
settings.endArray();
settings.sync();
}
void MainWindow::updateState(TorrentClient::State)
{
// Update the state string whenever the client's state changes.
TorrentClient *client = qobject_cast<TorrentClient *>(sender());
int row = rowOfClient(client);
QTreeWidgetItem *item = torrentView->topLevelItem(row);
if (item) {
item->setToolTip(0, tr("Torrent: %1<br>Destination: %2<br>State: %3")
.arg(jobs.at(row).torrentFileName)
.arg(jobs.at(row).destinationDirectory)
.arg(client->stateString()));
item->setText(5, client->stateString());
}
setActionsEnabled();
}
void MainWindow::updatePeerInfo()
{
// Update the number of connected, visited, seed and leecher peers.
TorrentClient *client = qobject_cast<TorrentClient *>(sender());
int row = rowOfClient(client);
QTreeWidgetItem *item = torrentView->topLevelItem(row);
item->setText(1, tr("%1/%2").arg(client->connectedPeerCount())
.arg(client->seedCount()));
}
void MainWindow::updateProgress(int percent)
{
TorrentClient *client = qobject_cast<TorrentClient *>(sender());
int row = rowOfClient(client);
// Update the progressbar.
QTreeWidgetItem *item = torrentView->topLevelItem(row);
if (item)
item->setText(2, QString::number(percent));
}
void MainWindow::setActionsEnabled()
{
// Find the view item and client for the current row, and update
// the states of the actions.
QTreeWidgetItem *item = 0;
if (!torrentView->selectedItems().isEmpty())
item = torrentView->selectedItems().first();
TorrentClient *client = item ? jobs.at(torrentView->indexOfTopLevelItem(item)).client : 0;
bool pauseEnabled = client && ((client->state() == TorrentClient::Paused)
|| (client->state() > TorrentClient::Preparing));
removeTorrentAction->setEnabled(item != 0);
pauseTorrentAction->setEnabled(item != 0 && pauseEnabled);
if (client && client->state() == TorrentClient::Paused) {
pauseTorrentAction->setIcon(QIcon(":/icons/player_play.png"));
pauseTorrentAction->setText(tr("Resume torrent"));
} else {
pauseTorrentAction->setIcon(QIcon(":/icons/player_pause.png"));
pauseTorrentAction->setText(tr("Pause torrent"));
}
int row = torrentView->indexOfTopLevelItem(item);
upActionTool->setEnabled(item && row != 0);
downActionTool->setEnabled(item && row != jobs.size() - 1);
}
void MainWindow::updateDownloadRate(int bytesPerSecond)
{
// Update the download rate.
TorrentClient *client = qobject_cast<TorrentClient *>(sender());
int row = rowOfClient(client);
QString num;
num.sprintf("%.1f KB/s", bytesPerSecond / 1024.0);
torrentView->topLevelItem(row)->setText(3, num);
if (!saveChanges) {
saveChanges = true;
QTimer::singleShot(5000, this, SLOT(saveSettings()));
}
}
void MainWindow::updateUploadRate(int bytesPerSecond)
{
// Update the upload rate.
TorrentClient *client = qobject_cast<TorrentClient *>(sender());
int row = rowOfClient(client);
QString num;
num.sprintf("%.1f KB/s", bytesPerSecond / 1024.0);
torrentView->topLevelItem(row)->setText(4, num);
if (!saveChanges) {
saveChanges = true;
QTimer::singleShot(5000, this, SLOT(saveSettings()));
}
}
void MainWindow::pauseTorrent()
{
// Pause or unpause the current torrent.
int row = torrentView->indexOfTopLevelItem(torrentView->currentItem());
TorrentClient *client = jobs.at(row).client;
client->setPaused(client->state() != TorrentClient::Paused);
setActionsEnabled();
}
void MainWindow::moveTorrentUp()
{
QTreeWidgetItem *item = torrentView->currentItem();
int row = torrentView->indexOfTopLevelItem(item);
if (row == 0)
return;
Job tmp = jobs.at(row - 1);
jobs[row - 1] = jobs[row];
jobs[row] = tmp;
QTreeWidgetItem *itemAbove = torrentView->takeTopLevelItem(row - 1);
torrentView->insertTopLevelItem(row, itemAbove);
setActionsEnabled();
}
void MainWindow::moveTorrentDown()
{
QTreeWidgetItem *item = torrentView->currentItem();
int row = torrentView->indexOfTopLevelItem(item);
if (row == jobs.size() - 1)
return;
Job tmp = jobs.at(row + 1);
jobs[row + 1] = jobs[row];
jobs[row] = tmp;
QTreeWidgetItem *itemAbove = torrentView->takeTopLevelItem(row + 1);
torrentView->insertTopLevelItem(row, itemAbove);
setActionsEnabled();
}
static int rateFromValue(int value)
{
int rate = 0;
if (value >= 0 && value < 250) {
rate = 1 + int(value * 0.124);
} else if (value < 500) {
rate = 32 + int((value - 250) * 0.384);
} else if (value < 750) {
rate = 128 + int((value - 500) * 1.536);
} else {
rate = 512 + int((value - 750) * 6.1445);
}
return rate;
}
void MainWindow::setUploadLimit(int value)
{
int rate = rateFromValue(value);
uploadLimitLabel->setText(tr("%1 KB/s").arg(QString().sprintf("%4d", rate)));
RateController::instance()->setUploadLimit(rate * 1024);
}
void MainWindow::setDownloadLimit(int value)
{
int rate = rateFromValue(value);
downloadLimitLabel->setText(tr("%1 KB/s").arg(QString().sprintf("%4d", rate)));
RateController::instance()->setDownloadLimit(rate * 1024);
}
void MainWindow::about()
{
QLabel *icon = new QLabel;
icon->setPixmap(QPixmap(":/icons/peertopeer.png"));
QLabel *text = new QLabel;
text->setWordWrap(true);
text->setText("<p>The <b>Torrent Client</b> example demonstrates how to"
" write a complete peer-to-peer file sharing"
" application using Qt's network and thread classes.</p>"
"<p>This feature complete client implementation of"
" the BitTorrent protocol can efficiently"
" maintain several hundred network connections"
" simultaneously.</p>");
QPushButton *quitButton = new QPushButton("OK");
QHBoxLayout *topLayout = new QHBoxLayout;
topLayout->setMargin(10);
topLayout->setSpacing(10);
topLayout->addWidget(icon);
topLayout->addWidget(text);
QHBoxLayout *bottomLayout = new QHBoxLayout;
bottomLayout->addStretch();
bottomLayout->addWidget(quitButton);
bottomLayout->addStretch();
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addLayout(topLayout);
mainLayout->addLayout(bottomLayout);
QDialog about(this);
about.setModal(true);
about.setWindowTitle(tr("About Torrent Client"));
about.setLayout(mainLayout);
connect(quitButton, SIGNAL(clicked()), &about, SLOT(close()));
about.exec();
}
void MainWindow::acceptFileDrop(const QString &fileName)
{
// Create and show the "Add Torrent" dialog.
AddTorrentDialog *addTorrentDialog = new AddTorrentDialog;
lastDirectory = QFileInfo(fileName).absolutePath();
addTorrentDialog->setTorrent(fileName);
addTorrentDialog->deleteLater();
if (!addTorrentDialog->exec())
return;
// Add the torrent to our list of downloads.
addTorrent(fileName, addTorrentDialog->destinationFolder());
saveSettings();
}
void MainWindow::closeEvent(QCloseEvent *)
{
if (jobs.isEmpty())
return;
// Save upload / download numbers.
saveSettings();
saveChanges = false;
quitDialog = new QProgressDialog(tr("Disconnecting from trackers"), tr("Abort"), 0, jobsToStop, this);
// Stop all clients, remove the rows from the view and wait for
// them to signal that they have stopped.
jobsToStop = 0;
jobsStopped = 0;
foreach (Job job, jobs) {
++jobsToStop;
TorrentClient *client = job.client;
client->disconnect();
connect(client, SIGNAL(stopped()), this, SLOT(torrentStopped()));
client->stop();
delete torrentView->takeTopLevelItem(0);
}
if (jobsToStop > jobsStopped)
quitDialog->exec();
quitDialog->deleteLater();
quitDialog = 0;
}
TorrentView::TorrentView(QWidget *parent)
: QTreeWidget(parent)
{
setAcceptDrops(true);
}
void TorrentView::dragMoveEvent(QDragMoveEvent *event)
{
// Accept file actions with a '.torrent' extension.
QUrl url(event->mimeData()->text());
if (url.isValid() && url.scheme().toLower() == "file"
&& url.path().toLower().endsWith(".torrent"))
event->acceptProposedAction();
}
void TorrentView::dropEvent(QDropEvent *event)
{
// Accept drops if the file has a '.torrent' extension and it
// exists.
QString fileName = QUrl(event->mimeData()->text()).path();
if (QFile::exists(fileName) && fileName.toLower().endsWith(".torrent"))
emit fileDropped(fileName);
}
#include "mainwindow.moc"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -