Browse Source

- new torrent content selection (as a tree). Merge from the new-torrent-selection branch

adaptive-webui-19844
Christophe Dumez 17 years ago
parent
commit
c478ba59ac
  1. 1
      Changelog
  2. 6
      TODO
  3. BIN
      src/Icons/file.png
  4. BIN
      src/Icons/folder.png
  5. 24
      src/PropListDelegate.h
  6. 49
      src/addTorrentDialog.ui
  7. 251
      src/arborescence.h
  8. 8
      src/bittorrent.cpp
  9. 18
      src/deleteThread.h
  10. 20
      src/icons.qrc
  11. 55
      src/misc.h
  12. 339
      src/properties.ui
  13. 179
      src/properties_imp.cpp
  14. 8
      src/properties_imp.h
  15. 1
      src/qtorrenthandle.h
  16. 4
      src/search.qrc
  17. 3
      src/src.pro
  18. 138
      src/torrentAddition.h

1
Changelog

@ -39,6 +39,7 @@
- FEATURE: Added an option to set the max number of uploads per torrent - FEATURE: Added an option to set the max number of uploads per torrent
- FEATURE: Added an option to automatically delete torrents when they reach a given ratio (>= 1.0) - FEATURE: Added an option to automatically delete torrents when they reach a given ratio (>= 1.0)
- FEATURE: Added an option to display current transfer speeds in title bar - FEATURE: Added an option to display current transfer speeds in title bar
- FEATURE: Torrent content is now displayed as a tree
- I18N: Added Hungarian translation - I18N: Added Hungarian translation
- I18N: Added Brazilian translation - I18N: Added Brazilian translation
- BUGFIX: Progress of paused torrents is now correct on restart - BUGFIX: Progress of paused torrents is now correct on restart

6
TODO

@ -49,11 +49,12 @@
- Fix all (or almost all) opened bugs in bug tracker - Fix all (or almost all) opened bugs in bug tracker
- Keep documention up to date - Keep documention up to date
- Windows port (Chris - Peerkoel) - Windows port (Chris - Peerkoel)
- debug new torrent content selection
* beta 7 * beta 7
- update doc for plugins (and add screenies) - update doc for plugins (and add screenies)
- update doc for options - update doc for options
- Review torrent content selection - See bug about negative ETA
* check the one in ktorrent - Fix search engines saving
- Translations update (IN PROGRESS) - Translations update (IN PROGRESS)
- Wait that http://pastebin.ca/690649 is fixed - Wait that http://pastebin.ca/690649 is fixed
@ -99,6 +100,7 @@ beta6->beta7 changelog:
- FEATURE: Articles in a RSS feed are now ordered by date (newer at the top) - FEATURE: Articles in a RSS feed are now ordered by date (newer at the top)
- FEATURE: Read articles in a feed are not resetted when the feed is refreshed anymore - FEATURE: Read articles in a feed are not resetted when the feed is refreshed anymore
- FEATURE: Allow to install plugins from their url - FEATURE: Allow to install plugins from their url
- FEATURE: torrent content is now displayed as a tree
- BUGFIX: In torrent content, it is now easier to filter all torrents using right click menu - BUGFIX: In torrent content, it is now easier to filter all torrents using right click menu
- BUGFIX: Updated man page / README / INSTALL - BUGFIX: Updated man page / README / INSTALL
- BUGFIX: Paused torrents could be displayed as connected for a sec after checking - BUGFIX: Paused torrents could be displayed as connected for a sec after checking

BIN
src/Icons/file.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 704 B

BIN
src/Icons/folder.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 449 B

24
src/PropListDelegate.h

@ -38,6 +38,7 @@
#define SIZE 1 #define SIZE 1
#define PROGRESS 2 #define PROGRESS 2
#define PRIORITY 3 #define PRIORITY 3
#define INDEX 4
#define IGNORED 0 #define IGNORED 0
#define NORMAL 1 #define NORMAL 1
@ -115,7 +116,6 @@ class PropListDelegate: public QItemDelegate {
QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &/* option */, const QModelIndex & index) const { QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &/* option */, const QModelIndex & index) const {
if(index.column() != PRIORITY) return 0; if(index.column() != PRIORITY) return 0;
if(onlyOneItem(index)) return 0;
QComboBox* editor = new QComboBox(parent); QComboBox* editor = new QComboBox(parent);
editor->setFocusPolicy(Qt::StrongFocus); editor->setFocusPolicy(Qt::StrongFocus);
editor->addItem(tr("Ignored")); editor->addItem(tr("Ignored"));
@ -128,6 +128,7 @@ class PropListDelegate: public QItemDelegate {
void setEditorData(QWidget *editor, const QModelIndex &index) const { void setEditorData(QWidget *editor, const QModelIndex &index) const {
unsigned short val = index.model()->data(index, Qt::DisplayRole).toInt(); unsigned short val = index.model()->data(index, Qt::DisplayRole).toInt();
QComboBox *combobox = static_cast<QComboBox*>(editor); QComboBox *combobox = static_cast<QComboBox*>(editor);
qDebug("Set Editor data: Prio is %d", val);
switch(val){ switch(val){
case IGNORED: case IGNORED:
combobox->setCurrentIndex(0); combobox->setCurrentIndex(0);
@ -156,28 +157,11 @@ class PropListDelegate: public QItemDelegate {
return textRect.size(); return textRect.size();
} }
bool onlyOneItem(const QModelIndex& index) const {
const QAbstractItemModel *model = index.model();
unsigned int nbRows = model->rowCount();
if(nbRows == 1) return true;
for(unsigned int i=0; i<nbRows; ++i){
if((unsigned int)index.row() == i) continue;
if(model->data(model->index(i, PRIORITY)).toInt()) return false;
}
return true;
}
public slots: public slots:
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const {
QComboBox *combobox = static_cast<QComboBox*>(editor); QComboBox *combobox = static_cast<QComboBox*>(editor);
int value = combobox->currentIndex(); int value = combobox->currentIndex();
qDebug("Setting combobox value in index: %d", value); qDebug("Setting combobox value in index: %d", value);
QString color;
if(value) {
color = QString::fromUtf8("green");
} else {
color = QString::fromUtf8("red");
}
unsigned short old_val = index.model()->data(index, Qt::DisplayRole).toInt(); unsigned short old_val = index.model()->data(index, Qt::DisplayRole).toInt();
switch(value){ switch(value){
case 0: case 0:
@ -215,14 +199,12 @@ class PropListDelegate: public QItemDelegate {
*filteredFilesChanged = true; *filteredFilesChanged = true;
} }
} }
for(int i=0; i<model->columnCount(); ++i){
model->setData(model->index(index.row(), i), QVariant(QColor(color)), Qt::ForegroundRole);
}
} }
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &/* index */) const { void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &/* index */) const {
editor->setGeometry(option.rect); editor->setGeometry(option.rect);
} }
}; };
#endif #endif

49
src/addTorrentDialog.ui

@ -5,20 +5,29 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>440</width> <width>511</width>
<height>389</height> <height>441</height>
</rect> </rect>
</property> </property>
<property name="windowTitle" > <property name="windowTitle" >
<string>Torrent addition dialog</string> <string>Torrent addition dialog</string>
</property> </property>
<layout class="QVBoxLayout" > <layout class="QVBoxLayout" >
<property name="margin" >
<number>9</number>
</property>
<property name="spacing" > <property name="spacing" >
<number>6</number> <number>6</number>
</property> </property>
<property name="leftMargin" >
<number>9</number>
</property>
<property name="topMargin" >
<number>9</number>
</property>
<property name="rightMargin" >
<number>9</number>
</property>
<property name="bottomMargin" >
<number>9</number>
</property>
<item> <item>
<widget class="QLabel" name="fileNameLbl" > <widget class="QLabel" name="fileNameLbl" >
<property name="text" > <property name="text" >
@ -48,12 +57,21 @@
</item> </item>
<item> <item>
<layout class="QHBoxLayout" > <layout class="QHBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" > <property name="spacing" >
<number>6</number> <number>6</number>
</property> </property>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<item> <item>
<widget class="QLineEdit" name="savePathTxt" /> <widget class="QLineEdit" name="savePathTxt" />
</item> </item>
@ -108,12 +126,21 @@
</item> </item>
<item> <item>
<layout class="QHBoxLayout" > <layout class="QHBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" > <property name="spacing" >
<number>6</number> <number>6</number>
</property> </property>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<item> <item>
<spacer> <spacer>
<property name="orientation" > <property name="orientation" >

