mirror of
https://github.com/d47081/qBittorrent.git
synced 2025-03-13 05:41:17 +00:00
- Huge forward porting of all previous properties features to the new properties panel (probably very buggy but most of the code should be there and it compiles)
This commit is contained in:
parent
6ecde51e45
commit
9bc90fc7b2
@ -43,26 +43,17 @@
|
||||
#include "misc.h"
|
||||
|
||||
// Defines for properties list columns
|
||||
#define NAME 0
|
||||
#define SIZE 1
|
||||
#define PROGRESS 2
|
||||
#define PRIORITY 3
|
||||
#define INDEX 4
|
||||
|
||||
#define IGNORED 0
|
||||
#define NORMAL 1
|
||||
#define HIGH 2
|
||||
#define MAXIMUM 7
|
||||
enum PropColumn {NAME, SIZE, PROGRESS, PRIORITY, INDEX};
|
||||
enum PropPriority {IGNORED=0, NORMAL=1, HIGH=2, MAXIMUM=7};
|
||||
|
||||
class PropListDelegate: public QItemDelegate {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
bool* filteredFilesChanged;
|
||||
signals:
|
||||
void filteredFilesChanged();
|
||||
|
||||
public:
|
||||
PropListDelegate(QObject *parent=0, bool* filteredFilesChanged=0) : QItemDelegate(parent){
|
||||
this->filteredFilesChanged = filteredFilesChanged;
|
||||
PropListDelegate(QObject *parent=0) : QItemDelegate(parent){
|
||||
}
|
||||
|
||||
~PropListDelegate(){}
|
||||
@ -165,7 +156,7 @@ class PropListDelegate: public QItemDelegate {
|
||||
}
|
||||
|
||||
public slots:
|
||||
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const {
|
||||
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) {
|
||||
QComboBox *combobox = static_cast<QComboBox*>(editor);
|
||||
int value = combobox->currentIndex();
|
||||
qDebug("Setting combobox value in index: %d", value);
|
||||
@ -174,8 +165,7 @@ class PropListDelegate: public QItemDelegate {
|
||||
case 0:
|
||||
if(old_val != IGNORED){
|
||||
model->setData(index, QVariant(IGNORED));
|
||||
if(filteredFilesChanged != 0)
|
||||
*filteredFilesChanged = true;
|
||||
emit filteredFilesChanged();
|
||||
} else {
|
||||
// XXX: hack to force the model to send the itemChanged() signal
|
||||
model->setData(index, QVariant(NORMAL));
|
||||
@ -190,15 +180,13 @@ class PropListDelegate: public QItemDelegate {
|
||||
// } else {
|
||||
model->setData(index, QVariant(HIGH));
|
||||
model->setData(index, QVariant(NORMAL));
|
||||
if(filteredFilesChanged != 0)
|
||||
*filteredFilesChanged = true;
|
||||
emit filteredFilesChanged();
|
||||
// }
|
||||
break;
|
||||
case 2:
|
||||
if(old_val != HIGH){
|
||||
model->setData(index, QVariant(HIGH));
|
||||
if(filteredFilesChanged != 0)
|
||||
*filteredFilesChanged = true;
|
||||
emit filteredFilesChanged();
|
||||
} else {
|
||||
model->setData(index, QVariant(NORMAL));
|
||||
model->setData(index, QVariant(HIGH));
|
||||
@ -207,8 +195,7 @@ class PropListDelegate: public QItemDelegate {
|
||||
case 3:
|
||||
if(old_val != MAXIMUM){
|
||||
model->setData(index, QVariant(MAXIMUM));
|
||||
if(filteredFilesChanged != 0)
|
||||
*filteredFilesChanged = true;
|
||||
emit filteredFilesChanged();
|
||||
} else {
|
||||
model->setData(index, QVariant(HIGH));
|
||||
model->setData(index, QVariant(MAXIMUM));
|
||||
@ -217,8 +204,7 @@ class PropListDelegate: public QItemDelegate {
|
||||
default:
|
||||
if(old_val != NORMAL){
|
||||
model->setData(index, QVariant(NORMAL));
|
||||
if(filteredFilesChanged != 0)
|
||||
*filteredFilesChanged = true;
|
||||
emit filteredFilesChanged();
|
||||
} else {
|
||||
model->setData(index, QVariant(HIGH));
|
||||
model->setData(index, QVariant(NORMAL));
|
||||
|
@ -832,3 +832,11 @@ void TransferListWidget::applyFilter(int f) {
|
||||
if(selectionModel()->selectedRows(0).empty() && proxyModel->rowCount() > 0)
|
||||
selectionModel()->setCurrentIndex(proxyModel->index(0, NAME), QItemSelectionModel::SelectCurrent|QItemSelectionModel::Rows);
|
||||
}
|
||||
|
||||
void TransferListWidget::updateTorrentSizeAndProgress(QString hash) {
|
||||
int row = getRowFromHash(hash);
|
||||
Q_ASSERT(row != -1);
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
listModel->setData(listModel->index(row, SIZE), QVariant((qlonglong)h.actual_size()));
|
||||
listModel->setData(listModel->index(row, PROGRESS), QVariant((double)h.progress()));
|
||||
}
|
||||
|
@ -101,6 +101,7 @@ public slots:
|
||||
void hidePriorityColumn(bool hide);
|
||||
void displayDLHoSMenu(const QPoint&);
|
||||
void applyFilter(int f);
|
||||
void updateTorrentSizeAndProgress(QString hash);
|
||||
|
||||
signals:
|
||||
void currentTorrentChanged(QTorrentHandle &h);
|
||||
|
@ -41,7 +41,7 @@ private:
|
||||
torrent_file *parent;
|
||||
bool is_dir;
|
||||
QString rel_path;
|
||||
QList<const torrent_file*> children;
|
||||
QList<torrent_file*> children;
|
||||
size_type size;
|
||||
float progress;
|
||||
int priority;
|
||||
@ -63,6 +63,19 @@ public:
|
||||
qDeleteAll(children);
|
||||
}
|
||||
|
||||
void updateProgress(std::vector<size_type> fp) {
|
||||
progress = fp[index]/size;
|
||||
Q_ASSERT(progress >= 0.);
|
||||
Q_ASSERT(progress <= 1.);
|
||||
// Update children
|
||||
foreach(torrent_file* child, children) {
|
||||
child->updateProgress(fp);
|
||||
}
|
||||
if(parent) {
|
||||
parent->updateProgress();
|
||||
}
|
||||
}
|
||||
|
||||
QString path() const {
|
||||
return rel_path;
|
||||
}
|
||||
@ -90,7 +103,7 @@ public:
|
||||
|
||||
void updatePriority(int prio) {
|
||||
Q_ASSERT(is_dir);
|
||||
foreach(const torrent_file *child, children) {
|
||||
foreach(torrent_file *child, children) {
|
||||
if(child->getPriority() != prio) return;
|
||||
}
|
||||
priority = prio;
|
||||
@ -120,13 +133,13 @@ public:
|
||||
return (!children.isEmpty());
|
||||
}
|
||||
|
||||
QList<const torrent_file*> getChildren() const {
|
||||
QList<torrent_file*> getChildren() const {
|
||||
return children;
|
||||
}
|
||||
|
||||
const torrent_file* getChild(QString fileName) const {
|
||||
torrent_file* getChild(QString fileName) const {
|
||||
Q_ASSERT(is_dir);
|
||||
foreach(const torrent_file *f, children) {
|
||||
foreach(torrent_file *f, children) {
|
||||
if(f->name() == fileName) return f;
|
||||
}
|
||||
return 0;
|
||||
@ -225,6 +238,10 @@ public:
|
||||
delete root;
|
||||
}
|
||||
|
||||
void updateFileProgress(std::vector<size_type> fp) {
|
||||
root->updateProgress(fp);
|
||||
}
|
||||
|
||||
torrent_file* getRoot() const {
|
||||
return root;
|
||||
}
|
||||
|
1080
src/properties.ui
1080
src/properties.ui
File diff suppressed because it is too large
Load Diff
@ -1,739 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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 : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#include "properties_imp.h"
|
||||
#include "misc.h"
|
||||
#include "PropListDelegate.h"
|
||||
#include "bittorrent.h"
|
||||
#include "arborescence.h"
|
||||
#include "realprogressbar.h"
|
||||
#include "realprogressbarthread.h"
|
||||
#include "TrackersAdditionDlg.h"
|
||||
#include "torrentPersistentData.h"
|
||||
|
||||
#include <QInputDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QMenu>
|
||||
#include <QTimer>
|
||||
#include <QStandardItemModel>
|
||||
#include <QSettings>
|
||||
#include <QDesktopWidget>
|
||||
#include <QFileDialog>
|
||||
#include <QHeaderView>
|
||||
|
||||
// Constructor
|
||||
properties::properties(QWidget *parent, bittorrent *BTSession, QTorrentHandle &h): QDialog(parent), h(h), BTSession(BTSession), changedFilteredfiles(false), hash(h.hash()) {
|
||||
setupUi(this);
|
||||
lbl_priorities->setText(tr("Priorities:")+"<ul><li>"+tr("Ignored: file is not downloaded at all")+"</li><li>"+tr("Normal: normal priority. Download order is dependent on availability")+"</li><li>"+tr("High: higher than normal priority. Pieces are preferred over pieces with the same availability, but not over pieces with lower availability")+"</li><li>"+tr("Maximum: maximum priority, availability is disregarded, the piece is preferred over any other piece with lower priority")+"</li></ul>");
|
||||
// set icons
|
||||
addTracker_button->setIcon(QIcon(QString::fromUtf8(":/Icons/oxygen/list-add.png")));
|
||||
removeTracker_button->setIcon(QIcon(QString::fromUtf8(":/Icons/oxygen/list-remove.png")));
|
||||
lowerTracker_button->setIcon(QIcon(QString::fromUtf8(":/Icons/downarrow.png")));
|
||||
riseTracker_button->setIcon(QIcon(QString::fromUtf8(":/Icons/uparrow.png")));
|
||||
addWS_button->setIcon(QIcon(QString::fromUtf8(":/Icons/oxygen/list-add.png")));
|
||||
deleteWS_button->setIcon(QIcon(QString::fromUtf8(":/Icons/oxygen/list-remove.png")));
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
// Set Properties list model
|
||||
PropListModel = new QStandardItemModel(0,5);
|
||||
PropListModel->setHeaderData(NAME, Qt::Horizontal, tr("File name"));
|
||||
PropListModel->setHeaderData(SIZE, Qt::Horizontal, tr("Size"));
|
||||
PropListModel->setHeaderData(PROGRESS, Qt::Horizontal, tr("Progress"));
|
||||
PropListModel->setHeaderData(PRIORITY, Qt::Horizontal, tr("Priority"));
|
||||
filesList->setModel(PropListModel);
|
||||
filesList->hideColumn(INDEX);
|
||||
PropDelegate = new PropListDelegate(0, &changedFilteredfiles);
|
||||
filesList->setItemDelegate(PropDelegate);
|
||||
connect(filesList, SIGNAL(clicked(const QModelIndex&)), filesList, SLOT(edit(const QModelIndex&)));
|
||||
connect(collapseAllButton, SIGNAL(clicked()), filesList, SLOT(collapseAll()));
|
||||
connect(expandAllButton, SIGNAL(clicked()), filesList, SLOT(expandAll()));
|
||||
connect(filesList, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayFilesListMenu(const QPoint&)));
|
||||
connect(addTracker_button, SIGNAL(clicked()), this, SLOT(askForTracker()));
|
||||
connect(removeTracker_button, SIGNAL(clicked()), this, SLOT(deleteSelectedTrackers()));
|
||||
connect(riseTracker_button, SIGNAL(clicked()), this, SLOT(riseSelectedTracker()));
|
||||
connect(lowerTracker_button, SIGNAL(clicked()), this, SLOT(lowerSelectedTracker()));
|
||||
connect(actionIgnored, SIGNAL(triggered()), this, SLOT(ignoreSelection()));
|
||||
connect(actionNormal, SIGNAL(triggered()), this, SLOT(normalSelection()));
|
||||
connect(actionHigh, SIGNAL(triggered()), this, SLOT(highSelection()));
|
||||
connect(actionMaximum, SIGNAL(triggered()), this, SLOT(maximumSelection()));
|
||||
connect(addWS_button, SIGNAL(clicked()), this, SLOT(askWebSeed()));
|
||||
connect(deleteWS_button, SIGNAL(clicked()), this, SLOT(deleteSelectedUrlSeeds()));
|
||||
// get Infos from torrent handle
|
||||
fileName->setText(h.name());
|
||||
// Torrent Infos
|
||||
save_path->setText(TorrentPersistentData::getSavePath(hash));
|
||||
QString author = h.creator().trimmed();
|
||||
if(author.isEmpty())
|
||||
author = tr("Unknown");
|
||||
creator->setText(author);
|
||||
hash_lbl->setText(hash);
|
||||
comment_txt->setText(h.comment());
|
||||
//Trackers
|
||||
loadTrackers();
|
||||
// Session infos
|
||||
failed->setText(misc::friendlyUnit(h.total_failed_bytes()));
|
||||
upTotal->setText(misc::friendlyUnit(h.total_payload_upload()));
|
||||
dlTotal->setText(misc::friendlyUnit(h.total_payload_download()));
|
||||
// Update ratio info
|
||||
float ratio;
|
||||
if(h.total_payload_download() == 0){
|
||||
if(h.total_payload_upload() == 0)
|
||||
ratio = 1.;
|
||||
else
|
||||
ratio = 10.; // Max ratio
|
||||
}else{
|
||||
ratio = (double)h.total_payload_upload()/(double)h.total_payload_download();
|
||||
if(ratio > 10.){
|
||||
ratio = 10.;
|
||||
}
|
||||
}
|
||||
shareRatio->setText(QString(QByteArray::number(ratio, 'f', 1)));
|
||||
std::vector<size_type> fp;
|
||||
h.file_progress(fp);
|
||||
std::vector<int> files_priority = loadFilesPriorities();
|
||||
// List files in torrent
|
||||
h.get_torrent_info();
|
||||
arborescence *arb = new arborescence(h.get_torrent_info(), fp, files_priority);
|
||||
addFilesToTree(arb->getRoot(), PropListModel->invisibleRootItem());
|
||||
delete arb;
|
||||
connect(PropListModel, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(updatePriorities(QStandardItem*)));
|
||||
filesList->expandAll();
|
||||
// List web seeds
|
||||
loadWebSeedsFromFile();
|
||||
loadWebSeeds();
|
||||
// Incremental download
|
||||
incrementalDownload->setChecked(TorrentPersistentData::isSequentialDownload(hash));
|
||||
updateInfosTimer = new QTimer(this);
|
||||
connect(updateInfosTimer, SIGNAL(timeout()), this, SLOT(updateInfos()));
|
||||
updateInfosTimer->start(3000);
|
||||
progressBar = new RealProgressBar(this);
|
||||
progressBar->setForegroundColor(Qt::blue);
|
||||
progressBarVbox = new QVBoxLayout(RealProgressBox);
|
||||
progressBarVbox->addWidget(progressBar);
|
||||
progressBarUpdater = new RealProgressBarThread(progressBar, h);
|
||||
progressBarUpdater->start();
|
||||
// progressBarUpdater->refresh();
|
||||
connect(updateInfosTimer, SIGNAL(timeout()), progressBarUpdater, SLOT(refresh()));
|
||||
loadSettings();
|
||||
}
|
||||
|
||||
properties::~properties(){
|
||||
writeSettings();
|
||||
qDebug("Properties destroyed");
|
||||
delete updateInfosTimer;
|
||||
delete PropDelegate;
|
||||
delete PropListModel;
|
||||
delete progressBarUpdater;
|
||||
delete progressBar;
|
||||
delete progressBarVbox;
|
||||
}
|
||||
|
||||
void properties::addFilesToTree(const torrent_file *root, QStandardItem *parent) {
|
||||
QList<QStandardItem*> child;
|
||||
// Name
|
||||
QStandardItem *first;
|
||||
if(root->isDir()) {
|
||||
first = new QStandardItem(QIcon(":/Icons/oxygen/folder.png"), root->name());
|
||||
} else {
|
||||
first = new QStandardItem(QIcon(":/Icons/oxygen/file.png"), root->name());
|
||||
}
|
||||
child << first;
|
||||
// Size
|
||||
child << new QStandardItem(misc::toQString(root->getSize()));
|
||||
// Progress
|
||||
child << new QStandardItem(misc::toQString(root->getProgress()));
|
||||
// Prio
|
||||
child << new QStandardItem(misc::toQString(root->getPriority()));
|
||||
// INDEX
|
||||
child << new QStandardItem(misc::toQString(root->getIndex()));
|
||||
// Add the child to the tree
|
||||
parent->appendRow(child);
|
||||
// Set row color
|
||||
if(root->getPriority() == IGNORED)
|
||||
setItemColor(first->index(), "red");
|
||||
else
|
||||
setItemColor(first->index(), "green");
|
||||
// Add childs
|
||||
foreach(const torrent_file *childFile, root->getChildren()) {
|
||||
addFilesToTree(childFile, first);
|
||||
}
|
||||
}
|
||||
|
||||
void properties::writeSettings() {
|
||||
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
||||
settings.beginGroup(QString::fromUtf8("PropWindow"));
|
||||
settings.setValue(QString::fromUtf8("size"), size());
|
||||
settings.setValue(QString::fromUtf8("pos"), pos());
|
||||
QVariantList contentColsWidths;
|
||||
for(int i=0; i<PropListModel->columnCount()-1; ++i) {
|
||||
contentColsWidths.append(filesList->columnWidth(i));
|
||||
}
|
||||
settings.setValue(QString::fromUtf8("contentColsWidths"), contentColsWidths);
|
||||
settings.endGroup();
|
||||
}
|
||||
|
||||
void properties::loadSettings() {
|
||||
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
||||
resize(settings.value(QString::fromUtf8("PropWindow/size"), size()).toSize());
|
||||
move(settings.value(QString::fromUtf8("PropWindow/pos"), screenCenter()).toPoint());
|
||||
QVariantList contentColsWidths = settings.value(QString::fromUtf8("PropWindow/contentColsWidths"), QVariantList()).toList();
|
||||
if(contentColsWidths.empty()) {
|
||||
filesList->header()->resizeSection(NAME, 200);
|
||||
} else {
|
||||
for(int i=0; i<contentColsWidths.size(); ++i) {
|
||||
filesList->setColumnWidth(i, contentColsWidths.at(i).toInt());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Center window
|
||||
QPoint properties::screenCenter() const{
|
||||
int scrn = 0;
|
||||
QWidget *w = this->topLevelWidget();
|
||||
|
||||
if(w)
|
||||
scrn = QApplication::desktop()->screenNumber(w);
|
||||
else if(QApplication::desktop()->isVirtualDesktop())
|
||||
scrn = QApplication::desktop()->screenNumber(QCursor::pos());
|
||||
else
|
||||
scrn = QApplication::desktop()->screenNumber(this);
|
||||
|
||||
QRect desk(QApplication::desktop()->availableGeometry(scrn));
|
||||
return QPoint((desk.width() - this->frameGeometry().width()) / 2, (desk.height() - this->frameGeometry().height()) / 2);
|
||||
}
|
||||
|
||||
// priority is the new priority of given item
|
||||
void properties::updateParentsPriority(QStandardItem *item, int priority) {
|
||||
QStandardItem *parent = item->parent();
|
||||
if(!parent) return;
|
||||
// Check if children have different priorities
|
||||
// then folder must have NORMAL priority
|
||||
unsigned int rowCount = parent->rowCount();
|
||||
for(unsigned int i=0; i<rowCount; ++i) {
|
||||
if(parent->child(i, PRIORITY)->text().toInt() != priority) {
|
||||
QStandardItem *grandFather = parent->parent();
|
||||
if(!grandFather) {
|
||||
grandFather = PropListModel->invisibleRootItem();
|
||||
}
|
||||
QStandardItem *parentPrio = grandFather->child(parent->row(), PRIORITY);
|
||||
if(parentPrio->text().toInt() != NORMAL) {
|
||||
parentPrio->setText(misc::toQString(NORMAL));
|
||||
setItemColor(parentPrio->index(), "green");
|
||||
// Recursively update ancesters of this parent too
|
||||
updateParentsPriority(grandFather->child(parent->row()), priority);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
// All the children have the same priority
|
||||
// Parent folder should have the same priority too
|
||||
QStandardItem *grandFather = parent->parent();
|
||||
if(!grandFather) {
|
||||
grandFather = PropListModel->invisibleRootItem();
|
||||
}
|
||||
QStandardItem *parentPrio = grandFather->child(parent->row(), PRIORITY);
|
||||
if(parentPrio->text().toInt() != priority) {
|
||||
parentPrio->setText(misc::toQString(priority));
|
||||
if(priority == IGNORED)
|
||||
setItemColor(parentPrio->index(), "red");
|
||||
else
|
||||
setItemColor(parentPrio->index(), "green");
|
||||
// Recursively update ancesters of this parent too
|
||||
updateParentsPriority(grandFather->child(parent->row()), priority);
|
||||
}
|
||||
}
|
||||
|
||||
void properties::updateChildrenPriority(QStandardItem *item, int priority) {
|
||||
QStandardItem *parent = item->parent();
|
||||
if(!parent) {
|
||||
parent = PropListModel->invisibleRootItem();
|
||||
}
|
||||
parent = parent->child(item->row());
|
||||
unsigned int rowCount = parent->rowCount();
|
||||
for(unsigned int i=0; i<rowCount; ++i) {
|
||||
QStandardItem * childPrio = parent->child(i, PRIORITY);
|
||||
if(childPrio->text().toInt() != priority) {
|
||||
childPrio->setText(misc::toQString(priority));
|
||||
if(priority == IGNORED)
|
||||
setItemColor(childPrio->index(), "red");
|
||||
else
|
||||
setItemColor(childPrio->index(), "green");
|
||||
// recursively update children of this child too
|
||||
updateChildrenPriority(parent->child(i), priority);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void properties::updatePriorities(QStandardItem *item) {
|
||||
qDebug("Priority changed");
|
||||
// First we disable the signal/slot on item edition
|
||||
// temporarily so that it doesn't mess with our manual updates
|
||||
disconnect(PropListModel, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(updatePriorities(QStandardItem*)));
|
||||
QStandardItem *parent = item->parent();
|
||||
if(!parent) {
|
||||
parent = PropListModel->invisibleRootItem();
|
||||
}
|
||||
int priority = parent->child(item->row(), PRIORITY)->text().toInt();
|
||||
if(priority == IGNORED)
|
||||
setItemColor(item->index(), "red");
|
||||
else
|
||||
setItemColor(item->index(), "green");
|
||||
// Update parents priorities
|
||||
updateParentsPriority(item, priority);
|
||||
// If this is not a directory, then there are
|
||||
// no children to update
|
||||
if(parent->child(item->row(), INDEX)->text().toInt() == -1) {
|
||||
// Updating children
|
||||
qDebug("Priority changed for a folder to %d", priority);
|
||||
updateChildrenPriority(item, priority);
|
||||
}
|
||||
// Reconnect the signal/slot on item edition so that we
|
||||
// get future updates
|
||||
connect(PropListModel, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(updatePriorities(QStandardItem*)));
|
||||
}
|
||||
|
||||
void properties::loadWebSeeds(){
|
||||
// Clear url seeds list
|
||||
listWebSeeds->clear();
|
||||
// Add manually added url seeds
|
||||
foreach(const QString &url_seed, urlSeeds){
|
||||
listWebSeeds->addItem(url_seed);
|
||||
qDebug("Added custom url seed to list: %s", url_seed.toLocal8Bit().data());
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<int> properties::loadFilesPriorities(){
|
||||
std::vector<int> fp;
|
||||
QVariantList files_priority = TorrentPersistentData::getFilesPriority(hash);
|
||||
if(files_priority.empty()) {
|
||||
for(int i=0; i<h.num_files(); ++i) {
|
||||
fp.push_back(1);
|
||||
}
|
||||
} else {
|
||||
foreach(const QVariant &var_prio, files_priority) {
|
||||
int priority = var_prio.toInt();
|
||||
if( priority < 0 || priority > 7){
|
||||
// Normal priority as default
|
||||
priority = 1;
|
||||
}
|
||||
fp.push_back(priority);
|
||||
}
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
bool properties::allFiltered() const {
|
||||
unsigned int nbRows = PropListModel->rowCount();
|
||||
for(unsigned int i=0; i<nbRows; ++i){
|
||||
if(PropListModel->data(PropListModel->index(i, PRIORITY)).toInt() != IGNORED)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void properties::getPriorities(QStandardItem *parent, int *priorities) {
|
||||
qDebug("In getPriorities");
|
||||
unsigned int nbRows = parent->rowCount();
|
||||
for(unsigned int i=0; i<nbRows; ++i){
|
||||
QStandardItem *item = parent->child(i, INDEX);
|
||||
int index = item->text().toInt();
|
||||
if(index < 0) {
|
||||
getPriorities(parent->child(i, NAME), priorities);
|
||||
} else {
|
||||
item = parent->child(i, PRIORITY);
|
||||
priorities[index] = item->text().toInt();
|
||||
qDebug("File at index %d has priority %d", index, priorities[index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void properties::displayFilesListMenu(const QPoint&){
|
||||
if(h.get_torrent_info().num_files() == 1) return;
|
||||
QMenu myFilesLlistMenu(this);
|
||||
QModelIndex index;
|
||||
// Enable/disable pause/start action given the DL state
|
||||
QModelIndexList selectedIndexes = filesList->selectionModel()->selectedIndexes();
|
||||
myFilesLlistMenu.setTitle(tr("Priority"));
|
||||
myFilesLlistMenu.addAction(actionIgnored);
|
||||
myFilesLlistMenu.addAction(actionNormal);
|
||||
myFilesLlistMenu.addAction(actionHigh);
|
||||
myFilesLlistMenu.addAction(actionMaximum);
|
||||
// Call menu
|
||||
myFilesLlistMenu.exec(QCursor::pos());
|
||||
}
|
||||
|
||||
void properties::ignoreSelection(){
|
||||
QModelIndexList selectedIndexes = filesList->selectionModel()->selectedIndexes();
|
||||
foreach(const QModelIndex &index, selectedIndexes){
|
||||
if(index.column() == PRIORITY){
|
||||
if(PropListModel->data(index) != QVariant(IGNORED)){
|
||||
PropListModel->setData(index, QVariant(IGNORED));
|
||||
changedFilteredfiles = true;
|
||||
setItemColor(index, "red");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void properties::normalSelection(){
|
||||
QModelIndexList selectedIndexes = filesList->selectionModel()->selectedIndexes();
|
||||
foreach(const QModelIndex &index, selectedIndexes){
|
||||
if(index.column() == PRIORITY){
|
||||
if(PropListModel->data(index) != QVariant(NORMAL)){
|
||||
PropListModel->setData(index, QVariant(NORMAL));
|
||||
changedFilteredfiles = true;
|
||||
setItemColor(index, "green");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void properties::highSelection(){
|
||||
QModelIndexList selectedIndexes = filesList->selectionModel()->selectedIndexes();
|
||||
foreach(const QModelIndex &index, selectedIndexes){
|
||||
if(index.column() == PRIORITY){
|
||||
if(PropListModel->data(index) != QVariant(HIGH)){
|
||||
PropListModel->setData(index, QVariant(HIGH));
|
||||
changedFilteredfiles = true;
|
||||
setItemColor(index, "green");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void properties::maximumSelection(){
|
||||
QModelIndexList selectedIndexes = filesList->selectionModel()->selectedIndexes();
|
||||
foreach(const QModelIndex &index, selectedIndexes){
|
||||
if(index.column() == PRIORITY){
|
||||
if(PropListModel->data(index) != QVariant(MAXIMUM)){
|
||||
PropListModel->setData(index, QVariant(MAXIMUM));
|
||||
changedFilteredfiles = true;
|
||||
setItemColor(index, "green");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void properties::loadTrackers(){
|
||||
//Trackers
|
||||
std::vector<announce_entry> trackers = h.trackers();
|
||||
trackersURLS->clear();
|
||||
QHash<QString, QString> errors = BTSession->getTrackersErrors(h.hash());
|
||||
unsigned int nbTrackers = trackers.size();
|
||||
for(unsigned int i=0; i<nbTrackers; ++i){
|
||||
QString current_tracker = misc::toQString(trackers[i].url);
|
||||
QListWidgetItem *item = new QListWidgetItem(current_tracker, trackersURLS);
|
||||
// IsThere any errors ?
|
||||
if(errors.contains(current_tracker)) {
|
||||
item->setForeground(QBrush(QColor("red")));
|
||||
// Set tooltip
|
||||
QString msg="";
|
||||
unsigned int i=0;
|
||||
foreach(QString word, errors[current_tracker].split(" ")) {
|
||||
if(i > 0 && i%5!=1) msg += " ";
|
||||
msg += word;
|
||||
if(i> 0 && i%5==0) msg += "\n";
|
||||
++i;
|
||||
}
|
||||
item->setToolTip(msg);
|
||||
} else {
|
||||
item->setForeground(QBrush(QColor("green")));
|
||||
}
|
||||
}
|
||||
QString tracker = h.current_tracker().trimmed();
|
||||
if(!tracker.isEmpty()){
|
||||
trackerURL->setText(tracker);
|
||||
}else{
|
||||
trackerURL->setText(tr("None - Unreachable?"));
|
||||
}
|
||||
}
|
||||
|
||||
void properties::askWebSeed(){
|
||||
bool ok;
|
||||
// Ask user for a new url seed
|
||||
QString url_seed = QInputDialog::getText(this, tr("New url seed", "New HTTP source"),
|
||||
tr("New url seed:"), QLineEdit::Normal,
|
||||
QString::fromUtf8("http://www."), &ok);
|
||||
if(!ok) return;
|
||||
qDebug("Adding %s web seed", url_seed.toLocal8Bit().data());
|
||||
if(urlSeeds.indexOf(url_seed) != -1) {
|
||||
QMessageBox::warning(this, tr("qBittorrent"),
|
||||
tr("This url seed is already in the list."),
|
||||
QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
urlSeeds << url_seed;
|
||||
h.add_url_seed(url_seed);
|
||||
TorrentPersistentData::saveUrlSeeds(h);
|
||||
// Refresh the seeds list
|
||||
loadWebSeeds();
|
||||
}
|
||||
|
||||
// Ask the user for a new tracker
|
||||
// and add it to the download list
|
||||
// if it is not already in it
|
||||
void properties::askForTracker(){
|
||||
TrackersAddDlg *dlg = new TrackersAddDlg(this);
|
||||
connect(dlg, SIGNAL(TrackersToAdd(QStringList)), this, SLOT(addTrackerList(QStringList)));
|
||||
}
|
||||
|
||||
void properties::addTrackerList(QStringList myTrackers) {
|
||||
// Add the trackers to the list
|
||||
std::vector<announce_entry> trackers = h.trackers();
|
||||
foreach(const QString& tracker, myTrackers) {
|
||||
announce_entry new_tracker(misc::toString(tracker.trimmed().toLocal8Bit().data()));
|
||||
new_tracker.tier = 0; // Will be fixed a bit later
|
||||
trackers.push_back(new_tracker);
|
||||
misc::fixTrackersTiers(trackers);
|
||||
}
|
||||
h.replace_trackers(trackers);
|
||||
h.force_reannounce();
|
||||
// Reload Trackers
|
||||
loadTrackers();
|
||||
emit trackersChanged(h.hash());
|
||||
}
|
||||
|
||||
void properties::deleteSelectedUrlSeeds(){
|
||||
QList<QListWidgetItem *> selectedItems = listWebSeeds->selectedItems();
|
||||
bool change = false;
|
||||
foreach(QListWidgetItem *item, selectedItems){
|
||||
QString url_seed = item->text();
|
||||
int index = urlSeeds.indexOf(url_seed);
|
||||
Q_ASSERT(index != -1);
|
||||
urlSeeds.removeAt(index);
|
||||
h.remove_url_seed(url_seed);
|
||||
change = true;
|
||||
}
|
||||
if(change){
|
||||
// Save them to disk
|
||||
TorrentPersistentData::saveUrlSeeds(h);
|
||||
// Refresh list
|
||||
loadWebSeeds();
|
||||
}
|
||||
}
|
||||
|
||||
void properties::deleteSelectedTrackers(){
|
||||
QList<QListWidgetItem *> selectedItems = trackersURLS->selectedItems();
|
||||
if(!selectedItems.size()) return;
|
||||
std::vector<announce_entry> trackers = h.trackers();
|
||||
unsigned int nbTrackers = trackers.size();
|
||||
if(nbTrackers == (unsigned int) selectedItems.size()){
|
||||
QMessageBox::warning(this, tr("qBittorrent"),
|
||||
tr("Trackers list can't be empty."),
|
||||
QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
foreach(QListWidgetItem *item, selectedItems){
|
||||
QString url = item->text();
|
||||
for(unsigned int i=0; i<nbTrackers; ++i){
|
||||
if(misc::toQString(trackers.at(i).url) == url){
|
||||
trackers.erase(trackers.begin()+i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
h.replace_trackers(trackers);
|
||||
h.force_reannounce();
|
||||
// Reload Trackers
|
||||
loadTrackers();
|
||||
emit trackersChanged(h.hash());
|
||||
}
|
||||
|
||||
void properties::riseSelectedTracker(){
|
||||
unsigned int i = 0;
|
||||
std::vector<announce_entry> trackers = h.trackers();
|
||||
QList<QListWidgetItem *> selectedItems = trackersURLS->selectedItems();
|
||||
bool change = false;
|
||||
unsigned int nbTrackers = trackers.size();
|
||||
foreach(QListWidgetItem *item, selectedItems){
|
||||
QString url = item->text();
|
||||
for(i=0; i<nbTrackers; ++i){
|
||||
if(misc::toQString(trackers.at(i).url) == url){
|
||||
qDebug("Asked to rise %s", trackers.at(i).url.c_str());
|
||||
qDebug("its tier was %d and will become %d", trackers[i].tier, trackers[i].tier-1);
|
||||
if(i > 0){
|
||||
announce_entry tmp = trackers[i];
|
||||
trackers[i] = trackers[i-1];
|
||||
trackers[i-1] = tmp;
|
||||
change = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(change){
|
||||
misc::fixTrackersTiers(trackers);
|
||||
h.replace_trackers(trackers);
|
||||
h.force_reannounce();
|
||||
// Reload Trackers
|
||||
loadTrackers();
|
||||
trackersURLS->item(i-1)->setSelected(true);
|
||||
emit trackersChanged(h.hash());
|
||||
}
|
||||
}
|
||||
|
||||
void properties::lowerSelectedTracker(){
|
||||
unsigned int i = 0;
|
||||
std::vector<announce_entry> trackers = h.trackers();
|
||||
QList<QListWidgetItem *> selectedItems = trackersURLS->selectedItems();
|
||||
bool change = false;
|
||||
unsigned int nbTrackers = trackers.size();
|
||||
foreach(QListWidgetItem *item, selectedItems){
|
||||
QString url = item->text();
|
||||
for(i=0; i<nbTrackers; ++i){
|
||||
if(misc::toQString(trackers.at(i).url) == url){
|
||||
qDebug("Asked to lower %s", trackers.at(i).url.c_str());
|
||||
qDebug("its tier was %d and will become %d", trackers[i].tier, trackers[i].tier+1);
|
||||
if(i < nbTrackers-1){
|
||||
announce_entry tmp = trackers[i];
|
||||
trackers[i] = trackers[i+1];
|
||||
trackers[i+1] = tmp;
|
||||
change = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(change){
|
||||
misc::fixTrackersTiers(trackers);
|
||||
h.replace_trackers(trackers);
|
||||
h.force_reannounce();
|
||||
// Reload Trackers
|
||||
loadTrackers();
|
||||
trackersURLS->item(i+1)->setSelected(true);
|
||||
emit trackersChanged(h.hash());
|
||||
}
|
||||
}
|
||||
|
||||
void properties::updateInfos(){
|
||||
// Update current tracker
|
||||
try {
|
||||
QString tracker = h.current_tracker().trimmed();
|
||||
if(!tracker.isEmpty()){
|
||||
trackerURL->setText(tracker);
|
||||
}else{
|
||||
trackerURL->setText(tr("None - Unreachable?"));
|
||||
}
|
||||
// XXX: This causes selection problems
|
||||
//loadTrackers();
|
||||
}catch(invalid_handle e){
|
||||
// torrent was removed, closing properties
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
void properties::setItemColor(QModelIndex index, QString color){
|
||||
for(int i=0; i<PropListModel->columnCount(); ++i){
|
||||
PropListModel->setData(index.sibling(index.row(), i), QVariant(QColor(color)), Qt::ForegroundRole);
|
||||
}
|
||||
}
|
||||
|
||||
void properties::on_incrementalDownload_stateChanged(int state){
|
||||
qDebug("Incremental download toggled");
|
||||
if(state == Qt::Checked){
|
||||
if(!TorrentPersistentData::isSequentialDownload(hash)) {
|
||||
h.set_sequential_download(true);
|
||||
TorrentPersistentData::saveSequentialStatus(h);
|
||||
}
|
||||
}else{
|
||||
h.set_sequential_download(false);
|
||||
TorrentPersistentData::saveSequentialStatus(h);
|
||||
}
|
||||
}
|
||||
|
||||
void properties::on_changeSavePathButton_clicked() {
|
||||
QString dir;
|
||||
QDir saveDir(h.save_path());
|
||||
if(saveDir.exists()){
|
||||
dir = QFileDialog::getExistingDirectory(this, tr("Choose save path"), h.save_path());
|
||||
}else{
|
||||
dir = QFileDialog::getExistingDirectory(this, tr("Choose save path"), QDir::homePath());
|
||||
}
|
||||
if(!dir.isNull()){
|
||||
// Check if savePath exists
|
||||
QDir savePath(dir);
|
||||
if(!savePath.exists()){
|
||||
if(!savePath.mkpath(savePath.path())){
|
||||
QMessageBox::critical(0, tr("Save path creation error"), tr("Could not create the save path"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Save savepath
|
||||
TorrentPersistentData::saveSavePath(hash, savePath.path());
|
||||
// Actually move storage
|
||||
if(!BTSession->useTemporaryFolder() || h.is_seed())
|
||||
h.move_storage(savePath.path());
|
||||
// Update save_path in dialog
|
||||
save_path->setText(savePath.path());
|
||||
}
|
||||
}
|
||||
|
||||
void properties::on_okButton_clicked(){
|
||||
if(savePiecesPriorities())
|
||||
close();
|
||||
}
|
||||
|
||||
void properties::loadWebSeedsFromFile(){
|
||||
urlSeeds.clear();
|
||||
QVariantList url_seeds = TorrentPersistentData::getUrlSeeds(hash);
|
||||
foreach(const QVariant &var_url_seed, url_seeds){
|
||||
QString url_seed = var_url_seed.toString();
|
||||
if(!url_seed.isEmpty())
|
||||
urlSeeds << url_seed;
|
||||
}
|
||||
// Load the hard-coded url seeds
|
||||
QStringList hc_seeds = h.url_seeds();
|
||||
// Add hard coded url seeds
|
||||
foreach(const QString &hc_seed, hc_seeds){
|
||||
if(urlSeeds.indexOf(hc_seed) == -1){
|
||||
urlSeeds << hc_seed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool properties::savePiecesPriorities() {
|
||||
if(!changedFilteredfiles) return true;
|
||||
if(allFiltered()) {
|
||||
QMessageBox::warning(0, tr("Priorities error"), tr("Error, you can't filter all the files in a torrent."));
|
||||
return false;
|
||||
}
|
||||
qDebug("Saving pieces priorities");
|
||||
int *priorities = new int[h.get_torrent_info().num_files()];
|
||||
getPriorities(PropListModel->invisibleRootItem(), priorities);
|
||||
unsigned int nbFiles = h.get_torrent_info().num_files();
|
||||
for(unsigned int i=0; i<nbFiles; ++i) {
|
||||
h.file_priority(i, priorities[i]);
|
||||
}
|
||||
delete[] priorities;
|
||||
TorrentPersistentData::saveFilesPriority(h);
|
||||
// Emit a signal so that the GUI updates the size
|
||||
emit filteredFilesChanged(hash);
|
||||
return true;
|
||||
}
|
@ -1,109 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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 : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#ifndef PROPERTIES_H
|
||||
#define PROPERTIES_H
|
||||
|
||||
#include "ui_properties.h"
|
||||
#include "qtorrenthandle.h"
|
||||
|
||||
class PropListDelegate;
|
||||
class QTimer;
|
||||
class bittorrent;
|
||||
class QStandardItemModel;
|
||||
class torrent_file;
|
||||
class QStandardItem;
|
||||
class RealProgressBar;
|
||||
class RealProgressBarThread;
|
||||
|
||||
using namespace libtorrent;
|
||||
|
||||
class properties : public QDialog, private Ui::properties{
|
||||
Q_OBJECT
|
||||
private:
|
||||
QTorrentHandle h;
|
||||
bittorrent *BTSession;
|
||||
bool changedFilteredfiles;
|
||||
QString hash;
|
||||
PropListDelegate *PropDelegate;
|
||||
QStandardItemModel *PropListModel;
|
||||
QTimer *updateInfosTimer;
|
||||
QStringList urlSeeds;
|
||||
RealProgressBar *progressBar;
|
||||
RealProgressBarThread *progressBarUpdater;
|
||||
QVBoxLayout *progressBarVbox;
|
||||
|
||||
protected slots:
|
||||
void on_okButton_clicked();
|
||||
void on_incrementalDownload_stateChanged(int);
|
||||
void setItemColor(QModelIndex index, QString color);
|
||||
void updateInfos();
|
||||
void askForTracker();
|
||||
void loadTrackers();
|
||||
void deleteSelectedTrackers();
|
||||
void lowerSelectedTracker();
|
||||
void riseSelectedTracker();
|
||||
void displayFilesListMenu(const QPoint& pos);
|
||||
void ignoreSelection();
|
||||
void normalSelection();
|
||||
void highSelection();
|
||||
void maximumSelection();
|
||||
void loadWebSeeds();
|
||||
void askWebSeed();
|
||||
void loadWebSeedsFromFile();
|
||||
void deleteSelectedUrlSeeds();
|
||||
void addFilesToTree(const torrent_file *root, QStandardItem *parent);
|
||||
void updateChildrenPriority(QStandardItem *item, int priority);
|
||||
void updateParentsPriority(QStandardItem *item, int priority);
|
||||
void updatePriorities(QStandardItem *item);
|
||||
void getPriorities(QStandardItem *parent, int *priorities);
|
||||
void addTrackerList(QStringList myTrackers);
|
||||
void writeSettings();
|
||||
void loadSettings();
|
||||
void on_changeSavePathButton_clicked();
|
||||
|
||||
signals:
|
||||
void filteredFilesChanged(QString hash);
|
||||
void fileSizeChanged(QString hash);
|
||||
void trackersChanged(QString hash);
|
||||
|
||||
public:
|
||||
// Constructor
|
||||
properties(QWidget *parent, bittorrent *BTSession, QTorrentHandle &h);
|
||||
~properties();
|
||||
bool allFiltered() const;
|
||||
bool savePiecesPriorities();
|
||||
std::vector<int> loadFilesPriorities();
|
||||
|
||||
protected:
|
||||
QPoint screenCenter() const;
|
||||
};
|
||||
|
||||
#endif
|
@ -30,15 +30,25 @@
|
||||
|
||||
#include <QTimer>
|
||||
#include <QListWidgetItem>
|
||||
#include <QStandardItemModel>
|
||||
#include <QStandardItem>
|
||||
#include <QVBoxLayout>
|
||||
#include <QStackedWidget>
|
||||
#include <QSplitter>
|
||||
#include <QAction>
|
||||
#include <QMessageBox>
|
||||
#include <QMenu>
|
||||
#include <QFileDialog>
|
||||
#include <QInputDialog>
|
||||
#include "propertieswidget.h"
|
||||
#include "TransferListWidget.h"
|
||||
#include "torrentPersistentData.h"
|
||||
#include "realprogressbar.h"
|
||||
#include "realprogressbarthread.h"
|
||||
#include "arborescence.h"
|
||||
#include "bittorrent.h"
|
||||
#include "PropListDelegate.h"
|
||||
#include "TrackersAdditionDlg.h"
|
||||
|
||||
#define DEFAULT_BUTTON_CSS "QPushButton {border: 1px solid rgb(85, 81, 91);border-radius: 3px;padding: 2px;}"
|
||||
#define SELECTED_BUTTON_CSS "QPushButton {border: 1px solid rgb(85, 81, 91);border-radius: 3px;padding: 2px;background-color: rgb(255, 208, 105);}"
|
||||
@ -54,15 +64,51 @@ PropertiesWidget::PropertiesWidget(QWidget *parent, TransferListWidget *transfer
|
||||
setEnabled(false);
|
||||
}
|
||||
|
||||
// Set Properties list model
|
||||
PropListModel = new QStandardItemModel(0,5);
|
||||
PropListModel->setHeaderData(NAME, Qt::Horizontal, tr("File name"));
|
||||
PropListModel->setHeaderData(SIZE, Qt::Horizontal, tr("Size"));
|
||||
PropListModel->setHeaderData(PROGRESS, Qt::Horizontal, tr("Progress"));
|
||||
PropListModel->setHeaderData(PRIORITY, Qt::Horizontal, tr("Priority"));
|
||||
filesList->setModel(PropListModel);
|
||||
filesList->hideColumn(INDEX);
|
||||
PropDelegate = new PropListDelegate(0);
|
||||
filesList->setItemDelegate(PropDelegate);
|
||||
|
||||
// QActions
|
||||
actionIgnored = new QAction(this);
|
||||
actionNormal = new QAction(this);
|
||||
actionMaximum = new QAction(this);
|
||||
actionHigh = new QAction(this);
|
||||
|
||||
// SIGNAL/SLOTS
|
||||
connect(filesList, SIGNAL(clicked(const QModelIndex&)), filesList, SLOT(edit(const QModelIndex&)));
|
||||
connect(collapseAllButton, SIGNAL(clicked()), filesList, SLOT(collapseAll()));
|
||||
connect(expandAllButton, SIGNAL(clicked()), filesList, SLOT(expandAll()));
|
||||
connect(filesList, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayFilesListMenu(const QPoint&)));
|
||||
connect(addTracker_button, SIGNAL(clicked()), this, SLOT(askForTracker()));
|
||||
connect(removeTracker_button, SIGNAL(clicked()), this, SLOT(deleteSelectedTrackers()));
|
||||
connect(riseTracker_button, SIGNAL(clicked()), this, SLOT(riseSelectedTracker()));
|
||||
connect(lowerTracker_button, SIGNAL(clicked()), this, SLOT(lowerSelectedTracker()));
|
||||
connect(actionIgnored, SIGNAL(triggered()), this, SLOT(ignoreSelection()));
|
||||
connect(actionNormal, SIGNAL(triggered()), this, SLOT(normalSelection()));
|
||||
connect(actionHigh, SIGNAL(triggered()), this, SLOT(highSelection()));
|
||||
connect(actionMaximum, SIGNAL(triggered()), this, SLOT(maximumSelection()));
|
||||
connect(addWS_button, SIGNAL(clicked()), this, SLOT(askWebSeed()));
|
||||
connect(deleteWS_button, SIGNAL(clicked()), this, SLOT(deleteSelectedUrlSeeds()));
|
||||
connect(transferList, SIGNAL(currentTorrentChanged(QTorrentHandle&)), this, SLOT(loadTorrentInfos(QTorrentHandle &)));
|
||||
connect(incrementalDownload, SIGNAL(stateChanged(int)), this, SLOT(setIncrementalDownload(int)));
|
||||
connect(PropListModel, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(updatePriorities(QStandardItem*)));
|
||||
connect(PropDelegate, SIGNAL(filteredFilesChanged()), this, SLOT(filteredFilesChanged()));
|
||||
|
||||
// Downloaded pieces progress bar
|
||||
progressBar = new RealProgressBar(this);
|
||||
progressBar->setForegroundColor(Qt::blue);
|
||||
progressBarVbox = new QVBoxLayout(RealProgressBox);
|
||||
progressBarVbox->addWidget(progressBar);
|
||||
// Pointers init
|
||||
progressBarUpdater = 0;
|
||||
arb = 0;
|
||||
// Dynamic data refresher
|
||||
refreshTimer = new QTimer(this);
|
||||
connect(refreshTimer, SIGNAL(timeout()), this, SLOT(loadDynamicData()));
|
||||
@ -77,6 +123,14 @@ PropertiesWidget::~PropertiesWidget() {
|
||||
delete progressBarUpdater;
|
||||
delete progressBar;
|
||||
delete progressBarVbox;
|
||||
delete PropListModel;
|
||||
if(arb)
|
||||
delete arb;
|
||||
// Delete QActions
|
||||
delete actionIgnored;
|
||||
delete actionNormal;
|
||||
delete actionMaximum;
|
||||
delete actionHigh;
|
||||
}
|
||||
|
||||
void PropertiesWidget::reduce() {
|
||||
@ -116,9 +170,14 @@ void PropertiesWidget::loadTorrentInfos(QTorrentHandle &_h) {
|
||||
return;
|
||||
}
|
||||
setEnabled(true);
|
||||
if(progressBarUpdater)
|
||||
if(progressBarUpdater) {
|
||||
delete progressBarUpdater;
|
||||
progressBarUpdater = 0;
|
||||
progressBarUpdater = 0;
|
||||
}
|
||||
if(arb != 0) {
|
||||
delete arb;
|
||||
arb = 0;
|
||||
}
|
||||
try {
|
||||
// Save path
|
||||
save_path->setText(TorrentPersistentData::getSavePath(h.hash()));
|
||||
@ -140,6 +199,13 @@ void PropertiesWidget::loadTorrentInfos(QTorrentHandle &_h) {
|
||||
// downloaded pieces updater
|
||||
progressBarUpdater = new RealProgressBarThread(progressBar, h);
|
||||
progressBarUpdater->start();
|
||||
// Create arborescence (Tree representation of files in the torrent)
|
||||
std::vector<size_type> fp;
|
||||
h.file_progress(fp);
|
||||
std::vector<int> files_priority = loadFilesPriorities();
|
||||
// List files in torrent
|
||||
arborescence *arb = new arborescence(h.get_torrent_info(), fp, files_priority);
|
||||
addFilesToTree(arb->getRoot(), PropListModel->invisibleRootItem());
|
||||
} catch(invalid_handle e) {
|
||||
|
||||
}
|
||||
@ -293,3 +359,428 @@ void PropertiesWidget::on_files_button_clicked() {
|
||||
files_button->setStyleSheet(SELECTED_BUTTON_CSS);
|
||||
}
|
||||
}
|
||||
|
||||
// priority is the new priority of given item
|
||||
void PropertiesWidget::updateParentsPriority(QStandardItem *item, int priority) {
|
||||
QStandardItem *parent = item->parent();
|
||||
if(!parent) return;
|
||||
// Check if children have different priorities
|
||||
// then folder must have NORMAL priority
|
||||
unsigned int rowCount = parent->rowCount();
|
||||
for(unsigned int i=0; i<rowCount; ++i) {
|
||||
if(parent->child(i, PRIORITY)->text().toInt() != priority) {
|
||||
QStandardItem *grandFather = parent->parent();
|
||||
if(!grandFather) {
|
||||
grandFather = PropListModel->invisibleRootItem();
|
||||
}
|
||||
QStandardItem *parentPrio = grandFather->child(parent->row(), PRIORITY);
|
||||
if(parentPrio->text().toInt() != NORMAL) {
|
||||
parentPrio->setText(misc::toQString(NORMAL));
|
||||
setItemColor(parentPrio->index(), "green");
|
||||
// Recursively update ancesters of this parent too
|
||||
updateParentsPriority(grandFather->child(parent->row()), priority);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
// All the children have the same priority
|
||||
// Parent folder should have the same priority too
|
||||
QStandardItem *grandFather = parent->parent();
|
||||
if(!grandFather) {
|
||||
grandFather = PropListModel->invisibleRootItem();
|
||||
}
|
||||
QStandardItem *parentPrio = grandFather->child(parent->row(), PRIORITY);
|
||||
if(parentPrio->text().toInt() != priority) {
|
||||
parentPrio->setText(misc::toQString(priority));
|
||||
if(priority == IGNORED)
|
||||
setItemColor(parentPrio->index(), "red");
|
||||
else
|
||||
setItemColor(parentPrio->index(), "green");
|
||||
// Recursively update ancesters of this parent too
|
||||
updateParentsPriority(grandFather->child(parent->row()), priority);
|
||||
}
|
||||
}
|
||||
|
||||
void PropertiesWidget::updateChildrenPriority(QStandardItem *item, int priority) {
|
||||
QStandardItem *parent = item->parent();
|
||||
if(!parent) {
|
||||
parent = PropListModel->invisibleRootItem();
|
||||
}
|
||||
parent = parent->child(item->row());
|
||||
unsigned int rowCount = parent->rowCount();
|
||||
for(unsigned int i=0; i<rowCount; ++i) {
|
||||
QStandardItem * childPrio = parent->child(i, PRIORITY);
|
||||
if(childPrio->text().toInt() != priority) {
|
||||
childPrio->setText(misc::toQString(priority));
|
||||
if(priority == IGNORED)
|
||||
setItemColor(childPrio->index(), "red");
|
||||
else
|
||||
setItemColor(childPrio->index(), "green");
|
||||
// recursively update children of this child too
|
||||
updateChildrenPriority(parent->child(i), priority);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PropertiesWidget::updatePriorities(QStandardItem *item) {
|
||||
qDebug("Priority changed");
|
||||
// First we disable the signal/slot on item edition
|
||||
// temporarily so that it doesn't mess with our manual updates
|
||||
disconnect(PropListModel, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(updatePriorities(QStandardItem*)));
|
||||
QStandardItem *parent = item->parent();
|
||||
if(!parent) {
|
||||
parent = PropListModel->invisibleRootItem();
|
||||
}
|
||||
int priority = parent->child(item->row(), PRIORITY)->text().toInt();
|
||||
if(priority == IGNORED)
|
||||
setItemColor(item->index(), "red");
|
||||
else
|
||||
setItemColor(item->index(), "green");
|
||||
// Update parents priorities
|
||||
updateParentsPriority(item, priority);
|
||||
// If this is not a directory, then there are
|
||||
// no children to update
|
||||
if(parent->child(item->row(), INDEX)->text().toInt() == -1) {
|
||||
// Updating children
|
||||
qDebug("Priority changed for a folder to %d", priority);
|
||||
updateChildrenPriority(item, priority);
|
||||
}
|
||||
// Reconnect the signal/slot on item edition so that we
|
||||
// get future updates
|
||||
connect(PropListModel, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(updatePriorities(QStandardItem*)));
|
||||
}
|
||||
|
||||
std::vector<int> PropertiesWidget::loadFilesPriorities(){
|
||||
std::vector<int> fp;
|
||||
QVariantList files_priority = TorrentPersistentData::getFilesPriority(h.hash());
|
||||
if(files_priority.empty()) {
|
||||
for(int i=0; i<h.num_files(); ++i) {
|
||||
fp.push_back(1);
|
||||
}
|
||||
} else {
|
||||
foreach(const QVariant &var_prio, files_priority) {
|
||||
int priority = var_prio.toInt();
|
||||
if( priority < 0 || priority > 7){
|
||||
// Normal priority as default
|
||||
priority = 1;
|
||||
}
|
||||
fp.push_back(priority);
|
||||
}
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
bool PropertiesWidget::allFiltered() const {
|
||||
unsigned int nbRows = PropListModel->rowCount();
|
||||
for(unsigned int i=0; i<nbRows; ++i){
|
||||
if(PropListModel->data(PropListModel->index(i, PRIORITY)).toInt() != IGNORED)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void PropertiesWidget::getPriorities(QStandardItem *parent, int *priorities) {
|
||||
qDebug("In getPriorities");
|
||||
unsigned int nbRows = parent->rowCount();
|
||||
for(unsigned int i=0; i<nbRows; ++i){
|
||||
QStandardItem *item = parent->child(i, INDEX);
|
||||
int index = item->text().toInt();
|
||||
if(index < 0) {
|
||||
getPriorities(parent->child(i, NAME), priorities);
|
||||
} else {
|
||||
item = parent->child(i, PRIORITY);
|
||||
priorities[index] = item->text().toInt();
|
||||
qDebug("File at index %d has priority %d", index, priorities[index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PropertiesWidget::displayFilesListMenu(const QPoint&){
|
||||
if(h.get_torrent_info().num_files() == 1) return;
|
||||
QMenu myFilesLlistMenu(this);
|
||||
QModelIndex index;
|
||||
// Enable/disable pause/start action given the DL state
|
||||
QModelIndexList selectedIndexes = filesList->selectionModel()->selectedIndexes();
|
||||
myFilesLlistMenu.setTitle(tr("Priority"));
|
||||
myFilesLlistMenu.addAction(actionIgnored);
|
||||
myFilesLlistMenu.addAction(actionNormal);
|
||||
myFilesLlistMenu.addAction(actionHigh);
|
||||
myFilesLlistMenu.addAction(actionMaximum);
|
||||
// Call menu
|
||||
myFilesLlistMenu.exec(QCursor::pos());
|
||||
}
|
||||
|
||||
void PropertiesWidget::ignoreSelection(){
|
||||
QModelIndexList selectedIndexes = filesList->selectionModel()->selectedIndexes();
|
||||
foreach(const QModelIndex &index, selectedIndexes){
|
||||
if(index.column() == PRIORITY){
|
||||
if(PropListModel->data(index) != QVariant(IGNORED)){
|
||||
PropListModel->setData(index, QVariant(IGNORED));
|
||||
transferList->updateTorrentSizeAndProgress(h.hash());
|
||||
setItemColor(index, "red");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PropertiesWidget::normalSelection(){
|
||||
QModelIndexList selectedIndexes = filesList->selectionModel()->selectedIndexes();
|
||||
foreach(const QModelIndex &index, selectedIndexes){
|
||||
if(index.column() == PRIORITY){
|
||||
if(PropListModel->data(index) != QVariant(NORMAL)){
|
||||
PropListModel->setData(index, QVariant(NORMAL));
|
||||
transferList->updateTorrentSizeAndProgress(h.hash());
|
||||
setItemColor(index, "green");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PropertiesWidget::highSelection(){
|
||||
QModelIndexList selectedIndexes = filesList->selectionModel()->selectedIndexes();
|
||||
foreach(const QModelIndex &index, selectedIndexes){
|
||||
if(index.column() == PRIORITY){
|
||||
if(PropListModel->data(index) != QVariant(HIGH)){
|
||||
PropListModel->setData(index, QVariant(HIGH));
|
||||
transferList->updateTorrentSizeAndProgress(h.hash());
|
||||
setItemColor(index, "green");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PropertiesWidget::maximumSelection(){
|
||||
QModelIndexList selectedIndexes = filesList->selectionModel()->selectedIndexes();
|
||||
foreach(const QModelIndex &index, selectedIndexes){
|
||||
if(index.column() == PRIORITY){
|
||||
if(PropListModel->data(index) != QVariant(MAXIMUM)){
|
||||
PropListModel->setData(index, QVariant(MAXIMUM));
|
||||
transferList->updateTorrentSizeAndProgress(h.hash());
|
||||
setItemColor(index, "green");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PropertiesWidget::askWebSeed(){
|
||||
bool ok;
|
||||
// Ask user for a new url seed
|
||||
QString url_seed = QInputDialog::getText(this, tr("New url seed", "New HTTP source"),
|
||||
tr("New url seed:"), QLineEdit::Normal,
|
||||
QString::fromUtf8("http://www."), &ok);
|
||||
if(!ok) return;
|
||||
qDebug("Adding %s web seed", url_seed.toLocal8Bit().data());
|
||||
if(!listWebSeeds->findItems(url_seed, Qt::MatchFixedString).empty()) {
|
||||
QMessageBox::warning(this, tr("qBittorrent"),
|
||||
tr("This url seed is already in the list."),
|
||||
QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
h.add_url_seed(url_seed);
|
||||
TorrentPersistentData::saveUrlSeeds(h);
|
||||
// Refresh the seeds list
|
||||
loadUrlSeeds();
|
||||
}
|
||||
|
||||
// Ask the user for a new tracker
|
||||
// and add it to the download list
|
||||
// if it is not already in it
|
||||
void PropertiesWidget::askForTracker(){
|
||||
TrackersAddDlg *dlg = new TrackersAddDlg(this);
|
||||
connect(dlg, SIGNAL(TrackersToAdd(QStringList)), this, SLOT(addTrackerList(QStringList)));
|
||||
}
|
||||
|
||||
void PropertiesWidget::addTrackerList(QStringList myTrackers) {
|
||||
// Add the trackers to the list
|
||||
std::vector<announce_entry> trackers = h.trackers();
|
||||
foreach(const QString& tracker, myTrackers) {
|
||||
announce_entry new_tracker(misc::toString(tracker.trimmed().toLocal8Bit().data()));
|
||||
new_tracker.tier = 0; // Will be fixed a bit later
|
||||
trackers.push_back(new_tracker);
|
||||
misc::fixTrackersTiers(trackers);
|
||||
}
|
||||
h.replace_trackers(trackers);
|
||||
h.force_reannounce();
|
||||
// Reload Trackers
|
||||
loadTrackers();
|
||||
BTSession->saveTrackerFile(h.hash());
|
||||
}
|
||||
|
||||
void PropertiesWidget::deleteSelectedUrlSeeds(){
|
||||
QList<QListWidgetItem *> selectedItems = listWebSeeds->selectedItems();
|
||||
bool change = false;
|
||||
foreach(QListWidgetItem *item, selectedItems){
|
||||
QString url_seed = item->text();
|
||||
h.remove_url_seed(url_seed);
|
||||
change = true;
|
||||
}
|
||||
if(change){
|
||||
// Save them to disk
|
||||
TorrentPersistentData::saveUrlSeeds(h);
|
||||
// Refresh list
|
||||
loadUrlSeeds();
|
||||
}
|
||||
}
|
||||
|
||||
void PropertiesWidget::deleteSelectedTrackers(){
|
||||
QList<QListWidgetItem *> selectedItems = trackersURLS->selectedItems();
|
||||
if(!selectedItems.size()) return;
|
||||
std::vector<announce_entry> trackers = h.trackers();
|
||||
unsigned int nbTrackers = trackers.size();
|
||||
if(nbTrackers == (unsigned int) selectedItems.size()){
|
||||
QMessageBox::warning(this, tr("qBittorrent"),
|
||||
tr("Trackers list can't be empty."),
|
||||
QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
foreach(QListWidgetItem *item, selectedItems){
|
||||
QString url = item->text();
|
||||
for(unsigned int i=0; i<nbTrackers; ++i){
|
||||
if(misc::toQString(trackers.at(i).url) == url){
|
||||
trackers.erase(trackers.begin()+i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
h.replace_trackers(trackers);
|
||||
h.force_reannounce();
|
||||
// Reload Trackers
|
||||
loadTrackers();
|
||||
BTSession->saveTrackerFile(h.hash());
|
||||
}
|
||||
|
||||
void PropertiesWidget::riseSelectedTracker(){
|
||||
unsigned int i = 0;
|
||||
std::vector<announce_entry> trackers = h.trackers();
|
||||
QList<QListWidgetItem *> selectedItems = trackersURLS->selectedItems();
|
||||
bool change = false;
|
||||
unsigned int nbTrackers = trackers.size();
|
||||
foreach(QListWidgetItem *item, selectedItems){
|
||||
QString url = item->text();
|
||||
for(i=0; i<nbTrackers; ++i){
|
||||
if(misc::toQString(trackers.at(i).url) == url){
|
||||
qDebug("Asked to rise %s", trackers.at(i).url.c_str());
|
||||
qDebug("its tier was %d and will become %d", trackers[i].tier, trackers[i].tier-1);
|
||||
if(i > 0){
|
||||
announce_entry tmp = trackers[i];
|
||||
trackers[i] = trackers[i-1];
|
||||
trackers[i-1] = tmp;
|
||||
change = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(change){
|
||||
misc::fixTrackersTiers(trackers);
|
||||
h.replace_trackers(trackers);
|
||||
h.force_reannounce();
|
||||
// Reload Trackers
|
||||
loadTrackers();
|
||||
trackersURLS->item(i-1)->setSelected(true);
|
||||
BTSession->saveTrackerFile(h.hash());
|
||||
}
|
||||
}
|
||||
|
||||
void PropertiesWidget::lowerSelectedTracker(){
|
||||
unsigned int i = 0;
|
||||
std::vector<announce_entry> trackers = h.trackers();
|
||||
QList<QListWidgetItem *> selectedItems = trackersURLS->selectedItems();
|
||||
bool change = false;
|
||||
unsigned int nbTrackers = trackers.size();
|
||||
foreach(QListWidgetItem *item, selectedItems){
|
||||
QString url = item->text();
|
||||
for(i=0; i<nbTrackers; ++i){
|
||||
if(misc::toQString(trackers.at(i).url) == url){
|
||||
qDebug("Asked to lower %s", trackers.at(i).url.c_str());
|
||||
qDebug("its tier was %d and will become %d", trackers[i].tier, trackers[i].tier+1);
|
||||
if(i < nbTrackers-1){
|
||||
announce_entry tmp = trackers[i];
|
||||
trackers[i] = trackers[i+1];
|
||||
trackers[i+1] = tmp;
|
||||
change = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(change){
|
||||
misc::fixTrackersTiers(trackers);
|
||||
h.replace_trackers(trackers);
|
||||
h.force_reannounce();
|
||||
// Reload Trackers
|
||||
loadTrackers();
|
||||
trackersURLS->item(i+1)->setSelected(true);
|
||||
BTSession->saveTrackerFile(h.hash());
|
||||
}
|
||||
}
|
||||
|
||||
void PropertiesWidget::setItemColor(QModelIndex index, QString color){
|
||||
for(int i=0; i<PropListModel->columnCount(); ++i){
|
||||
PropListModel->setData(index.sibling(index.row(), i), QVariant(QColor(color)), Qt::ForegroundRole);
|
||||
}
|
||||
}
|
||||
|
||||
void PropertiesWidget::on_changeSavePathButton_clicked() {
|
||||
QString dir;
|
||||
QDir saveDir(h.save_path());
|
||||
if(saveDir.exists()){
|
||||
dir = QFileDialog::getExistingDirectory(this, tr("Choose save path"), h.save_path());
|
||||
}else{
|
||||
dir = QFileDialog::getExistingDirectory(this, tr("Choose save path"), QDir::homePath());
|
||||
}
|
||||
if(!dir.isNull()){
|
||||
// Check if savePath exists
|
||||
QDir savePath(dir);
|
||||
if(!savePath.exists()){
|
||||
if(!savePath.mkpath(savePath.path())){
|
||||
QMessageBox::critical(0, tr("Save path creation error"), tr("Could not create the save path"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Save savepath
|
||||
TorrentPersistentData::saveSavePath(h.hash(), savePath.path());
|
||||
// Actually move storage
|
||||
if(!BTSession->useTemporaryFolder() || h.is_seed())
|
||||
h.move_storage(savePath.path());
|
||||
// Update save_path in dialog
|
||||
save_path->setText(savePath.path());
|
||||
}
|
||||
}
|
||||
|
||||
void PropertiesWidget::filteredFilesChanged() {
|
||||
if(h.is_valid())
|
||||
transferList->updateTorrentSizeAndProgress(h.hash());
|
||||
}
|
||||
|
||||
void PropertiesWidget::addFilesToTree(torrent_file *root, QStandardItem *parent) {
|
||||
QList<QStandardItem*> child;
|
||||
// Name
|
||||
QStandardItem *first;
|
||||
if(root->isDir()) {
|
||||
first = new QStandardItem(QIcon(":/Icons/oxygen/folder.png"), root->name());
|
||||
} else {
|
||||
first = new QStandardItem(QIcon(":/Icons/oxygen/file.png"), root->name());
|
||||
}
|
||||
child << first;
|
||||
// Size
|
||||
child << new QStandardItem(misc::toQString(root->getSize()));
|
||||
// Progress
|
||||
child << new QStandardItem(misc::toQString(root->getProgress()));
|
||||
// Prio
|
||||
child << new QStandardItem(misc::toQString(root->getPriority()));
|
||||
// INDEX
|
||||
child << new QStandardItem(misc::toQString(root->getIndex()));
|
||||
// Add the child to the tree
|
||||
parent->appendRow(child);
|
||||
// Set row color
|
||||
if(root->getPriority() == IGNORED)
|
||||
setItemColor(first->index(), "red");
|
||||
else
|
||||
setItemColor(first->index(), "green");
|
||||
// Add childs
|
||||
foreach(torrent_file *childFile, root->getChildren()) {
|
||||
addFilesToTree(childFile, first);
|
||||
}
|
||||
}
|
||||
|
@ -41,6 +41,12 @@ class RealProgressBar;
|
||||
class QVBoxLayout;
|
||||
class RealProgressBarThread;
|
||||
class bittorrent;
|
||||
class arborescence;
|
||||
class QStandardItemModel;
|
||||
class PropListDelegate;
|
||||
class QStandardItem;
|
||||
class QAction;
|
||||
class torrent_file;
|
||||
|
||||
enum Tab {MAIN_TAB, TRACKERS_TAB, URLSEEDS_TAB, FILES_TAB};
|
||||
enum SlideState {REDUCED, VISIBLE};
|
||||
@ -57,9 +63,18 @@ private:
|
||||
QVBoxLayout *progressBarVbox;
|
||||
bittorrent* BTSession;
|
||||
SlideState state;
|
||||
arborescence *arb;
|
||||
QStandardItemModel *PropListModel;
|
||||
PropListDelegate *PropDelegate;
|
||||
QAction *actionIgnored;
|
||||
QAction *actionNormal;
|
||||
QAction *actionMaximum;
|
||||
QAction *actionHigh;
|
||||
|
||||
protected:
|
||||
QPushButton* getButtonFromIndex(int index);
|
||||
std::vector<int> loadFilesPriorities();
|
||||
bool allFiltered() const;
|
||||
|
||||
protected slots:
|
||||
void loadTorrentInfos(QTorrentHandle &h);
|
||||
@ -71,6 +86,26 @@ protected slots:
|
||||
void on_trackers_button_clicked();
|
||||
void on_url_seeds_button_clicked();
|
||||
void on_files_button_clicked();
|
||||
void updateChildrenPriority(QStandardItem *item, int priority);
|
||||
void updateParentsPriority(QStandardItem *item, int priority);
|
||||
void updatePriorities(QStandardItem *item);
|
||||
void ignoreSelection();
|
||||
void normalSelection();
|
||||
void highSelection();
|
||||
void maximumSelection();
|
||||
void askWebSeed();
|
||||
void deleteSelectedUrlSeeds();
|
||||
void askForTracker();
|
||||
void deleteSelectedTrackers();
|
||||
void lowerSelectedTracker();
|
||||
void riseSelectedTracker();
|
||||
void displayFilesListMenu(const QPoint& pos);
|
||||
void setItemColor(QModelIndex index, QString color);
|
||||
void on_changeSavePathButton_clicked();
|
||||
void addFilesToTree(torrent_file *root, QStandardItem *parent);
|
||||
void getPriorities(QStandardItem *parent, int *priorities);
|
||||
void addTrackerList(QStringList myTrackers);
|
||||
void filteredFilesChanged();
|
||||
|
||||
public slots:
|
||||
void reduce();
|
||||
|
159
src/seeding.ui
159
src/seeding.ui
@ -1,159 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>seeding</class>
|
||||
<widget class="QWidget" name="seeding">
|
||||
<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">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTreeView" name="finishedList">
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lbl_note">
|
||||
<property name="font">
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><u>Note:</u> It is important that you keep sharing your torrents after they are finished for the well being of the network.</string>
|
||||
</property>
|
||||
</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="actionDelete_Permanently">
|
||||
<property name="text">
|
||||
<string>Delete Permanently</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionTorrent_Properties">
|
||||
<property name="text">
|
||||
<string>Torrent Properties</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="actionOpen_destination_folder">
|
||||
<property name="icon">
|
||||
<iconset resource="icons.qrc">
|
||||
<normaloff>:/Icons/oxygen/folder.png</normaloff>:/Icons/oxygen/folder.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Open destination folder</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionHOSColName">
|
||||
<property name="text">
|
||||
<string>Name</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionHOSColSize">
|
||||
<property name="text">
|
||||
<string>Size</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionHOSColUpSpeed">
|
||||
<property name="text">
|
||||
<string>Upload Speed</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionHOSColPeers">
|
||||
<property name="text">
|
||||
<string>Connected peers</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Connected peers</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionHOSColRatio">
|
||||
<property name="text">
|
||||
<string>Ratio</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionBuy_it">
|
||||
<property name="icon">
|
||||
<iconset resource="icons.qrc">
|
||||
<normaloff>:/Icons/oxygen/wallet.png</normaloff>:/Icons/oxygen/wallet.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Buy it</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionForce_recheck">
|
||||
<property name="icon">
|
||||
<iconset resource="icons.qrc">
|
||||
<normaloff>:/Icons/oxygen/gear.png</normaloff>:/Icons/oxygen/gear.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Force recheck</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionHOSColUpload">
|
||||
<property name="text">
|
||||
<string>Total uploaded</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionHOSColSwarm">
|
||||
<property name="text">
|
||||
<string>Seeds / Leechers</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Seeds / Leechers</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionCopy_magnet_link">
|
||||
<property name="text">
|
||||
<string>Copy magnet link</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="icons.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
@ -143,7 +143,6 @@ HEADERS += GUI.h \
|
||||
misc.h \
|
||||
options_imp.h \
|
||||
about_imp.h \
|
||||
properties_imp.h \
|
||||
createtorrent_imp.h \
|
||||
SearchListDelegate.h \
|
||||
PropListDelegate.h \
|
||||
@ -189,7 +188,6 @@ HEADERS += GUI.h \
|
||||
FORMS += MainWindow.ui \
|
||||
options.ui \
|
||||
about.ui \
|
||||
properties.ui \
|
||||
createtorrent.ui \
|
||||
preview.ui \
|
||||
login.ui \
|
||||
@ -197,7 +195,6 @@ FORMS += MainWindow.ui \
|
||||
addTorrentDialog.ui \
|
||||
search.ui \
|
||||
rss.ui \
|
||||
seeding.ui \
|
||||
bandwidth_limit.ui \
|
||||
engineSelect.ui \
|
||||
pluginSource.ui \
|
||||
@ -208,7 +205,6 @@ FORMS += MainWindow.ui \
|
||||
SOURCES += GUI.cpp \
|
||||
main.cpp \
|
||||
options_imp.cpp \
|
||||
properties_imp.cpp \
|
||||
createtorrent_imp.cpp \
|
||||
bittorrent.cpp \
|
||||
searchEngine.cpp \
|
||||
|
@ -179,8 +179,8 @@ public:
|
||||
// set row Color
|
||||
setItemColor(first->index(), "green");
|
||||
// Add children
|
||||
QList<const torrent_file*> children = root->getChildren();
|
||||
foreach(const torrent_file *child, children) {
|
||||
QList<torrent_file*> children = root->getChildren();
|
||||
foreach(torrent_file *child, children) {
|
||||
addFilesToTree(child, first);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user