diff --git a/src/PropListDelegate.h b/src/PropListDelegate.h index 6bd694c5d..d77bbb5fe 100644 --- a/src/PropListDelegate.h +++ b/src/PropListDelegate.h @@ -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(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)); diff --git a/src/TransferListWidget.cpp b/src/TransferListWidget.cpp index 2dfc949de..e5d9d84d1 100644 --- a/src/TransferListWidget.cpp +++ b/src/TransferListWidget.cpp @@ -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())); +} diff --git a/src/TransferListWidget.h b/src/TransferListWidget.h index 7e451af3a..b6de5da87 100644 --- a/src/TransferListWidget.h +++ b/src/TransferListWidget.h @@ -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); diff --git a/src/arborescence.h b/src/arborescence.h index 5b6ff0f87..bad1919a9 100644 --- a/src/arborescence.h +++ b/src/arborescence.h @@ -41,7 +41,7 @@ private: torrent_file *parent; bool is_dir; QString rel_path; - QList children; + QList children; size_type size; float progress; int priority; @@ -63,6 +63,19 @@ public: qDeleteAll(children); } + void updateProgress(std::vector 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 getChildren() const { + QList 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 fp) { + root->updateProgress(fp); + } + torrent_file* getRoot() const { return root; } diff --git a/src/properties.ui b/src/properties.ui deleted file mode 100644 index 2f83b0d11..000000000 --- a/src/properties.ui +++ /dev/null @@ -1,1080 +0,0 @@ - - - properties - - - - 0 - 0 - 594 - 621 - - - - Torrent Properties - - - - 6 - - - 9 - - - - - 0 - - - - Main info - - - - - - - 16777215 - 20 - - - - - Sans Serif - 9 - 75 - false - true - false - false - - - - - - - Qt::AlignCenter - - - - - - - Qt::Horizontal - - - - - - - - 75 - true - - - - Torrent information - - - - - - - - 6 - - - 0 - - - - - - 0 - 29 - - - - - 75 - true - - - - Save path: - - - - - - - - 0 - 28 - - - - - 75 - true - - - - Creator: - - - - - - - - 0 - 29 - - - - - 75 - true - - - - Torrent hash: - - - - - - - - 0 - 128 - - - - - 16777215 - 120 - - - - - 75 - true - - - - Comment: - - - - - - - - - - - - - - 0 - 29 - - - - - - - - - - - - 21 - 0 - - - - - 21 - 16777215 - - - - ... - - - - - - - - - - 0 - 28 - - - - - - - - - - - - 0 - 29 - - - - - - - - - - - - 16777215 - 120 - - - - false - - - true - - - false - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - - 0 - 50 - - - - - 75 - true - - - - Downloaded pieces - - - - - - - - 0 - 0 - - - - - 0 - 115 - - - - - Sans Serif - 9 - 75 - false - true - false - false - - - - Current session - - - - 6 - - - 9 - - - - - 6 - - - 0 - - - - - 6 - - - 0 - - - - - - Sans Serif - 9 - 50 - false - false - false - false - - - - Total uploaded: - - - - - - - - Sans Serif - 9 - 50 - false - false - false - false - - - - Total downloaded: - - - - - - - - Sans Serif - 9 - 50 - false - false - false - false - - - - Share ratio: - - - - - - - - Sans Serif - 9 - 50 - false - false - false - false - - - - Total failed: - - - - - - - - - 6 - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Qt::Horizontal - - - - 181 - 20 - - - - - - - - - - - - - - Sans Serif - 9 - 50 - false - false - false - false - - - - Download in correct order (slower but good for previewing) - - - - - - - - Trackers - - - - - - 6 - - - 0 - - - - - - Sans Serif - 9 - 50 - false - false - false - false - - - - Trackers: - - - - - - - 6 - - - 0 - - - - - - 0 - 0 - - - - QAbstractItemView::ExtendedSelection - - - - - - - 6 - - - 0 - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 24 - 24 - - - - - 24 - 24 - - - - - - - - - - - - 24 - 24 - - - - - 24 - 24 - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - 6 - - - 0 - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - 24 - 24 - - - - - 24 - 24 - - - - - - - - - - - - 24 - 24 - - - - - 24 - 24 - - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - 6 - - - 0 - - - - - - 16777215 - 16 - - - - - Sans Serif - 9 - 50 - false - false - false - false - - - - Current tracker: - - - - - - - - 16777215 - 16 - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Qt::Vertical - - - QSizePolicy::Minimum - - - - 20 - 40 - - - - - - - - - Url seeds - - - - 6 - - - 9 - - - - - - 75 - true - - - - The following url seeds are available for this torrent: - - - - - - - - - - 6 - - - 0 - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 24 - 24 - - - - - - - - - - - - 24 - 24 - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - Torrent content - - - - - - - Sans Serif - 9 - 75 - false - true - false - false - - - - Files contained in current torrent: - - - - - - - - 0 - 301 - - - - Qt::CustomContextMenu - - - QAbstractItemView::AllEditTriggers - - - QAbstractItemView::ExtendedSelection - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Collapse all - - - - - - - Expand all - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - Sans Serif - 8 - 50 - false - false - false - false - - - - - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - true - - - - - - - - - - - 6 - - - 0 - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - OK - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Ignored - - - - - Normal - - - - - Maximum - - - - - High - - - - - - - okButton - clicked() - properties - accept() - - - 306 - 556 - - - 96 - 254 - - - - - diff --git a/src/properties_imp.cpp b/src/properties_imp.cpp deleted file mode 100644 index efe99c0ae..000000000 --- a/src/properties_imp.cpp +++ /dev/null @@ -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 -#include -#include -#include -#include -#include -#include -#include -#include - -// 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:")+"
  • "+tr("Ignored: file is not downloaded at all")+"
  • "+tr("Normal: normal priority. Download order is dependent on availability")+"
  • "+tr("High: higher than normal priority. Pieces are preferred over pieces with the same availability, but not over pieces with lower availability")+"
  • "+tr("Maximum: maximum priority, availability is disregarded, the piece is preferred over any other piece with lower priority")+"
"); - // 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 fp; - h.file_progress(fp); - std::vector 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 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; icolumnCount()-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; isetColumnWidth(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; ichild(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; ichild(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 properties::loadFilesPriorities(){ - std::vector fp; - QVariantList files_priority = TorrentPersistentData::getFilesPriority(hash); - if(files_priority.empty()) { - for(int i=0; i 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; idata(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; ichild(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 trackers = h.trackers(); - trackersURLS->clear(); - QHash errors = BTSession->getTrackersErrors(h.hash()); - unsigned int nbTrackers = trackers.size(); - for(unsigned int i=0; isetForeground(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 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 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 selectedItems = trackersURLS->selectedItems(); - if(!selectedItems.size()) return; - std::vector 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 trackers = h.trackers(); - QList selectedItems = trackersURLS->selectedItems(); - bool change = false; - unsigned int nbTrackers = trackers.size(); - foreach(QListWidgetItem *item, selectedItems){ - QString url = item->text(); - for(i=0; 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 trackers = h.trackers(); - QList selectedItems = trackersURLS->selectedItems(); - bool change = false; - unsigned int nbTrackers = trackers.size(); - foreach(QListWidgetItem *item, selectedItems){ - QString url = item->text(); - for(i=0; iitem(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; icolumnCount(); ++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 loadFilesPriorities(); - - protected: - QPoint screenCenter() const; -}; - -#endif diff --git a/src/propertieswidget.cpp b/src/propertieswidget.cpp index a784650b3..82d667ed2 100644 --- a/src/propertieswidget.cpp +++ b/src/propertieswidget.cpp @@ -30,15 +30,25 @@ #include #include +#include +#include #include #include #include +#include +#include +#include +#include +#include #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 fp; + h.file_progress(fp); + std::vector 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; ichild(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; ichild(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 PropertiesWidget::loadFilesPriorities(){ + std::vector fp; + QVariantList files_priority = TorrentPersistentData::getFilesPriority(h.hash()); + if(files_priority.empty()) { + for(int i=0; i 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; idata(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; ichild(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 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 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 selectedItems = trackersURLS->selectedItems(); + if(!selectedItems.size()) return; + std::vector 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; isaveTrackerFile(h.hash()); +} + +void PropertiesWidget::riseSelectedTracker(){ + unsigned int i = 0; + std::vector trackers = h.trackers(); + QList selectedItems = trackersURLS->selectedItems(); + bool change = false; + unsigned int nbTrackers = trackers.size(); + foreach(QListWidgetItem *item, selectedItems){ + QString url = item->text(); + for(i=0; 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 trackers = h.trackers(); + QList selectedItems = trackersURLS->selectedItems(); + bool change = false; + unsigned int nbTrackers = trackers.size(); + foreach(QListWidgetItem *item, selectedItems){ + QString url = item->text(); + for(i=0; iitem(i+1)->setSelected(true); + BTSession->saveTrackerFile(h.hash()); + } +} + +void PropertiesWidget::setItemColor(QModelIndex index, QString color){ + for(int i=0; icolumnCount(); ++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 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); + } +} diff --git a/src/propertieswidget.h b/src/propertieswidget.h index d0a3ae1d7..6c563c2a1 100644 --- a/src/propertieswidget.h +++ b/src/propertieswidget.h @@ -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 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(); diff --git a/src/seeding.ui b/src/seeding.ui deleted file mode 100644 index 6cf5f042b..000000000 --- a/src/seeding.ui +++ /dev/null @@ -1,159 +0,0 @@ - - - seeding - - - - 0 - 0 - 811 - 453 - - - - Search - - - - 6 - - - 9 - - - - - Qt::CustomContextMenu - - - QAbstractItemView::ExtendedSelection - - - - - - - - true - - - - <u>Note:</u> It is important that you keep sharing your torrents after they are finished for the well being of the network. - - - - - - - Start - - - - - Pause - - - - - Delete - - - - - Delete Permanently - - - - - Torrent Properties - - - - - Preview file - - - - - Set upload limit - - - - - - :/Icons/oxygen/folder.png:/Icons/oxygen/folder.png - - - Open destination folder - - - - - Name - - - - - Size - - - - - Upload Speed - - - - - Connected peers - - - Connected peers - - - - - Ratio - - - - - - :/Icons/oxygen/wallet.png:/Icons/oxygen/wallet.png - - - Buy it - - - - - - :/Icons/oxygen/gear.png:/Icons/oxygen/gear.png - - - Force recheck - - - - - Total uploaded - - - - - Seeds / Leechers - - - Seeds / Leechers - - - - - Copy magnet link - - - - - - - - diff --git a/src/src.pro b/src/src.pro index 46288d5da..c393feda9 100644 --- a/src/src.pro +++ b/src/src.pro @@ -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 \ diff --git a/src/torrentAddition.h b/src/torrentAddition.h index ba0d6d8a1..c259f02d5 100644 --- a/src/torrentAddition.h +++ b/src/torrentAddition.h @@ -179,8 +179,8 @@ public: // set row Color setItemColor(first->index(), "green"); // Add children - QList children = root->getChildren(); - foreach(const torrent_file *child, children) { + QList children = root->getChildren(); + foreach(torrent_file *child, children) { addFilesToTree(child, first); } }