📄 mainwindow.cpp
字号:
/******************************************************************************** Copyright (C) 2004-2006 Trolltech ASA. All rights reserved.**** This file is part of the example classes of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file. Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://www.trolltech.com/products/qt/opensource.html**** If you are unsure which license is appropriate for your use, please** review the following information:** http://www.trolltech.com/products/qt/licensing.html or contact the** sales department at sales@trolltech.com.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include <QtGui>#include "addtorrentdialog.h"#include "mainwindow.h"#include "ratecontroller.h"#include "torrentclient.h"// TorrentView extends QTreeWidget to allow drag and drop.class TorrentView : public QTreeWidget{ Q_OBJECTpublic: TorrentView(QWidget *parent = 0);signals: void fileDropped(const QString &fileName);protected: void dragMoveEvent(QDragMoveEvent *event); void dropEvent(QDropEvent *event);};// TorrentViewDelegate is used to draw the progress bars.class TorrentViewDelegate : public QItemDelegate{ Q_OBJECTpublic: inline TorrentViewDelegate(MainWindow *mainWindow) : QItemDelegate(mainWindow) {} inline void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const { if (index.column() != 2) { QItemDelegate::paint(painter, option, index); return; } // Set up a QStyleOptionProgressBar to precisely mimic the // environment of a progress bar. QStyleOptionProgressBar progressBarOption; progressBarOption.state = QStyle::State_Enabled; progressBarOption.direction = QApplication::layoutDirection(); progressBarOption.rect = option.rect; progressBarOption.fontMetrics = QApplication::fontMetrics(); progressBarOption.minimum = 0; progressBarOption.maximum = 100; progressBarOption.textAlignment = Qt::AlignCenter; progressBarOption.textVisible = true; // Set the progress and text values of the style option. int progress = qobject_cast<MainWindow *>(parent())->clientForRow(index.row())->progress(); progressBarOption.progress = progress < 0 ? 0 : progress; progressBarOption.text = QString().sprintf("%d%%", progressBarOption.progress); // Draw the progress bar onto the view. QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, painter); }};MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), quitDialog(0), saveChanges(false){ // Initialize some static strings QStringList headers; headers << tr("Torrent") << tr("Peers/Seeds") << tr("Progress") << tr("Down rate") << tr("Up rate") << tr("Status"); // Main torrent list torrentView = new TorrentView(this); torrentView->setItemDelegate(new TorrentViewDelegate(this)); torrentView->setHeaderLabels(headers); torrentView->setSelectionBehavior(QAbstractItemView::SelectRows); torrentView->setAlternatingRowColors(true); torrentView->setRootIsDecorated(false); setCentralWidget(torrentView); // Set header resize modes and initial section sizes QFontMetrics fm = fontMetrics(); QHeaderView *header = torrentView->header(); header->resizeSection(0, fm.width("typical-name-for-a-torrent.torrent")); header->resizeSection(1, fm.width(headers.at(1) + " ")); header->resizeSection(2, fm.width(headers.at(2) + " ")); header->resizeSection(3, qMax(fm.width(headers.at(3) + " "), fm.width(" 1234.0 KB/s "))); header->resizeSection(4, qMax(fm.width(headers.at(4) + " "), fm.width(" 1234.0 KB/s "))); header->resizeSection(5, qMax(fm.width(headers.at(5) + " "), fm.width(tr("Downloading") + " "))); // Create common actions QAction *newTorrentAction = new QAction(QIcon(":/icons/bottom.png"), tr("Add &new torrent"), this); pauseTorrentAction = new QAction(QIcon(":/icons/player_pause.png"), tr("&Pause torrent"), this); removeTorrentAction = new QAction(QIcon(":/icons/player_stop.png"), tr("&Remove torrent"), this); // File menu QMenu *fileMenu = menuBar()->addMenu(tr("&File")); fileMenu->addAction(newTorrentAction); fileMenu->addAction(pauseTorrentAction); fileMenu->addAction(removeTorrentAction); fileMenu->addSeparator(); fileMenu->addAction(QIcon(":/icons/exit.png"), tr("E&xit"), this, SLOT(close())); // Help menu QMenu *helpMenu = menuBar()->addMenu(tr("&Help")); helpMenu->addAction(tr("&About"), this, SLOT(about())); helpMenu->addAction(tr("About &Qt"), qApp, SLOT(aboutQt())); // Top toolbar QToolBar *topBar = new QToolBar(tr("Tools")); addToolBar(Qt::TopToolBarArea, topBar); topBar->setMovable(false); topBar->addAction(newTorrentAction); topBar->addAction(removeTorrentAction); topBar->addAction(pauseTorrentAction); topBar->addSeparator(); downActionTool = topBar->addAction(QIcon(tr(":/icons/1downarrow.png")), tr("Move down")); upActionTool = topBar->addAction(QIcon(tr(":/icons/1uparrow.png")), tr("Move up")); // Bottom toolbar QToolBar *bottomBar = new QToolBar(tr("Rate control")); addToolBar(Qt::BottomToolBarArea, bottomBar); bottomBar->setMovable(false); downloadLimitSlider = new QSlider(Qt::Horizontal); downloadLimitSlider->setRange(0, 1000); bottomBar->addWidget(new QLabel(tr("Max download:"))); bottomBar->addWidget(downloadLimitSlider); bottomBar->addWidget((downloadLimitLabel = new QLabel(tr("0 KB/s")))); downloadLimitLabel->setFixedSize(QSize(fm.width(tr("99999 KB/s")), fm.lineSpacing())); bottomBar->addSeparator(); uploadLimitSlider = new QSlider(Qt::Horizontal); uploadLimitSlider->setRange(0, 1000); bottomBar->addWidget(new QLabel(tr("Max upload:"))); bottomBar->addWidget(uploadLimitSlider); bottomBar->addWidget((uploadLimitLabel = new QLabel(tr("0 KB/s")))); uploadLimitLabel->setFixedSize(QSize(fm.width(tr("99999 KB/s")), fm.lineSpacing())); // Set up connections connect(torrentView, SIGNAL(itemSelectionChanged()), this, SLOT(setActionsEnabled())); connect(torrentView, SIGNAL(fileDropped(const QString &)), this, SLOT(acceptFileDrop(const QString &))); connect(uploadLimitSlider, SIGNAL(valueChanged(int)), this, SLOT(setUploadLimit(int))); connect(downloadLimitSlider, SIGNAL(valueChanged(int)), this, SLOT(setDownloadLimit(int))); connect(newTorrentAction, SIGNAL(triggered()), this, SLOT(addTorrent())); connect(pauseTorrentAction, SIGNAL(triggered()), this, SLOT(pauseTorrent())); connect(removeTorrentAction, SIGNAL(triggered()), this, SLOT(removeTorrent())); connect(upActionTool, SIGNAL(triggered(bool)), this, SLOT(moveTorrentUp())); connect(downActionTool, SIGNAL(triggered(bool)), this, SLOT(moveTorrentDown())); // Load settings and start setWindowTitle(tr("Torrent Client")); setActionsEnabled(); QMetaObject::invokeMethod(this, "loadSettings", Qt::QueuedConnection);}QSize MainWindow::sizeHint() const{ const QHeaderView *header = torrentView->header(); // Add up the sizes of all header sections. The last section is // stretched, so its size is relative to the size of the width; // instead of counting it, we count the size of its largest value. int width = fontMetrics().width(tr("Downloading") + " "); for (int i = 0; i < header->count() - 1; ++i) width += header->sectionSize(i); return QSize(width, QMainWindow::sizeHint().height()) .expandedTo(QApplication::globalStrut());}const TorrentClient *MainWindow::clientForRow(int row) const{ // Return the client at the given row. return jobs.at(row).client;}int MainWindow::rowOfClient(TorrentClient *client) const{ // Return the row that displays this client's status, or -1 if the // client is not known. int row = 0; foreach (Job job, jobs) { if (job.client == client) return row; ++row; } return -1;}void MainWindow::loadSettings(){ // Load base settings (last working directory, upload/download limits). QSettings settings("Trolltech", "Torrent"); lastDirectory = settings.value("LastDirectory").toString(); if (lastDirectory.isEmpty()) lastDirectory = QDir::currentPath(); int up = settings.value("UploadLimit").toInt(); int down = settings.value("DownloadLimit").toInt(); uploadLimitSlider->setValue(up ? up : 170); downloadLimitSlider->setValue(down ? down : 550); // Resume all previous downloads. int size = settings.beginReadArray("Torrents"); for (int i = 0; i < size; ++i) { settings.setArrayIndex(i); QByteArray resumeState = settings.value("resumeState").toByteArray(); QString fileName = settings.value("sourceFileName").toString(); QString dest = settings.value("destinationFolder").toString(); if (addTorrent(fileName, dest, resumeState)) { TorrentClient *client = jobs.last().client; client->setDownloadedBytes(settings.value("downloadedBytes").toLongLong()); client->setUploadedBytes(settings.value("uploadedBytes").toLongLong()); } }}bool MainWindow::addTorrent(){ // Show the file dialog, let the user select what torrent to start downloading. QString fileName = QFileDialog::getOpenFileName(this, tr("Choose a torrent file"), lastDirectory, tr("Torrents (*.torrent);;" " All files (*.*)")); if (fileName.isEmpty()) return false; lastDirectory = QFileInfo(fileName).absolutePath(); // Show the "Add Torrent" dialog. AddTorrentDialog *addTorrentDialog = new AddTorrentDialog(this); addTorrentDialog->setTorrent(fileName); addTorrentDialog->deleteLater(); if (!addTorrentDialog->exec()) return false; // Add the torrent to our list of downloads addTorrent(fileName, addTorrentDialog->destinationFolder()); if (!saveChanges) { saveChanges = true; QTimer::singleShot(1000, this, SLOT(saveSettings())); } return true;}void MainWindow::removeTorrent(){ // Find the row of the current item, and find the torrent client // for that row. int row = torrentView->indexOfTopLevelItem(torrentView->currentItem()); TorrentClient *client = jobs.at(row).client; // Stop the client. client->disconnect(); connect(client, SIGNAL(stopped()), this, SLOT(torrentStopped())); client->stop(); // Remove the row from the view. delete torrentView->takeTopLevelItem(row); jobs.removeAt(row); setActionsEnabled(); saveChanges = true; saveSettings();}void MainWindow::torrentStopped(){ // Schedule the client for deletion. TorrentClient *client = qobject_cast<TorrentClient *>(sender()); client->deleteLater(); // If the quit dialog is shown, update its progress. if (quitDialog) { if (++jobsStopped == jobsToStop) quitDialog->close(); }}void MainWindow::torrentError(TorrentClient::Error){ // Delete the client. TorrentClient *client = qobject_cast<TorrentClient *>(sender()); int row = rowOfClient(client); QString fileName = jobs.at(row).torrentFileName; jobs.removeAt(row); // Display the warning. QMessageBox::warning(this, tr("Error"), tr("An error occurred while downloading %0: %1") .arg(fileName) .arg(client->errorString()), tr("&OK")); delete torrentView->takeTopLevelItem(row); client->deleteLater();}bool MainWindow::addTorrent(const QString &fileName, const QString &destinationFolder, const QByteArray &resumeState){ // Check if the torrent is already being downloaded. foreach (Job job, jobs) { if (job.torrentFileName == fileName && job.destinationDirectory == destinationFolder) { QMessageBox::warning(this, tr("Already downloading"), tr("The torrent file you have selected is " "already being downloaded.")); return false; } } // Create a new torrent client and attempt to parse the torrent data. TorrentClient *client = new TorrentClient(this); if (!client->setTorrent(fileName)) { QMessageBox::warning(this, tr("Error"), tr("The torrent file you have selected can not be opened."), tr("&OK")); delete client; return false; } client->setDestinationFolder(destinationFolder); client->setDumpedState(resumeState);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -