diff --git a/src/Icons/oxygen/office-chart-bar.png b/src/Icons/oxygen/office-chart-bar.png new file mode 100644 index 000000000..dd8ae4e42 Binary files /dev/null and b/src/Icons/oxygen/office-chart-bar.png differ diff --git a/src/icons.qrc b/src/icons.qrc index c0a6f6e2a..23f9b7867 100644 --- a/src/icons.qrc +++ b/src/icons.qrc @@ -294,6 +294,7 @@ Icons/oxygen/network-server.png Icons/oxygen/network-wired.png Icons/oxygen/object-locked.png + Icons/oxygen/office-chart-bar.png Icons/oxygen/preferences-desktop.png Icons/oxygen/preferences-other.png Icons/oxygen/preferences-system-network.png diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index fad5791d1..0c5c37057 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -123,6 +123,7 @@ MainWindow::MainWindow(QWidget *parent, const QStringList& torrentCmdLine) : QMa actionSet_global_download_limit->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/download.png"))); actionCreate_torrent->setIcon(IconProvider::instance()->getIcon("document-edit")); actionAbout->setIcon(IconProvider::instance()->getIcon("help-about")); + actionStatistics->setIcon(IconProvider::instance()->getIcon("office-chart-bar")); actionBugReport->setIcon(IconProvider::instance()->getIcon("tools-report-bug")); actionDecreasePriority->setIcon(IconProvider::instance()->getIcon("go-down")); actionDelete->setIcon(IconProvider::instance()->getIcon("list-remove")); @@ -361,6 +362,8 @@ MainWindow::~MainWindow() { delete m_executionLog; if (aboutDlg) delete aboutDlg; + if (statsDlg) + delete statsDlg; if (options) delete options; if (downloadFromURLDialog) @@ -740,6 +743,13 @@ void MainWindow::on_actionAbout_triggered() { } } +void MainWindow::on_actionStatistics_triggered() { + if (statsDlg) + statsDlg->setFocus(); + else + statsDlg = new StatsDialog(this); +} + void MainWindow::showEvent(QShowEvent *e) { qDebug("** Show Event **"); diff --git a/src/mainwindow.h b/src/mainwindow.h index 4c79ae762..e27ed6c9b 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -36,6 +36,7 @@ #include #include "ui_mainwindow.h" #include "qtorrenthandle.h" +#include "statsdialog.h" class QBtSession; class downloadFromURL; @@ -93,6 +94,7 @@ protected slots: void dragEnterEvent(QDragEnterEvent *event); void toggleVisibility(QSystemTrayIcon::ActivationReason e = QSystemTrayIcon::Trigger); void on_actionAbout_triggered(); + void on_actionStatistics_triggered(); void on_actionCreate_torrent_triggered(); void on_actionWebsite_triggered() const; void on_actionBugReport_triggered() const; @@ -165,6 +167,7 @@ private: QPointer options; QPointer console; QPointer aboutDlg; + QPointer statsDlg; QPointer createTorrentDlg; QPointer downloadFromURLDialog; QPointer systrayIcon; diff --git a/src/mainwindow.ui b/src/mainwindow.ui index dc1a75221..aa7eaaaa3 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -72,6 +72,7 @@ + @@ -375,6 +376,11 @@ Minimize + + + Statistics + + diff --git a/src/src.pro b/src/src.pro index 38be01971..01f51f16d 100644 --- a/src/src.pro +++ b/src/src.pro @@ -149,7 +149,8 @@ nox { updownratiodlg.h \ loglistwidget.h \ addnewtorrentdialog.h \ - autoexpandabledialog.h + autoexpandabledialog.h \ + statsdialog.h SOURCES += mainwindow.cpp \ ico.cpp \ @@ -167,7 +168,8 @@ nox { updownratiodlg.cpp \ loglistwidget.cpp \ addnewtorrentdialog.cpp \ - autoexpandabledialog.cpp + autoexpandabledialog.cpp \ + statsdialog.cpp win32 { HEADERS += programupdater.h @@ -193,7 +195,8 @@ nox { torrentimportdlg.ui \ executionlog.ui \ addnewtorrentdialog.ui \ - autoexpandabledialog.ui + autoexpandabledialog.ui \ + statsdialog.ui } DESTDIR = . diff --git a/src/statsdialog.cpp b/src/statsdialog.cpp new file mode 100644 index 000000000..14459f6c4 --- /dev/null +++ b/src/statsdialog.cpp @@ -0,0 +1,109 @@ +/* + * Bittorrent Client using Qt4 and libtorrent. + * Copyright (C) 2013 Nick Tiskov + * + * 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. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + * + * Contact : daymansmail@gmail.com + */ + +#include "statsdialog.h" +#include "ui_statsdialog.h" + +#include "misc.h" + +StatsDialog::StatsDialog(QWidget *parent) : QDialog(parent), ui(new Ui::StatsDialog) { + ui->setupUi(this); + setAttribute(Qt::WA_DeleteOnClose); + connect(ui->buttonOK, SIGNAL(clicked()), SLOT(close())); + session = QBtSession::instance(); + updateUI(); + t = new QTimer(this); + t->setInterval(1500); + connect(t, SIGNAL(timeout()), SLOT(updateUI())); + t->start(); + show(); +} + +StatsDialog::~StatsDialog() { + t->stop(); + delete t; + delete ui; +} + +void StatsDialog::updateUI() { + libtorrent::session* s = session->getSession(); + libtorrent::cache_status cache = s->get_cache_status(); + libtorrent::session_status ss = s->status(); + + // Alltime DL/UL + quint64 atd = session->getAlltimeDL(); + quint64 atu = session->getAlltimeUL(); + ui->labelAlltimeDL->setText(misc::friendlyUnit(atd)); + ui->labelAlltimeUL->setText(misc::friendlyUnit(atu)); + // Total waste (this session) + ui->labelWaste->setText(misc::friendlyUnit(ss.total_redundant_bytes + ss.total_failed_bytes)); + // Global ratio + ui->labelGlobalRatio->setText( + ( atd > 0 && atu > 0 ) ? + QString::number( (qreal)atu / (qreal)atd, 'f', 2) : + "-" + ); + // Cache hits + ui->labelCacheHits->setText( + ( cache.blocks_read > 0 && cache.blocks_read_hit > 0 ) ? + QString("%L1\%").arg(100. * (qreal)cache.blocks_read_hit / (qreal)cache.blocks_read, 0, 'f', 2) : + "-" + ); + // Buffers size + ui->labelTotalBuf->setText(misc::friendlyUnit(cache.total_used_buffers * 16 * 1024)); + // Disk overload (100%) equivalent + // From lt manual: disk_write_queue and disk_read_queue are the number of peers currently waiting on a disk write or disk read + // to complete before it receives or sends any more data on the socket. It'a a metric of how disk bound you are. + + // num_peers is not reliable (adds up peers, which didn't even overcome tcp handshake) + const std::vector torrents = session->getTorrents(); + std::vector::const_iterator iBegin = torrents.begin(); + std::vector::const_iterator iEnd = torrents.begin(); + quint32 peers = 0; + for ( ; iBegin < iEnd ; ++iBegin) + peers += (*iBegin).status().num_peers; + ui->labelWriteStarve->setText( + ( ss.disk_write_queue > 0 && peers > 0 ) ? + QString("%L1\%").arg(100. * (qreal)ss.disk_write_queue / (qreal)peers, 0, 'f', 2) : + QString("0\%") + ); + ui->labelReadStarve->setText( + ( ss.disk_read_queue > 0 && peers > 0 ) ? + QString("%L1\%").arg(100. * (qreal)ss.disk_read_queue / (qreal)peers, 0, 'f', 2) : + QString("0\%") + ); + // Disk queues + ui->labelQueuedJobs->setText(QString::number(cache.job_queue_length)); + ui->labelJobsTime->setText(QString::number(cache.average_job_time)); + ui->labelQueuedBytes->setText(misc::friendlyUnit(cache.queued_bytes)); + + // Total connected peers + ui->labelPeers->setText(QString::number(ss.num_peers)); +} diff --git a/src/statsdialog.h b/src/statsdialog.h new file mode 100644 index 000000000..004fde022 --- /dev/null +++ b/src/statsdialog.h @@ -0,0 +1,58 @@ +/* + * Bittorrent Client using Qt4 and libtorrent. + * Copyright (C) 2013 Nick Tiskov + * + * 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. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + * + * Contact : daymansmail@gmail.com + */ + +#ifndef STATSDIALOG_H +#define STATSDIALOG_H + +#include +#include +#include "qbtsession.h" + +namespace Ui { + class StatsDialog; +} + +class StatsDialog : public QDialog { + Q_OBJECT + +public: + explicit StatsDialog(QWidget *parent = 0); + ~StatsDialog(); + +private slots: + void updateUI(); + +private: + Ui::StatsDialog *ui; + QBtSession* session; + QTimer* t; +}; + +#endif // STATSDIALOG_H diff --git a/src/statsdialog.ui b/src/statsdialog.ui new file mode 100644 index 000000000..7829b15dc --- /dev/null +++ b/src/statsdialog.ui @@ -0,0 +1,253 @@ + + + StatsDialog + + + + 0 + 0 + 273 + 395 + + + + Statistics + + + + + + User statistics + + + + + + Total peer connections: + + + + + + + Global ratio: + + + + + + + TextLabel + + + + + + + Alltime download: + + + + + + + TextLabel + + + + + + + TextLabel + + + + + + + Alltime upload: + + + + + + + TextLabel + + + + + + + Total waste (this session): + + + + + + + TextLabel + + + + + + + + + + Cache statistics + + + + + + Read cache Hits: + + + + + + + TextLabel + + + + + + + TextLabel + + + + + + + Total buffers size: + + + + + + + + + + Performance statistics + + + + + + TextLabel + + + + + + + TextLabel + + + + + + + TextLabel + + + + + + + TextLabel + + + + + + + Queued I/O jobs: + + + + + + + Write cache overload: + + + + + + + Average time in queue (ms): + + + + + + + Read cache overload: + + + + + + + Total queued size: + + + + + + + TextLabel + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + OK + + + + + + + + + +