251
src/arborescence.h

@ -0,0 +1,251 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2006 Christophe Dumez
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contact : chris@qbittorrent.org
*/
#ifndef ARBORESCENCE_H
#define ARBORESCENCE_H
#include <QFileInfo>
#include <QStringList>
#include <QDir>
#include "misc.h"
class file {
private:
file *parent;
bool is_dir;
QString rel_path;
QList<file*> children;
size_type size;
float progress;
int priority;
int index; // Index in torrent_info
public:
file(file *parent, QString path, bool dir, size_type size=0, float progress=0., int priority=1, int index=-1): parent(parent), is_dir(dir), size(size), progress(progress), priority(priority), index(index){
rel_path = QDir::cleanPath(path);
if(parent) {
parent->updateProgress();
parent->updatePriority(priority);
}
}
~file() {
qDeleteAll(children);
}
QString path() const {
return rel_path;
}
QString name() const {
return rel_path.split(QDir::separator()).last();
}
void updateProgress() {
Q_ASSERT(is_dir);
float sum = 0;
file *child;
foreach(child, children) {
sum += child->getProgress();
}
progress = sum / (float)children.size();
}
void updatePriority(int prio) {
Q_ASSERT(is_dir);
file *child;
foreach(child, children) {
if(child->getPriority() != prio) return;
}
priority = prio;
}
int getPriority() const {
return priority;
}
size_type getSize() const {
return size;
}
float getProgress() const {
return progress;
}
int getIndex() const {
return index;
}
bool isDir() const {
return is_dir;
}
bool hasChildren() const {
return (!children.isEmpty());
}
QList<file*> getChildren() const {
return children;
}
file* getChild(QString fileName) const {
Q_ASSERT(is_dir);
file* f;
foreach(f, children) {
if(f->name() == fileName) return f;
}
return 0;
}
void addBytes(size_type b) {
size += b;
if(parent)
parent->addBytes(b);
}
file* addChild(QString fileName, bool dir, size_type size=0, float progress=0., int priority=1, int index = -1) {
Q_ASSERT(is_dir);
qDebug("Adding a new child of size: %ld", (long)size);
file *f = new file(this, QDir::cleanPath(rel_path+QDir::separator()+fileName), dir, size, progress, priority, index);
children << f;
if(size) {
addBytes(size);
}
return f;
}
bool removeFromFS(QString saveDir) {
QString full_path = saveDir + QDir::separator() + rel_path;
if(!QFile::exists(full_path)) {
qDebug("%s does not exist, no need to remove it", full_path.toUtf8().data());
return true;
}
bool success = true;
file *f;
foreach(f, children) {
success = success && f->removeFromFS(saveDir);
success = false;
}
if(is_dir) {
qDebug("trying to remove directory: %s", full_path.toUtf8().data());
QDir dir(full_path);
dir.rmdir(full_path);
} else {
qDebug("trying to remove file: %s", full_path.toUtf8().data());
success = success && QFile::remove(full_path);
}
return success;
}
};
class arborescence {
private:
file *root;
public:
arborescence(torrent_info t) {
torrent_info::file_iterator fi = t.begin_files();
if(t.num_files() > 1) {
root = new file(0, misc::toQString(t.name()), true);
} else {
// XXX: Will crash if there is no file in torrent
root = new file(0, misc::toQString(t.name()), false, fi->size, 0);
return;
}
int i = 0;
while(fi != t.end_files()) {
QString path = QDir::cleanPath(misc::toQString(fi->path.string()));
addFile(path, fi->size, i);
fi++;
++i;
}
qDebug("real size: %ld, tree size: %ld", (long)t.total_size(), (long)root->getSize());
Q_ASSERT(root->getSize() == t.total_size());
}
arborescence(torrent_info t, std::vector<float> fp, int *prioritiesTab) {
torrent_info::file_iterator fi = t.begin_files();
if(t.num_files() > 1) {
root = new file(0, misc::toQString(t.name()), true);
} else {
// XXX: Will crash if there is no file in torrent
root = new file(0, misc::toQString(t.name()), false, fi->size, fp[0], prioritiesTab[0], 0);
return;
}
int i = 0;
while(fi != t.end_files()) {
QString path = QDir::cleanPath(misc::toQString(fi->path.string()));
addFile(path, fi->size, i, fp[i], prioritiesTab[i]);
fi++;
++i;
}
qDebug("real size: %ld, tree size: %ld", (long)t.total_size(), (long)root->getSize());
Q_ASSERT(root->getSize() == t.total_size());
}
~arborescence() {
delete root;
}
file* getRoot() const {
return root;
}
bool removeFromFS(QString saveDir) {
if(!QFile::exists(saveDir+QDir::separator()+root->path())) return true;
bool success = root->removeFromFS(saveDir);
QDir root_dir(root->path());
root_dir.rmdir(saveDir+QDir::separator()+root->path());
return success;
}
protected:
void addFile(QString path, size_type file_size, int index, float progress=0., int priority=1) {
Q_ASSERT(root->isDir());
path = QDir::cleanPath(path);
Q_ASSERT(path.startsWith(root->path()));
QString relative_path = path.remove(0, root->path().size());
if(relative_path.at(0) ==QDir::separator())
relative_path.remove(0, 1);
QStringList fileNames = relative_path.split(QDir::separator());
QString fileName;
file *dad = root;
unsigned int nb_i = 0;
unsigned int size = fileNames.size();
foreach(fileName, fileNames) {
++nb_i;
if(fileName == ".") continue;
file* child = dad->getChild(fileName);
if(!child) {
if(nb_i != size) {
// Folder
child = dad->addChild(fileName, true);
} else {
// File
child = dad->addChild(fileName, false, file_size, progress, priority, index);
}
}
dad = child;
}
}
};
#endif

8
src/bittorrent.cpp

@ -208,9 +208,9 @@ void bittorrent::deleteTorrent(QString hash, bool permanent) {
} }
QString savePath = h.save_path(); QString savePath = h.save_path();
QString fileName = h.name(); QString fileName = h.name();
QStringList files_path; arborescence *files_arb = 0;
if(permanent){ if(permanent){
files_path = h.files_path(); files_arb = new arborescence(h.get_torrent_info());
} }
// Remove it from session // Remove it from session
s->remove_torrent(h.get_torrent_handle()); s->remove_torrent(h.get_torrent_handle());
@ -241,11 +241,11 @@ void bittorrent::deleteTorrent(QString hash, bool permanent) {
std::cerr << "Error: Torrent " << hash.toStdString() << " is neither in finished or unfinished list\n"; std::cerr << "Error: Torrent " << hash.toStdString() << " is neither in finished or unfinished list\n";
} }
} }
if(permanent) { if(permanent && files_arb != 0) {
// Remove from Hard drive // Remove from Hard drive
qDebug("Removing this on hard drive: %s", qPrintable(savePath+QDir::separator()+fileName)); qDebug("Removing this on hard drive: %s", qPrintable(savePath+QDir::separator()+fileName));
// Deleting in a thread to avoid GUI freeze // Deleting in a thread to avoid GUI freeze
deleter->deleteTorrent(savePath, files_path); deleter->deleteTorrent(savePath, files_arb);
} }
} }

18
src/deleteThread.h

