Browse Source

- Merged splitGUI branch, GUI and download tab are now splitted. Code is a lot cleaner and easier to understand. I also fixed some bugs I found on the way :)

adaptive-webui-19844
Christophe Dumez 18 years ago
parent
commit
32c330092a
  1. 2
      TODO
  2. 95
      src/FinishedTorrents.cpp
  3. 32
      src/FinishedTorrents.h
  4. 1324
      src/GUI.cpp
  5. 55
      src/GUI.h
  6. 330
      src/MainWindow.ui
  7. 4
      src/about_imp.h
  8. 24
      src/bittorrent.cpp
  9. 2
      src/bittorrent.h
  10. 386
      src/download.ui
  11. 697
      src/downloadingTorrents.cpp
  12. 97
      src/downloadingTorrents.h
  13. 8
      src/src.pro

2
TODO

@ -76,4 +76,6 @@ LANGUAGES UPDATED:
- Korean *BETA5* - Korean *BETA5*
beta5->beta6 changelog: beta5->beta6 changelog:
- FEATURE: Split GUI class from download tab
- BUGFIX: Made torrent deletion from hard-drive safer - BUGFIX: Made torrent deletion from hard-drive safer
- BUGFIX: Fixed a bug when switching from finished to downloading list

95
src/FinishedTorrents.cpp

