diff --git a/TODO b/TODO index 11f7dcd6f..c7dec6ba7 100644 --- a/TODO +++ b/TODO @@ -46,6 +46,8 @@ - Translations update - .ico support? - display debug when fastresume data is rejected + - Fix icon bugs in rss tab + - Download/Finished lists cleanup - Wait for some bug fixes in libtorrent : - upload/download limit per torrent - ipfilter crash diff --git a/src/FinishedListDelegate.h b/src/FinishedListDelegate.h new file mode 100644 index 000000000..0c1035a52 --- /dev/null +++ b/src/FinishedListDelegate.h @@ -0,0 +1,145 @@ +/* + * 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 FINISHEDLISTDELEGATE_H +#define FINISHEDLISTDELEGATE_H + +#include +#include +#include +#include +#include +#include +#include "misc.h" + +// Defines for download list list columns +#define F_NAME 0 +#define F_SIZE 1 +#define F_PROGRESS 2 +#define F_UPSPEED 3 +#define F_SEEDSLEECH 4 +#define F_RATIO 5 +#define F_HASH 6 + +class FinishedListDelegate: public QAbstractItemDelegate { + Q_OBJECT + + public: + FinishedListDelegate(QObject *parent) : QAbstractItemDelegate(parent){} + + ~FinishedListDelegate(){} + + void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const{ + QStyleOptionViewItem opt = option; + char tmp[MAX_CHAR_TMP]; + // set text color + QVariant value = index.data(Qt::TextColorRole); + if (value.isValid() && qvariant_cast(value).isValid()){ + opt.palette.setColor(QPalette::Text, qvariant_cast(value)); + } + QPalette::ColorGroup cg = option.state & QStyle::State_Enabled + ? QPalette::Normal : QPalette::Disabled; + if (option.state & QStyle::State_Selected){ + painter->setPen(opt.palette.color(cg, QPalette::HighlightedText)); + }else{ + painter->setPen(opt.palette.color(cg, QPalette::Text)); + } + // draw the background color + if(index.column() != F_PROGRESS){ + if (option.showDecorationSelected && (option.state & QStyle::State_Selected)){ + if (cg == QPalette::Normal && !(option.state & QStyle::State_Active)){ + cg = QPalette::Inactive; + } + painter->fillRect(option.rect, option.palette.brush(cg, QPalette::Highlight)); + }else{ + value = index.data(Qt::BackgroundColorRole); + if (value.isValid() && qvariant_cast(value).isValid()){ + painter->fillRect(option.rect, qvariant_cast(value)); + } + } + } + switch(index.column()){ + case F_SIZE: + painter->drawText(option.rect, Qt::AlignCenter, misc::friendlyUnit(index.data().toLongLong())); + break; + case F_UPSPEED:{ + float speed = index.data().toDouble(); + snprintf(tmp, MAX_CHAR_TMP, "%.1f", speed/1024.); + painter->drawText(option.rect, Qt::AlignCenter, QString(tmp)+" "+tr("KiB/s")); + break; + } + case F_RATIO:{ + float ratio = index.data().toDouble(); + snprintf(tmp, MAX_CHAR_TMP, "%.1f", ratio); + painter->drawText(option.rect, Qt::AlignCenter, QString(tmp)); + break; + } + case F_PROGRESS:{ + QStyleOptionProgressBarV2 newopt; + float progress; + progress = index.data().toDouble()*100.; + snprintf(tmp, MAX_CHAR_TMP, "%.1f", progress); + newopt.rect = opt.rect; + newopt.text = QString(tmp)+"%"; + newopt.progress = (int)progress; + newopt.maximum = 100; + newopt.minimum = 0; + newopt.state |= QStyle::State_Enabled; + newopt.textVisible = false; + QApplication::style()->drawControl(QStyle::CE_ProgressBar, &newopt, + painter); + //We prefer to display text manually to control color/font/boldness + if (option.state & QStyle::State_Selected){ + opt.palette.setColor(QPalette::Text, QColor("grey")); + painter->setPen(opt.palette.color(cg, QPalette::Text)); + } + painter->drawText(option.rect, Qt::AlignCenter, newopt.text); + break; + } + case F_NAME:{ + // decoration + value = index.data(Qt::DecorationRole); + QPixmap pixmap = qvariant_cast(value).pixmap(option.decorationSize, option.state & QStyle::State_Enabled ? QIcon::Normal : QIcon::Disabled, option.state & QStyle::State_Open ? QIcon::On : QIcon::Off); + QRect pixmapRect = (pixmap.isNull() ? QRect(0, 0, 0, 0): QRect(QPoint(0, 0), option.decorationSize)); + if (pixmapRect.isValid()){ + QPoint p = QStyle::alignedRect(option.direction, Qt::AlignLeft, pixmap.size(), option.rect).topLeft(); + painter->drawPixmap(p, pixmap); + } + painter->drawText(option.rect.translated(pixmap.size().width(), 0), Qt::AlignLeft, index.data().toString()); + break; + } + default: + painter->drawText(option.rect, Qt::AlignCenter, index.data().toString()); + } + } + + QSize sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const{ + QVariant value = index.data(Qt::FontRole); + QFont fnt = value.isValid() ? qvariant_cast(value) : option.font; + QFontMetrics fontMetrics(fnt); + const QString text = index.data(Qt::DisplayRole).toString(); + QRect textRect = QRect(0, 0, 0, fontMetrics.lineSpacing() * (text.count(QLatin1Char('\n')) + 1)); + return textRect.size(); + } + +}; + +#endif diff --git a/src/FinishedTorrents.cpp b/src/FinishedTorrents.cpp index 281a50d86..53395f718 100644 --- a/src/FinishedTorrents.cpp +++ b/src/FinishedTorrents.cpp @@ -31,20 +31,16 @@ FinishedTorrents::FinishedTorrents(QObject *parent, bittorrent *BTSession){ nbFinished = 0; this->parent = parent; this->BTSession = BTSession; - finishedListModel = new QStandardItemModel(0,9); - finishedListModel->setHeaderData(NAME, Qt::Horizontal, tr("Name", "i.e: file name")); - finishedListModel->setHeaderData(SIZE, Qt::Horizontal, tr("Size", "i.e: file size")); - finishedListModel->setHeaderData(PROGRESS, Qt::Horizontal, tr("Progress", "i.e: % downloaded")); - finishedListModel->setHeaderData(DLSPEED, Qt::Horizontal, tr("DL Speed", "i.e: Download speed")); - finishedListModel->setHeaderData(UPSPEED, Qt::Horizontal, tr("UP Speed", "i.e: Upload speed")); - finishedListModel->setHeaderData(SEEDSLEECH, Qt::Horizontal, tr("Seeds/Leechs", "i.e: full/partial sources")); - finishedListModel->setHeaderData(RATIO, Qt::Horizontal, tr("Ratio")); - finishedListModel->setHeaderData(ETA, Qt::Horizontal, tr("ETA", "i.e: Estimated Time of Arrival / Time left")); + finishedListModel = new QStandardItemModel(0,7); + 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_PROGRESS, Qt::Horizontal, tr("Progress", "i.e: % downloaded")); + finishedListModel->setHeaderData(F_UPSPEED, Qt::Horizontal, tr("UP Speed", "i.e: Upload speed")); + finishedListModel->setHeaderData(F_SEEDSLEECH, Qt::Horizontal, tr("Seeds/Leechs", "i.e: full/partial sources")); + finishedListModel->setHeaderData(F_RATIO, Qt::Horizontal, tr("Ratio")); finishedList->setModel(finishedListModel); // Hide ETA & hash column - finishedList->hideColumn(HASH); - finishedList->hideColumn(ETA); - finishedList->hideColumn(DLSPEED); + finishedList->hideColumn(F_HASH); // Load last columns width for download list if(!loadColWidthFinishedList()){ finishedList->header()->resizeSection(0, 200); @@ -53,7 +49,7 @@ FinishedTorrents::FinishedTorrents(QObject *parent, bittorrent *BTSession){ finishedList->header()->setClickable(true); finishedList->header()->setSortIndicatorShown(true); connect(finishedList->header(), SIGNAL(sectionPressed(int)), this, SLOT(sortFinishedList(int))); - finishedListDelegate = new DLListDelegate(finishedList); + finishedListDelegate = new FinishedListDelegate(finishedList); finishedList->setItemDelegate(finishedListDelegate); connect(finishedList, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayFinishedListMenu(const QPoint&))); connect(finishedList, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(propertiesSelection())); @@ -84,15 +80,13 @@ void FinishedTorrents::addFinishedSHA(QString hash){ torrent_handle h = BTSession->getTorrentHandle(hash); // Adding torrent to download list finishedListModel->insertRow(row); - finishedListModel->setData(finishedListModel->index(row, NAME), QVariant(h.name().c_str())); - finishedListModel->setData(finishedListModel->index(row, SIZE), QVariant((qlonglong)h.get_torrent_info().total_size())); - finishedListModel->setData(finishedListModel->index(row, DLSPEED), QVariant((double)0.)); - finishedListModel->setData(finishedListModel->index(row, UPSPEED), QVariant((double)0.)); - finishedListModel->setData(finishedListModel->index(row, SEEDSLEECH), QVariant("0/0")); - finishedListModel->setData(finishedListModel->index(row, RATIO), QVariant(QString(misc::toString(BTSession->getRealRatio(hash)).c_str()))); - finishedListModel->setData(finishedListModel->index(row, ETA), QVariant((qlonglong)-1)); - finishedListModel->setData(finishedListModel->index(row, HASH), QVariant(hash)); - finishedListModel->setData(finishedListModel->index(row, PROGRESS), QVariant((double)1.)); + finishedListModel->setData(finishedListModel->index(row, F_NAME), QVariant(h.name().c_str())); + finishedListModel->setData(finishedListModel->index(row, F_SIZE), QVariant((qlonglong)h.get_torrent_info().total_size())); + finishedListModel->setData(finishedListModel->index(row, F_UPSPEED), QVariant((double)0.)); + finishedListModel->setData(finishedListModel->index(row, F_SEEDSLEECH), QVariant("0/0")); + finishedListModel->setData(finishedListModel->index(row, F_RATIO), QVariant(QString(misc::toString(BTSession->getRealRatio(hash)).c_str()))); + finishedListModel->setData(finishedListModel->index(row, F_HASH), QVariant(hash)); + finishedListModel->setData(finishedListModel->index(row, F_PROGRESS), QVariant((double)1.)); // Start the torrent if it was paused if(h.is_paused()) { h.resume(); @@ -100,7 +94,7 @@ void FinishedTorrents::addFinishedSHA(QString hash){ QFile::remove(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+hash+".paused"); } } - finishedListModel->setData(finishedListModel->index(row, NAME), QVariant(QIcon(":/Icons/skin/seeding.png")), Qt::DecorationRole); + finishedListModel->setData(finishedListModel->index(row, F_NAME), QVariant(QIcon(":/Icons/skin/seeding.png")), Qt::DecorationRole); setRowColor(row, "orange"); // Create .finished file QFile finished_file(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+hash+".finished"); @@ -132,11 +126,9 @@ void FinishedTorrents::sortFinishedList(int index){ } finishedList->header()->setSortIndicator(index, sortOrder); switch(index){ - case SIZE: - case ETA: - case UPSPEED: - case DLSPEED: - case PROGRESS: + case F_SIZE: + case F_UPSPEED: + case F_PROGRESS: sortFinishedListFloat(index, sortOrder); break; default: @@ -228,9 +220,9 @@ void FinishedTorrents::on_actionSet_upload_limit_triggered(){ QModelIndex index; QStringList hashes; foreach(index, selectedIndexes){ - if(index.column() == NAME){ + if(index.column() == F_NAME){ // Get the file hash - hashes << finishedListModel->data(finishedListModel->index(index.row(), HASH)).toString(); + hashes << finishedListModel->data(finishedListModel->index(index.row(), F_HASH)).toString(); } } new BandwidthAllocationDialog(this, true, BTSession, hashes); @@ -261,9 +253,9 @@ void FinishedTorrents::updateFinishedList(){ std::cerr << "ERROR: Can't find torrent in finished list\n"; continue; } - finishedListModel->setData(finishedListModel->index(row, UPSPEED), QVariant((double)torrentStatus.upload_payload_rate)); - finishedListModel->setData(finishedListModel->index(row, SEEDSLEECH), QVariant(QString(misc::toString(torrentStatus.num_seeds, true).c_str())+"/"+QString(misc::toString(torrentStatus.num_peers - torrentStatus.num_seeds, true).c_str()))); - finishedListModel->setData(finishedListModel->index(row, RATIO), QVariant(QString(misc::toString(BTSession->getRealRatio(hash)).c_str()))); + finishedListModel->setData(finishedListModel->index(row, F_UPSPEED), QVariant((double)torrentStatus.upload_payload_rate)); + finishedListModel->setData(finishedListModel->index(row, F_SEEDSLEECH), QVariant(QString(misc::toString(torrentStatus.num_seeds, true).c_str())+"/"+QString(misc::toString(torrentStatus.num_peers - torrentStatus.num_seeds, true).c_str()))); + finishedListModel->setData(finishedListModel->index(row, F_RATIO), QVariant(QString(misc::toString(BTSession->getRealRatio(hash)).c_str()))); } } @@ -274,7 +266,7 @@ QStringList FinishedTorrents::getFinishedSHAs(){ int FinishedTorrents::getRowFromHash(QString hash) const{ unsigned int nbRows = finishedListModel->rowCount(); for(unsigned int i=0; idata(finishedListModel->index(i, HASH)) == hash){ + if(finishedListModel->data(finishedListModel->index(i, F_HASH)) == hash){ return i; } } @@ -305,20 +297,26 @@ QStandardItemModel* FinishedTorrents::getFinishedListModel(){ // Show torrent properties dialog void FinishedTorrents::showProperties(const QModelIndex &index){ int row = index.row(); - QString fileHash = finishedListModel->data(finishedListModel->index(row, HASH)).toString(); + QString fileHash = finishedListModel->data(finishedListModel->index(row, F_HASH)).toString(); torrent_handle h = BTSession->getTorrentHandle(fileHash); QStringList errors = ((GUI*)parent)->trackerErrors.value(fileHash, QStringList(tr("None", "i.e: No error message"))); properties *prop = new properties(this, BTSession, h, errors); - connect(prop, SIGNAL(changedFilteredFiles(torrent_handle, bool)), BTSession, SLOT(reloadTorrent(torrent_handle, bool))); + connect(prop, SIGNAL(mustHaveFullAllocationMode(torrent_handle)), BTSession, SLOT(reloadTorrent(torrent_handle))); + connect(prop, SIGNAL(filteredFilesChanged(QString)), this, SLOT(updateFileSize(QString))); prop->show(); } +void FinishedTorrents::updateFileSize(QString hash){ + int row = getRowFromHash(hash); + finishedListModel->setData(finishedListModel->index(row, F_SIZE), QVariant((qlonglong)BTSession->torrentEffectiveSize(hash))); +} + // display properties of selected items void FinishedTorrents::propertiesSelection(){ QModelIndexList selectedIndexes = finishedList->selectionModel()->selectedIndexes(); QModelIndex index; foreach(index, selectedIndexes){ - if(index.column() == NAME){ + if(index.column() == F_NAME){ showProperties(index); } } @@ -332,9 +330,9 @@ void FinishedTorrents::displayFinishedListMenu(const QPoint& pos){ QSettings settings("qBittorrent", "qBittorrent"); QString previewProgram = settings.value("Options/Misc/PreviewProgram", QString()).toString(); foreach(index, selectedIndexes){ - if(index.column() == NAME){ + if(index.column() == F_NAME){ // Get the file name - QString fileHash = finishedListModel->data(finishedListModel->index(index.row(), HASH)).toString(); + QString fileHash = finishedListModel->data(finishedListModel->index(index.row(), F_HASH)).toString(); // Get handle and pause the torrent torrent_handle h = BTSession->getTorrentHandle(fileHash); myFinishedListMenu.addAction(actionDelete); diff --git a/src/FinishedTorrents.h b/src/FinishedTorrents.h index 5c235758f..bb19f0af0 100644 --- a/src/FinishedTorrents.h +++ b/src/FinishedTorrents.h @@ -24,7 +24,7 @@ #include "ui_seeding.h" #include "bittorrent.h" -#include "DLListDelegate.h" +#include "FinishedListDelegate.h" #include class FinishedTorrents : public QWidget, public Ui::seeding{ @@ -32,7 +32,7 @@ class FinishedTorrents : public QWidget, public Ui::seeding{ private: QObject *parent; bittorrent *BTSession; - DLListDelegate *finishedListDelegate; + FinishedListDelegate *finishedListDelegate; QStringList finishedSHAs; QStandardItemModel *finishedListModel; unsigned int nbFinished; @@ -59,6 +59,7 @@ class FinishedTorrents : public QWidget, public Ui::seeding{ void sortFinishedList(int index); void sortFinishedListFloat(int index, Qt::SortOrder sortOrder); void sortFinishedListString(int index, Qt::SortOrder sortOrder); + void updateFileSize(QString hash); protected slots: void on_actionSet_upload_limit_triggered(); diff --git a/src/src.pro b/src/src.pro index 4b7e02d54..0e2d01ea6 100644 --- a/src/src.pro +++ b/src/src.pro @@ -119,7 +119,7 @@ HEADERS += GUI.h misc.h options_imp.h about_imp.h \ torrentAddition.h deleteThread.h \ bittorrent.h searchEngine.h \ rss.h rss_imp.h FinishedTorrents.h \ - allocationDlg.h + allocationDlg.h FinishedListDelegate.h FORMS += MainWindow.ui options.ui about.ui \ properties.ui createtorrent.ui preview.ui \ login.ui downloadFromURL.ui addTorrentDialog.ui \