Browse Source

- Transfer lists refreshers were moved to separate threads to improve GUI responsiveness. Please report any problem (like mutex deadlocks in console output) or crashes.

adaptive-webui-19844
Christophe Dumez 17 years ago
parent
commit
2ab7f6f923
  1. 1
      Changelog
  2. 1
      TODO
  3. 11
      src/FinishedTorrents.cpp
  4. 29
      src/FinishedTorrents.h
  5. 33
      src/GUI.cpp
  6. 32
      src/GUI.h
  7. 4
      src/src.pro

1
Changelog

@ -41,6 +41,7 @@
- BUGFIX: search plugin update - do not display only last version changelog - BUGFIX: search plugin update - do not display only last version changelog
- BUGFIX: Search plugin update - fixed missing new lines in changelog - BUGFIX: Search plugin update - fixed missing new lines in changelog
- BUGFIX: The number of search results was not reset when clicking on 'Clear' button - BUGFIX: The number of search results was not reset when clicking on 'Clear' button
- BUGFIX: Transfers lists refreshers were moved to separate threads
- COSMETIC: Redesigned torrent properties a little - COSMETIC: Redesigned torrent properties a little
- COSMETIC: Redesigned options a little - COSMETIC: Redesigned options a little
- COSMETIC: Display more logs messages concerning features - COSMETIC: Display more logs messages concerning features

1
TODO

@ -42,7 +42,6 @@
* beta3 * beta3
- Windows port (Chris - Peerkoel) - Windows port (Chris - Peerkoel)
- Translations update - Translations update
- Move transfer lists refreshers to threads?
- Optimize and cleanup code - Optimize and cleanup code
- Wait for some bug fixes in libtorrent : - Wait for some bug fixes in libtorrent :
- upload/download limit per torrent - upload/download limit per torrent

11
src/FinishedTorrents.cpp