@ -20,21 +20,24 @@
*/ */
#include "FinishedTorrents.h" #include "FinishedTorrents.h"
#include "misc.h" #include "misc.h"
#include "GUI.h"
#include "properties_imp.h" #include "properties_imp.h"
#include "bittorrent.h" #include "bittorrent.h"
#include "allocationDlg.h" #include "allocationDlg.h"
#include "FinishedListDelegate.h"
#include "GUI.h"
#include <QFile> #include <QFile>
#include <QSettings> #include <QSettings>
#include <QStandardItemModel> #include <QStandardItemModel>
#include <QHeaderView> #include <QHeaderView>
#include <QMenu>
FinishedTorrents::FinishedTorrents(QObject *parent, bittorrent *BTSession){ FinishedTorrents::FinishedTorrents(QObject *parent, bittorrent *BTSession){
setupUi(this); setupUi(this);
nbFinished = 0; nbFinished = 0;
this->parent = parent;
this->BTSession = BTSession; this->BTSession = BTSession;
this->parent = parent;
connect(BTSession, SIGNAL(addedTorrent(QString, QTorrentHandle&, bool)), this, SLOT(torrentAdded(QString, QTorrentHandle&, bool)));
finishedListModel = new QStandardItemModel(0,7); finishedListModel = new QStandardItemModel(0,7);
finishedListModel->setHeaderData(F_NAME, Qt::Horizontal, tr("Name", "i.e: file name")); finishedListModel->setHeaderData(F_NAME, Qt::Horizontal, tr("Name", "i.e: file name"));
finishedListModel->setHeaderData(F_SIZE, Qt::Horizontal, tr("Size", "i.e: file size")); finishedListModel->setHeaderData(F_SIZE, Qt::Horizontal, tr("Size", "i.e: file size"));
@ -56,7 +59,7 @@ FinishedTorrents::FinishedTorrents(QObject *parent, bittorrent *BTSession){
finishedListDelegate = new FinishedListDelegate(finishedList); finishedListDelegate = new FinishedListDelegate(finishedList);
finishedList->setItemDelegate(finishedListDelegate); finishedList->setItemDelegate(finishedListDelegate);
connect(finishedList, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayFinishedListMenu(const QPoint&))); connect(finishedList, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayFinishedListMenu(const QPoint&)));
connect(finishedList, SIGNAL(doubleClicked(const QModelIndex&)), parent, SLOT(togglePausedState(const QModelIndex&))); connect(finishedList, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(notifyTorrentDoubleClicked(const QModelIndex&)));
actionDelete->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/delete.png"))); actionDelete->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/delete.png")));
actionPreview_file->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/preview.png"))); actionPreview_file->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/preview.png")));
actionDelete_Permanently->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/delete_perm.png"))); actionDelete_Permanently->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/delete_perm.png")));
@ -74,7 +77,16 @@ FinishedTorrents::~FinishedTorrents(){
delete finishedListModel; delete finishedListModel;
} }
void FinishedTorrents::addFinishedTorrent(QString hash){ void FinishedTorrents::notifyTorrentDoubleClicked(const QModelIndex& index) {
unsigned int row = index.row();
QString hash = getHashFromRow(row);
emit torrentDoubleClicked(hash);
}
void FinishedTorrents::addTorrent(QString hash){
if(!BTSession->isFinished(hash)){
BTSession->setFinishedTorrent(hash);
}
int row = getRowFromHash(hash); int row = getRowFromHash(hash);
if(row != -1) return; if(row != -1) return;
row = finishedListModel->rowCount(); row = finishedListModel->rowCount();
@ -101,7 +113,14 @@ void FinishedTorrents::addFinishedTorrent(QString hash){
finished_file.close(); finished_file.close();
// Update the number of finished torrents // Update the number of finished torrents
++nbFinished; ++nbFinished;
((GUI*)parent)->setTabText(1, tr("Finished") +" ("+QString::fromUtf8(misc::toString(nbFinished).c_str())+")"); emit finishedTorrentsNumberChanged(nbFinished);
}
void FinishedTorrents::torrentAdded(QString, QTorrentHandle& h, bool) {
QString hash = h.hash();
if(BTSession->isFinished(hash)) {
addTorrent(hash);
}
} }
// Set the color of a row in data model // Set the color of a row in data model
@ -111,6 +130,25 @@ void FinishedTorrents::setRowColor(int row, QString color){
} }
} }
QStringList FinishedTorrents::getSelectedTorrents(bool only_one) const{
QStringList res;
QModelIndex index;
QModelIndexList selectedIndexes = finishedList->selectionModel()->selectedIndexes();
foreach(index, selectedIndexes) {
if(index.column() == F_NAME) {
// Get the file hash
QString hash = finishedListModel->data(finishedListModel->index(index.row(), F_HASH)).toString();
res << hash;
if(only_one) break;
}
}
return res;
}
unsigned int FinishedTorrents::getNbTorrentsInList() const {
return nbFinished;
}
// Load columns width in a file that were saved previously // Load columns width in a file that were saved previously
// (finished list) // (finished list)
bool FinishedTorrents::loadColWidthFinishedList(){ bool FinishedTorrents::loadColWidthFinishedList(){
@ -158,7 +196,6 @@ void FinishedTorrents::on_actionSet_upload_limit_triggered(){
} }
void FinishedTorrents::updateFinishedList(){ void FinishedTorrents::updateFinishedList(){
Q_ASSERT(((GUI*)parent)->getCurrentTabIndex() == 1);
QString hash; QString hash;
QStringList finishedSHAs = BTSession->getFinishedTorrents(); QStringList finishedSHAs = BTSession->getFinishedTorrents();
foreach(hash, finishedSHAs){ foreach(hash, finishedSHAs){
@ -170,17 +207,18 @@ void FinishedTorrents::updateFinishedList(){
int row = getRowFromHash(hash); int row = getRowFromHash(hash);
if(row == -1){ if(row == -1){
qDebug("Cannot find torrent in finished list, adding it"); qDebug("Cannot find torrent in finished list, adding it");
addFinishedTorrent(hash); addTorrent(hash);
continue; row = getRowFromHash(hash);
} }
Q_ASSERT(row != -1);
if(h.is_paused()) continue; if(h.is_paused()) continue;
Q_ASSERT(h.progress() <= 1. && h.progress() >= 0.); Q_ASSERT(h.progress() <= 1. && h.progress() >= 0.);
if(h.state() == torrent_status::downloading || (h.state() != torrent_status::checking_files && h.state() != torrent_status::queued_for_checking && h.progress() < 1.)) { if(h.state() == torrent_status::downloading || (h.state() != torrent_status::checking_files && h.state() != torrent_status::queued_for_checking && h.progress() < 1.)) {
// What are you doing here? go back to download tab! // What are you doing here? go back to download tab!
qDebug("Info: a torrent was moved from finished to download tab"); qDebug("Info: a torrent was moved from finished to download tab");
deleteFromFinishedList(hash, true); deleteTorrent(hash);
BTSession->setFinishedTorrent(hash); BTSession->setFinishedTorrent(hash);
emit torrentMovedFromFinishedList(h); emit torrentMovedFromFinishedList(hash);
continue; continue;
} }
finishedListModel->setData(finishedListModel->index(row, F_UPSPEED), QVariant((double)h.upload_payload_rate())); finishedListModel->setData(finishedListModel->index(row, F_UPSPEED), QVariant((double)h.upload_payload_rate()));
@ -199,24 +237,36 @@ int FinishedTorrents::getRowFromHash(QString hash) const{
return -1; return -1;
} }
// Will move it to download tab // Note: does not actually pause the torrent in BT Session
void FinishedTorrents::deleteFromFinishedList(QString hash, bool switchTab){ void FinishedTorrents::pauseTorrent(QString hash) {
int row = getRowFromHash(hash); int row = getRowFromHash(hash);
Q_ASSERT(row != -1); Q_ASSERT(row != -1);
finishedListModel->removeRow(row); finishedListModel->setData(finishedListModel->index(row, F_UPSPEED), QVariant((double)0.0));
QFile::remove(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+hash+".finished"); finishedListModel->setData(finishedListModel->index(row, F_NAME), QIcon(QString::fromUtf8(":/Icons/skin/paused.png")), Qt::DecorationRole);
--nbFinished; finishedListModel->setData(finishedListModel->index(row, F_SEEDSLEECH), QVariant(QString::fromUtf8("0/0")));
((GUI*)parent)->setTabText(1, tr("Finished") +" ("+QString::fromUtf8(misc::toString(nbFinished).c_str())+")"); setRowColor(row, QString::fromUtf8("red"));
if(switchTab)
BTSession->setUnfinishedTorrent(hash);
} }
QTreeView* FinishedTorrents::getFinishedList(){ void FinishedTorrents::resumeTorrent(QString hash) {
return finishedList; int row = getRowFromHash(hash);
Q_ASSERT(row != -1);
finishedListModel->setData(finishedListModel->index(row, F_NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/seeding.png"))), Qt::DecorationRole);
setRowColor(row, QString::fromUtf8("orange"));
} }
QStandardItemModel* FinishedTorrents::getFinishedListModel(){ QString FinishedTorrents::getHashFromRow(unsigned int row) const {
return finishedListModel; Q_ASSERT(row < (unsigned int)finishedListModel->rowCount());
return finishedListModel->data(finishedListModel->index(row, F_HASH)).toString();
}
// Will move it to download tab
void FinishedTorrents::deleteTorrent(QString hash){
int row = getRowFromHash(hash);
Q_ASSERT(row != -1);
finishedListModel->removeRow(row);
QFile::remove(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+hash+".finished");
--nbFinished;
emit finishedTorrentsNumberChanged(nbFinished);
} }
// Show torrent properties dialog // Show torrent properties dialog
@ -225,7 +275,6 @@ void FinishedTorrents::showProperties(const QModelIndex &index){
QString hash = finishedListModel->data(finishedListModel->index(row, F_HASH)).toString(); QString hash = finishedListModel->data(finishedListModel->index(row, F_HASH)).toString();
QTorrentHandle h = BTSession->getTorrentHandle(hash); QTorrentHandle h = BTSession->getTorrentHandle(hash);
properties *prop = new properties(this, BTSession, h); properties *prop = new properties(this, BTSession, h);
connect(prop, SIGNAL(mustHaveFullAllocationMode(QTorrentHandle)), BTSession, SLOT(reloadTorrent(QTorrentHandle)));
connect(prop, SIGNAL(filteredFilesChanged(QString)), this, SLOT(updateFileSize(QString))); connect(prop, SIGNAL(filteredFilesChanged(QString)), this, SLOT(updateFileSize(QString)));
prop->show(); prop->show();
} }

32
src/FinishedTorrents.h

@ -23,7 +23,6 @@
#define SEEDING_H #define SEEDING_H
#include "ui_seeding.h" #include "ui_seeding.h"
#include "FinishedListDelegate.h"
#include "qtorrenthandle.h" #include "qtorrenthandle.h"
class QStandardItemModel; class QStandardItemModel;
@ -32,30 +31,27 @@ class FinishedListDelegate;
using namespace libtorrent; using namespace libtorrent;
class FinishedTorrents : public QWidget, public Ui::seeding{ class FinishedTorrents : public QWidget, public Ui::seeding {
Q_OBJECT Q_OBJECT
private: private:
QObject *parent;
bittorrent *BTSession; bittorrent *BTSession;
FinishedListDelegate *finishedListDelegate; FinishedListDelegate *finishedListDelegate;
QStandardItemModel *finishedListModel; QStandardItemModel *finishedListModel;
unsigned int nbFinished; unsigned int nbFinished;
QObject *parent;
public: public:
FinishedTorrents(QObject *parent, bittorrent *BTSession); FinishedTorrents(QObject *parent, bittorrent *BTSession);
~FinishedTorrents(); ~FinishedTorrents();
// Methods // Methods
QTreeView* getFinishedList();
QStandardItemModel* getFinishedListModel();
bool loadColWidthFinishedList(); bool loadColWidthFinishedList();
int getRowFromHash(QString hash) const; int getRowFromHash(QString hash) const;
QStringList getSelectedTorrents(bool only_one=false) const;
unsigned int getNbTorrentsInList() const;
QString getHashFromRow(unsigned int row) const;
public slots: protected slots:
void addFinishedTorrent(QString hash);
void updateFinishedList();
void deleteFromFinishedList(QString hash, bool switchTab=false);
void showProperties(const QModelIndex &index); void showProperties(const QModelIndex &index);
void propertiesSelection();
void displayFinishedListMenu(const QPoint&); void displayFinishedListMenu(const QPoint&);
void setRowColor(int row, QString color); void setRowColor(int row, QString color);
void saveColWidthFinishedList() const; void saveColWidthFinishedList() const;
@ -63,12 +59,22 @@ class FinishedTorrents : public QWidget, public Ui::seeding{
void sortFinishedListFloat(int index, Qt::SortOrder sortOrder); void sortFinishedListFloat(int index, Qt::SortOrder sortOrder);
void sortFinishedListString(int index, Qt::SortOrder sortOrder); void sortFinishedListString(int index, Qt::SortOrder sortOrder);
void updateFileSize(QString hash); void updateFileSize(QString hash);
void torrentAdded(QString path, QTorrentHandle& h, bool fastResume);
protected slots:
void on_actionSet_upload_limit_triggered(); void on_actionSet_upload_limit_triggered();
void notifyTorrentDoubleClicked(const QModelIndex& index);
public slots:
void addTorrent(QString hash);
void updateFinishedList();
void pauseTorrent(QString hash);
void resumeTorrent(QString hash);
void propertiesSelection();
void deleteTorrent(QString hash);
signals: signals:
void torrentMovedFromFinishedList(QTorrentHandle); void torrentMovedFromFinishedList(QString);
void torrentDoubleClicked(QString hash);
void finishedTorrentsNumberChanged(unsigned int);
}; };

1324
src/GUI.cpp

File diff suppressed because it is too large Load Diff

55
src/GUI.h

@ -31,6 +31,7 @@
class bittorrent; class bittorrent;
class createtorrent; class createtorrent;
class QTimer; class QTimer;
class DownloadingTorrents;
class FinishedTorrents; class FinishedTorrents;
class DLListDelegate; class DLListDelegate;
class downloadThread; class downloadThread;
@ -45,6 +46,9 @@ class about;
class previewSelect; class previewSelect;
class options_imp; class options_imp;
class QStandardItemModel; class QStandardItemModel;
class QTabWidget;
class QLabel;
class QModelIndex;
class GUI : public QMainWindow, private Ui::MainWindow{ class GUI : public QMainWindow, private Ui::MainWindow{
Q_OBJECT Q_OBJECT
@ -54,23 +58,17 @@ class GUI : public QMainWindow, private Ui::MainWindow{
bittorrent *BTSession; bittorrent *BTSession;
QTimer *checkConnect; QTimer *checkConnect;
QList<QPair<QTorrentHandle,QString> > unauthenticated_trackers; QList<QPair<QTorrentHandle,QString> > unauthenticated_trackers;
downloadFromURL *downloadFromURLDialog;
// GUI related // GUI related
QTabWidget *tabs;
options_imp *options; options_imp *options;
createtorrent *createWindow;
QTimer *refresher;
QSystemTrayIcon *myTrayIcon; QSystemTrayIcon *myTrayIcon;
QMenu *myTrayIconMenu; QMenu *myTrayIconMenu;
about *aboutdlg; DownloadingTorrents *downloadingTorrentTab;
QStandardItemModel *DLListModel;
DLListDelegate *DLDelegate;
FinishedTorrents *finishedTorrentTab; FinishedTorrents *finishedTorrentTab;
unsigned int nbTorrents;
QLabel *connecStatusLblIcon; QLabel *connecStatusLblIcon;
bool systrayIntegration; bool systrayIntegration;
bool force_exit; bool force_exit;
bool delayedSorting; QTimer *refresher;
Qt::SortOrder delayedSortingOrder;
// Keyboard shortcuts // Keyboard shortcuts
QShortcut *switchSearchShortcut; QShortcut *switchSearchShortcut;
QShortcut *switchSearchShortcut2; QShortcut *switchSearchShortcut2;
@ -78,7 +76,6 @@ class GUI : public QMainWindow, private Ui::MainWindow{
QShortcut *switchUpShortcut; QShortcut *switchUpShortcut;
QShortcut *switchRSSShortcut; QShortcut *switchRSSShortcut;
// Preview // Preview
previewSelect *previewSelection;
QProcess *previewProcess; QProcess *previewProcess;
// Search // Search
SearchEngine *searchEngine; SearchEngine *searchEngine;
@ -94,22 +91,12 @@ class GUI : public QMainWindow, private Ui::MainWindow{
void dragEnterEvent(QDragEnterEvent *event); void dragEnterEvent(QDragEnterEvent *event);
void toggleVisibility(QSystemTrayIcon::ActivationReason e); void toggleVisibility(QSystemTrayIcon::ActivationReason e);
void on_actionAbout_triggered(); void on_actionAbout_triggered();
void setInfoBar(QString info, QString color="black");
void updateDlList(bool force=false);
void on_actionCreate_torrent_triggered(); void on_actionCreate_torrent_triggered();
void on_actionClearLog_triggered();
void on_actionWebsite_triggered(); void on_actionWebsite_triggered();
void on_actionBugReport_triggered(); void on_actionBugReport_triggered();
void readParamsOnSocket(); void readParamsOnSocket();
void acceptConnection(); void acceptConnection();
void saveColWidthDLList() const; void togglePausedState(QString hash);
bool loadColWidthDLList();
void sortDownloadList(int index, Qt::SortOrder startSortOrder=Qt::AscendingOrder, bool fromLoadColWidth=false);
void sortDownloadListFloat(int index, Qt::SortOrder sortOrder);
void sortDownloadListString(int index, Qt::SortOrder sortOrder);
void displayDLListMenu(const QPoint& pos);
void togglePausedState(const QModelIndex& index);
void displayInfoBarMenu(const QPoint& pos);
void on_actionPreview_file_triggered(); void on_actionPreview_file_triggered();
void previewFile(QString filePath); void previewFile(QString filePath);
void cleanTempPreviewFile(int, QProcess::ExitStatus); void cleanTempPreviewFile(int, QProcess::ExitStatus);
@ -118,28 +105,25 @@ class GUI : public QMainWindow, private Ui::MainWindow{
void readSettings(); void readSettings();
void on_actionExit_triggered(); void on_actionExit_triggered();
void createTrayIcon(); void createTrayIcon();
void addLogPeerBlocked(QString); void updateUnfinishedTorrentNumber(unsigned int nb);
void addFastResumeRejectedAlert(QString); void updateFinishedTorrentNumber(unsigned int nb);
void fullDiskError(QTorrentHandle& h);
void handleDownloadFromUrlFailure(QString, QString) const;
// Keyboard shortcuts // Keyboard shortcuts
void createKeyboardShortcuts(); void createKeyboardShortcuts();
void displayDownTab(); void displayDownTab();
void displayUpTab(); void displayUpTab();
void displaySearchTab(); void displaySearchTab();
void displayRSSTab(); void displayRSSTab();
void handleDownloadFromUrlFailure(QString, QString) const;
// Torrent actions // Torrent actions
void showProperties(const QModelIndex &index);
void on_actionTorrent_Properties_triggered(); void on_actionTorrent_Properties_triggered();
void on_actionPause_triggered(); void on_actionPause_triggered();
void on_actionPause_All_triggered(); void on_actionPause_All_triggered();
void restoreInDownloadList(QTorrentHandle h);
void on_actionStart_triggered(); void on_actionStart_triggered();
void on_actionStart_All_triggered(); void on_actionStart_All_triggered();
void on_actionOpen_triggered(); void on_actionOpen_triggered();
void on_actionDelete_Permanently_triggered(); void on_actionDelete_Permanently_triggered();
void on_actionDelete_triggered(); void on_actionDelete_triggered();
void on_actionSet_download_limit_triggered();
void on_actionSet_upload_limit_triggered();
void on_actionSet_global_upload_limit_triggered(); void on_actionSet_global_upload_limit_triggered();
void on_actionSet_global_download_limit_triggered(); void on_actionSet_global_download_limit_triggered();
void on_actionDocumentation_triggered(); void on_actionDocumentation_triggered();
@ -150,10 +134,9 @@ class GUI : public QMainWindow, private Ui::MainWindow{
void processScannedFiles(const QStringList& params); void processScannedFiles(const QStringList& params);
void processDownloadedFiles(QString path, QString url); void processDownloadedFiles(QString path, QString url);
void downloadFromURLList(const QStringList& urls); void downloadFromURLList(const QStringList& urls);
void displayDownloadingUrlInfos(QString url); void finishedTorrent(QTorrentHandle& h);
void torrentChecked(QString hash); void torrentChecked(QString hash);
// Utils slots void updateLists();
void setRowColor(int row, QString color);
// Options slots // Options slots
void on_actionOptions_triggered(); void on_actionOptions_triggered();
void OptionsSaved(QString info, bool deleteOptions); void OptionsSaved(QString info, bool deleteOptions);
@ -162,17 +145,8 @@ class GUI : public QMainWindow, private Ui::MainWindow{
public slots: public slots:
void torrentAdded(QString path, QTorrentHandle& h, bool fastResume);
void torrentDuplicate(QString path);
void torrentCorrupted(QString path);
void finishedTorrent(QTorrentHandle& h);
void fullDiskError(QTorrentHandle& h);
void portListeningFailure();
void trackerAuthenticationRequired(QTorrentHandle& h); void trackerAuthenticationRequired(QTorrentHandle& h);
void setTabText(int index, QString text); void setTabText(int index, QString text);
void updateFileSizeAndProgress(QString hash);
void sortProgressColumnDelayed();
void addUrlSeedError(QString url, QString msg);
protected: protected:
void closeEvent(QCloseEvent *); void closeEvent(QCloseEvent *);
@ -183,7 +157,6 @@ class GUI : public QMainWindow, private Ui::MainWindow{
GUI(QWidget *parent=0, QStringList torrentCmdLine=QStringList()); GUI(QWidget *parent=0, QStringList torrentCmdLine=QStringList());
~GUI(); ~GUI();
// Methods // Methods
int getRowFromHash(QString hash) const;
unsigned int getCurrentTabIndex() const; unsigned int getCurrentTabIndex() const;
QPoint screenCenter() const; QPoint screenCenter() const;
}; };

330
src/MainWindow.ui

@ -17,322 +17,21 @@
</property> </property>
<widget class="QWidget" name="centralwidget" > <widget class="QWidget" name="centralwidget" >
<layout class="QVBoxLayout" > <layout class="QVBoxLayout" >
<property name="margin" >
<number>9</number>
</property>
<property name="spacing" > <property name="spacing" >
<number>6</number> <number>6</number>
</property> </property>
<item> <property name="leftMargin" >
<widget class="QTabWidget" name="tabs" > <number>9</number>
<property name="tabPosition" > </property>
<enum>QTabWidget::North</enum> <property name="topMargin" >
</property> <number>9</number>
<property name="currentIndex" > </property>
<number>0</number> <property name="rightMargin" >
</property> <number>9</number>
<widget class="QWidget" name="tab" > </property>
<attribute name="title" > <property name="bottomMargin" >
<string>Downloads</string> <number>9</number>
</attribute> </property>
<layout class="QVBoxLayout" >
<property name="margin" >
<number>9</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<layout class="QVBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<layout class="QHBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="lbl_DLSpeed" >
<property name="text" >
<string>Total DL Speed:</string>
</property>
<property name="alignment" >
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
</property>
</widget>
</item>
<item>
<widget class="QLCDNumber" name="LCD_DownSpeed" >
<property name="autoFillBackground" >
<bool>true</bool>
</property>
<property name="frameShadow" >
<enum>QFrame::Raised</enum>
</property>
<property name="smallDecimalPoint" >
<bool>false</bool>
</property>
<property name="numDigits" >
<number>6</number>
</property>
<property name="segmentStyle" >
<enum>QLCDNumber::Flat</enum>
</property>
<property name="value" stdset="0" >
<double>0.000000000000000</double>
</property>
<property name="intValue" stdset="0" >
<number>0</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="unitDL" >
<property name="text" >
<string>KiB/s</string>
</property>
<property name="alignment" >
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label" >
<property name="text" >
<string>Session ratio: </string>
</property>
<property name="alignment" >
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
</property>
</widget>
</item>
<item>
<widget class="QLCDNumber" name="LCD_Ratio" >
<property name="autoFillBackground" >
<bool>true</bool>
</property>
<property name="numDigits" >
<number>4</number>
</property>
<property name="segmentStyle" >
<enum>QLCDNumber::Flat</enum>
</property>
<property name="value" stdset="0" >
<double>1.000000000000000</double>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lbl_ratio_icon" >
<property name="text" >
<string/>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="lbl_UPSpeed" >
<property name="text" >
<string>Total UP Speed:</string>
</property>
<property name="alignment" >
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
</property>
</widget>
</item>
<item>
<widget class="QLCDNumber" name="LCD_UpSpeed" >
<property name="autoFillBackground" >
<bool>true</bool>
</property>
<property name="smallDecimalPoint" >
<bool>false</bool>
</property>
<property name="numDigits" >
<number>6</number>
</property>
<property name="segmentStyle" >
<enum>QLCDNumber::Flat</enum>
</property>
<property name="value" stdset="0" >
<double>0.000000000000000</double>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="unitUP" >
<property name="text" >
<string>KiB/s</string>
</property>
<property name="alignment" >
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QTreeView" name="downloadList" >
<property name="minimumSize" >
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="contextMenuPolicy" >
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="autoScroll" >
<bool>true</bool>
</property>
<property name="selectionMode" >
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
<property name="indentation" >
<number>1</number>
</property>
<property name="itemsExpandable" >
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QTabWidget" name="tabBottom" >
<property name="maximumSize" >
<size>
<width>16777215</width>
<height>142</height>
</size>
</property>
<property name="tabPosition" >
<enum>QTabWidget::West</enum>
</property>
<property name="currentIndex" >
<number>1</number>
</property>
<widget class="QWidget" name="log_tab" >
<attribute name="title" >
<string>Log</string>
</attribute>
<layout class="QVBoxLayout" >
<property name="margin" >
<number>9</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<widget class="QTextBrowser" name="infoBar" >
<property name="sizePolicy" >
<sizepolicy>
<hsizetype>7</hsizetype>
<vsizetype>7</vsizetype>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize" >
<size>
<width>16777215</width>
<height>120</height>
</size>
</property>
<property name="contextMenuPolicy" >
<enum>Qt::CustomContextMenu</enum>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="filter_tab" >
<attribute name="title" >
<string>IP filter</string>
</attribute>
<layout class="QVBoxLayout" >
<property name="margin" >
<number>9</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<widget class="QTextBrowser" name="textBlockedUsers" >
<property name="maximumSize" >
<size>
<width>16777215</width>
<height>123</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<widget class="QMenuBar" name="menubar" > <widget class="QMenuBar" name="menubar" >
@ -408,7 +107,10 @@
</size> </size>
</property> </property>
<attribute name="toolBarArea" > <attribute name="toolBarArea" >
<number>4</number> <enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak" >
<bool>false</bool>
</attribute> </attribute>
<addaction name="actionOpen" /> <addaction name="actionOpen" />
<addaction name="actionDownload_from_URL" /> <addaction name="actionDownload_from_URL" />

4
src/about_imp.h

@ -29,6 +29,10 @@ class about : public QDialog, private Ui::AboutDlg{
Q_OBJECT Q_OBJECT
public: public:
~about() {
qDebug("Deleting about dlg");
}
about(QWidget *parent): QDialog(parent){ about(QWidget *parent): QDialog(parent){
setupUi(this); setupUi(this);
setAttribute(Qt::WA_DeleteOnClose); setAttribute(Qt::WA_DeleteOnClose);

24
src/bittorrent.cpp

@ -26,12 +26,12 @@
#include <libtorrent/extensions/metadata_transfer.hpp> #include <libtorrent/extensions/metadata_transfer.hpp>
#include <libtorrent/extensions/ut_pex.hpp> #include <libtorrent/extensions/ut_pex.hpp>
#include <libtorrent/entry.hpp> #include <libtorrent/entry.hpp>
#include <libtorrent/bencode.hpp> #include <libtorrent/bencode.hpp>
#include <libtorrent/identify_client.hpp> #include <libtorrent/identify_client.hpp>
#include <libtorrent/alert_types.hpp> #include <libtorrent/alert_types.hpp>
#include <libtorrent/ip_filter.hpp> #include <libtorrent/ip_filter.hpp>
#include <libtorrent/torrent_info.hpp>
#include <boost/filesystem/exception.hpp> #include <boost/filesystem/exception.hpp>
#include "bittorrent.h" #include "bittorrent.h"
@ -70,9 +70,10 @@ bittorrent::bittorrent() {
// To download from urls // To download from urls
downloader = new downloadThread(this); downloader = new downloadThread(this);
connect(downloader, SIGNAL(downloadFinished(QString, QString)), this, SLOT(processDownloadedFile(QString, QString))); connect(downloader, SIGNAL(downloadFinished(QString, QString)), this, SLOT(processDownloadedFile(QString, QString)));
connect(downloader, SIGNAL(downloadFailure(QString, QString)), this, SLOT(HandleDownloadFailure(QString, QString))); connect(downloader, SIGNAL(downloadFailure(QString, QString)), this, SLOT(handleDownloadFailure(QString, QString)));
// File deleter (thread) // File deleter (thread)
deleter = new deleteThread(this); deleter = new deleteThread(this);
qDebug("* BTSession constructed");
} }
// Main destructor // Main destructor
@ -106,7 +107,7 @@ void bittorrent::setUploadLimit(QString hash, long val) {
saveTorrentSpeedLimits(hash); saveTorrentSpeedLimits(hash);
} }
void bittorrent::HandleDownloadFailure(QString url, QString reason) { void bittorrent::handleDownloadFailure(QString url, QString reason) {
emit downloadFromUrlFailure(url, reason); emit downloadFromUrlFailure(url, reason);
} }
@ -366,10 +367,27 @@ void bittorrent::addTorrent(QString path, bool fromScanDir, QString from_url) {
entry e = bdecode(std::istream_iterator<char>(in), std::istream_iterator<char>()); entry e = bdecode(std::istream_iterator<char>(in), std::istream_iterator<char>());
// Getting torrent file informations // Getting torrent file informations
torrent_info t(e); torrent_info t(e);
std::cout << t.info_hash() << "\n";
QString hash = QString::fromUtf8(misc::toString(t.info_hash()).c_str()); QString hash = QString::fromUtf8(misc::toString(t.info_hash()).c_str());
if(s->find_torrent(t.info_hash()).is_valid()) { if(s->find_torrent(t.info_hash()).is_valid()) {
// Update info Bar // Update info Bar
if(!fromScanDir) { if(!fromScanDir) {
if(file.startsWith(torrentBackup.path())){
// Torrent hash has changed. This should not be possible but...
// XXX: Why does this happen sometimes?
QFileInfo fi(file);
QString old_hash = fi.baseName();
qDebug("Strange, hash changed to %s", old_hash.toUtf8().data());
QStringList filters;
filters << old_hash+".*";
QStringList files = torrentBackup.entryList(filters, QDir::Files, QDir::Unsorted);
QString my_f;
foreach(my_f, files) {
qDebug("* deleting %s", my_f.toUtf8().data());
torrentBackup.remove(my_f);
}
return;
}
if(!from_url.isNull()) { if(!from_url.isNull()) {
// If download from url, remove temp file // If download from url, remove temp file
QFile::remove(file); QFile::remove(file);

2
src/bittorrent.h

@ -111,7 +111,7 @@ class bittorrent : public QObject{
void loadTorrentSpeedLimits(QString hash); void loadTorrentSpeedLimits(QString hash);
void saveDownloadUploadForTorrent(QString hash); void saveDownloadUploadForTorrent(QString hash);
void loadDownloadUploadForTorrent(QString hash); void loadDownloadUploadForTorrent(QString hash);
void HandleDownloadFailure(QString url, QString reason); void handleDownloadFailure(QString url, QString reason);
void loadWebSeeds(QString fileHash); void loadWebSeeds(QString fileHash);
// Session configuration - Setters // Session configuration - Setters
void setListeningPortsRange(std::pair<unsigned short, unsigned short> ports); void setListeningPortsRange(std::pair<unsigned short, unsigned short> ports);

386
src/download.ui

@ -0,0 +1,386 @@
<ui version="4.0" >
<class>downloading</class>
<widget class="QWidget" name="downloading" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>811</width>
<height>453</height>
</rect>
</property>
<property name="windowTitle" >
<string>Search</string>
</property>
<layout class="QVBoxLayout" >
<item>
<layout class="QVBoxLayout" >
<property name="spacing" >
<number>6</number>
</property>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" >
<property name="spacing" >
<number>6</number>
</property>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="lbl_DLSpeed" >
<property name="text" >
<string>Total DL Speed:</string>
</property>
<property name="alignment" >
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
</property>
</widget>
</item>
<item>
<widget class="QLCDNumber" name="LCD_DownSpeed" >
<property name="autoFillBackground" >
<bool>true</bool>
</property>
<property name="frameShadow" >
<enum>QFrame::Raised</enum>
</property>
<property name="smallDecimalPoint" >
<bool>false</bool>
</property>
<property name="numDigits" >
<number>6</number>
</property>
<property name="segmentStyle" >
<enum>QLCDNumber::Flat</enum>
</property>
<property name="value" stdset="0" >
<double>0.000000000000000</double>
</property>
<property name="intValue" stdset="0" >
<number>0</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="unitDL" >
<property name="text" >
<string>KiB/s</string>
</property>
<property name="alignment" >
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label" >
<property name="text" >
<string>Session ratio: </string>
</property>
<property name="alignment" >
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
</property>
</widget>
</item>
<item>
<widget class="QLCDNumber" name="LCD_Ratio" >
<property name="autoFillBackground" >
<bool>true</bool>
</property>
<property name="numDigits" >
<number>4</number>
</property>
<property name="segmentStyle" >
<enum>QLCDNumber::Flat</enum>
</property>
<property name="value" stdset="0" >
<double>1.000000000000000</double>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lbl_ratio_icon" >
<property name="text" >
<string/>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="lbl_UPSpeed" >
<property name="text" >
<string>Total UP Speed:</string>
</property>
<property name="alignment" >
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
</property>
</widget>
</item>
<item>
<widget class="QLCDNumber" name="LCD_UpSpeed" >
<property name="autoFillBackground" >
<bool>true</bool>
</property>
<property name="smallDecimalPoint" >
<bool>false</bool>
</property>
<property name="numDigits" >
<number>6</number>
</property>
<property name="segmentStyle" >
<enum>QLCDNumber::Flat</enum>
</property>
<property name="value" stdset="0" >
<double>0.000000000000000</double>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="unitUP" >
<property name="text" >
<string>KiB/s</string>
</property>
<property name="alignment" >
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QTreeView" name="downloadList" >
<property name="minimumSize" >
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="contextMenuPolicy" >
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="autoScroll" >
<bool>true</bool>
</property>
<property name="selectionMode" >
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
<property name="indentation" >
<number>1</number>
</property>
<property name="itemsExpandable" >
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QTabWidget" name="tabBottom" >
<property name="maximumSize" >
<size>
<width>16777215</width>
<height>142</height>
</size>
</property>
<property name="tabPosition" >
<enum>QTabWidget::West</enum>
</property>
<property name="currentIndex" >
<number>0</number>
</property>
<widget class="QWidget" name="log_tab" >
<attribute name="title" >
<string>Log</string>
</attribute>
<layout class="QVBoxLayout" >
<property name="spacing" >
<number>6</number>
</property>
<property name="leftMargin" >
<number>9</number>
</property>
<property name="topMargin" >
<number>9</number>
</property>
<property name="rightMargin" >
<number>9</number>
</property>
<property name="bottomMargin" >
<number>9</number>
</property>
<item>
<widget class="QTextBrowser" name="infoBar" >
<property name="sizePolicy" >
<sizepolicy vsizetype="Expanding" hsizetype="Expanding" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize" >
<size>
<width>16777215</width>
<height>120</height>
</size>
</property>
<property name="contextMenuPolicy" >
<enum>Qt::CustomContextMenu</enum>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="filter_tab" >
<attribute name="title" >
<string>IP filter</string>
</attribute>
<layout class="QVBoxLayout" >
<property name="spacing" >
<number>6</number>
</property>
<property name="leftMargin" >
<number>9</number>
</property>
<property name="topMargin" >
<number>9</number>
</property>
<property name="rightMargin" >
<number>9</number>
</property>
<property name="bottomMargin" >
<number>9</number>
</property>
<item>
<widget class="QTextBrowser" name="textBlockedUsers" >
<property name="maximumSize" >
<size>
<width>16777215</width>
<height>123</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
<action name="actionStart" >
<property name="text" >
<string>Start</string>
</property>
</action>
<action name="actionPause" >
<property name="text" >
<string>Pause</string>
</property>
</action>
<action name="actionDelete" >
<property name="text" >
<string>Delete</string>
</property>
</action>
<action name="actionClearLog" >
<property name="text" >
<string>Clear</string>
</property>
</action>
<action name="actionPreview_file" >
<property name="text" >
<string>Preview file</string>
</property>
</action>
<action name="actionSet_upload_limit" >
<property name="text" >
<string>Set upload limit</string>
</property>
</action>
<action name="actionSet_download_limit" >
<property name="text" >
<string>Set download limit</string>
</property>
</action>
<action name="actionDelete_Permanently" >
<property name="text" >
<string>Delete Permanently</string>
</property>
</action>
<action name="actionTorrent_Properties" >
<property name="text" >
<string>Torrent Properties</string>
</property>
</action>
</widget>
<resources/>
<connections/>
</ui>

697
src/downloadingTorrents.cpp

@ -0,0 +1,697 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2006 Christophe Dumez
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contact : chris@qbittorrent.org
*/
#include "downloadingTorrents.h"
#include "misc.h"
#include "properties_imp.h"
#include "bittorrent.h"
#include "allocationDlg.h"
#include "DLListDelegate.h"
#include "previewSelect.h"
#include "GUI.h"
#include <QFile>
#include <QSettings>
#include <QStandardItemModel>
#include <QHeaderView>
#include <QTime>
#include <QMenu>
DownloadingTorrents::DownloadingTorrents(QObject *parent, bittorrent *BTSession) {
setupUi(this);
this->BTSession = BTSession;
this->parent = parent;
delayedSorting = false;
nbTorrents = 0;
// Setting icons
actionStart->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/play.png")));
actionPause->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/pause.png")));
actionDelete->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/delete.png")));
actionClearLog->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/delete.png")));
actionPreview_file->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/preview.png")));
actionSet_upload_limit->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/seeding.png")));
actionSet_download_limit->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/downloading.png")));
actionDelete_Permanently->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/delete_perm.png")));
actionTorrent_Properties->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/properties.png")));
// tabBottom->setTabIcon(0, QIcon(QString::fromUtf8(":/Icons/log.png")));
// tabBottom->setTabIcon(1, QIcon(QString::fromUtf8(":/Icons/filter.png")));
// Set default ratio
lbl_ratio_icon->setPixmap(QPixmap(QString::fromUtf8(":/Icons/stare.png")));
// Set Download list model
DLListModel = new QStandardItemModel(0,9);
DLListModel->setHeaderData(NAME, Qt::Horizontal, tr("Name", "i.e: file name"));
DLListModel->setHeaderData(SIZE, Qt::Horizontal, tr("Size", "i.e: file size"));
DLListModel->setHeaderData(PROGRESS, Qt::Horizontal, tr("Progress", "i.e: % downloaded"));
DLListModel->setHeaderData(DLSPEED, Qt::Horizontal, tr("DL Speed", "i.e: Download speed"));
DLListModel->setHeaderData(UPSPEED, Qt::Horizontal, tr("UP Speed", "i.e: Upload speed"));
DLListModel->setHeaderData(SEEDSLEECH, Qt::Horizontal, tr("Seeds/Leechs", "i.e: full/partial sources"));
DLListModel->setHeaderData(RATIO, Qt::Horizontal, tr("Ratio"));
DLListModel->setHeaderData(ETA, Qt::Horizontal, tr("ETA", "i.e: Estimated Time of Arrival / Time left"));
downloadList->setModel(DLListModel);
DLDelegate = new DLListDelegate(downloadList);
downloadList->setItemDelegate(DLDelegate);
// Hide hash column
downloadList->hideColumn(HASH);
connect(BTSession, SIGNAL(addedTorrent(QString, QTorrentHandle&, bool)), this, SLOT(torrentAdded(QString, QTorrentHandle&, bool)));
connect(BTSession, SIGNAL(duplicateTorrent(QString)), this, SLOT(torrentDuplicate(QString)));
connect(BTSession, SIGNAL(invalidTorrent(QString)), this, SLOT(torrentCorrupted(QString)));
connect(BTSession, SIGNAL(portListeningFailure()), this, SLOT(portListeningFailure()));
connect(BTSession, SIGNAL(peerBlocked(QString)), this, SLOT(addLogPeerBlocked(const QString)));
connect(BTSession, SIGNAL(fastResumeDataRejected(QString)), this, SLOT(addFastResumeRejectedAlert(QString)));
connect(BTSession, SIGNAL(aboutToDownloadFromUrl(QString)), this, SLOT(displayDownloadingUrlInfos(QString)));
connect(BTSession, SIGNAL(urlSeedProblem(QString, QString)), this, SLOT(addUrlSeedError(QString, QString)));
// Load last columns width for download list
if(!loadColWidthDLList()) {
downloadList->header()->resizeSection(0, 200);
}
// Make download list header clickable for sorting
downloadList->header()->setClickable(true);
downloadList->header()->setSortIndicatorShown(true);
// Connecting Actions to slots
connect(downloadList, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(notifyTorrentDoubleClicked(const QModelIndex&)));
connect(downloadList->header(), SIGNAL(sectionPressed(int)), this, SLOT(sortDownloadList(int)));
connect(downloadList, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayDLListMenu(const QPoint&)));
connect(infoBar, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayInfoBarMenu(const QPoint&)));
// Actions
connect(actionDelete, SIGNAL(triggered()), (GUI*)parent, SLOT(on_actionDelete_triggered()));
connect(actionPreview_file, SIGNAL(triggered()), (GUI*)parent, SLOT(on_actionPreview_file_triggered()));
connect(actionDelete_Permanently, SIGNAL(triggered()), (GUI*)parent, SLOT(on_actionDelete_Permanently_triggered()));
connect(actionTorrent_Properties, SIGNAL(triggered()), this, SLOT(propertiesSelection()));
// Set info Bar infos
setInfoBar(tr("qBittorrent %1 started.", "e.g: qBittorrent v0.x started.").arg(QString::fromUtf8(""VERSION)));
setInfoBar(tr("Be careful, sharing copyrighted material without permission is against the law."), QString::fromUtf8("red"));
qDebug("Download tab built");
}
DownloadingTorrents::~DownloadingTorrents() {
saveColWidthDLList();
delete DLDelegate;
delete DLListModel;
}
void DownloadingTorrents::notifyTorrentDoubleClicked(const QModelIndex& index) {
unsigned int row = index.row();
QString hash = getHashFromRow(row);
emit torrentDoubleClicked(hash);
}
void DownloadingTorrents::addLogPeerBlocked(QString ip) {
static unsigned short nbLines = 0;
++nbLines;
if(nbLines > 200) {
textBlockedUsers->clear();
nbLines = 1;
}
textBlockedUsers->append(QString::fromUtf8("<font color='grey'>")+ QTime::currentTime().toString(QString::fromUtf8("hh:mm:ss")) + QString::fromUtf8("</font> - ")+tr("<font color='red'>%1</font> <i>was blocked</i>", "x.y.z.w was blocked").arg(ip));
}
unsigned int DownloadingTorrents::getNbTorrentsInList() const {
return nbTorrents;
}
// Note: do not actually pause the torrent in BT session
void DownloadingTorrents::pauseTorrent(QString hash) {
int row = getRowFromHash(hash);
Q_ASSERT(row != -1);
DLListModel->setData(DLListModel->index(row, DLSPEED), QVariant((double)0.0));
DLListModel->setData(DLListModel->index(row, UPSPEED), QVariant((double)0.0));
DLListModel->setData(DLListModel->index(row, ETA), QVariant((qlonglong)-1));
DLListModel->setData(DLListModel->index(row, NAME), QIcon(QString::fromUtf8(":/Icons/skin/paused.png")), Qt::DecorationRole);
DLListModel->setData(DLListModel->index(row, SEEDSLEECH), QVariant(QString::fromUtf8("0/0")));
QTorrentHandle h = BTSession->getTorrentHandle(hash);
Q_ASSERT(h.progress() <= 1. && h.progress() >= 0.);
DLListModel->setData(DLListModel->index(row, PROGRESS), QVariant((double)h.progress()));
setRowColor(row, QString::fromUtf8("red"));
}
QString DownloadingTorrents::getHashFromRow(unsigned int row) const {
Q_ASSERT(row < (unsigned int)DLListModel->rowCount());
return DLListModel->data(DLListModel->index(row, HASH)).toString();
}
void DownloadingTorrents::setBottomTabEnabled(unsigned int index, bool b){
if(index and !b)
tabBottom->setCurrentIndex(0);
tabBottom->setTabEnabled(index, b);
}
// Show torrent properties dialog
void DownloadingTorrents::showProperties(const QModelIndex &index) {
int row = index.row();
QString hash = DLListModel->data(DLListModel->index(row, HASH)).toString();
QTorrentHandle h = BTSession->getTorrentHandle(hash);
properties *prop = new properties(this, BTSession, h);
connect(prop, SIGNAL(filteredFilesChanged(QString)), this, SLOT(updateFileSizeAndProgress(QString)));
prop->show();
}
void DownloadingTorrents::resumeTorrent(QString hash){
int row = getRowFromHash(hash);
Q_ASSERT(row != -1);
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/connecting.png"))), Qt::DecorationRole);
setRowColor(row, QString::fromUtf8("grey"));
}
// Remove a torrent from the download list but NOT from the BT Session
void DownloadingTorrents::deleteTorrent(QString hash) {
int row = getRowFromHash(hash);
Q_ASSERT(row != -1);
DLListModel->removeRow(row);
--nbTorrents;
emit unfinishedTorrentsNumberChanged(nbTorrents);
}
// Update Info Bar information
void DownloadingTorrents::setInfoBar(QString info, QString color) {
static unsigned short nbLines = 0;
++nbLines;
// Check log size, clear it if too big
if(nbLines > 200) {
infoBar->clear();
nbLines = 1;
}
infoBar->append(QString::fromUtf8("<font color='grey'>")+ QTime::currentTime().toString(QString::fromUtf8("hh:mm:ss")) + QString::fromUtf8("</font> - <font color='") + color +QString::fromUtf8("'><i>") + info + QString::fromUtf8("</i></font>"));
}
void DownloadingTorrents::addFastResumeRejectedAlert(QString name) {
setInfoBar(tr("Fast resume data was rejected for torrent %1, checking again...").arg(name), QString::fromUtf8("red"));
}
void DownloadingTorrents::addUrlSeedError(QString url, QString msg) {
setInfoBar(tr("Url seed lookup failed for url: %1, message: %2").arg(url).arg(msg), QString::fromUtf8("red"));
}
void DownloadingTorrents::on_actionSet_download_limit_triggered() {
QModelIndexList selectedIndexes = downloadList->selectionModel()->selectedIndexes();
QModelIndex index;
QStringList hashes;
foreach(index, selectedIndexes) {
if(index.column() == NAME) {
// Get the file hash
hashes << DLListModel->data(DLListModel->index(index.row(), HASH)).toString();
}
}
Q_ASSERT(hashes.size() > 0);
new BandwidthAllocationDialog(this, false, BTSession, hashes);
}
void DownloadingTorrents::on_actionSet_upload_limit_triggered() {
QModelIndexList selectedIndexes = downloadList->selectionModel()->selectedIndexes();
QModelIndex index;
QStringList hashes;
foreach(index, selectedIndexes) {
if(index.column() == NAME) {
// Get the file hash
hashes << DLListModel->data(DLListModel->index(index.row(), HASH)).toString();
}
}
Q_ASSERT(hashes.size() > 0);
new BandwidthAllocationDialog(this, true, BTSession, hashes);
}
// display properties of selected items
void DownloadingTorrents::propertiesSelection(){
QModelIndexList selectedIndexes = downloadList->selectionModel()->selectedIndexes();
QModelIndex index;
foreach(index, selectedIndexes){
if(index.column() == NAME){
showProperties(index);
}
}
}
void DownloadingTorrents::displayDLListMenu(const QPoint& pos) {
QMenu myDLLlistMenu(this);
QModelIndex index;
// Enable/disable pause/start action given the DL state
QModelIndexList selectedIndexes = downloadList->selectionModel()->selectedIndexes();
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
QString previewProgram = settings.value(QString::fromUtf8("Options/Misc/PreviewProgram"), QString()).toString();
bool has_pause = false, has_start = false, has_preview = false;
foreach(index, selectedIndexes) {
if(index.column() == NAME) {
// Get the file name
QString hash = DLListModel->data(DLListModel->index(index.row(), HASH)).toString();
// Get handle and pause the torrent
QTorrentHandle h = BTSession->getTorrentHandle(hash);
if(!h.is_valid()) continue;
if(h.is_paused()) {
if(!has_start) {
myDLLlistMenu.addAction(actionStart);
has_start = true;
}
}else{
if(!has_pause) {
myDLLlistMenu.addAction(actionPause);
has_pause = true;
}
}
if(!previewProgram.isEmpty() && BTSession->isFilePreviewPossible(hash) && !has_preview) {
myDLLlistMenu.addAction(actionPreview_file);
has_preview = true;
}
if(has_pause && has_start && has_preview) break;
}
}
myDLLlistMenu.addSeparator();
myDLLlistMenu.addAction(actionDelete);
myDLLlistMenu.addAction(actionDelete_Permanently);
myDLLlistMenu.addSeparator();
myDLLlistMenu.addAction(actionSet_download_limit);
myDLLlistMenu.addAction(actionSet_upload_limit);
myDLLlistMenu.addSeparator();
myDLLlistMenu.addAction(actionTorrent_Properties);
// Call menu
// XXX: why mapToGlobal() is not enough?
myDLLlistMenu.exec(mapToGlobal(pos)+QPoint(10,55));
}
void DownloadingTorrents::on_actionClearLog_triggered() {
infoBar->clear();
}
QStringList DownloadingTorrents::getSelectedTorrents(bool only_one) const{
QStringList res;
QModelIndex index;
QModelIndexList selectedIndexes = downloadList->selectionModel()->selectedIndexes();
foreach(index, selectedIndexes) {
if(index.column() == NAME) {
// Get the file hash
QString hash = DLListModel->data(DLListModel->index(index.row(), HASH)).toString();
res << hash;
if(only_one) break;
}
}
return res;
}
void DownloadingTorrents::updateRatio() {
char tmp[MAX_CHAR_TMP];
// Update ratio info
float ratio = 1.;
session_status sessionStatus = BTSession->getSessionStatus();
if(sessionStatus.total_payload_download == 0) {
if(sessionStatus.total_payload_upload == 0)
ratio = 1.;
else
ratio = 10.;
}else{
ratio = (double)sessionStatus.total_payload_upload / (double)sessionStatus.total_payload_download;
if(ratio > 10.)
ratio = 10.;
}
snprintf(tmp, MAX_CHAR_TMP, "%.1f", ratio);
LCD_Ratio->display(tmp);
if(ratio < 0.5) {
lbl_ratio_icon->setPixmap(QPixmap(QString::fromUtf8(":/Icons/unhappy.png")));
}else{
if(ratio > 1.0) {
lbl_ratio_icon->setPixmap(QPixmap(QString::fromUtf8(":/Icons/smile.png")));
}else{
lbl_ratio_icon->setPixmap(QPixmap(QString::fromUtf8(":/Icons/stare.png")));
}
}
}
void DownloadingTorrents::displayInfoBarMenu(const QPoint& pos) {
// Log Menu
QMenu myLogMenu(this);
myLogMenu.addAction(actionClearLog);
// XXX: Why mapToGlobal() is not enough?
myLogMenu.exec(mapToGlobal(pos)+QPoint(22,383));
}
void DownloadingTorrents::sortProgressColumnDelayed() {
if(delayedSorting) {
sortDownloadListFloat(PROGRESS, delayedSortingOrder);
qDebug("Delayed sorting of progress column");
}
}
// get information from torrent handles and
// update download list accordingly
void DownloadingTorrents::updateDlList() {
char tmp[MAX_CHAR_TMP];
char tmp2[MAX_CHAR_TMP];
// update global informations
snprintf(tmp, MAX_CHAR_TMP, "%.1f", BTSession->getPayloadUploadRate()/1024.);
snprintf(tmp2, MAX_CHAR_TMP, "%.1f", BTSession->getPayloadDownloadRate()/1024.);
//BTSession->printPausedTorrents();
LCD_UpSpeed->display(QString::fromUtf8(tmp)); // UP LCD
LCD_DownSpeed->display(QString::fromUtf8(tmp2)); // DL LCD
// browse handles
QStringList unfinishedTorrents = BTSession->getUnfinishedTorrents();
QString hash;
foreach(hash, unfinishedTorrents) {
QTorrentHandle h = BTSession->getTorrentHandle(hash);
if(!h.is_valid()){
qDebug("We have an invalid handle for: %s", qPrintable(hash));
continue;
}
try{
QString hash = h.hash();
int row = getRowFromHash(hash);
if(row == -1) {
qDebug("Info: Could not find filename in download list, adding it...");
addTorrent(hash);
row = getRowFromHash(hash);
}
Q_ASSERT(row != -1);
// No need to update a paused torrent
if(h.is_paused()) continue;
// Parse download state
// Setting download state
switch(h.state()) {
case torrent_status::finished:
case torrent_status::seeding:
qDebug("A torrent that was in download tab just finished, moving it to finished tab");
BTSession->setUnfinishedTorrent(hash);
emit torrentFinished(hash);
deleteTorrent(hash);
continue;
case torrent_status::checking_files:
case torrent_status::queued_for_checking:
if(BTSession->getTorrentsToPauseAfterChecking().indexOf(hash) == -1) {
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/time.png"))), Qt::DecorationRole);
setRowColor(row, QString::fromUtf8("grey"));
Q_ASSERT(h.progress() <= 1. && h.progress() >= 0.);
DLListModel->setData(DLListModel->index(row, PROGRESS), QVariant((double)h.progress()));
}
break;
case torrent_status::connecting_to_tracker:
if(h.download_payload_rate() > 0) {
// Display "Downloading" status when connecting if download speed > 0
DLListModel->setData(DLListModel->index(row, ETA), QVariant((qlonglong)BTSession->getETA(hash)));
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/downloading.png"))), Qt::DecorationRole);
setRowColor(row, QString::fromUtf8("green"));
}else{
DLListModel->setData(DLListModel->index(row, ETA), QVariant((qlonglong)-1));
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/connecting.png"))), Qt::DecorationRole);
setRowColor(row, QString::fromUtf8("grey"));
}
Q_ASSERT(h.progress() <= 1. && h.progress() >= 0.);
DLListModel->setData(DLListModel->index(row, PROGRESS), QVariant((double)h.progress()));
DLListModel->setData(DLListModel->index(row, DLSPEED), QVariant((double)h.download_payload_rate()));
DLListModel->setData(DLListModel->index(row, UPSPEED), QVariant((double)h.upload_payload_rate()));
break;
case torrent_status::downloading:
case torrent_status::downloading_metadata:
if(h.download_payload_rate() > 0) {
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/downloading.png"))), Qt::DecorationRole);
DLListModel->setData(DLListModel->index(row, ETA), QVariant((qlonglong)BTSession->getETA(hash)));
setRowColor(row, QString::fromUtf8("green"));
}else{
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/stalled.png"))), Qt::DecorationRole);
DLListModel->setData(DLListModel->index(row, ETA), QVariant((qlonglong)-1));
setRowColor(row, QString::fromUtf8("black"));
}
Q_ASSERT(h.progress() <= 1. && h.progress() >= 0.);
DLListModel->setData(DLListModel->index(row, PROGRESS), QVariant((double)h.progress()));
DLListModel->setData(DLListModel->index(row, DLSPEED), QVariant((double)h.download_payload_rate()));
DLListModel->setData(DLListModel->index(row, UPSPEED), QVariant((double)h.upload_payload_rate()));
break;
default:
DLListModel->setData(DLListModel->index(row, ETA), QVariant((qlonglong)-1));
}
DLListModel->setData(DLListModel->index(row, SEEDSLEECH), QVariant(misc::toQString(h.num_seeds(), true)+QString::fromUtf8("/")+misc::toQString(h.num_peers() - h.num_seeds(), true)));
DLListModel->setData(DLListModel->index(row, RATIO), QVariant(misc::toQString(BTSession->getRealRatio(hash))));
}catch(invalid_handle e) {
continue;
}
}
}
void DownloadingTorrents::addTorrent(QString hash) {
if(BTSession->isFinished(hash)){
BTSession->setUnfinishedTorrent(hash);
}
QTorrentHandle h = BTSession->getTorrentHandle(hash);
int row = getRowFromHash(hash);
if(row != -1) return;
row = DLListModel->rowCount();
// Adding torrent to download list
DLListModel->insertRow(row);
DLListModel->setData(DLListModel->index(row, NAME), QVariant(h.name()));
DLListModel->setData(DLListModel->index(row, SIZE), QVariant((qlonglong)h.actual_size()));
DLListModel->setData(DLListModel->index(row, DLSPEED), QVariant((double)0.));
DLListModel->setData(DLListModel->index(row, UPSPEED), QVariant((double)0.));
DLListModel->setData(DLListModel->index(row, SEEDSLEECH), QVariant(QString::fromUtf8("0/0")));
DLListModel->setData(DLListModel->index(row, ETA), QVariant((qlonglong)-1));
DLListModel->setData(DLListModel->index(row, HASH), QVariant(hash));
// Pause torrent if it was paused last time
if(BTSession->isPaused(hash)) {
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/paused.png"))), Qt::DecorationRole);
setRowColor(row, QString::fromUtf8("red"));
}else{
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/connecting.png"))), Qt::DecorationRole);
setRowColor(row, QString::fromUtf8("grey"));
}
++nbTorrents;
emit unfinishedTorrentsNumberChanged(nbTorrents);
}
void DownloadingTorrents::sortDownloadListFloat(int index, Qt::SortOrder sortOrder) {
QList<QPair<int, double> > lines;
// insertion sorting
unsigned int nbRows = DLListModel->rowCount();
for(unsigned int i=0; i<nbRows; ++i) {
misc::insertSort(lines, QPair<int,double>(i, DLListModel->data(DLListModel->index(i, index)).toDouble()), sortOrder);
}
// Insert items in new model, in correct order
unsigned int nbRows_old = lines.size();
for(unsigned int row=0; row<nbRows_old; ++row) {
DLListModel->insertRow(DLListModel->rowCount());
unsigned int sourceRow = lines[row].first;
unsigned int nbColumns = DLListModel->columnCount();
for(unsigned int col=0; col<nbColumns; ++col) {
DLListModel->setData(DLListModel->index(nbRows_old+row, col), DLListModel->data(DLListModel->index(sourceRow, col)));
DLListModel->setData(DLListModel->index(nbRows_old+row, col), DLListModel->data(DLListModel->index(sourceRow, col), Qt::DecorationRole), Qt::DecorationRole);
DLListModel->setData(DLListModel->index(nbRows_old+row, col), DLListModel->data(DLListModel->index(sourceRow, col), Qt::ForegroundRole), Qt::ForegroundRole);
}
}
// Remove old rows
DLListModel->removeRows(0, nbRows_old);
}
void DownloadingTorrents::sortDownloadListString(int index, Qt::SortOrder sortOrder) {
QList<QPair<int, QString> > lines;
// Insertion sorting
unsigned int nbRows = DLListModel->rowCount();
for(unsigned int i=0; i<nbRows; ++i) {
misc::insertSortString(lines, QPair<int, QString>(i, DLListModel->data(DLListModel->index(i, index)).toString()), sortOrder);
}
// Insert items in new model, in correct order
unsigned int nbRows_old = lines.size();
for(unsigned int row=0; row<nbRows_old; ++row) {
DLListModel->insertRow(DLListModel->rowCount());
unsigned int sourceRow = lines[row].first;
unsigned int nbColumns = DLListModel->columnCount();
for(unsigned int col=0; col<nbColumns; ++col) {
DLListModel->setData(DLListModel->index(nbRows_old+row, col), DLListModel->data(DLListModel->index(sourceRow, col)));
DLListModel->setData(DLListModel->index(nbRows_old+row, col), DLListModel->data(DLListModel->index(sourceRow, col), Qt::DecorationRole), Qt::DecorationRole);
DLListModel->setData(DLListModel->index(nbRows_old+row, col), DLListModel->data(DLListModel->index(sourceRow, col), Qt::ForegroundRole), Qt::ForegroundRole);
}
}
// Remove old rows
DLListModel->removeRows(0, nbRows_old);
}
void DownloadingTorrents::sortDownloadList(int index, Qt::SortOrder startSortOrder, bool fromLoadColWidth) {
qDebug("Called sort download list");
static Qt::SortOrder sortOrder = startSortOrder;
if(!fromLoadColWidth && downloadList->header()->sortIndicatorSection() == index) {
if(sortOrder == Qt::AscendingOrder) {
sortOrder = Qt::DescendingOrder;
}else{
sortOrder = Qt::AscendingOrder;
}
}
QString sortOrderLetter;
if(sortOrder == Qt::AscendingOrder)
sortOrderLetter = QString::fromUtf8("a");
else
sortOrderLetter = QString::fromUtf8("d");
if(fromLoadColWidth) {
// XXX: Why is this needed?
if(sortOrder == Qt::DescendingOrder)
downloadList->header()->setSortIndicator(index, Qt::AscendingOrder);
else
downloadList->header()->setSortIndicator(index, Qt::DescendingOrder);
} else {
downloadList->header()->setSortIndicator(index, sortOrder);
}
switch(index) {
case SIZE:
case ETA:
case UPSPEED:
case DLSPEED:
sortDownloadListFloat(index, sortOrder);
break;
case PROGRESS:
if(fromLoadColWidth) {
// Progress sorting must be delayed until files are checked (on startup)
delayedSorting = true;
qDebug("Delayed sorting of the progress column");
delayedSortingOrder = sortOrder;
}else{
sortDownloadListFloat(index, sortOrder);
}
break;
default:
sortDownloadListString(index, sortOrder);
}
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
settings.setValue(QString::fromUtf8("DownloadListSortedCol"), misc::toQString(index)+sortOrderLetter);
}
// Save columns width in a file to remember them
// (download list)
void DownloadingTorrents::saveColWidthDLList() const{
qDebug("Saving columns width in download list");
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
QStringList width_list;
unsigned int nbColumns = DLListModel->columnCount()-1;
for(unsigned int i=0; i<nbColumns; ++i) {
width_list << misc::toQString(downloadList->columnWidth(i));
}
settings.setValue(QString::fromUtf8("DownloadListColsWidth"), width_list.join(QString::fromUtf8(" ")));
qDebug("Download list columns width saved");
}
// Load columns width in a file that were saved previously
// (download list)
bool DownloadingTorrents::loadColWidthDLList() {
qDebug("Loading columns width for download list");
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
QString line = settings.value(QString::fromUtf8("DownloadListColsWidth"), QString()).toString();
if(line.isEmpty())
return false;
QStringList width_list = line.split(QString::fromUtf8(" "));
if(width_list.size() != DLListModel->columnCount()-1) {
qDebug("Corrupted values for download list columns sizes");
return false;
}
unsigned int listSize = width_list.size();
for(unsigned int i=0; i<listSize; ++i) {
downloadList->header()->resizeSection(i, width_list.at(i).toInt());
}
// Loading last sorted column
QString sortedCol = settings.value(QString::fromUtf8("DownloadListSortedCol"), QString()).toString();
if(!sortedCol.isEmpty()) {
Qt::SortOrder sortOrder;
if(sortedCol.endsWith(QString::fromUtf8("d")))
sortOrder = Qt::DescendingOrder;
else
sortOrder = Qt::AscendingOrder;
sortedCol = sortedCol.left(sortedCol.size()-1);
int index = sortedCol.toInt();
sortDownloadList(index, sortOrder, true);
}
qDebug("Download list columns width loaded");
return true;
}
// Called when a torrent is added
void DownloadingTorrents::torrentAdded(QString path, QTorrentHandle& h, bool fastResume) {
QString hash = h.hash();
if(BTSession->isFinished(hash)) {
return;
}
int row = DLListModel->rowCount();
// Adding torrent to download list
DLListModel->insertRow(row);
DLListModel->setData(DLListModel->index(row, NAME), QVariant(h.name()));
DLListModel->setData(DLListModel->index(row, SIZE), QVariant((qlonglong)h.actual_size()));
DLListModel->setData(DLListModel->index(row, DLSPEED), QVariant((double)0.));
DLListModel->setData(DLListModel->index(row, UPSPEED), QVariant((double)0.));
DLListModel->setData(DLListModel->index(row, SEEDSLEECH), QVariant(QString::fromUtf8("0/0")));
DLListModel->setData(DLListModel->index(row, RATIO), QVariant(misc::toQString(BTSession->getRealRatio(hash))));
DLListModel->setData(DLListModel->index(row, ETA), QVariant((qlonglong)-1));
DLListModel->setData(DLListModel->index(row, HASH), QVariant(hash));
// Pause torrent if it was paused last time
// Not using isPaused function because torrents are paused after checking now
if(QFile::exists(misc::qBittorrentPath()+QString::fromUtf8("BT_backup")+QDir::separator()+hash+QString::fromUtf8(".paused"))) {
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/paused.png"))), Qt::DecorationRole);
setRowColor(row, QString::fromUtf8("red"));
}else{
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/connecting.png"))), Qt::DecorationRole);
setRowColor(row, QString::fromUtf8("grey"));
}
if(!fastResume) {
setInfoBar(tr("'%1' added to download list.", "'/home/y/xxx.torrent' was added to download list.").arg(path));
}else{
setInfoBar(tr("'%1' resumed. (fast resume)", "'/home/y/xxx.torrent' was resumed. (fast resume)").arg(path));
}
++nbTorrents;
emit unfinishedTorrentsNumberChanged(nbTorrents);
}
// Called when trying to add a duplicate torrent
void DownloadingTorrents::torrentDuplicate(QString path) {
setInfoBar(tr("'%1' is already in download list.", "e.g: 'xxx.avi' is already in download list.").arg(path));
}
void DownloadingTorrents::torrentCorrupted(QString path) {
setInfoBar(tr("Unable to decode torrent file: '%1'", "e.g: Unable to decode torrent file: '/home/y/xxx.torrent'").arg(path), QString::fromUtf8("red"));
setInfoBar(tr("This file is either corrupted or this isn't a torrent."),QString::fromUtf8("red"));
}
void DownloadingTorrents::updateFileSizeAndProgress(QString hash) {
int row = getRowFromHash(hash);
Q_ASSERT(row != -1);
QTorrentHandle h = BTSession->getTorrentHandle(hash);
DLListModel->setData(DLListModel->index(row, SIZE), QVariant((qlonglong)h.actual_size()));
Q_ASSERT(h.progress() <= 1.);
DLListModel->setData(DLListModel->index(row, PROGRESS), QVariant((double)h.progress()));
}
// Called when we couldn't listen on any port
// in the given range.
void DownloadingTorrents::portListeningFailure() {
setInfoBar(tr("Couldn't listen on any of the given ports."), QString::fromUtf8("red"));
}
// Set the color of a row in data model
void DownloadingTorrents::setRowColor(int row, QString color) {
unsigned int nbColumns = DLListModel->columnCount();
for(unsigned int i=0; i<nbColumns; ++i) {
DLListModel->setData(DLListModel->index(row, i), QVariant(QColor(color)), Qt::ForegroundRole);
}
}
// return the row of in data model
// corresponding to the given the hash
int DownloadingTorrents::getRowFromHash(QString hash) const{
unsigned int nbRows = DLListModel->rowCount();
for(unsigned int i=0; i<nbRows; ++i) {
if(DLListModel->data(DLListModel->index(i, HASH)) == hash) {
return i;
}
}
return -1;
}
void DownloadingTorrents::displayDownloadingUrlInfos(QString url) {
setInfoBar(tr("Downloading '%1', please wait...", "e.g: Downloading 'xxx.torrent', please wait...").arg(url), QString::fromUtf8("black"));
}

97
src/downloadingTorrents.h

@ -0,0 +1,97 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2006 Christophe Dumez
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contact : chris@qbittorrent.org
*/
#ifndef DOWNLOADINGTORRENTS_H
#define DOWNLOADINGTORRENTS_H
#include "ui_download.h"
#include "qtorrenthandle.h"
class QStandardItemModel;
class bittorrent;
class DLListDelegate;
using namespace libtorrent;
class DownloadingTorrents : public QWidget, public Ui::downloading{
Q_OBJECT
private:
bittorrent *BTSession;
DLListDelegate *DLDelegate;
QStandardItemModel *DLListModel;
unsigned int nbTorrents;
bool delayedSorting;
Qt::SortOrder delayedSortingOrder;
QObject *parent;
public:
DownloadingTorrents(QObject *parent, bittorrent *BTSession);
~DownloadingTorrents();
// Methods
bool loadColWidthDLList();
int getRowFromHash(QString hash) const;
QString getHashFromRow(unsigned int row) const;
QStringList getSelectedTorrents(bool only_one=false) const;
unsigned int getNbTorrentsInList() const;
signals:
void unfinishedTorrentsNumberChanged(unsigned int);
void torrentDoubleClicked(QString hash);
void torrentFinished(QString hash);
protected slots:
void addLogPeerBlocked(QString);
void addFastResumeRejectedAlert(QString);
void addUrlSeedError(QString url, QString msg);
void on_actionSet_download_limit_triggered();
void notifyTorrentDoubleClicked(const QModelIndex& index);
void on_actionSet_upload_limit_triggered();
void displayDLListMenu(const QPoint& pos);
void on_actionClearLog_triggered();
void displayInfoBarMenu(const QPoint& pos);
void addTorrent(QString hash);
void sortDownloadList(int index, Qt::SortOrder startSortOrder=Qt::AscendingOrder, bool fromLoadColWidth=false);
void sortDownloadListFloat(int index, Qt::SortOrder sortOrder);
void sortDownloadListString(int index, Qt::SortOrder sortOrder);
void saveColWidthDLList() const;
void torrentAdded(QString path, QTorrentHandle& h, bool fastResume);
void torrentDuplicate(QString path);
void torrentCorrupted(QString path);
void updateFileSizeAndProgress(QString hash);
void portListeningFailure();
void setRowColor(int row, QString color);
void displayDownloadingUrlInfos(QString url);
void showProperties(const QModelIndex &index);
public slots:
void updateDlList();
void setInfoBar(QString info, QString color="black");
void pauseTorrent(QString hash);
void resumeTorrent(QString hash);
void updateRatio();
void deleteTorrent(QString hash);
void setBottomTabEnabled(unsigned int index, bool b);
void propertiesSelection();
void sortProgressColumnDelayed();
};
#endif

8
src/src.pro

@ -144,11 +144,12 @@ HEADERS += GUI.h misc.h options_imp.h about_imp.h \
bittorrent.h searchEngine.h \ bittorrent.h searchEngine.h \
rss.h rss_imp.h FinishedTorrents.h \ rss.h rss_imp.h FinishedTorrents.h \
allocationDlg.h FinishedListDelegate.h \ allocationDlg.h FinishedListDelegate.h \
qtorrenthandle.h qtorrenthandle.h downloadingTorrents.h
FORMS += MainWindow.ui options.ui about.ui \ FORMS += MainWindow.ui options.ui about.ui \
properties.ui createtorrent.ui preview.ui \ properties.ui createtorrent.ui preview.ui \
login.ui downloadFromURL.ui addTorrentDialog.ui \ login.ui downloadFromURL.ui addTorrentDialog.ui \
search.ui rss.ui seeding.ui bandwidth_limit.ui search.ui rss.ui seeding.ui bandwidth_limit.ui \
download.ui
SOURCES += GUI.cpp \ SOURCES += GUI.cpp \
main.cpp \ main.cpp \
options_imp.cpp \ options_imp.cpp \
@ -158,5 +159,6 @@ SOURCES += GUI.cpp \
searchEngine.cpp \ searchEngine.cpp \
rss_imp.cpp \ rss_imp.cpp \
FinishedTorrents.cpp \ FinishedTorrents.cpp \
qtorrenthandle.cpp qtorrenthandle.cpp \
downloadingTorrents.cpp

Loading…
Cancel
Save