@ -28,17 +28,17 @@
#include <QMutexLocker> #include <QMutexLocker>
#include <QPair> #include <QPair>
#include "misc.h" #include "arborescence.h"
class subDeleteThread : public QThread { class subDeleteThread : public QThread {
Q_OBJECT Q_OBJECT
private: private:
QString save_path; QString save_path;
QStringList files_path; arborescence *arb;
bool abort; bool abort;
public: public:
subDeleteThread(QObject *parent, QString save_path, QStringList files_path) : QThread(parent), save_path(save_path), files_path(files_path), abort(false){} subDeleteThread(QObject *parent, QString saveDir, arborescence *arb) : QThread(parent), save_path(saveDir), arb(arb), abort(false){}
~subDeleteThread(){ ~subDeleteThread(){
abort = true; abort = true;
@ -52,10 +52,11 @@ class subDeleteThread : public QThread {
protected: protected:
void run(){ void run(){
if(misc::removeTorrentSavePath(save_path, files_path)) if(arb->removeFromFS(save_path))
emit deletionSuccessST(this); emit deletionSuccessST(this);
else else
emit deletionFailureST(this); emit deletionFailureST(this);
delete arb;
} }
}; };
@ -63,7 +64,7 @@ class deleteThread : public QThread {
Q_OBJECT Q_OBJECT
private: private:
QList<QPair<QString, QStringList> > torrents_list; QList<QPair<QString, arborescence*> > torrents_list;
QMutex mutex; QMutex mutex;
QWaitCondition condition; QWaitCondition condition;
bool abort; bool abort;
@ -81,9 +82,10 @@ class deleteThread : public QThread {
wait(); wait();
} }
void deleteTorrent(QString save_path, QStringList files_path){ void deleteTorrent(QString saveDir, arborescence *arb){
qDebug("deleteThread called");
QMutexLocker locker(&mutex); QMutexLocker locker(&mutex);
torrents_list << QPair<QString, QStringList>(save_path, files_path); torrents_list << QPair<QString, arborescence*>(saveDir, arb);
if(!isRunning()){ if(!isRunning()){
start(); start();
}else{ }else{
@ -98,7 +100,7 @@ class deleteThread : public QThread {
return; return;
mutex.lock(); mutex.lock();
if(torrents_list.size() != 0){ if(torrents_list.size() != 0){
QPair<QString, QStringList> torrent = torrents_list.takeFirst(); QPair<QString, arborescence *> torrent = torrents_list.takeFirst();
mutex.unlock(); mutex.unlock();
subDeleteThread *st = new subDeleteThread(0, torrent.first, torrent.second); subDeleteThread *st = new subDeleteThread(0, torrent.first, torrent.second);
subThreads << st; subThreads << st;

20
src/icons.qrc

@ -1,17 +1,18 @@
<!DOCTYPE RCC><RCC version="1.0"> <!DOCTYPE RCC><RCC version="1.0">
<qresource> <qresource>
<file>Icons/locale.png</file>
<file>Icons/time.png</file> <file>Icons/time.png</file>
<file>Icons/connection.png</file> <file>Icons/connection.png</file>
<file>Icons/locale.png</file>
<file>Icons/newmsg.png</file> <file>Icons/newmsg.png</file>
<file>Icons/stare.png</file>
<file>Icons/url.png</file> <file>Icons/url.png</file>
<file>Icons/qbittorrent32.png</file>
<file>Icons/button_ok.png</file> <file>Icons/button_ok.png</file>
<file>Icons/stare.png</file>
<file>Icons/log.png</file> <file>Icons/log.png</file>
<file>Icons/qbittorrent32.png</file> <file>Icons/qbittorrent16.png</file>
<file>Icons/downarrow.png</file> <file>Icons/downarrow.png</file>
<file>Icons/description.png</file> <file>Icons/description.png</file>
<file>Icons/qbittorrent16.png</file> <file>Icons/button_cancel.png</file>
<file>Icons/systemtray.png</file> <file>Icons/systemtray.png</file>
<file>Icons/unhappy.png</file> <file>Icons/unhappy.png</file>
<file>Icons/filter.png</file> <file>Icons/filter.png</file>
@ -27,7 +28,7 @@
<file>Icons/sphere2.png</file> <file>Icons/sphere2.png</file>
<file>Icons/smile.png</file> <file>Icons/smile.png</file>
<file>Icons/loading.png</file> <file>Icons/loading.png</file>
<file>Icons/button_cancel.png</file> <file>Icons/file.png</file>
<file>Icons/qbittorrent22.png</file> <file>Icons/qbittorrent22.png</file>
<file>Icons/proxy.png</file> <file>Icons/proxy.png</file>
<file>Icons/add_folder.png</file> <file>Icons/add_folder.png</file>
@ -46,25 +47,26 @@
<file>Icons/star.png</file> <file>Icons/star.png</file>
<file>Icons/configure.png</file> <file>Icons/configure.png</file>
<file>Icons/download.png</file> <file>Icons/download.png</file>
<file>Icons/folder.png</file>
<file>Icons/flags/netherlands.png</file>
<file>Icons/flags/portugal.png</file> <file>Icons/flags/portugal.png</file>
<file>Icons/flags/france.png</file> <file>Icons/flags/france.png</file>
<file>Icons/flags/ukraine.png</file> <file>Icons/flags/ukraine.png</file>
<file>Icons/flags/united_kingdom.png</file>
<file>Icons/flags/germany.png</file> <file>Icons/flags/germany.png</file>
<file>Icons/flags/united_kingdom.png</file>
<file>Icons/flags/russia.png</file> <file>Icons/flags/russia.png</file>
<file>Icons/flags/netherlands.png</file> <file>Icons/flags/south_korea.png</file>
<file>Icons/flags/slovakia.png</file> <file>Icons/flags/slovakia.png</file>
<file>Icons/flags/spain.png</file> <file>Icons/flags/spain.png</file>
<file>Icons/flags/finland.png</file> <file>Icons/flags/finland.png</file>
<file>Icons/flags/spain_catalunya.png</file>
<file>Icons/flags/poland.png</file> <file>Icons/flags/poland.png</file>
<file>Icons/flags/spain_catalunya.png</file>
<file>Icons/flags/hungary.png</file> <file>Icons/flags/hungary.png</file>
<file>Icons/flags/norway.png</file> <file>Icons/flags/norway.png</file>
<file>Icons/flags/denmark.png</file> <file>Icons/flags/denmark.png</file>
<file>Icons/flags/italy.png</file> <file>Icons/flags/italy.png</file>
<file>Icons/flags/china.png</file> <file>Icons/flags/china.png</file>
<file>Icons/flags/brazil.png</file> <file>Icons/flags/brazil.png</file>
<file>Icons/flags/south_korea.png</file>
<file>Icons/flags/turkey.png</file> <file>Icons/flags/turkey.png</file>
<file>Icons/flags/sweden.png</file> <file>Icons/flags/sweden.png</file>
<file>Icons/flags/bulgaria.png</file> <file>Icons/flags/bulgaria.png</file>

55
src/misc.h

@ -34,7 +34,6 @@
#include <QThread> #include <QThread>
#include <libtorrent/torrent_info.hpp> #include <libtorrent/torrent_info.hpp>
#include "qtorrenthandle.h"
using namespace libtorrent; using namespace libtorrent;
/* Miscellaneaous functions that can be useful */ /* Miscellaneaous functions that can be useful */
@ -205,60 +204,6 @@ class misc : public QObject{
// return true; // return true;
// } // }
// safe function to remove a torrent from hard-drive
static bool removeTorrentSavePath(QString savePath, QStringList filesPath) {
bool success = true;
QDir saveDir(savePath);
QString path;
// Check how many file there are
if(filesPath.size() == 1){
// Only one file, not in a folder
path = filesPath.first();
if(QFile::exists(path)) {
if(QFile::remove(path)){
qDebug("Deleted only file in torrent at %s", path.toUtf8().data());
} else {
std::cerr << "Could not delete only file in torrent at " << path.toUtf8().data() << '\n';
success = false;
}
}else{
// File didn't exist, nothing to do
qDebug("Only file %s did not exist, nothing to delete", path.toUtf8().data());
}
// Try to remove parent folder if empty (and not save_dir)
QFileInfo fi(path);
QDir parentFolder = fi.absoluteDir();
while(parentFolder != saveDir) {
qDebug("trying to remove parent folder: %s", parentFolder.absolutePath().toUtf8().data());
if(!saveDir.rmdir(parentFolder.absolutePath())) break;
parentFolder.cdUp();
}
return success;
}
// Torrent has several files in a subFolder
foreach(path, filesPath) {
if(QFile::exists(path)) {
if(QFile::remove(path)){
qDebug("Deleted file in torrent at %s", path.toUtf8().data());
} else {
std::cerr << "Could not delete file in torrent at " << path.toUtf8().data() << '\n';
success = false;
}
} else {
qDebug("File %s did not exist, nothing to delete", path.toUtf8().data());
}
// Try to remove parent folder if empty (and not save_dir)
QFileInfo fi(path);
QDir parentFolder = fi.absoluteDir();
while(parentFolder != saveDir) {
qDebug("trying to remove parent folder: %s", parentFolder.absolutePath().toUtf8().data());
if(!saveDir.rmdir(parentFolder.absolutePath())) break;
parentFolder.cdUp();
}
}
return success;
}
static QString findFileInDir(QString dir_path, QString fileName) { static QString findFileInDir(QString dir_path, QString fileName) {
QDir dir(dir_path); QDir dir(dir_path);
if(dir.exists(fileName)) { if(dir.exists(fileName)) {

339
src/properties.ui

@ -13,12 +13,21 @@
<string>Torrent Properties</string> <string>Torrent Properties</string>
</property> </property>
<layout class="QVBoxLayout" > <layout class="QVBoxLayout" >
<property name="margin" >
<number>9</number>
</property>
<property name="spacing" > <property name="spacing" >
<number>6</number> <number>6</number>
</property> </property>
<property name="leftMargin" >
<number>9</number>
</property>
<property name="topMargin" >
<number>9</number>
</property>
<property name="rightMargin" >
<number>9</number>
</property>
<property name="bottomMargin" >
<number>9</number>
</property>
<item> <item>
<widget class="QTabWidget" name="torrentContent" > <widget class="QTabWidget" name="torrentContent" >
<property name="currentIndex" > <property name="currentIndex" >
@ -29,12 +38,6 @@
<string>Main infos</string> <string>Main infos</string>
</attribute> </attribute>
<layout class="QVBoxLayout" > <layout class="QVBoxLayout" >
<property name="margin" >
<number>9</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item> <item>
<widget class="QLabel" name="fileName" > <widget class="QLabel" name="fileName" >
<property name="maximumSize" > <property name="maximumSize" >
@ -81,28 +84,55 @@
<string>Torrent infos</string> <string>Torrent infos</string>
</property> </property>
<layout class="QVBoxLayout" > <layout class="QVBoxLayout" >
<property name="margin" >
<number>9</number>
</property>
<property name="spacing" > <property name="spacing" >
<number>6</number> <number>6</number>
</property> </property>
<property name="leftMargin" >
<number>9</number>
</property>
<property name="topMargin" >
<number>9</number>
</property>
<property name="rightMargin" >
<number>9</number>
</property>
<property name="bottomMargin" >
<number>9</number>
</property>
<item> <item>
<layout class="QHBoxLayout" > <layout class="QHBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" > <property name="spacing" >
<number>6</number> <number>6</number>
</property> </property>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<item> <item>
<layout class="QVBoxLayout" > <layout class="QVBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" > <property name="spacing" >
<number>6</number> <number>6</number>
</property> </property>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<item> <item>
<widget class="QLabel" name="savePath_lbl" > <widget class="QLabel" name="savePath_lbl" >
<property name="minimumSize" > <property name="minimumSize" >
@ -189,12 +219,21 @@
</item> </item>
<item> <item>
<layout class="QVBoxLayout" > <layout class="QVBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" > <property name="spacing" >
<number>6</number> <number>6</number>
</property> </property>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<item> <item>
<widget class="QLabel" name="save_path" > <widget class="QLabel" name="save_path" >
<property name="minimumSize" > <property name="minimumSize" >
@ -276,9 +315,7 @@
<item> <item>
<widget class="QGroupBox" name="groupBox" > <widget class="QGroupBox" name="groupBox" >
<property name="sizePolicy" > <property name="sizePolicy" >
<sizepolicy> <sizepolicy vsizetype="Expanding" hsizetype="Expanding" >
<hsizetype>0</hsizetype>
<vsizetype>0</vsizetype>
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
@ -304,28 +341,55 @@
<string>Current session</string> <string>Current session</string>
</property> </property>
<layout class="QVBoxLayout" > <layout class="QVBoxLayout" >
<property name="margin" >
<number>9</number>
</property>
<property name="spacing" > <property name="spacing" >
<number>6</number> <number>6</number>
</property> </property>
<property name="leftMargin" >
<number>9</number>
</property>
<property name="topMargin" >
<number>9</number>
</property>
<property name="rightMargin" >
<number>9</number>
</property>
<property name="bottomMargin" >
<number>9</number>
</property>
<item> <item>
<layout class="QHBoxLayout" > <layout class="QHBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" > <property name="spacing" >
<number>6</number> <number>6</number>
</property> </property>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<item> <item>
<layout class="QVBoxLayout" > <layout class="QVBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" > <property name="spacing" >
<number>6</number> <number>6</number>
</property> </property>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<item> <item>
<widget class="QLabel" name="label_5" > <widget class="QLabel" name="label_5" >
<property name="font" > <property name="font" >
@ -402,12 +466,21 @@
</item> </item>
<item> <item>
<layout class="QVBoxLayout" > <layout class="QVBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" > <property name="spacing" >
<number>6</number> <number>6</number>
</property> </property>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<item> <item>
<widget class="QLabel" name="upTotal" > <widget class="QLabel" name="upTotal" >
<property name="text" > <property name="text" >
@ -481,18 +554,25 @@
<string>Trackers</string> <string>Trackers</string>
</attribute> </attribute>
<layout class="QVBoxLayout" > <layout class="QVBoxLayout" >
<property name="margin" >
<number>9</number>
</property>
<property name="spacing" > <property name="spacing" >
<number>6</number> <number>6</number>
</property> </property>
<property name="leftMargin" >
<number>9</number>
</property>
<property name="topMargin" >
<number>9</number>
</property>
<property name="rightMargin" >
<number>9</number>
</property>
<property name="bottomMargin" >
<number>9</number>
</property>
<item> <item>
<widget class="QGroupBox" name="groupBox_2" > <widget class="QGroupBox" name="groupBox_2" >
<property name="sizePolicy" > <property name="sizePolicy" >
<sizepolicy> <sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
<hsizetype>7</hsizetype>
<vsizetype>0</vsizetype>
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
@ -518,20 +598,38 @@
<string>Tracker</string> <string>Tracker</string>
</property> </property>
<layout class="QVBoxLayout" > <layout class="QVBoxLayout" >
<property name="margin" >
<number>9</number>
</property>
<property name="spacing" > <property name="spacing" >
<number>6</number> <number>6</number>
</property> </property>
<property name="leftMargin" >
<number>9</number>
</property>
<property name="topMargin" >
<number>9</number>
</property>
<property name="rightMargin" >
<number>9</number>
</property>
<property name="bottomMargin" >
<number>9</number>
</property>
<item> <item>
<layout class="QHBoxLayout" > <layout class="QHBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" > <property name="spacing" >
<number>6</number> <number>6</number>
</property> </property>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<item> <item>
<widget class="QLabel" name="label_9" > <widget class="QLabel" name="label_9" >
<property name="font" > <property name="font" >
@ -552,18 +650,25 @@
</item> </item>
<item> <item>
<layout class="QVBoxLayout" > <layout class="QVBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" > <property name="spacing" >
<number>6</number> <number>6</number>
</property> </property>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<item> <item>
<widget class="QListWidget" name="trackersURLS" > <widget class="QListWidget" name="trackersURLS" >
<property name="sizePolicy" > <property name="sizePolicy" >
<sizepolicy> <sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
<hsizetype>7</hsizetype>
<vsizetype>0</vsizetype>
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
@ -572,12 +677,21 @@
</item> </item>
<item> <item>
<layout class="QHBoxLayout" > <layout class="QHBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" > <property name="spacing" >
<number>6</number> <number>6</number>
</property> </property>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<item> <item>
<spacer> <spacer>
<property name="orientation" > <property name="orientation" >
@ -648,12 +762,21 @@
</item> </item>
<item> <item>
<layout class="QVBoxLayout" > <layout class="QVBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" > <property name="spacing" >
<number>6</number> <number>6</number>
</property> </property>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<item> <item>
<spacer> <spacer>
<property name="orientation" > <property name="orientation" >
@ -724,12 +847,21 @@
</item> </item>
<item> <item>
<layout class="QHBoxLayout" > <layout class="QHBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" > <property name="spacing" >
<number>6</number> <number>6</number>
</property> </property>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<item> <item>
<widget class="QLabel" name="label_10" > <widget class="QLabel" name="label_10" >
<property name="font" > <property name="font" >
@ -759,12 +891,21 @@
</item> </item>
<item> <item>
<layout class="QHBoxLayout" > <layout class="QHBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" > <property name="spacing" >
<number>6</number> <number>6</number>
</property> </property>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<item> <item>
<widget class="QLabel" name="label_2" > <widget class="QLabel" name="label_2" >
<property name="maximumSize" > <property name="maximumSize" >
@ -827,12 +968,21 @@
<string>Url seeds</string> <string>Url seeds</string>
</attribute> </attribute>
<layout class="QVBoxLayout" > <layout class="QVBoxLayout" >
<property name="margin" >
<number>9</number>
</property>
<property name="spacing" > <property name="spacing" >
<number>6</number> <number>6</number>
</property> </property>
<property name="leftMargin" >
<number>9</number>
</property>
<property name="topMargin" >
<number>9</number>
</property>
<property name="rightMargin" >
<number>9</number>
</property>
<property name="bottomMargin" >
<number>9</number>
</property>
<item> <item>
<widget class="QLabel" name="webSeeds_lbl" > <widget class="QLabel" name="webSeeds_lbl" >
<property name="font" > <property name="font" >
@ -851,12 +1001,21 @@
</item> </item>
<item> <item>
<layout class="QHBoxLayout" > <layout class="QHBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" > <property name="spacing" >
<number>6</number> <number>6</number>
</property> </property>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<item> <item>
<spacer> <spacer>
<property name="orientation" > <property name="orientation" >
@ -931,12 +1090,21 @@
<string>Torrent content</string> <string>Torrent content</string>
</attribute> </attribute>
<layout class="QVBoxLayout" > <layout class="QVBoxLayout" >
<property name="margin" >
<number>9</number>
</property>
<property name="spacing" > <property name="spacing" >
<number>6</number> <number>6</number>
</property> </property>
<property name="leftMargin" >
<number>9</number>
</property>
<property name="topMargin" >
<number>9</number>
</property>
<property name="rightMargin" >
<number>9</number>
</property>
<property name="bottomMargin" >
<number>9</number>
</property>
<item> <item>
<widget class="QLabel" name="label_4" > <widget class="QLabel" name="label_4" >
<property name="font" > <property name="font" >
@ -972,12 +1140,6 @@
<property name="selectionMode" > <property name="selectionMode" >
<enum>QAbstractItemView::ExtendedSelection</enum> <enum>QAbstractItemView::ExtendedSelection</enum>
</property> </property>
<property name="indentation" >
<number>1</number>
</property>
<property name="itemsExpandable" >
<bool>false</bool>
</property>
</widget> </widget>
</item> </item>
<item> <item>
@ -1010,12 +1172,21 @@
</item> </item>
<item> <item>
<layout class="QHBoxLayout" > <layout class="QHBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" > <property name="spacing" >
<number>6</number> <number>6</number>
</property> </property>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<item> <item>
<spacer> <spacer>
<property name="orientation" > <property name="orientation" >

179
src/properties_imp.cpp

@ -23,6 +23,7 @@
#include "misc.h" #include "misc.h"
#include "PropListDelegate.h" #include "PropListDelegate.h"
#include "bittorrent.h" #include "bittorrent.h"
#include "arborescence.h"
#include <QInputDialog> #include <QInputDialog>
#include <QMessageBox> #include <QMessageBox>
@ -31,7 +32,7 @@
#include <QStandardItemModel> #include <QStandardItemModel>
// Constructor // Constructor
properties::properties(QWidget *parent, bittorrent *BTSession, QTorrentHandle &h): QDialog(parent), h(h), BTSession(BTSession), changedFilteredfiles(false), hash(h.hash()) { properties::properties(QWidget *parent, bittorrent *BTSession, QTorrentHandle &h): QDialog(parent), h(h), BTSession(BTSession), changedFilteredfiles(false), hash(h.hash()), editParentsOnly(false) {
setupUi(this); 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>"); 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 // set icons
@ -43,12 +44,13 @@ properties::properties(QWidget *parent, bittorrent *BTSession, QTorrentHandle &h
deleteWS_button->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/remove.png"))); deleteWS_button->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/remove.png")));
setAttribute(Qt::WA_DeleteOnClose); setAttribute(Qt::WA_DeleteOnClose);
// Set Properties list model // Set Properties list model
PropListModel = new QStandardItemModel(0,4); PropListModel = new QStandardItemModel(0,5);
PropListModel->setHeaderData(NAME, Qt::Horizontal, tr("File name")); PropListModel->setHeaderData(NAME, Qt::Horizontal, tr("File name"));
PropListModel->setHeaderData(SIZE, Qt::Horizontal, tr("Size")); PropListModel->setHeaderData(SIZE, Qt::Horizontal, tr("Size"));
PropListModel->setHeaderData(PROGRESS, Qt::Horizontal, tr("Progress")); PropListModel->setHeaderData(PROGRESS, Qt::Horizontal, tr("Progress"));
PropListModel->setHeaderData(PRIORITY, Qt::Horizontal, tr("Priority")); PropListModel->setHeaderData(PRIORITY, Qt::Horizontal, tr("Priority"));
filesList->setModel(PropListModel); filesList->setModel(PropListModel);
filesList->hideColumn(INDEX);
PropDelegate = new PropListDelegate(0, &changedFilteredfiles); PropDelegate = new PropListDelegate(0, &changedFilteredfiles);
filesList->setItemDelegate(PropDelegate); filesList->setItemDelegate(PropDelegate);
connect(filesList, SIGNAL(clicked(const QModelIndex&)), filesList, SLOT(edit(const QModelIndex&))); connect(filesList, SIGNAL(clicked(const QModelIndex&)), filesList, SLOT(edit(const QModelIndex&)));
@ -96,16 +98,14 @@ properties::properties(QWidget *parent, bittorrent *BTSession, QTorrentHandle &h
loadTrackersErrors(); loadTrackersErrors();
std::vector<float> fp; std::vector<float> fp;
h.file_progress(fp); h.file_progress(fp);
int *prioritiesTab = loadPiecesPriorities();
// List files in torrent // List files in torrent
unsigned int nbFiles = h.num_files(); arborescence *arb = new arborescence(h.get_torrent_info(), fp, prioritiesTab);
for(unsigned int i=0; i<nbFiles; ++i){ addFilesToTree(arb->getRoot(), PropListModel->invisibleRootItem());
unsigned int row = PropListModel->rowCount(); delete arb;
PropListModel->insertRow(row); delete prioritiesTab;
PropListModel->setData(PropListModel->index(row, NAME), QVariant(h.file_at(i))); connect(PropListModel, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(updateChildrenPriority(QStandardItem*)));
PropListModel->setData(PropListModel->index(row, SIZE), QVariant((qlonglong)h.filesize_at(i))); filesList->expandAll();
PropListModel->setData(PropListModel->index(row, PROGRESS), QVariant((double)fp[i]));
}
loadPiecesPriorities();
// List web seeds // List web seeds
loadWebSeedsFromFile(); loadWebSeedsFromFile();
loadWebSeeds(); loadWebSeeds();
@ -127,6 +127,91 @@ properties::~properties(){
delete PropListModel; delete PropListModel;
} }
void properties::addFilesToTree(file *root, QStandardItem *parent) {
QList<QStandardItem*> child;
// Name
QStandardItem *first;
if(root->isDir()) {
first = new QStandardItem(QIcon(":/Icons/folder.png"), root->name());
} else {
first = new QStandardItem(QIcon(":/Icons/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()));
// TODO: row Color?
// Add the child to the tree
parent->appendRow(child);
// Add childs
file *childFile;
foreach(childFile, root->getChildren()) {
addFilesToTree(childFile, first);
}
}
void properties::updateChildrenPriority(QStandardItem *item) {
qDebug("Priority changed");
QStandardItem *parent = item->parent();
int row = item->row();
if(!parent) {
parent = PropListModel->invisibleRootItem();
}
bool is_dir = (parent->child(row, INDEX)->text().toInt() == -1);
int priority = parent->child(row, PRIORITY)->text().toInt();
// Update parent priority
if(item->parent()) {
bool parentUpdate = true;
unsigned int rowCount = parent->rowCount();
for(unsigned int i=0; i<rowCount; ++i) {
if(parent->child(i, PRIORITY)->text().toInt() != priority) {
// Check if parent priority is NORMAL
QStandardItem *grandFather = parent->parent();
if(!grandFather) {
grandFather = PropListModel->invisibleRootItem();
}
QStandardItem *parentPrio = grandFather->child(parent->row(), PRIORITY);
editParentsOnly = true;
parentPrio->setText(misc::toQString(NORMAL));
editParentsOnly = false;
parentUpdate = false;
break;
}
}
if(parentUpdate) {
QStandardItem *grandFather = parent->parent();
if(!grandFather) {
grandFather = PropListModel->invisibleRootItem();
}
QStandardItem *parentPrio = grandFather->child(parent->row(), PRIORITY);
editParentsOnly = true;
parentPrio->setText(misc::toQString(priority));
editParentsOnly = false;
}
}
if(editParentsOnly) return;
if(!is_dir) return;
// Updating children
qDebug("Priority changed for a folder to %d", priority);
parent = parent->child(row);
unsigned int rowCount = parent->rowCount();
qDebug("The folder has %d children", rowCount);
for(unsigned int i=0; i<rowCount; ++i) {
// get child priority
QStandardItem *child = parent->child(i, PRIORITY);
int child_prio = child->text().toInt();
qDebug("Child priority is %d", child_prio);
if(child_prio != priority) {
child->setText(misc::toQString(priority));
}
}
}
void properties::loadTrackersErrors(){ void properties::loadTrackersErrors(){
// Tracker Errors // Tracker Errors
QList<QPair<QString, QString> > errors = BTSession->getTrackersErrors(hash); QList<QPair<QString, QString> > errors = BTSession->getTrackersErrors(hash);
@ -151,8 +236,9 @@ void properties::loadWebSeeds(){
} }
} }
void properties::loadPiecesPriorities(){ int* properties::loadPiecesPriorities(){
unsigned int nbFiles = h.num_files(); unsigned int nbFiles = h.num_files();
int *prioritiesTab = new int[nbFiles];
QString fileName = h.name(); QString fileName = h.name();
QFile pieces_file(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+hash+".priorities"); QFile pieces_file(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+hash+".priorities");
has_filtered_files = false; has_filtered_files = false;
@ -160,16 +246,18 @@ void properties::loadPiecesPriorities(){
// Read saved file // Read saved file
if(!pieces_file.open(QIODevice::ReadOnly | QIODevice::Text)){ if(!pieces_file.open(QIODevice::ReadOnly | QIODevice::Text)){
qDebug("Could not find pieces file"); qDebug("Could not find pieces file");
setAllPiecesState(NORMAL); for(unsigned int i=0; i<nbFiles; ++i)
return; prioritiesTab[i] = NORMAL;
return prioritiesTab;
} }
QByteArray pieces_text = pieces_file.readAll(); QByteArray pieces_text = pieces_file.readAll();
pieces_file.close(); pieces_file.close();
QList<QByteArray> pieces_priority_list = pieces_text.split('\n'); QList<QByteArray> pieces_priority_list = pieces_text.split('\n');
if((unsigned int)pieces_priority_list.size() != nbFiles+1){ if((unsigned int)pieces_priority_list.size() != nbFiles+1){
std::cerr << "Error: Corrupted pieces file\n"; std::cerr << "Error: Corrupted pieces file\n";
setAllPiecesState(NORMAL); for(unsigned int i=0; i<nbFiles; ++i)
return; prioritiesTab[i] = NORMAL;
return prioritiesTab;
} }
for(unsigned int i=0; i<nbFiles; ++i){ for(unsigned int i=0; i<nbFiles; ++i){
int priority = pieces_priority_list.at(i).toInt(); int priority = pieces_priority_list.at(i).toInt();
@ -178,13 +266,11 @@ void properties::loadPiecesPriorities(){
priority = 1; priority = 1;
} }
if(!priority){ if(!priority){
setRowColor(i, "red");
has_filtered_files = true; has_filtered_files = true;
}else{
setRowColor(i, "green");
} }
PropListModel->setData(PropListModel->index(i, PRIORITY), QVariant(priority)); prioritiesTab[i] = priority;
} }
return prioritiesTab;
} }
bool properties::allFiltered() const { bool properties::allFiltered() const {
@ -196,9 +282,23 @@ bool properties::allFiltered() const {
return true; return true;
} }
void properties::getPriorities(QStandardItem *parent, int *priorities) {
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();
}
}
}
void properties::displayFilesListMenu(const QPoint& pos){ void properties::displayFilesListMenu(const QPoint& pos){
unsigned int nbRows = PropListModel->rowCount(); if(h.get_torrent_info().num_files() == 1) return;
if(nbRows == 1) return;
QMenu myFilesLlistMenu(this); QMenu myFilesLlistMenu(this);
QModelIndex index; QModelIndex index;
// Enable/disable pause/start action given the DL state // Enable/disable pause/start action given the DL state
@ -453,24 +553,18 @@ void properties::lowerSelectedTracker(){
} }
void properties::updateInfos(){ void properties::updateInfos(){
std::vector<float> fp; // Update current tracker
try{ try {
h.file_progress(fp); QString tracker = h.current_tracker().trimmed();
unsigned int nbFiles = h.num_files(); if(!tracker.isEmpty()){
for(unsigned int i=0; i<nbFiles; ++i){ trackerURL->setText(tracker);
PropListModel->setData(PropListModel->index(i, PROGRESS), QVariant((double)fp[i])); }else{
trackerURL->setText(tr("None - Unreachable?"));
} }
}catch(invalid_handle e){ }catch(invalid_handle e){
// torrent was removed, closing properties // torrent was removed, closing properties
close(); close();
} }
// Update current tracker
QString tracker = h.current_tracker().trimmed();
if(!tracker.isEmpty()){
trackerURL->setText(tracker);
}else{
trackerURL->setText(tr("None - Unreachable?"));
}
} }
// Set the color of a row in data model // Set the color of a row in data model
@ -563,21 +657,22 @@ bool properties::savePiecesPriorities() {
QFile pieces_file(misc::qBittorrentPath()+QString::fromUtf8("BT_backup")+QDir::separator()+hash+QString::fromUtf8(".priorities")); QFile pieces_file(misc::qBittorrentPath()+QString::fromUtf8("BT_backup")+QDir::separator()+hash+QString::fromUtf8(".priorities"));
// First, remove old file // First, remove old file
pieces_file.remove(); pieces_file.remove();
// Write new files int *priorities = new int[h.get_torrent_info().num_files()];
getPriorities(PropListModel->invisibleRootItem(), priorities);
// Ok, we have priorities, save them
if(!pieces_file.open(QIODevice::WriteOnly | QIODevice::Text)){ if(!pieces_file.open(QIODevice::WriteOnly | QIODevice::Text)){
std::cerr << "Error: Could not save pieces priorities\n"; std::cerr << "Error: Could not save pieces priorities\n";
return true; return true;
} }
unsigned int nbRows = PropListModel->rowCount(); unsigned int nbFiles = h.get_torrent_info().num_files();
for(unsigned int i=0; i<nbRows; ++i){ for(unsigned int i=0; i<nbFiles; ++i) {
QStandardItem *item = PropListModel->item(i, PRIORITY); if(!priorities[i]) {
unsigned short priority = item->text().toInt();
if(!priority) {
hasFilteredFiles = true; hasFilteredFiles = true;
} }
pieces_file.write(misc::toQByteArray(priority)+"\n"); pieces_file.write(misc::toQByteArray(priorities[i])+misc::toQByteArray("\n"));
} }
pieces_file.close(); pieces_file.close();
delete[] priorities;
// If h.has_filtered_pieces() s true, then the torrent // If h.has_filtered_pieces() s true, then the torrent
// is already in full allocation mode, no need to // is already in full allocation mode, no need to
// reload it. // reload it.

8
src/properties_imp.h

@ -29,6 +29,8 @@ class PropListDelegate;
class QTimer; class QTimer;
class bittorrent; class bittorrent;
class QStandardItemModel; class QStandardItemModel;
class file;
class QStandardItem;
using namespace libtorrent; using namespace libtorrent;
@ -43,6 +45,7 @@ class properties : public QDialog, private Ui::properties{
QStandardItemModel *PropListModel; QStandardItemModel *PropListModel;
QTimer *updateInfosTimer; QTimer *updateInfosTimer;
bool has_filtered_files; bool has_filtered_files;
bool editParentsOnly;
QStringList urlSeeds; QStringList urlSeeds;
protected slots: protected slots:
@ -50,7 +53,6 @@ class properties : public QDialog, private Ui::properties{
void on_incrementalDownload_stateChanged(int); void on_incrementalDownload_stateChanged(int);
void setRowColor(int row, QString color); void setRowColor(int row, QString color);
void updateInfos(); void updateInfos();
void loadPiecesPriorities();
void setAllPiecesState(unsigned short priority); void setAllPiecesState(unsigned short priority);
void askForTracker(); void askForTracker();
void loadTrackers(); void loadTrackers();
@ -68,6 +70,9 @@ class properties : public QDialog, private Ui::properties{
void loadWebSeedsFromFile(); void loadWebSeedsFromFile();
void deleteSelectedUrlSeeds(); void deleteSelectedUrlSeeds();
void loadTrackersErrors(); void loadTrackersErrors();
void addFilesToTree(file *root, QStandardItem *parent);
void updateChildrenPriority(QStandardItem *item);
void getPriorities(QStandardItem *parent, int *priorities);
signals: signals:
void filteredFilesChanged(QString hash); void filteredFilesChanged(QString hash);
@ -79,6 +84,7 @@ class properties : public QDialog, private Ui::properties{
~properties(); ~properties();
bool allFiltered() const; bool allFiltered() const;
bool savePiecesPriorities(); bool savePiecesPriorities();
int* loadPiecesPriorities();
}; };
#endif #endif

1
src/qtorrenthandle.h

@ -24,6 +24,7 @@
#include <libtorrent/torrent_handle.hpp> #include <libtorrent/torrent_handle.hpp>
#include <libtorrent/torrent_info.hpp> #include <libtorrent/torrent_info.hpp>
using namespace libtorrent; using namespace libtorrent;
class QString; class QString;

4
src/search.qrc

@ -2,11 +2,11 @@
<qresource> <qresource>
<file>search_engine/nova2.py</file> <file>search_engine/nova2.py</file>
<file>search_engine/novaprinter.py</file> <file>search_engine/novaprinter.py</file>
<file>search_engine/engines/piratebay.png</file>
<file>search_engine/engines/isohunt.py</file> <file>search_engine/engines/isohunt.py</file>
<file>search_engine/engines/torrentreactor.png</file>
<file>search_engine/engines/btjunkie.py</file> <file>search_engine/engines/btjunkie.py</file>
<file>search_engine/engines/torrentreactor.png</file>
<file>search_engine/engines/mininova.png</file> <file>search_engine/engines/mininova.png</file>
<file>search_engine/engines/piratebay.png</file>
<file>search_engine/engines/torrentreactor.py</file> <file>search_engine/engines/torrentreactor.py</file>
<file>search_engine/engines/mininova.py</file> <file>search_engine/engines/mininova.py</file>
<file>search_engine/engines/piratebay.py</file> <file>search_engine/engines/piratebay.py</file>

3
src/src.pro

@ -136,7 +136,8 @@ HEADERS += GUI.h misc.h options_imp.h about_imp.h \
rss.h rss_imp.h FinishedTorrents.h \ rss.h rss_imp.h FinishedTorrents.h \
allocationDlg.h FinishedListDelegate.h \ allocationDlg.h FinishedListDelegate.h \
qtorrenthandle.h downloadingTorrents.h \ qtorrenthandle.h downloadingTorrents.h \
engineSelectDlg.h pluginSource.h engineSelectDlg.h pluginSource.h \
arborescence.h
FORMS += MainWindow.ui options.ui about.ui \ FORMS += MainWindow.ui options.ui about.ui \
properties.ui createtorrent.ui preview.ui \ properties.ui createtorrent.ui preview.ui \
login.ui downloadFromURL.ui addTorrentDialog.ui \ login.ui downloadFromURL.ui addTorrentDialog.ui \

138
src/torrentAddition.h

@ -37,6 +37,7 @@
#include "misc.h" #include "misc.h"
#include "PropListDelegate.h" #include "PropListDelegate.h"
#include "ui_addTorrentDialog.h" #include "ui_addTorrentDialog.h"
#include "arborescence.h"
using namespace libtorrent; using namespace libtorrent;
@ -55,19 +56,22 @@ class torrentAdditionDialog : public QDialog, private Ui_addTorrentDialog{
QString from_url; QString from_url;
QStandardItemModel *PropListModel; QStandardItemModel *PropListModel;
PropListDelegate *PropDelegate; PropListDelegate *PropDelegate;
unsigned int nbFiles;
bool editParentsOnly;
public: public:
torrentAdditionDialog(QWidget *parent) : QDialog(parent) { torrentAdditionDialog(QWidget *parent) : QDialog(parent), editParentsOnly(false){
setupUi(this); setupUi(this);
setAttribute(Qt::WA_DeleteOnClose); setAttribute(Qt::WA_DeleteOnClose);
// Set Properties list model // Set Properties list model
PropListModel = new QStandardItemModel(0,4); PropListModel = new QStandardItemModel(0,5);
PropListModel->setHeaderData(NAME, Qt::Horizontal, tr("File name")); PropListModel->setHeaderData(NAME, Qt::Horizontal, tr("File name"));
PropListModel->setHeaderData(SIZE, Qt::Horizontal, tr("Size")); PropListModel->setHeaderData(SIZE, Qt::Horizontal, tr("Size"));
PropListModel->setHeaderData(PROGRESS, Qt::Horizontal, tr("Progress")); PropListModel->setHeaderData(PROGRESS, Qt::Horizontal, tr("Progress"));
PropListModel->setHeaderData(PRIORITY, Qt::Horizontal, tr("Priority")); PropListModel->setHeaderData(PRIORITY, Qt::Horizontal, tr("Priority"));
torrentContentList->setModel(PropListModel); torrentContentList->setModel(PropListModel);
torrentContentList->hideColumn(PROGRESS); torrentContentList->hideColumn(PROGRESS);
torrentContentList->hideColumn(INDEX);
PropDelegate = new PropListDelegate(); PropDelegate = new PropListDelegate();
torrentContentList->setItemDelegate(PropDelegate); torrentContentList->setItemDelegate(PropDelegate);
connect(torrentContentList, SIGNAL(clicked(const QModelIndex&)), torrentContentList, SLOT(edit(const QModelIndex&))); connect(torrentContentList, SIGNAL(clicked(const QModelIndex&)), torrentContentList, SLOT(edit(const QModelIndex&)));
@ -100,6 +104,7 @@ class torrentAdditionDialog : public QDialog, private Ui_addTorrentDialog{
entry e = bdecode(std::istream_iterator<char>(in), std::istream_iterator<char>()); entry e = bdecode(std::istream_iterator<char>(in), std::istream_iterator<char>());
// Getting torrent file informations // Getting torrent file informations
torrent_info t(e); torrent_info t(e);
nbFiles = t.num_files();
// Setting file name // Setting file name
fileName = misc::toQString(t.name()); fileName = misc::toQString(t.name());
hash = misc::toQString(t.info_hash()); hash = misc::toQString(t.info_hash());
@ -112,15 +117,11 @@ class torrentAdditionDialog : public QDialog, private Ui_addTorrentDialog{
} }
fileNameLbl->setText(QString::fromUtf8("<center><b>")+newFileName+QString::fromUtf8("</b></center>")); fileNameLbl->setText(QString::fromUtf8("<center><b>")+newFileName+QString::fromUtf8("</b></center>"));
// List files in torrent // List files in torrent
unsigned int nbFiles = t.num_files(); arborescence *arb = new arborescence(t);
for(unsigned int i=0; i<nbFiles; ++i){ addFilesToTree(arb->getRoot(), PropListModel->invisibleRootItem());
unsigned int row = PropListModel->rowCount(); delete arb;
PropListModel->insertRow(row); connect(PropListModel, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(updateChildrenPriority(QStandardItem*)));
PropListModel->setData(PropListModel->index(row, NAME), QVariant(misc::toQString(t.file_at(i).path.leaf()))); torrentContentList->expandAll();
PropListModel->setData(PropListModel->index(row, SIZE), QVariant((qlonglong)t.file_at(i).size));
PropListModel->setData(PropListModel->index(i, PRIORITY), QVariant(NORMAL));
setRowColor(i, QString::fromUtf8("green"));
}
}catch (invalid_torrent_file&){ // Raised by torrent_info constructor }catch (invalid_torrent_file&){ // Raised by torrent_info constructor
// Display warning to tell user we can't decode the torrent file // Display warning to tell user we can't decode the torrent file
if(!from_url.isNull()){ if(!from_url.isNull()){
@ -157,7 +158,93 @@ class torrentAdditionDialog : public QDialog, private Ui_addTorrentDialog{
show(); show();
} }
void addFilesToTree(file *root, QStandardItem *parent) {
QList<QStandardItem*> child;
// Name
QStandardItem *first;
if(root->isDir()) {
first = new QStandardItem(QIcon(":/Icons/folder.png"), root->name());
} else {
first = new QStandardItem(QIcon(":/Icons/file.png"), root->name());
}
child << first;
// Size
child << new QStandardItem(misc::toQString(root->getSize()));
// Hidden progress
child << new QStandardItem("");
// Prio
child << new QStandardItem(misc::toQString(NORMAL));
// INDEX
child << new QStandardItem(misc::toQString(root->getIndex()));
// TODO: row Color?
// Add the child to the tree
parent->appendRow(child);
// Add childs
file *childFile;
foreach(childFile, root->getChildren()) {
addFilesToTree(childFile, first);
}
}
public slots: public slots:
void updateChildrenPriority(QStandardItem *item) {
qDebug("Priority changed");
QStandardItem *parent = item->parent();
int row = item->row();
if(!parent) {
parent = PropListModel->invisibleRootItem();
}
bool is_dir = (parent->child(row, INDEX)->text().toInt() == -1);
int priority = parent->child(row, PRIORITY)->text().toInt();
// Update parent priority
if(item->parent()) {
bool parentUpdate = true;
unsigned int rowCount = parent->rowCount();
for(unsigned int i=0; i<rowCount; ++i) {
if(parent->child(i, PRIORITY)->text().toInt() != priority) {
// Check if parent priority is NORMAL
QStandardItem *grandFather = parent->parent();
if(!grandFather) {
grandFather = PropListModel->invisibleRootItem();
}
QStandardItem *parentPrio = grandFather->child(parent->row(), PRIORITY);
editParentsOnly = true;
parentPrio->setText(misc::toQString(NORMAL));
editParentsOnly = false;
parentUpdate = false;
break;
}
}
if(parentUpdate) {
QStandardItem *grandFather = parent->parent();
if(!grandFather) {
grandFather = PropListModel->invisibleRootItem();
}
QStandardItem *parentPrio = grandFather->child(parent->row(), PRIORITY);
editParentsOnly = true;
parentPrio->setText(misc::toQString(priority));
editParentsOnly = false;
}
}
if(editParentsOnly) return;
if(!is_dir) return;
// Updating children
qDebug("Priority changed for a folder to %d", priority);
parent = parent->child(row);
unsigned int rowCount = parent->rowCount();
qDebug("The folder has %d children", rowCount);
for(unsigned int i=0; i<rowCount; ++i) {
// get child priority
QStandardItem *child = parent->child(i, PRIORITY);
int child_prio = child->text().toInt();
qDebug("Child priority is %d", child_prio);
if(child_prio != priority) {
child->setText(misc::toQString(priority));
}
}
}
void on_browseButton_clicked(){ void on_browseButton_clicked(){
QString dir; QString dir;
QDir saveDir(savePathTxt->text()); QDir saveDir(savePathTxt->text());
@ -192,8 +279,7 @@ class torrentAdditionDialog : public QDialog, private Ui_addTorrentDialog{
} }
void displayFilesListMenu(const QPoint& pos){ void displayFilesListMenu(const QPoint& pos){
unsigned int nbRows = PropListModel->rowCount(); if(nbFiles == 1) return;
if(nbRows == 1) return;
QMenu myFilesLlistMenu(this); QMenu myFilesLlistMenu(this);
QModelIndex index; QModelIndex index;
// Enable/disable pause/start action given the DL state // Enable/disable pause/start action given the DL state
@ -260,23 +346,37 @@ class torrentAdditionDialog : public QDialog, private Ui_addTorrentDialog{
} }
} }
void getPriorities(QStandardItem *parent, int *priorities) {
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();
}
}
}
void savePiecesPriorities(){ void savePiecesPriorities(){
qDebug("Saving pieces priorities"); qDebug("Saving pieces priorities");
QFile pieces_file(misc::qBittorrentPath()+QString::fromUtf8("BT_backup")+QDir::separator()+hash+QString::fromUtf8(".priorities")); QFile pieces_file(misc::qBittorrentPath()+QString::fromUtf8("BT_backup")+QDir::separator()+hash+QString::fromUtf8(".priorities"));
// First, remove old file // First, remove old file
pieces_file.remove(); pieces_file.remove();
// Write new files int *priorities = new int[nbFiles];
getPriorities(PropListModel->invisibleRootItem(), priorities);
// Ok, we have priorities, save them
if(!pieces_file.open(QIODevice::WriteOnly | QIODevice::Text)){ if(!pieces_file.open(QIODevice::WriteOnly | QIODevice::Text)){
std::cerr << "Error: Could not save pieces priorities\n"; std::cerr << "Error: Could not save pieces priorities\n";
return; return;
} }
unsigned int nbRows = PropListModel->rowCount(); for(unsigned int i=0; i<nbFiles; ++i) {
for(unsigned int i=0; i<nbRows; ++i){ pieces_file.write(misc::toQByteArray(priorities[i])+misc::toQByteArray("\n"));
QStandardItem *item = PropListModel->item(i, PRIORITY);
unsigned short priority = item->text().toInt();
pieces_file.write((misc::toQByteArray(priority)+misc::toQByteArray("\n")));
} }
pieces_file.close(); pieces_file.close();
delete[] priorities;
} }
void on_OkButton_clicked(){ void on_OkButton_clicked(){

Loading…
Cancel
Save