@ -30,6 +30,7 @@
#include <QSettings> #include <QSettings>
#include <QStandardItemModel> #include <QStandardItemModel>
#include <QHeaderView> #include <QHeaderView>
#include <QMutexLocker>
FinishedTorrents::FinishedTorrents(QObject *parent, bittorrent *BTSession){ FinishedTorrents::FinishedTorrents(QObject *parent, bittorrent *BTSession){
setupUi(this); setupUi(this);
@ -51,6 +52,7 @@ FinishedTorrents::FinishedTorrents(QObject *parent, bittorrent *BTSession){
finishedList->header()->resizeSection(0, 200); finishedList->header()->resizeSection(0, 200);
} }
// Make download list header clickable for sorting // Make download list header clickable for sorting
qRegisterMetaType<QModelIndex>("QModelIndex");
finishedList->header()->setClickable(true); finishedList->header()->setClickable(true);
finishedList->header()->setSortIndicatorShown(true); finishedList->header()->setSortIndicatorShown(true);
connect(finishedList->header(), SIGNAL(sectionPressed(int)), this, SLOT(sortFinishedList(int))); connect(finishedList->header(), SIGNAL(sectionPressed(int)), this, SLOT(sortFinishedList(int)));
@ -67,12 +69,15 @@ FinishedTorrents::FinishedTorrents(QObject *parent, bittorrent *BTSession){
connect(actionPreview_file, SIGNAL(triggered()), (GUI*)parent, SLOT(on_actionPreview_file_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(actionDelete_Permanently, SIGNAL(triggered()), (GUI*)parent, SLOT(on_actionDelete_Permanently_triggered()));
connect(actionTorrent_Properties, SIGNAL(triggered()), this, SLOT(propertiesSelection())); connect(actionTorrent_Properties, SIGNAL(triggered()), this, SLOT(propertiesSelection()));
refresher = new FinishedListRefresher(this);
refresher->start();
} }
FinishedTorrents::~FinishedTorrents(){ FinishedTorrents::~FinishedTorrents(){
saveColWidthFinishedList(); saveColWidthFinishedList();
delete finishedListDelegate; delete finishedListDelegate;
delete finishedListModel; delete finishedListModel;
delete refresher;
} }
void FinishedTorrents::addFinishedSHA(QString hash){ void FinishedTorrents::addFinishedSHA(QString hash){
@ -80,6 +85,7 @@ void FinishedTorrents::addFinishedSHA(QString hash){
BTSession->setTorrentFinishedChecking(hash); BTSession->setTorrentFinishedChecking(hash);
} }
if(finishedSHAs.indexOf(hash) == -1) { if(finishedSHAs.indexOf(hash) == -1) {
QMutexLocker locker(&finishedListAccess);
finishedSHAs << hash; finishedSHAs << hash;
int row = finishedListModel->rowCount(); int row = finishedListModel->rowCount();
torrent_handle h = BTSession->getTorrentHandle(hash); torrent_handle h = BTSession->getTorrentHandle(hash);
@ -168,6 +174,8 @@ void FinishedTorrents::on_actionSet_upload_limit_triggered(){
void FinishedTorrents::updateFinishedList(){ void FinishedTorrents::updateFinishedList(){
// qDebug("Updating finished list"); // qDebug("Updating finished list");
if(((GUI*)parent)->getCurrentTab() != 1) return;
QMutexLocker locker(&finishedListAccess);
QString hash; QString hash;
foreach(hash, finishedSHAs){ foreach(hash, finishedSHAs){
torrent_handle h = BTSession->getTorrentHandle(hash); torrent_handle h = BTSession->getTorrentHandle(hash);
@ -213,6 +221,7 @@ int FinishedTorrents::getRowFromHash(QString hash) const{
// Will move it to download tab // Will move it to download tab
void FinishedTorrents::deleteFromFinishedList(QString hash){ void FinishedTorrents::deleteFromFinishedList(QString hash){
QMutexLocker locker(&finishedListAccess);
int row = getRowFromHash(hash); int row = getRowFromHash(hash);
if(row == -1){ if(row == -1){
std::cerr << "Error: couldn't find hash in finished list\n"; std::cerr << "Error: couldn't find hash in finished list\n";
@ -246,6 +255,7 @@ void FinishedTorrents::showProperties(const QModelIndex &index){
} }
void FinishedTorrents::updateFileSize(QString hash){ void FinishedTorrents::updateFileSize(QString hash){
QMutexLocker locker(&finishedListAccess);
int row = getRowFromHash(hash); int row = getRowFromHash(hash);
finishedListModel->setData(finishedListModel->index(row, F_SIZE), QVariant((qlonglong)BTSession->torrentEffectiveSize(hash))); finishedListModel->setData(finishedListModel->index(row, F_SIZE), QVariant((qlonglong)BTSession->torrentEffectiveSize(hash)));
} }
@ -294,6 +304,7 @@ void FinishedTorrents::displayFinishedListMenu(const QPoint& pos){
*/ */
void FinishedTorrents::sortFinishedList(int index){ void FinishedTorrents::sortFinishedList(int index){
QMutexLocker locker(&finishedListAccess);
static Qt::SortOrder sortOrder = Qt::AscendingOrder; static Qt::SortOrder sortOrder = Qt::AscendingOrder;
if(finishedList->header()->sortIndicatorSection() == index){ if(finishedList->header()->sortIndicatorSection() == index){
if(sortOrder == Qt::AscendingOrder){ if(sortOrder == Qt::AscendingOrder){

29
src/FinishedTorrents.h

@ -25,9 +25,13 @@
#include "ui_seeding.h" #include "ui_seeding.h"
#include <libtorrent/torrent_handle.hpp> #include <libtorrent/torrent_handle.hpp>
#include <QThread>
#include <QMutex>
class QStandardItemModel; class QStandardItemModel;
class bittorrent; class bittorrent;
class FinishedListDelegate; class FinishedListDelegate;
class FinishedListRefresher;
using namespace libtorrent; using namespace libtorrent;
@ -40,6 +44,8 @@ class FinishedTorrents : public QWidget, public Ui::seeding{
QStringList finishedSHAs; QStringList finishedSHAs;
QStandardItemModel *finishedListModel; QStandardItemModel *finishedListModel;
unsigned int nbFinished; unsigned int nbFinished;
FinishedListRefresher *refresher;
QMutex finishedListAccess;
public: public:
FinishedTorrents(QObject *parent, bittorrent *BTSession); FinishedTorrents(QObject *parent, bittorrent *BTSession);
@ -73,4 +79,27 @@ class FinishedTorrents : public QWidget, public Ui::seeding{
}; };
class FinishedListRefresher : public QThread {
private:
FinishedTorrents* parent;
bool abort;
public:
FinishedListRefresher(FinishedTorrents* parent){
this->parent = parent;
abort = false;
}
~FinishedListRefresher(){
abort = true;
wait();
}
protected:
void run(){
forever{
if(abort) return;
parent->updateFinishedList();
msleep(2000);
}
}
};
#endif #endif

33
src/GUI.cpp

@ -29,6 +29,7 @@
#include <QCloseEvent> #include <QCloseEvent>
#include <QShortcut> #include <QShortcut>
#include <QStandardItemModel> #include <QStandardItemModel>
#include <QMutexLocker>
#include "GUI.h" #include "GUI.h"
#include "misc.h" #include "misc.h"
@ -179,10 +180,6 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent){
connect(downloadList, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayDLListMenu(const QPoint&))); connect(downloadList, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayDLListMenu(const QPoint&)));
// connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayGUIMenu(const QPoint&))); // connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayGUIMenu(const QPoint&)));
connect(infoBar, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayInfoBarMenu(const QPoint&))); connect(infoBar, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayInfoBarMenu(const QPoint&)));
// Start download list refresher
refresher = new QTimer(this);
connect(refresher, SIGNAL(timeout()), this, SLOT(updateDlList()));
refresher->start(2000);
// Use a tcp server to allow only one instance of qBittorrent // Use a tcp server to allow only one instance of qBittorrent
tcpServer = new QTcpServer(); tcpServer = new QTcpServer();
if (!tcpServer->listen(QHostAddress::LocalHost, 1666)) { if (!tcpServer->listen(QHostAddress::LocalHost, 1666)) {
@ -195,6 +192,9 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent){
checkConnect->start(5000); checkConnect->start(5000);
previewProcess = new QProcess(this); previewProcess = new QProcess(this);
connect(previewProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(cleanTempPreviewFile(int, QProcess::ExitStatus))); connect(previewProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(cleanTempPreviewFile(int, QProcess::ExitStatus)));
// Download list refresher thread
refresher = new DownloadListRefresher(this);
refresher->start();
// Accept drag 'n drops // Accept drag 'n drops
setAcceptDrops(true); setAcceptDrops(true);
// Set info Bar infos // Set info Bar infos
@ -231,6 +231,14 @@ GUI::~GUI(){
delete switchRSSShortcut; delete switchRSSShortcut;
} }
int GUI::getCurrentTab() const{
if(isHidden() || isMinimized()){
return -1;
}else{
return tabs->currentIndex();
}
}
void GUI::on_actionWebsite_triggered(){ void GUI::on_actionWebsite_triggered(){
QDesktopServices::openUrl(QUrl("http://www.qbittorrent.org")); QDesktopServices::openUrl(QUrl("http://www.qbittorrent.org"));
} }
@ -554,17 +562,14 @@ void GUI::updateDlList(bool force){
if(systrayIntegration){ if(systrayIntegration){
myTrayIcon->setToolTip("<b>"+tr("qBittorrent")+"</b><br>"+tr("DL speed: %1 KiB/s", "e.g: Download speed: 10 KiB/s").arg(QString(tmp2))+"<br>"+tr("UP speed: %1 KiB/s", "e.g: Upload speed: 10 KiB/s").arg(QString(tmp))); // tray icon myTrayIcon->setToolTip("<b>"+tr("qBittorrent")+"</b><br>"+tr("DL speed: %1 KiB/s", "e.g: Download speed: 10 KiB/s").arg(QString(tmp2))+"<br>"+tr("UP speed: %1 KiB/s", "e.g: Upload speed: 10 KiB/s").arg(QString(tmp))); // tray icon
} }
if( !force && (isMinimized() || isHidden() || tabs->currentIndex() > 1)){ if( !force && getCurrentTab()){
// No need to update if qBittorrent DL list is hidden // No need to update if qBittorrent DL list is hidden
return; return;
} }
if(tabs->currentIndex()){
finishedTorrentTab->updateFinishedList();
return;
}
// qDebug("Updating download list"); // qDebug("Updating download list");
LCD_UpSpeed->display(tmp); // UP LCD LCD_UpSpeed->display(tmp); // UP LCD
LCD_DownSpeed->display(tmp2); // DL LCD LCD_DownSpeed->display(tmp2); // DL LCD
QMutexLocker locker(&DLListAccess);
// browse handles // browse handles
std::vector<torrent_handle> handles = BTSession->getTorrentHandles(); std::vector<torrent_handle> handles = BTSession->getTorrentHandles();
QStringList finishedSHAs = finishedTorrentTab->getFinishedSHAs(); QStringList finishedSHAs = finishedTorrentTab->getFinishedSHAs();
@ -658,6 +663,7 @@ void GUI::updateDlList(bool force){
} }
void GUI::restoreInDownloadList(torrent_handle h){ void GUI::restoreInDownloadList(torrent_handle h){
QMutexLocker locker(&DLListAccess);
unsigned int row = DLListModel->rowCount(); unsigned int row = DLListModel->rowCount();
QString hash = QString(misc::toString(h.info_hash()).c_str()); QString hash = QString(misc::toString(h.info_hash()).c_str());
// Adding torrent to download list // Adding torrent to download list
@ -732,6 +738,7 @@ void GUI::sortDownloadListString(int index, Qt::SortOrder sortOrder){
void GUI::sortDownloadList(int index, Qt::SortOrder startSortOrder, bool fromLoadColWidth){ void GUI::sortDownloadList(int index, Qt::SortOrder startSortOrder, bool fromLoadColWidth){
qDebug("Called sort download list"); qDebug("Called sort download list");
QMutexLocker locker(&DLListAccess);
static Qt::SortOrder sortOrder = startSortOrder; static Qt::SortOrder sortOrder = startSortOrder;
if(!fromLoadColWidth && downloadList->header()->sortIndicatorSection() == index){ if(!fromLoadColWidth && downloadList->header()->sortIndicatorSection() == index){
if(sortOrder == Qt::AscendingOrder){ if(sortOrder == Qt::AscendingOrder){
@ -987,6 +994,7 @@ void GUI::on_actionOpen_triggered(){
// delete from download list AND from hard drive // delete from download list AND from hard drive
void GUI::on_actionDelete_Permanently_triggered(){ void GUI::on_actionDelete_Permanently_triggered(){
if(tabs->currentIndex() > 1) return; if(tabs->currentIndex() > 1) return;
QMutexLocker locker(&DLListAccess);
QModelIndexList selectedIndexes; QModelIndexList selectedIndexes;
bool inDownloadList; bool inDownloadList;
if(tabs->currentIndex() == 0) { if(tabs->currentIndex() == 0) {
@ -1058,6 +1066,7 @@ void GUI::on_actionDelete_Permanently_triggered(){
// delete selected items in the list // delete selected items in the list
void GUI::on_actionDelete_triggered(){ void GUI::on_actionDelete_triggered(){
QMutexLocker locker(&DLListAccess);
if(tabs->currentIndex() > 1) return; if(tabs->currentIndex() > 1) return;
QModelIndexList selectedIndexes; QModelIndexList selectedIndexes;
bool inDownloadList = true; bool inDownloadList = true;
@ -1129,6 +1138,7 @@ void GUI::on_actionDelete_triggered(){
// Called when a torrent is added // Called when a torrent is added
void GUI::torrentAdded(QString path, torrent_handle& h, bool fastResume){ void GUI::torrentAdded(QString path, torrent_handle& h, bool fastResume){
QMutexLocker locker(&DLListAccess);
QString hash = QString(misc::toString(h.info_hash()).c_str()); QString hash = QString(misc::toString(h.info_hash()).c_str());
if(QFile::exists(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+hash+".finished")){ if(QFile::exists(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+hash+".finished")){
finishedTorrentTab->addFinishedSHA(hash); finishedTorrentTab->addFinishedSHA(hash);
@ -1371,6 +1381,7 @@ void GUI::configureSession(bool deleteOptions){
// Pause All Downloads in DL list // Pause All Downloads in DL list
void GUI::on_actionPause_All_triggered(){ void GUI::on_actionPause_All_triggered(){
QMutexLocker locker(&DLListAccess);
QString fileHash; QString fileHash;
// Pause all torrents // Pause all torrents
if(BTSession->pauseAllTorrents()){ if(BTSession->pauseAllTorrents()){
@ -1396,6 +1407,7 @@ void GUI::on_actionPause_All_triggered(){
// pause selected items in the list // pause selected items in the list
void GUI::on_actionPause_triggered(){ void GUI::on_actionPause_triggered(){
QMutexLocker locker(&DLListAccess);
QModelIndexList selectedIndexes = downloadList->selectionModel()->selectedIndexes(); QModelIndexList selectedIndexes = downloadList->selectionModel()->selectedIndexes();
QModelIndex index; QModelIndex index;
foreach(index, selectedIndexes){ foreach(index, selectedIndexes){
@ -1421,6 +1433,7 @@ void GUI::on_actionPause_triggered(){
// Resume All Downloads in DL list // Resume All Downloads in DL list
void GUI::on_actionStart_All_triggered(){ void GUI::on_actionStart_All_triggered(){
QMutexLocker locker(&DLListAccess);
QString fileHash; QString fileHash;
// Pause all torrents // Pause all torrents
if(BTSession->resumeAllTorrents()){ if(BTSession->resumeAllTorrents()){
@ -1440,6 +1453,7 @@ void GUI::on_actionStart_All_triggered(){
// start selected items in the list // start selected items in the list
void GUI::on_actionStart_triggered(){ void GUI::on_actionStart_triggered(){
QMutexLocker locker(&DLListAccess);
QModelIndexList selectedIndexes = downloadList->selectionModel()->selectedIndexes(); QModelIndexList selectedIndexes = downloadList->selectionModel()->selectedIndexes();
QModelIndex index; QModelIndex index;
foreach(index, selectedIndexes){ foreach(index, selectedIndexes){
@ -1486,6 +1500,7 @@ void GUI::on_actionTorrent_Properties_triggered(){
// called when a torrent has finished // called when a torrent has finished
void GUI::finishedTorrent(torrent_handle& h){ void GUI::finishedTorrent(torrent_handle& h){
QMutexLocker locker(&DLListAccess);
QSettings settings("qBittorrent", "qBittorrent"); QSettings settings("qBittorrent", "qBittorrent");
QString fileName = QString(h.name().c_str()); QString fileName = QString(h.name().c_str());
int useOSD = settings.value("Options/OSDEnabled", 1).toInt(); int useOSD = settings.value("Options/OSDEnabled", 1).toInt();

32
src/GUI.h

@ -23,7 +23,9 @@
#define GUI_H #define GUI_H
#include <QProcess> #include <QProcess>
#include <QThread>
#include <QSystemTrayIcon> #include <QSystemTrayIcon>
#include <QMutex>
#include <libtorrent/torrent_handle.hpp> #include <libtorrent/torrent_handle.hpp>
#include "ui_MainWindow.h" #include "ui_MainWindow.h"
@ -45,6 +47,7 @@ class about;
class previewSelect; class previewSelect;
class options_imp; class options_imp;
class QStandardItemModel; class QStandardItemModel;
class DownloadListRefresher;
using namespace libtorrent; using namespace libtorrent;
namespace fs = boost::filesystem; namespace fs = boost::filesystem;
@ -64,7 +67,6 @@ class GUI : public QMainWindow, private Ui::MainWindow{
// GUI related // GUI related
options_imp *options; options_imp *options;
createtorrent *createWindow; createtorrent *createWindow;
QTimer *refresher;
QSystemTrayIcon *myTrayIcon; QSystemTrayIcon *myTrayIcon;
QMenu *myTrayIconMenu; QMenu *myTrayIconMenu;
about *aboutdlg; about *aboutdlg;
@ -77,6 +79,8 @@ class GUI : public QMainWindow, private Ui::MainWindow{
bool force_exit; bool force_exit;
bool delayedSorting; bool delayedSorting;
Qt::SortOrder delayedSortingOrder; Qt::SortOrder delayedSortingOrder;
DownloadListRefresher *refresher;
QMutex DLListAccess;
// Keyboard shortcuts // Keyboard shortcuts
QShortcut *createShortcut; QShortcut *createShortcut;
QShortcut *openShortcut; QShortcut *openShortcut;
@ -111,7 +115,6 @@ class GUI : public QMainWindow, private Ui::MainWindow{
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 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_actionClearLog_triggered();
void on_actionWebsite_triggered(); void on_actionWebsite_triggered();
@ -190,6 +193,7 @@ class GUI : public QMainWindow, private Ui::MainWindow{
void setTabText(int index, QString text); void setTabText(int index, QString text);
void updateFileSize(QString hash); void updateFileSize(QString hash);
void sortProgressColumnDelayed(); void sortProgressColumnDelayed();
void updateDlList(bool force=false);
protected: protected:
void closeEvent(QCloseEvent *); void closeEvent(QCloseEvent *);
@ -202,6 +206,30 @@ class GUI : public QMainWindow, private Ui::MainWindow{
// Methods // Methods
int getRowFromHash(QString hash) const; int getRowFromHash(QString hash) const;
QPoint screenCenter(); QPoint screenCenter();
int getCurrentTab() const;
};
class DownloadListRefresher : public QThread {
private:
GUI* parent;
bool abort;
public:
DownloadListRefresher(GUI* parent){
this->parent = parent;
abort = false;
}
~DownloadListRefresher(){
abort = true;
wait();
}
protected:
void run(){
forever{
if(abort) return;
((GUI*)parent)->updateDlList();
msleep(1500);
}
}
}; };
#endif #endif

4
src/src.pro

@ -25,8 +25,8 @@ contains(DEBUG_MODE, 0){
message(Release build!) message(Release build!)
} }
QMAKE_CXXFLAGS_RELEASE += -fwrapv -O2 QMAKE_CXXFLAGS_RELEASE += -fwrapv
QMAKE_CXXFLAGS_DEBUG += -fwrapv -O2 QMAKE_CXXFLAGS_DEBUG += -fwrapv
CONFIG += link_pkgconfig CONFIG += link_pkgconfig
PKGCONFIG += libtorrent libccext2 libccgnu2 PKGCONFIG += libtorrent libccext2 libccgnu2

Loading…
Cancel
Save