Compare commits

..

46 Commits

Author SHA1 Message Date
Christophe Dumez
3d9c81ffa7 - Tagged both 1.3.4 and 1.4.0beta3 releases 2009-07-12 09:31:40 +00:00
Christophe Dumez
9b86ea56ab - Updated v1.3.4 date in changelog 2009-07-12 09:14:56 +00:00
Christophe Dumez
a326307b0d - Display date as well as time in log window
- bump to v1.3.4
2009-07-12 09:13:11 +00:00
Christophe Dumez
2e888a1e68 Tuned lists properties to make sure they are displayed properly 2009-07-12 09:01:18 +00:00
Christophe Dumez
2b1755eb2a - BUGFIX: Remove last separator in top tool bar 2009-07-12 08:46:44 +00:00
Christophe Dumez
7f3832a73d Display a ratio of 0.0 if total_upload and total_download are both 0 2009-07-12 08:26:01 +00:00
Christophe Dumez
935de375b9 - BUGFIX: Torrents with an infinite ratio are no longer affected by ratio_limit set in program preferences (closes #364730) 2009-07-12 07:27:24 +00:00
Christophe Dumez
b88ea10937 - Fixed memory leak in search engine 2009-07-12 06:44:55 +00:00
Christophe Dumez
9b29302d42 - Cleanly fixed popup menus position in lists (no more workarounds) 2009-07-12 06:07:20 +00:00
Christophe Dumez
e67d3243e8 - Fixed percentages disapearing with default version of cleanlooks style 2009-07-12 03:39:24 +00:00
Christophe Dumez
977dba4be6 - Updated Changelog 2009-07-12 03:12:41 +00:00
Christophe Dumez
114d96195b - Suppressed QLayout: Attempting to add QLayout "" to properties "properties" warning message when opening a properties dialog (closes #380414) 2009-07-12 03:07:40 +00:00
Christophe Dumez
99786cdf17 - Fixing compiling with Qt 4.3 2009-06-21 15:04:17 +00:00
Christophe Dumez
0ad7781c8b - Fixed a bug in download_url() function in helpers.py 2009-06-19 06:54:54 +00:00
Christophe Dumez
dceba7e2e1 - Fixed ip filter parsing on 64bits (Fix by Eric Porter) 2009-05-03 15:39:49 +00:00
Christophe Dumez
3a6b5af494 - Fixed copyright in helpers.py 2009-04-07 06:48:30 +00:00
Christophe Dumez
d6ca454bad - Forgot to commit those headers 2009-04-05 18:49:27 +00:00
Christophe Dumez
e7581df394 - Fixed typo in novaprinter (Thanks Cristian Greco) 2009-04-05 17:13:03 +00:00
Christophe Dumez
65d763b30b - Cosmetic fix to license
- Updated Changelog
2009-04-05 17:03:17 +00:00
Christophe Dumez
16798879b9 - License fix due to problems with OpenSSL 2009-04-05 17:01:07 +00:00
Christophe Dumez
74ce8fc87e - Added ico favicon support to search engine plugins manager (until now, only png was supported)
- Updated server url for search plugins update (new search engine plugins are not compatible with qBittorrent < v1.3.3)
2009-03-30 21:40:35 +00:00
Christophe Dumez
7dde3423f7 - Updated nova2.py version to force update 2009-03-30 20:32:14 +00:00
Christophe Dumez
4a960a289e - Fix search item download when a column was sorted 2009-03-30 13:43:20 +00:00
Christophe Dumez
aad78a92f6 - Updated Finnish translation 2009-03-30 07:37:13 +00:00
Christophe Dumez
edaad3f605 - fix compilation with Qt <= 4.3 2009-03-28 19:55:44 +00:00
Christophe Dumez
6ef317da16 - bump to v1.3.3 2009-03-27 22:44:06 +00:00
Christophe Dumez
4ba084e7d5 - Torrent downloading is now handled by search engine plugins to allow for more flexibility 2009-03-27 22:29:42 +00:00
Christophe Dumez
6732d2e3de - Removed useless variable 2009-03-27 19:57:11 +00:00
Christophe Dumez
8e5f0404a8 - Force UTF-8 printing to term in search engine for avoid encoding problems 2009-03-27 14:35:35 +00:00
Christophe Dumez
080965f0e5 BUGFIX: Fixed search engine bug that prevented a torrent from appearing more than
once among all tabs
2009-03-27 13:30:21 +00:00
Christophe Dumez
cd9b6ec54e - fix for last commit 2009-03-26 21:00:47 +00:00
Christophe Dumez
e01a87e644 - Removed some debug output 2009-03-26 20:25:28 +00:00
Christophe Dumez
e0cba78dac - Should completely fix unicode problems in search engine 2009-03-26 20:17:14 +00:00
Christophe Dumez
22ff0374d5 - Fixed unicode support in btjunkie and mininova search engines 2009-03-26 16:53:17 +00:00
Christophe Dumez
813f52f452 - forgot to commit this file 2009-03-14 15:23:32 +00:00
Christophe Dumez
2dd376a5b1 BUGFIX: Fixed Web UI torrent upload form 2009-03-12 13:26:12 +00:00
Christophe Dumez
16832d52c0 - Updated changelog 2009-03-06 23:47:20 +00:00
Christophe Dumez
d128b734b0 - Updated splash screen 2009-03-06 23:37:04 +00:00
Christophe Dumez
9a300db87a - BUGFIX: RSS items read status is now remembered upon restart 2009-03-06 23:22:16 +00:00
Christophe Dumez
c6698cbf5a - Added patches for v1.3.2 2009-03-06 22:25:42 +00:00
Christophe Dumez
4c8ecf5459 - Tagged v1.3.x 2009-03-06 22:22:19 +00:00
Christophe Dumez
1a2fdc259c - BUGFIX: Fixed "hide top toolBar" feature 2009-02-04 19:16:56 +00:00
Christophe Dumez
5c3f2f0aed - Updated release date 2009-01-26 15:16:02 +00:00
Christophe Dumez
e0ef409220 - Updated release date 2009-01-26 15:15:19 +00:00
Christophe Dumez
d9199ce836 Moved v1.3.x to its own branch 2009-01-26 15:12:59 +00:00
Christophe Dumez
d78a47ad30 Tagged v1.3.1 release 2009-01-26 15:10:23 +00:00
208 changed files with 33901 additions and 40913 deletions

View File

@@ -17,11 +17,6 @@ Images Authors:
license: GPLv2
url: http://ftp.acc.umu.se/pub/GNOME/sources/gnome-icon-theme
* files: src/oxygen/*.png
copyright: Oxygen Icon Theme (KDE)
license: LGPL
url: http://www.oxygen-icons.org
* files: src/Icons/flags/*.png
copyright: Open Clip Art Library
license: Creative Commons Public Domain Dedication

View File

@@ -1,52 +1,3 @@
* Unknown - Christophe Dumez <chris@qbittorrent.org> - v1.5.0
- FEATURE: Added Magnet URI support
- FEATURE: Search engine supports category-based requests
- FEATURE: Make use of torrent enclosure in RSS feeds for direct download
- FEATURE: Implemented a RSS feed downloader with filter support
- FEATURE: Save old RSS item to hard disk to remember them on start up
- FEATURE: Display free disk space in torrent addition dialog
- FEATURE: In torrent addition from URL, paste clipboard content if it contains an URL
- FEATURE: RSS feeds URLs can now be copied to clipboard
- FEATURE: RSS feeds can now be grouped into folders
- FEATURE: Added "Unread" item to RSS feed list to display all unread news
- FEATURE: If a torrent contains a torrent file, process downloaded torrent file too
- FEATURE: A random listening port can be chosen automatically
- BUGFIX: torrent resume code rewrited
- BUGFIX: Greatly improved column sorting code
- BUGFIX: Possibility to create trackerless torrents
- BUGFIX: Better item coloring in torrent content filtering dialog
- COSMETIC: Redesigned search tab to improve usability
- COSMETIC: Redesigned RSS tab to improve usability
* Sun Aug 21 2009 - Christophe Dumez <chris@qbittorrent.org> - v1.4.1
- BUGFIX: Fix problems when changing save path (if using temporary download folder)
- BUGFIX: Display real save path instead of the temporary one in torrent properties
- BUGFIX: Catching invalid_handle exception to avoid rare crashes
- BUGFIX: Fixed popup menu position in RSS feeds list
- BUGFIX: Don't save RSS feed state if it could not be updated
* Thu Aug 13 2009 - Christophe Dumez <chris@qbittorrent.org> - v1.4.0
- FEATURE: Display swarm information in lists
- FEATURE: Allow to define temporary download folder
- FEATURE: Display total amount of uploaded data in finished list
- FEATURE: Resizing a column in a search results tab affects all tabs
- FEATURE: Search results tab columns are now remembered upon startup
- FEATURE: Added right click menu in search engine to clear completion history
- FEATURE: Allow to set a different port for DHT (UDP) than the one used for Bittorrent
- FEATURE: Updated spoofing code to avoid trackers ban
- BUGFIX: Provide more helpful explanation when an I/O error occured
- BUGFIX: Stop enforcing UTF-8 and use system locale instead
- COSMETIC: Redesigned program preferences
- COSMETIC: Updated icons set
* Fri Jul 24 2009 - Christophe DUMEZ <chris@qbittorrent.org> - 1.3.5
- BUGFIX: Made IP filter parser more robust
- BUGFIX: Fixed torrent creation tool
- BUGFIX: Fixed possible overflow in progress calculation in arborescence.h
- BUGFIX: Save properties window size, position, columns width and restore them
- BUGFIX: Set a minimum default width for NAME column in properties
- BUGFIX: Remember visual indexes of columns in transfer lists
* Sun Jul 12 2009 - Christophe DUMEZ <chris@qbittorrent.org> - v1.3.4
- BUGFIX: Fixed IP filter file parsing on 64bits
- BUGFIX: Suppressed QLayout: Attempting to add QLayout "" to properties "properties" warning message when opening a properties dialog

19
TODO
View File

@@ -1,2 +1,21 @@
See https://blueprints.launchpad.net/qbittorrent/
// translations done in v1.3.0
- Romanian
- Russian
- Hungarian
- German
- Chinese (traditional)
- Chinese (simplified)
- Italian
- Swedish
- Turkish
- French
- Slovak
- Czech
- Korean
- Portuguese
- Brazilian
- Greek
- Bulgarian
- Finnish

95
configure vendored
View File

@@ -18,6 +18,11 @@ Main options:
--help This help text.
Dependency options:
--with-libtorrent-inc=[path] Path to libtorrent-rasterbar include
files
--with-libtorrent-lib=[path] Path to libtorrent-rasterbar library
files
--with-libtorrent-static-lib=[path] Path to libtorrent-rasterbar .a file
--with-libboost-inc=[path] Path to libboost include files
--with-libcurl-inc=[path] Path to libcurl include files
--with-libcurl-lib=[path] Path to libcurl library files
@@ -140,6 +145,21 @@ while [ $# -gt 0 ]; do
shift
;;
--with-libtorrent-inc=*)
QC_WITH_LIBTORRENT_INC=$optarg
shift
;;
--with-libtorrent-lib=*)
QC_WITH_LIBTORRENT_LIB=$optarg
shift
;;
--with-libtorrent-static-lib=*)
QC_WITH_LIBTORRENT_STATIC_LIB=$optarg
shift
;;
--with-libboost-inc=*)
QC_WITH_LIBBOOST_INC=$optarg
shift
@@ -191,6 +211,9 @@ echo PREFIX=$PREFIX
echo BINDIR=$BINDIR
echo DATADIR=$DATADIR
echo EX_QTDIR=$EX_QTDIR
echo QC_WITH_LIBTORRENT_INC=$QC_WITH_LIBTORRENT_INC
echo QC_WITH_LIBTORRENT_LIB=$QC_WITH_LIBTORRENT_LIB
echo QC_WITH_LIBTORRENT_STATIC_LIB=$QC_WITH_LIBTORRENT_STATIC_LIB
echo QC_WITH_LIBBOOST_INC=$QC_WITH_LIBBOOST_INC
echo QC_WITH_LIBCURL_INC=$QC_WITH_LIBCURL_INC
echo QC_WITH_LIBCURL_LIB=$QC_WITH_LIBCURL_LIB
@@ -323,29 +346,70 @@ public:
/*
-----BEGIN QCMOD-----
name: libtorrent-rasterbar
arg: with-libtorrent-inc=[path], Path to libtorrent-rasterbar include files
arg: with-libtorrent-lib=[path], Path to libtorrent-rasterbar library files
arg: with-libtorrent-static-lib=[path], Path to libtorrent-rasterbar .a file
-----END QCMOD-----
*/
// see Conf::findPkgConfig
class qc_libtorrent_rasterbar : public ConfObj
{
public:
qc_libtorrent_rasterbar(Conf *c) : ConfObj(c) {}
QString name() const { return "libtorrent-rasterbar >= 0.14.0 (>= 0.14.4 advised)"; }
QString name() const { return "libtorrent-rasterbar >= 0.14"; }
QString shortname() const { return "libtorrent-rasterbar"; }
bool exec(){
QStringList incs;
QString req_ver = "0.14.0";
QString adv_ver = "0.14.4";
QString version, libs, other;
VersionMode mode = VersionMin;
if(!conf->findPkgConfig("libtorrent-rasterbar", mode, req_ver, &version, &incs, &libs, &other))
QString s;
s = conf->getenv("QC_WITH_LIBTORRENT_INC");
if(!s.isEmpty()) {
if(!conf->checkHeader(s, "libtorrent/magnet_uri.hpp")) {
return false;
for(int n = 0; n < incs.count(); ++n)
conf->addIncludePath(incs[n]);
if(!libs.isEmpty())
conf->addLib(libs);
if(!conf->findPkgConfig("libtorrent-rasterbar", mode, adv_ver, &version, &incs, &libs, &other))
printf("\nWarning: libtorrent-rasterbar v%s was detected. Although it will compile and run, you will probably experience some bugs. Please consider updating to v%s!\n", version.toUtf8().data(), adv_ver.toUtf8().data());
}
}else{
QStringList sl;
sl << "/usr/include";
sl << "/usr/local/include";
bool found = false;
foreach(s, sl){
if(conf->checkHeader(s, "libtorrent/magnet_uri.hpp")){
found = true;
break;
}
}
if(!found) {
return false;
}
}
conf->addIncludePath(s);
conf->addIncludePath(s+QDir::separator()+"libtorrent");
s = conf->getenv("QC_WITH_LIBTORRENT_STATIC_LIB");
if(!s.isEmpty() && QFile::exists(s) && s.endsWith(".a")){
conf->addLib(s);
return true;
}
s = conf->getenv("QC_WITH_LIBTORRENT_LIB");
if(!s.isEmpty()) {
if(!conf->checkLibrary(s, "torrent-rasterbar")) {
return false;
}
conf->addLib(QString("-L") + s);
}else{
QStringList sl;
sl << "/usr/lib/";
sl << "/usr/lib64/";
sl << "/usr/local/lib/";
sl << "/usr/local/lib64/";
bool found = false;
foreach(s, sl){
if(conf->checkLibrary(s, "torrent-rasterbar")){
found = true;
break;
}
}
if(!found) return false;
conf->addLib(QString("-L") + s);
}
return true;
}
};
@@ -1503,6 +1567,9 @@ export PREFIX
export BINDIR
export DATADIR
export EX_QTDIR
export QC_WITH_LIBTORRENT_INC
export QC_WITH_LIBTORRENT_LIB
export QC_WITH_LIBTORRENT_STATIC_LIB
export QC_WITH_LIBBOOST_INC
export QC_WITH_LIBCURL_INC
export QC_WITH_LIBCURL_LIB

View File

@@ -64,11 +64,14 @@ public:
return false;
}
conf->addLib(QString("-L") + s);
QString out = "";
QProcess magickConfig;
QStringList params;
params << "--libs";
qconf->doCommand("Magick++-config", params, &out);
out = out.replace("\n", "");
magickConfig.start("Magick++-config", params, QIODevice::ReadOnly);
magickConfig.waitForStarted();
magickConfig.waitForFinished();
QByteArray result = magickConfig.readAll();
result = result.replace("\n", "");
conf->addLib(result.data());
conf->addDefine("HAVE_MAGICK");
return true;

View File

@@ -1,6 +1,9 @@
/*
-----BEGIN QCMOD-----
name: libtorrent-rasterbar
arg: with-libtorrent-inc=[path], Path to libtorrent-rasterbar include files
arg: with-libtorrent-lib=[path], Path to libtorrent-rasterbar library files
arg: with-libtorrent-static-lib=[path], Path to libtorrent-rasterbar .a file
-----END QCMOD-----
*/
// see Conf::findPkgConfig
@@ -8,22 +11,61 @@ class qc_libtorrent_rasterbar : public ConfObj
{
public:
qc_libtorrent_rasterbar(Conf *c) : ConfObj(c) {}
QString name() const { return "libtorrent-rasterbar >= 0.14.0 (>= 0.14.4 advised)"; }
QString name() const { return "libtorrent-rasterbar >= 0.14"; }
QString shortname() const { return "libtorrent-rasterbar"; }
bool exec(){
QStringList incs;
QString req_ver = "0.14.0";
QString adv_ver = "0.14.4";
QString version, libs, other;
VersionMode mode = VersionMin;
if(!conf->findPkgConfig("libtorrent-rasterbar", mode, req_ver, &version, &incs, &libs, &other))
QString s;
s = conf->getenv("QC_WITH_LIBTORRENT_INC");
if(!s.isEmpty()) {
if(!conf->checkHeader(s, "libtorrent/magnet_uri.hpp")) {
return false;
for(int n = 0; n < incs.count(); ++n)
conf->addIncludePath(incs[n]);
if(!libs.isEmpty())
conf->addLib(libs);
if(!conf->findPkgConfig("libtorrent-rasterbar", mode, adv_ver, &version, &incs, &libs, &other))
printf("\nWarning: libtorrent-rasterbar v%s was detected. Although it will compile and run, you will probably experience some bugs. Please consider updating to v%s!\n", version.toLocal8Bit().data(), adv_ver.toUtf8().data());
}
}else{
QStringList sl;
sl << "/usr/include";
sl << "/usr/local/include";
bool found = false;
foreach(s, sl){
if(conf->checkHeader(s, "libtorrent/magnet_uri.hpp")){
found = true;
break;
}
}
if(!found) {
return false;
}
}
conf->addIncludePath(s);
conf->addIncludePath(s+QDir::separator()+"libtorrent");
s = conf->getenv("QC_WITH_LIBTORRENT_STATIC_LIB");
if(!s.isEmpty() && QFile::exists(s) && s.endsWith(".a")){
conf->addLib(s);
return true;
}
s = conf->getenv("QC_WITH_LIBTORRENT_LIB");
if(!s.isEmpty()) {
if(!conf->checkLibrary(s, "torrent-rasterbar")) {
return false;
}
conf->addLib(QString("-L") + s);
}else{
QStringList sl;
sl << "/usr/lib/";
sl << "/usr/lib64/";
sl << "/usr/local/lib/";
sl << "/usr/local/lib64/";
bool found = false;
foreach(s, sl){
if(conf->checkLibrary(s, "torrent-rasterbar")){
found = true;
break;
}
}
if(!found) return false;
conf->addLib(QString("-L") + s);
}
return true;
}
};

View File

@@ -1,480 +0,0 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2006 Christophe Dumez
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* In addition, as a special exception, the copyright holders give permission to
* link this program with the OpenSSL project's "OpenSSL" library (or with
* modified versions of it that use the same license as the "OpenSSL" library),
* and distribute the linked executables. You must obey the GNU General Public
* License in all respects for all of the code used other than "OpenSSL". If you
* modify file(s), you may extend this exception to your version of the file(s),
* but you are not obligated to do so. If you do not wish to do so, delete this
* exception statement from your version.
*
* Contact : chris@qbittorrent.org
*/
#ifndef FEEDDOWNLOADER_H
#define FEEDDOWNLOADER_H
#include <QString>
#include <QHash>
#include <QSettings>
#include <QListWidget>
#include <QListWidgetItem>
#include <QInputDialog>
#include <QMessageBox>
#include <QRegExp>
#include <QMenu>
#include <QFile>
#include <QDataStream>
#include <QFileDialog>
#include "bittorrent.h"
#include "ui_FeedDownloader.h"
class FeedFilter: public QHash<QString, QVariant> {
private:
bool valid;
public:
FeedFilter():valid(true) {}
FeedFilter(bool valid): valid(valid) {}
FeedFilter(QHash<QString, QVariant> filter): QHash<QString, QVariant>(filter), valid(true) {}
bool matches(QString s) {
QStringList match_tokens = getMatchingTokens();
foreach(const QString& token, match_tokens) {
if(token.isEmpty() || token == "")
continue;
QRegExp reg(token, Qt::CaseInsensitive);
if(reg.indexIn(s) < 0) return false;
}
// Checking not matching
QStringList notmatch_tokens = getNotMatchingTokens();
foreach(const QString& token, notmatch_tokens) {
if(token.isEmpty()) continue;
QRegExp reg(token, Qt::CaseInsensitive);
if(reg.indexIn(s) > -1) return false;
}
return true;
}
bool isValid() const {
return valid;
}
QStringList getMatchingTokens() const {
QString matches = this->value("matches", "").toString();
return matches.split(" ");
}
QString getMatchingTokens_str() const {
return this->value("matches", "").toString();
}
void setMatchingTokens(QString tokens) {
tokens = tokens.trimmed();
if(tokens.isEmpty())
(*this)["matches"] = "";
else
(*this)["matches"] = tokens;
}
QStringList getNotMatchingTokens() const {
QString notmatching = this->value("not", "").toString();
return notmatching.split(" ");
}
QString getNotMatchingTokens_str() const {
return this->value("not", "").toString();
}
void setNotMatchingTokens(QString tokens) {
(*this)["not"] = tokens.trimmed();
}
QString getSavePath() const {
return this->value("save_path", "").toString();
}
void setSavePath(QString save_path) {
(*this)["save_path"] = save_path;
}
};
class FeedFilters : public QHash<QString, QVariant> {
private:
QString feed_url;
public:
FeedFilters() {}
FeedFilters(QString feed_url, QHash<QString, QVariant> filters): QHash<QString, QVariant>(filters), feed_url(feed_url) {}
bool hasFilter(QString name) const {
return this->contains(name);
}
FeedFilter* matches(QString s) {
if(!isDownloadingEnabled()) return 0;
if(this->size() == 0) return new FeedFilter(false);
foreach(QVariant var_hash_filter, this->values()) {
QHash<QString, QVariant> hash_filter = var_hash_filter.toHash();
FeedFilter *filter = new FeedFilter(hash_filter);
if(filter->matches(s))
return filter;
else
delete filter;
}
return 0;
}
QStringList names() const {
return this->keys();
}
FeedFilter getFilter(QString name) const {
if(this->contains(name))
return FeedFilter(this->value(name).toHash());
return FeedFilter();
}
void setFilter(QString name, FeedFilter f) {
(*this)[name] = f;
}
bool isDownloadingEnabled() const {
QSettings qBTRSS("qBittorrent", "qBittorrent-rss");
QHash<QString, QVariant> feeds_w_downloader = qBTRSS.value("downloader_on", QHash<QString, QVariant>()).toHash();
return feeds_w_downloader.value(feed_url, false).toBool();
}
void setDownloadingEnabled(bool enabled) {
QSettings qBTRSS("qBittorrent", "qBittorrent-rss");
QHash<QString, QVariant> feeds_w_downloader = qBTRSS.value("downloader_on", QHash<QString, QVariant>()).toHash();
feeds_w_downloader[feed_url] = enabled;
qBTRSS.setValue("downloader_on", feeds_w_downloader);
}
static FeedFilters getFeedFilters(QString url) {
QSettings qBTRSS("qBittorrent", "qBittorrent-rss");
QHash<QString, QVariant> all_feeds_filters = qBTRSS.value("feed_filters", QHash<QString, QVariant>()).toHash();
return FeedFilters(url, all_feeds_filters.value(url, QHash<QString, QVariant>()).toHash());
}
void rename(QString old_name, QString new_name) {
Q_ASSERT(this->contains(old_name));
(*this)[new_name] = this->take(old_name);
}
bool serialize(QString path) {
QFile f(path);
if(f.open(QIODevice::WriteOnly)) {
QDataStream out(&f);
out.setVersion(QDataStream::Qt_4_3);
out << (QHash<QString, QVariant>)(*this);
f.close();
return true;
} else {
return false;
}
}
bool unserialize(QString path) {
QFile f(path);
if(f.open(QIODevice::ReadOnly)) {
QDataStream in(&f);
in.setVersion(QDataStream::Qt_4_3);
QHash<QString, QVariant> tmp;
in >> tmp;
qDebug("Unserialized %d filters", tmp.size());
foreach(const QString& key, tmp.keys()) {
(*this)[key] = tmp[key];
}
return true;
} else {
return false;
}
}
void save() {
QSettings qBTRSS("qBittorrent", "qBittorrent-rss");
QHash<QString, QVariant> all_feeds_filters = qBTRSS.value("feed_filters", QHash<QString, QVariant>()).toHash();
qDebug("Saving filters for feed: %s (%d filters)", feed_url.toLocal8Bit().data(), (*this).size());
all_feeds_filters[feed_url] = *this;
qBTRSS.setValue("feed_filters", all_feeds_filters);
}
};
class FeedDownloaderDlg : public QDialog, private Ui_FeedDownloader{
Q_OBJECT
private:
QString feed_url;
QString feed_name;
FeedFilters filters;
bittorrent *BTSession;
QString selected_filter; // name
public:
FeedDownloaderDlg(QWidget *parent, QString feed_url, QString feed_name, bittorrent* BTSession): QDialog(parent), feed_url(feed_url), feed_name(feed_name), BTSession(BTSession), selected_filter(QString::null){
setupUi(this);
setAttribute(Qt::WA_DeleteOnClose);
Q_ASSERT(!feed_name.isEmpty());
rssfeed_lbl->setText(feed_name);
filters = FeedFilters::getFeedFilters(feed_url);
// Connect Signals/Slots
connect(filtersList, SIGNAL(currentItemChanged(QListWidgetItem* , QListWidgetItem *)), this, SLOT(showFilterSettings(QListWidgetItem *)));
connect(filtersList, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayFiltersListMenu(const QPoint&)));
connect(actionAdd_filter, SIGNAL(triggered()), this, SLOT(addFilter()));
connect(actionRemove_filter, SIGNAL(triggered()), this, SLOT(deleteFilter()));
connect(actionRename_filter, SIGNAL(triggered()), this, SLOT(renameFilter()));
connect(del_button, SIGNAL(clicked(bool)), this, SLOT(deleteFilter()));
connect(add_button, SIGNAL(clicked(bool)), this, SLOT(addFilter()));
connect(enableDl_cb, SIGNAL(stateChanged(int)), this, SLOT(enableFilterBox(int)));
// Restore saved info
enableDl_cb->setChecked(filters.isDownloadingEnabled());
fillFiltersList();
if(filters.size() > 0) {
// Select first filter
filtersList->setCurrentItem(filtersList->item(0));
//showFilterSettings(filtersList->item(0));
}
// Show
show();
}
~FeedDownloaderDlg() {
// Make sure we save everything
saveCurrentFilterSettings();
filters.save();
}
protected slots:
void saveCurrentFilterSettings() {
if(!selected_filter.isEmpty()) {
FeedFilter filter = filters.getFilter(selected_filter);
filter.setMatchingTokens(match_line->text());
filter.setNotMatchingTokens(notmatch_line->text());
QString save_path = savepath_line->text().trimmed();
if(save_path.isEmpty())
save_path = BTSession->getDefaultSavePath();
filter.setSavePath(save_path);
// Save updated filter
filters.setFilter(selected_filter, filter);
}
}
void fillFiltersList() {
// Fill filter list
foreach(QString filter_name, filters.names()) {
new QListWidgetItem(filter_name, filtersList);
}
}
void displayFiltersListMenu(const QPoint&) {
QMenu myFiltersListMenu(this);
if(filtersList->selectedItems().size() > 0) {
myFiltersListMenu.addAction(actionRename_filter);
myFiltersListMenu.addAction(actionRemove_filter);
} else {
myFiltersListMenu.addAction(actionAdd_filter);
}
// Call menu
myFiltersListMenu.exec(QCursor::pos());
}
void showFilterSettings(QListWidgetItem *item) {
// First, save current filter settings
saveCurrentFilterSettings();
// Clear all fields
clearFields();
if(!item) {
qDebug("No new selected item");
return;
}
// Actually show filter settings
QString filter_name = item->text();
FeedFilter filter = filters.getFilter(filter_name);
filterSettingsBox->setEnabled(true);
match_line->setText(filter.getMatchingTokens_str());
if(match_line->text().trimmed().isEmpty()) {
match_line->setText(filter_name);
}
notmatch_line->setText(filter.getNotMatchingTokens_str());
QString save_path = filter.getSavePath();
if(save_path.isEmpty())
save_path = BTSession->getDefaultSavePath();
savepath_line->setText(save_path);
// Update selected filter
selected_filter = filter_name;
}
void deleteFilter() {
QList<QListWidgetItem *> items = filtersList->selectedItems();
if(items.size() == 1) {
QListWidgetItem * item = items.first();
filters.remove(item->text());
selected_filter = QString::null;
delete item;
// Reset Filter settings view
if(filters.size() == 0) {
clearFields();
filterSettingsBox->setEnabled(false);
}
}
}
void renameFilter() {
QList<QListWidgetItem *> items = filtersList->selectedItems();
if(items.size() == 1) {
QListWidgetItem *item = items.first();
QString current_name = item->text();
QString new_name;
bool validated = false;
do {
new_name = askFilterName(current_name);
if(new_name.isNull() || new_name == current_name) return;
if(!filters.hasFilter(new_name)) {
validated = true;
} else {
QMessageBox::warning(0, tr("Invalid filter name"), tr("This filter name is already in use."));
}
}while(!validated);
// Rename the filter
filters.rename(current_name, new_name);
if(selected_filter == current_name)
selected_filter = new_name;
item->setText(new_name);
}
}
void enableFilterBox(int state) {
if(state == Qt::Checked) {
filtersBox->setEnabled(true);
filters.setDownloadingEnabled(true);
} else {
filtersBox->setEnabled(false);
filters.setDownloadingEnabled(false);
}
}
QString askFilterName(QString name=QString::null) {
QString name_prop;
if(name.isEmpty())
name_prop = tr("New filter");
else
name_prop = name;
QString new_name;
bool validated = false;
do {
bool ok;
new_name = QInputDialog::getText(this, tr("Please choose a name for this filter"), tr("Filter name:"), QLineEdit::Normal, name_prop, &ok);
if(!ok) {
return QString::null;
}
// Validate filter name
new_name = new_name.trimmed();
if(new_name.isEmpty()) {
// Cannot be left empty
QMessageBox::warning(0, tr("Invalid filter name"), tr("The filter name cannot be left empty."));
} else {
validated = true;
}
} while(!validated);
return new_name;
}
void addFilter() {
QString filter_name = QString::null;
bool validated = false;
do {
filter_name = askFilterName();
if(filter_name.isNull()) return;
if(filters.hasFilter(filter_name)) {
// Filter alread exists
QMessageBox::warning(0, tr("Invalid filter name"), tr("This filter name is already in use."));
} else {
validated = true;
}
}while(!validated);
QListWidgetItem *it = new QListWidgetItem(filter_name, filtersList);
filtersList->setCurrentItem(it);
//showFilterSettings(it);
}
void clearFields() {
match_line->clear();
notmatch_line->clear();
savepath_line->clear();
test_res_lbl->setText("");
test_line->clear();
}
void on_testButton_clicked(bool) {
if(selected_filter.isEmpty()) return;
QString s = test_line->text().trimmed();
if(s.isEmpty()) {
QMessageBox::warning(0, tr("Filter testing error"), tr("Please specify a test torrent name."));
return;
}
// Get current filter
saveCurrentFilterSettings();
FeedFilter f = filters.getFilter(selected_filter);
if(f.matches(s))
test_res_lbl->setText("<b><font color=\"green\">"+tr("matches")+"</font></b>");
else
test_res_lbl->setText("<b><font color=\"red\">"+tr("does not match")+"</font></b>");
}
void on_importButton_clicked(bool) {
QString source = QFileDialog::getOpenFileName(0, tr("Select file to import"), QDir::homePath(), tr("Filters Files")+QString::fromUtf8(" (*.filters)"));
if(source.isEmpty()) return;
if(filters.unserialize(source)) {
// Clean up first
clearFields();
filtersList->clear();
selected_filter = QString::null;
fillFiltersList();
if(filters.size() > 0)
filtersList->setCurrentItem(filtersList->item(0));
QMessageBox::information(0, tr("Import successful"), tr("Filters import was successful."));
} else {
QMessageBox::warning(0, tr("Import failure"), tr("Filters could not be imported due to an I/O error."));
}
}
void on_exportButton_clicked(bool) {
QString destination = QFileDialog::getSaveFileName(this, tr("Select destination file"), QDir::homePath(), tr("Filters Files")+QString::fromUtf8(" (*.filters)"));
if(destination.isEmpty()) return;
// Append file extension
if(!destination.endsWith(".filters"))
destination += ".filters";
if(QFile::exists(destination)) {
int ret = QMessageBox::question(0, tr("Overwriting confirmation"), tr("Are you sure you want to overwrite existing file?"), QMessageBox::Yes|QMessageBox::No);
if(ret != QMessageBox::Yes) return;
}
if(filters.serialize(destination))
QMessageBox::information(0, tr("Export successful"), tr("Filters export was successful."));
else
QMessageBox::warning(0, tr("Export failure"), tr("Filters could not be exported due to an I/O error."));
}
};
#endif // FEEDDOWNLOADER_H

View File

@@ -1,546 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>FeedDownloader</class>
<widget class="QDialog" name="FeedDownloader">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>737</width>
<height>415</height>
</rect>
</property>
<property name="windowTitle">
<string>RSS Feed downloader</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_7">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="label_2">
<property name="font">
<font>
<pointsize>16</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>RSS feed:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="rssfeed_lbl">
<property name="font">
<font>
<pointsize>16</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Feed name</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="enableDl_cb">
<property name="text">
<string>Automatically download torrents from this feed</string>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="filtersBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="title">
<string>Download filters</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Filters:</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QListWidget" name="filtersList">
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="del_button">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="icons.qrc">
<normaloff>:/Icons/oxygen/list-remove.png</normaloff>:/Icons/oxygen/list-remove.png</iconset>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="add_button">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="icons.qrc">
<normaloff>:/Icons/oxygen/list-add.png</normaloff>:/Icons/oxygen/list-add.png</iconset>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="filterSettingsBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="styleSheet">
<string/>
</property>
<property name="title">
<string>Filter settings</string>
</property>
<property name="flat">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_9">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="label_3">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>Matches:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_4">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>Does not match:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_5">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>Destination folder:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QLineEdit" name="match_line">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="notmatch_line"/>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLineEdit" name="savepath_line">
<property name="minimumSize">
<size>
<width>300</width>
<height>0</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="browse_button">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="testerBox">
<property name="title">
<string>Filter testing</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_8">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_9">
<item>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="QLabel" name="label_6">
<property name="minimumSize">
<size>
<width>0</width>
<height>28</height>
</size>
</property>
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>Torrent title:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_7">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>Result:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<widget class="QLineEdit" name="test_line"/>
</item>
<item>
<widget class="QPushButton" name="testButton">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>Test</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_7">
<item>
<widget class="QLabel" name="test_res_lbl">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string> </string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>9</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_10">
<item>
<widget class="QPushButton" name="importButton">
<property name="text">
<string>Import...</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="exportButton">
<property name="text">
<string>Export...</string>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Close</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
<action name="actionRename_filter">
<property name="icon">
<iconset resource="icons.qrc">
<normaloff>:/Icons/oxygen/edit_clear.png</normaloff>:/Icons/oxygen/edit_clear.png</iconset>
</property>
<property name="text">
<string>Rename filter</string>
</property>
<property name="toolTip">
<string>Rename filter</string>
</property>
</action>
<action name="actionRemove_filter">
<property name="icon">
<iconset resource="icons.qrc">
<normaloff>:/Icons/oxygen/list-remove.png</normaloff>:/Icons/oxygen/list-remove.png</iconset>
</property>
<property name="text">
<string>Remove filter</string>
</property>
<property name="toolTip">
<string>Remove filter</string>
</property>
</action>
<action name="actionAdd_filter">
<property name="icon">
<iconset resource="icons.qrc">
<normaloff>:/Icons/oxygen/list-add.png</normaloff>:/Icons/oxygen/list-add.png</iconset>
</property>
<property name="text">
<string>Add filter</string>
</property>
</action>
</widget>
<resources>
<include location="icons.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>FeedDownloader</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>FeedDownloader</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -44,11 +44,9 @@
#define F_NAME 0
#define F_SIZE 1
#define F_UPSPEED 2
#define F_SWARM 3
#define F_PEERS 4
#define F_UPLOAD 5
#define F_RATIO 6
#define F_HASH 7
#define F_LEECH 3
#define F_RATIO 4
#define F_HASH 5
#define MAX_RATIO 100.
@@ -64,7 +62,6 @@ class FinishedListDelegate: public QItemDelegate {
QStyleOptionViewItemV2 opt = QItemDelegate::setOptions(index, option);
switch(index.column()){
case F_SIZE:
case F_UPLOAD:
QItemDelegate::drawBackground(painter, opt, index);
QItemDelegate::drawDisplay(painter, opt, option.rect, misc::friendlyUnit(index.data().toLongLong()));
break;

View File

@@ -38,7 +38,6 @@
#include <QFile>
#include <QSettings>
#include <QStandardItemModel>
#include <QSortFilterProxyModel>
#include <QHeaderView>
#include <QMenu>
#include <QMessageBox>
@@ -47,24 +46,15 @@ FinishedTorrents::FinishedTorrents(QObject *parent, bittorrent *BTSession) : par
setupUi(this);
actionStart->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/play.png")));
actionPause->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/pause.png")));
finishedListModel = new QStandardItemModel(0,8);
finishedListModel = new QStandardItemModel(0,6);
finishedListModel->setHeaderData(F_NAME, Qt::Horizontal, tr("Name", "i.e: file name"));
finishedListModel->setHeaderData(F_SIZE, Qt::Horizontal, tr("Size", "i.e: file size"));
finishedListModel->setHeaderData(F_UPSPEED, Qt::Horizontal, tr("UP Speed", "i.e: Upload speed"));
finishedListModel->setHeaderData(F_SWARM, Qt::Horizontal, tr("Seeds / Leechers"));
finishedListModel->setHeaderData(F_PEERS, Qt::Horizontal, tr("Connected peers"));
finishedListModel->setHeaderData(F_UPLOAD, Qt::Horizontal, tr("Total uploaded", "i.e: Total amount of uploaded data"));
finishedListModel->setHeaderData(F_LEECH, Qt::Horizontal, tr("Leechers", "i.e: full/partial sources"));
finishedListModel->setHeaderData(F_RATIO, Qt::Horizontal, tr("Ratio"));
proxyModel = new QSortFilterProxyModel();
proxyModel->setDynamicSortFilter(true);
proxyModel->setSourceModel(finishedListModel);
finishedList->setModel(proxyModel);
finishedList->setModel(finishedListModel);
finishedList->setRootIsDecorated(false);
finishedList->setAllColumnsShowFocus(true);
finishedList->setSortingEnabled(true);
loadHiddenColumns();
// Hide hash column
finishedList->hideColumn(F_HASH);
@@ -72,11 +62,10 @@ FinishedTorrents::FinishedTorrents(QObject *parent, bittorrent *BTSession) : par
if(!loadColWidthFinishedList()){
finishedList->header()->resizeSection(0, 200);
}
// Connect BTSession signals
connect(BTSession, SIGNAL(metadataReceived(QTorrentHandle&)), this, SLOT(updateMetadata(QTorrentHandle&)));
// Make download list header clickable for sorting
finishedList->header()->setClickable(true);
finishedList->header()->setSortIndicatorShown(true);
connect(finishedList->header(), SIGNAL(sectionPressed(int)), this, SLOT(toggleFinishedListSortOrder(int)));
finishedListDelegate = new FinishedListDelegate(finishedList);
finishedList->setItemDelegate(finishedListDelegate);
connect(finishedList, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayFinishedListMenu(const QPoint&)));
@@ -88,8 +77,6 @@ FinishedTorrents::FinishedTorrents(QObject *parent, bittorrent *BTSession) : par
actionDelete_Permanently->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/delete_perm.png")));
actionTorrent_Properties->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/properties.png")));
actionSet_upload_limit->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/seeding.png")));
actionCopy_magnet_link->setIcon(QIcon(QString::fromUtf8(":/Icons/magnet.png")));
connect(actionPause, SIGNAL(triggered()), (GUI*)parent, SLOT(on_actionPause_triggered()));
connect(actionStart, SIGNAL(triggered()), (GUI*)parent, SLOT(on_actionStart_triggered()));
connect(actionDelete, SIGNAL(triggered()), (GUI*)parent, SLOT(on_actionDelete_triggered()));
@@ -99,23 +86,18 @@ FinishedTorrents::FinishedTorrents(QObject *parent, bittorrent *BTSession) : par
connect(actionBuy_it, SIGNAL(triggered()), (GUI*)parent, SLOT(goBuyPage()));
connect(actionTorrent_Properties, SIGNAL(triggered()), this, SLOT(propertiesSelection()));
connect(actionForce_recheck, SIGNAL(triggered()), this, SLOT(forceRecheck()));
connect(actionCopy_magnet_link, SIGNAL(triggered()), (GUI*)parent, SLOT(copyMagnetURI()));
connect(actionHOSColName, SIGNAL(triggered()), this, SLOT(hideOrShowColumnName()));
connect(actionHOSColSize, SIGNAL(triggered()), this, SLOT(hideOrShowColumnSize()));
connect(actionHOSColUpSpeed, SIGNAL(triggered()), this, SLOT(hideOrShowColumnUpSpeed()));
connect(actionHOSColSwarm, SIGNAL(triggered()), this, SLOT(hideOrShowColumnSwarm()));
connect(actionHOSColPeers, SIGNAL(triggered()), this, SLOT(hideOrShowColumnPeers()));
connect(actionHOSColUpload, SIGNAL(triggered()), this, SLOT(hideOrShowColumnUpload()));
connect(actionHOSColLeechers, SIGNAL(triggered()), this, SLOT(hideOrShowColumnLeechers()));
connect(actionHOSColRatio, SIGNAL(triggered()), this, SLOT(hideOrShowColumnRatio()));
}
FinishedTorrents::~FinishedTorrents(){
saveLastSortedColumn();
saveColWidthFinishedList();
saveHiddenColumns();
delete finishedListDelegate;
delete proxyModel;
delete finishedListModel;
}
@@ -135,9 +117,7 @@ void FinishedTorrents::addTorrent(QString hash){
finishedListModel->setData(finishedListModel->index(row, F_NAME), QVariant(h.name()));
finishedListModel->setData(finishedListModel->index(row, F_SIZE), QVariant((qlonglong)h.actual_size()));
finishedListModel->setData(finishedListModel->index(row, F_UPSPEED), QVariant((double)0.));
finishedListModel->setData(finishedListModel->index(row, F_SWARM), QVariant("-1/-1"));
finishedListModel->setData(finishedListModel->index(row, F_PEERS), QVariant("0"));
finishedListModel->setData(finishedListModel->index(row, F_UPLOAD), QVariant((qlonglong)h.all_time_upload()));
finishedListModel->setData(finishedListModel->index(row, F_LEECH), QVariant("0"));
finishedListModel->setData(finishedListModel->index(row, F_RATIO), QVariant(QString::fromUtf8(misc::toString(BTSession->getRealRatio(hash)).c_str())));
finishedListModel->setData(finishedListModel->index(row, F_HASH), QVariant(hash));
if(h.is_paused()) {
@@ -150,8 +130,8 @@ void FinishedTorrents::addTorrent(QString hash){
// Update the number of finished torrents
++nbFinished;
emit finishedTorrentsNumberChanged(nbFinished);
loadLastSortedColumn();
// Sort List
sortFinishedList();
}
// Set the color of a row in data model
@@ -168,7 +148,7 @@ QStringList FinishedTorrents::getSelectedTorrents(bool only_one) const{
foreach(const QModelIndex &index, selectedIndexes) {
if(index.column() == F_NAME) {
// Get the file hash
QString hash = getHashFromRow(index.row());
QString hash = finishedListModel->data(finishedListModel->index(index.row(), F_HASH)).toString();
res << hash;
if(only_one) break;
}
@@ -196,39 +176,10 @@ bool FinishedTorrents::loadColWidthFinishedList(){
finishedList->header()->resizeSection(i, width_list.at(i).toInt());
}
loadLastSortedColumn();
QVariantList visualIndexes = settings.value(QString::fromUtf8("FinishedListVisualIndexes"), QVariantList()).toList();
if(visualIndexes.size() != finishedListModel->columnCount()-1) {
qDebug("Corrupted values for download list columns sizes");
return false;
}
bool change = false;
do {
change = false;
for(int i=0;i<visualIndexes.size(); ++i) {
int new_visual_index = visualIndexes.at(finishedList->header()->logicalIndex(i)).toInt();
if(i != new_visual_index) {
qDebug("Moving column from %d to %d", finishedList->header()->logicalIndex(i), new_visual_index);
finishedList->header()->moveSection(i, new_visual_index);
change = true;
}
}
}while(change);
qDebug("Finished list columns width loaded");
return true;
}
void FinishedTorrents::saveLastSortedColumn() {
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
Qt::SortOrder sortOrder = finishedList->header()->sortIndicatorOrder();
QString sortOrderLetter;
if(sortOrder == Qt::AscendingOrder)
sortOrderLetter = QString::fromUtf8("a");
else
sortOrderLetter = QString::fromUtf8("d");
int index = finishedList->header()->sortIndicatorSection();
settings.setValue(QString::fromUtf8("FinishedListSortedCol"), misc::toQString(index)+sortOrderLetter);
}
void FinishedTorrents::loadLastSortedColumn() {
// Loading last sorted column
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
@@ -241,7 +192,7 @@ void FinishedTorrents::loadLastSortedColumn() {
sortOrder = Qt::AscendingOrder;
sortedCol = sortedCol.left(sortedCol.size()-1);
int index = sortedCol.toInt();
finishedList->sortByColumn(index, sortOrder);
sortFinishedList(index, sortOrder);
}
}
@@ -259,7 +210,7 @@ void FinishedTorrents::saveColWidthFinishedList() const{
width_list = line.split(' ');
}
for(short i=0; i<nbColumns; ++i){
if(finishedList->columnWidth(i)<1 && width_list.size() == nbColumns && width_list.at(i).toInt()>=1) {
if(finishedList->columnWidth(i)<1 && width_list.size() == finishedListModel->columnCount()-1 && width_list.at(i).toInt()>=1) {
// load the former width
new_width_list << width_list.at(i);
} else if(finishedList->columnWidth(i)>=1) {
@@ -272,11 +223,6 @@ void FinishedTorrents::saveColWidthFinishedList() const{
}
}
settings.setValue("FinishedListColsWidth", new_width_list.join(" "));
QVariantList visualIndexes;
for(int i=0; i<nbColumns; ++i) {
visualIndexes.append(finishedList->header()->visualIndex(i));
}
settings.setValue(QString::fromUtf8("FinishedListVisualIndexes"), visualIndexes);
qDebug("Finished list columns width saved");
}
@@ -286,24 +232,13 @@ void FinishedTorrents::on_actionSet_upload_limit_triggered(){
foreach(const QModelIndex &index, selectedIndexes){
if(index.column() == F_NAME){
// Get the file hash
hashes << getHashFromRow(index.row());
hashes << finishedListModel->data(finishedListModel->index(index.row(), F_HASH)).toString();
}
}
new BandwidthAllocationDialog(this, true, BTSession, hashes);
}
void FinishedTorrents::updateMetadata(QTorrentHandle &h) {
QString hash = h.hash();
int row = getRowFromHash(hash);
if(row != -1) {
qDebug("Updating torrent metadata in download list");
finishedListModel->setData(finishedListModel->index(row, F_NAME), QVariant(h.name()));
finishedListModel->setData(finishedListModel->index(row, F_SIZE), QVariant((qlonglong)h.actual_size()));
}
}
void FinishedTorrents::updateTorrent(QTorrentHandle h) {
if(!h.is_valid()) return;
QString hash = h.hash();
int row = getRowFromHash(hash);
if(row == -1){
@@ -312,25 +247,22 @@ void FinishedTorrents::updateTorrent(QTorrentHandle h) {
row = getRowFromHash(hash);
}
Q_ASSERT(row != -1);
if(!finishedList->isColumnHidden(F_SWARM)) {
finishedListModel->setData(finishedListModel->index(row, F_SWARM), misc::toQString(h.num_complete())+QString("/")+misc::toQString(h.num_incomplete()));
}
if(h.is_paused()) return;
// Update queued torrent
if(BTSession->isQueueingEnabled() && h.is_queued()) {
if(h.state() == torrent_status::checking_files || h.state() == torrent_status::queued_for_checking){
finishedListModel->setData(finishedListModel->index(row, F_NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/oxygen/time.png"))), Qt::DecorationRole);
finishedListModel->setData(finishedListModel->index(row, F_NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/time.png"))), Qt::DecorationRole);
} else {
finishedListModel->setData(finishedListModel->index(row, F_NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/queued.png"))), Qt::DecorationRole);
}
// Reset upload speed and seeds/leech
finishedListModel->setData(finishedListModel->index(row, F_UPSPEED), 0.);
finishedListModel->setData(finishedListModel->index(row, F_PEERS), "0");
finishedListModel->setData(finishedListModel->index(row, F_LEECH), "0");
setRowColor(row, QString::fromUtf8("grey"));
return;
}
if(h.state() == torrent_status::checking_files || h.state() == torrent_status::queued_for_checking){
finishedListModel->setData(finishedListModel->index(row, F_NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/oxygen/time.png"))), Qt::DecorationRole);
finishedListModel->setData(finishedListModel->index(row, F_NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/time.png"))), Qt::DecorationRole);
setRowColor(row, QString::fromUtf8("grey"));
return;
}
@@ -339,11 +271,8 @@ void FinishedTorrents::updateTorrent(QTorrentHandle h) {
if(!finishedList->isColumnHidden(F_UPSPEED)) {
finishedListModel->setData(finishedListModel->index(row, F_UPSPEED), QVariant((double)h.upload_payload_rate()));
}
if(!finishedList->isColumnHidden(F_PEERS)) {
finishedListModel->setData(finishedListModel->index(row, F_PEERS), misc::toQString(h.num_peers() - h.num_seeds(), true));
}
if(!finishedList->isColumnHidden(F_UPLOAD)) {
finishedListModel->setData(finishedListModel->index(row, F_UPLOAD), QVariant((double)h.all_time_upload()));
if(!finishedList->isColumnHidden(F_LEECH)) {
finishedListModel->setData(finishedListModel->index(row, F_LEECH), misc::toQString(h.num_peers() - h.num_seeds(), true));
}
if(!finishedList->isColumnHidden(F_RATIO)) {
finishedListModel->setData(finishedListModel->index(row, F_RATIO), QVariant(misc::toQString(BTSession->getRealRatio(hash))));
@@ -367,13 +296,13 @@ void FinishedTorrents::pauseTorrent(QString hash) {
return;
finishedListModel->setData(finishedListModel->index(row, F_UPSPEED), QVariant((double)0.0));
finishedListModel->setData(finishedListModel->index(row, F_NAME), QIcon(QString::fromUtf8(":/Icons/skin/paused.png")), Qt::DecorationRole);
finishedListModel->setData(finishedListModel->index(row, F_PEERS), QVariant(QString::fromUtf8("0")));
finishedListModel->setData(finishedListModel->index(row, F_LEECH), QVariant(QString::fromUtf8("0")));
setRowColor(row, QString::fromUtf8("red"));
}
QString FinishedTorrents::getHashFromRow(unsigned int row) const {
Q_ASSERT(row < (unsigned int)proxyModel->rowCount());
return proxyModel->data(proxyModel->index(row, F_HASH)).toString();
Q_ASSERT(row < (unsigned int)finishedListModel->rowCount());
return finishedListModel->data(finishedListModel->index(row, F_HASH)).toString();
}
// Will move it to download tab
@@ -390,7 +319,7 @@ void FinishedTorrents::deleteTorrent(QString hash){
// Show torrent properties dialog
void FinishedTorrents::showProperties(const QModelIndex &index){
showPropertiesFromHash(getHashFromRow(index.row()));
showPropertiesFromHash(finishedListModel->data(finishedListModel->index(index.row(), F_HASH)).toString());
}
void FinishedTorrents::showPropertiesFromHash(QString hash){
@@ -421,9 +350,8 @@ void FinishedTorrents::forceRecheck(){
QModelIndexList selectedIndexes = finishedList->selectionModel()->selectedIndexes();
foreach(const QModelIndex &index, selectedIndexes){
if(index.column() == F_NAME){
QString hash = getHashFromRow(index.row());
QString hash = finishedListModel->data(finishedListModel->index(index.row(), F_HASH)).toString();
QTorrentHandle h = BTSession->getTorrentHandle(hash);
qDebug("Forcing recheck for torrent %s", hash.toLocal8Bit().data());
h.force_recheck();
}
}
@@ -437,7 +365,7 @@ void FinishedTorrents::displayFinishedListMenu(const QPoint&){
foreach(const QModelIndex &index, selectedIndexes) {
if(index.column() == F_NAME) {
// Get the file name
QString hash = getHashFromRow(index.row());
QString hash = finishedListModel->data(finishedListModel->index(index.row(), F_HASH)).toString();
// Get handle and pause the torrent
QTorrentHandle h = BTSession->getTorrentHandle(hash);
if(!h.is_valid()) continue;
@@ -470,7 +398,6 @@ void FinishedTorrents::displayFinishedListMenu(const QPoint&){
myFinishedListMenu.addAction(actionOpen_destination_folder);
myFinishedListMenu.addAction(actionTorrent_Properties);
myFinishedListMenu.addSeparator();
myFinishedListMenu.addAction(actionCopy_magnet_link);
myFinishedListMenu.addAction(actionBuy_it);
// Call menu
@@ -483,7 +410,7 @@ void FinishedTorrents::displayFinishedListMenu(const QPoint&){
*/
// hide/show columns menu
void FinishedTorrents::displayFinishedHoSMenu(const QPoint&){
void FinishedTorrents::displayFinishedHoSMenu(const QPoint& pos){
QMenu hideshowColumn(this);
hideshowColumn.setTitle(tr("Hide or Show Column"));
int lastCol = F_RATIO;
@@ -491,7 +418,7 @@ void FinishedTorrents::displayFinishedHoSMenu(const QPoint&){
hideshowColumn.addAction(getActionHoSCol(i));
}
// Call menu
hideshowColumn.exec(QCursor::pos());
hideshowColumn.exec(mapToGlobal(pos)+QPoint(10,34));
}
// toggle hide/show a column
@@ -509,12 +436,12 @@ void FinishedTorrents::hideOrShowColumn(int index) {
if(nbVisibleColumns <= 1) return;
// User can hide the column, do it.
finishedList->setColumnHidden(index, true);
getActionHoSCol(index)->setIcon(QIcon(QString::fromUtf8(":/Icons/oxygen/button_cancel.png")));
getActionHoSCol(index)->setIcon(QIcon(QString::fromUtf8(":/Icons/button_cancel.png")));
--nbVisibleColumns;
} else {
// User want to display the column
finishedList->setColumnHidden(index, false);
getActionHoSCol(index)->setIcon(QIcon(QString::fromUtf8(":/Icons/oxygen/button_ok.png")));
getActionHoSCol(index)->setIcon(QIcon(QString::fromUtf8(":/Icons/button_ok.png")));
++nbVisibleColumns;
}
//resize all others non-hidden columns
@@ -537,16 +464,8 @@ void FinishedTorrents::hideOrShowColumnUpSpeed() {
hideOrShowColumn(F_UPSPEED);
}
void FinishedTorrents::hideOrShowColumnSwarm() {
hideOrShowColumn(F_SWARM);
}
void FinishedTorrents::hideOrShowColumnPeers() {
hideOrShowColumn(F_PEERS);
}
void FinishedTorrents::hideOrShowColumnUpload() {
hideOrShowColumn(F_UPLOAD);
void FinishedTorrents::hideOrShowColumnLeechers() {
hideOrShowColumn(F_LEECH);
}
void FinishedTorrents::hideOrShowColumnRatio() {
@@ -572,9 +491,9 @@ bool FinishedTorrents::loadHiddenColumns() {
for(int i=0; i<finishedListModel->columnCount()-1; i++) {
if(loaded && ishidden_list.at(i) == "0") {
finishedList->setColumnHidden(i, true);
getActionHoSCol(i)->setIcon(QIcon(QString::fromUtf8(":/Icons/oxygen/button_cancel.png")));
getActionHoSCol(i)->setIcon(QIcon(QString::fromUtf8(":/Icons/button_cancel.png")));
} else {
getActionHoSCol(i)->setIcon(QIcon(QString::fromUtf8(":/Icons/oxygen/button_ok.png")));
getActionHoSCol(i)->setIcon(QIcon(QString::fromUtf8(":/Icons/button_ok.png")));
}
}
return loaded;
@@ -608,14 +527,8 @@ QAction* FinishedTorrents::getActionHoSCol(int index) {
case F_UPSPEED :
return actionHOSColUpSpeed;
break;
case F_SWARM :
return actionHOSColSwarm;
break;
case F_PEERS :
return actionHOSColPeers;
break;
case F_UPLOAD :
return actionHOSColUpload;
case F_LEECH :
return actionHOSColLeechers;
break;
case F_RATIO :
return actionHOSColRatio;
@@ -624,3 +537,94 @@ QAction* FinishedTorrents::getActionHoSCol(int index) {
return NULL;
}
}
/*
* Sorting functions
*/
void FinishedTorrents::toggleFinishedListSortOrder(int index) {
Qt::SortOrder sortOrder = Qt::AscendingOrder;
if(finishedList->header()->sortIndicatorSection() == index){
sortOrder = (Qt::SortOrder)!(bool)finishedList->header()->sortIndicatorOrder();
}
switch(index) {
case F_SIZE:
case F_UPSPEED:
case F_RATIO:
sortFinishedListFloat(index, sortOrder);
break;
default:
sortFinishedListString(index, sortOrder);
}
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
QString sortOrderLetter;
if(sortOrder == Qt::AscendingOrder)
sortOrderLetter = QString::fromUtf8("a");
else
sortOrderLetter = QString::fromUtf8("d");
settings.setValue(QString::fromUtf8("FinishedListSortedCol"), misc::toQString(index)+sortOrderLetter);
}
void FinishedTorrents::sortFinishedList(int index, Qt::SortOrder sortOrder){
if(index == -1) {
index = finishedList->header()->sortIndicatorSection();
sortOrder = finishedList->header()->sortIndicatorOrder();
} else {
finishedList->header()->setSortIndicator(index, sortOrder);
}
switch(index) {
case F_SIZE:
case F_UPSPEED:
sortFinishedListFloat(index, sortOrder);
break;
default:
sortFinishedListString(index, sortOrder);
}
}
void FinishedTorrents::sortFinishedListFloat(int index, Qt::SortOrder sortOrder){
QList<QPair<int, double> > lines;
// insertion sorting
unsigned int nbRows = finishedListModel->rowCount();
for(unsigned int i=0; i<nbRows; ++i){
misc::insertSort(lines, QPair<int,double>(i, finishedListModel->data(finishedListModel->index(i, index)).toDouble()), sortOrder);
}
// Insert items in new model, in correct order
unsigned int nbRows_old = lines.size();
for(unsigned int row=0; row<nbRows_old; ++row){
finishedListModel->insertRow(finishedListModel->rowCount());
unsigned int sourceRow = lines[row].first;
unsigned int nbColumns = finishedListModel->columnCount();
for(unsigned int col=0; col<nbColumns; ++col){
finishedListModel->setData(finishedListModel->index(nbRows_old+row, col), finishedListModel->data(finishedListModel->index(sourceRow, col)));
finishedListModel->setData(finishedListModel->index(nbRows_old+row, col), finishedListModel->data(finishedListModel->index(sourceRow, col), Qt::DecorationRole), Qt::DecorationRole);
finishedListModel->setData(finishedListModel->index(nbRows_old+row, col), finishedListModel->data(finishedListModel->index(sourceRow, col), Qt::ForegroundRole), Qt::ForegroundRole);
}
}
// Remove old rows
finishedListModel->removeRows(0, nbRows_old);
}
void FinishedTorrents::sortFinishedListString(int index, Qt::SortOrder sortOrder){
QList<QPair<int, QString> > lines;
// Insertion sorting
unsigned int nbRows = finishedListModel->rowCount();
for(unsigned int i=0; i<nbRows; ++i){
misc::insertSortString(lines, QPair<int, QString>(i, finishedListModel->data(finishedListModel->index(i, index)).toString()), sortOrder);
}
// Insert items in new model, in correct order
unsigned int nbRows_old = lines.size();
for(unsigned int row=0; row<nbRows_old; ++row){
finishedListModel->insertRow(finishedListModel->rowCount());
unsigned int sourceRow = lines[row].first;
unsigned int nbColumns = finishedListModel->columnCount();
for(unsigned int col=0; col<nbColumns; ++col){
finishedListModel->setData(finishedListModel->index(nbRows_old+row, col), finishedListModel->data(finishedListModel->index(sourceRow, col)));
finishedListModel->setData(finishedListModel->index(nbRows_old+row, col), finishedListModel->data(finishedListModel->index(sourceRow, col), Qt::DecorationRole), Qt::DecorationRole);
finishedListModel->setData(finishedListModel->index(nbRows_old+row, col), finishedListModel->data(finishedListModel->index(sourceRow, col), Qt::ForegroundRole), Qt::ForegroundRole);
}
}
// Remove old rows
finishedListModel->removeRows(0, nbRows_old);
}

View File

@@ -35,7 +35,6 @@
#include "qtorrenthandle.h"
class QStandardItemModel;
class QSortFilterProxyModel;
class bittorrent;
class FinishedListDelegate;
@@ -48,7 +47,6 @@ class FinishedTorrents : public QWidget, public Ui::seeding {
bittorrent *BTSession;
FinishedListDelegate *finishedListDelegate;
QStandardItemModel *finishedListModel;
QSortFilterProxyModel *proxyModel;
unsigned int nbFinished;
void hideOrShowColumn(int index);
bool loadHiddenColumns();
@@ -71,15 +69,17 @@ class FinishedTorrents : public QWidget, public Ui::seeding {
void displayFinishedHoSMenu(const QPoint&);
void setRowColor(int row, QString color);
void saveColWidthFinishedList() const;
void toggleFinishedListSortOrder(int index);
void sortFinishedList(int index=-1, Qt::SortOrder sortOrder=Qt::AscendingOrder);
void sortFinishedListFloat(int index, Qt::SortOrder sortOrder);
void sortFinishedListString(int index, Qt::SortOrder sortOrder);
void updateFileSize(QString hash);
void on_actionSet_upload_limit_triggered();
void notifyTorrentDoubleClicked(const QModelIndex& index);
void hideOrShowColumnName();
void hideOrShowColumnSize();
void hideOrShowColumnUpSpeed();
void hideOrShowColumnSwarm();
void hideOrShowColumnPeers();
void hideOrShowColumnUpload();
void hideOrShowColumnLeechers();
void hideOrShowColumnRatio();
void forceRecheck();
@@ -91,8 +91,6 @@ class FinishedTorrents : public QWidget, public Ui::seeding {
void deleteTorrent(QString hash);
void showPropertiesFromHash(QString hash);
void loadLastSortedColumn();
void saveLastSortedColumn();
void updateMetadata(QTorrentHandle &h);
signals:
void torrentMovedFromFinishedList(QString);

View File

@@ -34,7 +34,6 @@
#include <QDesktopServices>
#include <QStatusBar>
#include <QFrame>
#include <QClipboard>
#ifdef QT_4_4
#include <QLocalServer>
#include <QLocalSocket>
@@ -68,7 +67,6 @@
#include <stdlib.h>
#include "console_imp.h"
#include "httpserver.h"
#include "torrentPersistentData.h"
using namespace libtorrent;
@@ -101,14 +99,14 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
qDebug("Info: System tray unavailable");
}
// Setting icons
this->setWindowIcon(QIcon(QString::fromUtf8(":/Icons/skin/qbittorrent32.png")));
this->setWindowIcon(QIcon(QString::fromUtf8(":/Icons/qbittorrent32.png")));
actionOpen->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/open.png")));
actionExit->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/exit.png")));
actionDownload_from_URL->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/url.png")));
actionOptions->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/settings.png")));
actionAbout->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/info.png")));
actionWebsite->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/qbittorrent32.png")));
actionBugReport->setIcon(QIcon(QString::fromUtf8(":/Icons/oxygen/bug.png")));
actionWebsite->setIcon(QIcon(QString::fromUtf8(":/Icons/qbittorrent32.png")));
actionBugReport->setIcon(QIcon(QString::fromUtf8(":/Icons/newmsg.png")));
actionStart->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/play.png")));
actionPause->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/pause.png")));
actionDelete->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/delete.png")));
@@ -134,7 +132,7 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
options = new options_imp(this);
connect(options, SIGNAL(status_changed(bool)), this, SLOT(OptionsSaved(bool)));
BTSession = new bittorrent();
connect(BTSession, SIGNAL(fullDiskError(QTorrentHandle&, QString)), this, SLOT(fullDiskError(QTorrentHandle&, QString)));
connect(BTSession, SIGNAL(fullDiskError(QTorrentHandle&)), this, SLOT(fullDiskError(QTorrentHandle&)));
connect(BTSession, SIGNAL(finishedTorrent(QTorrentHandle&)), this, SLOT(finishedTorrent(QTorrentHandle&)));
connect(BTSession, SIGNAL(addedTorrent(QTorrentHandle&)), this, SLOT(addedTorrent(QTorrentHandle&)));
connect(BTSession, SIGNAL(pausedTorrent(QTorrentHandle&)), this, SLOT(pausedTorrent(QTorrentHandle&)));
@@ -144,7 +142,6 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
connect(BTSession, SIGNAL(newDownloadedTorrent(QString, QString)), this, SLOT(processDownloadedFiles(QString, QString)));
connect(BTSession, SIGNAL(downloadFromUrlFailure(QString, QString)), this, SLOT(handleDownloadFromUrlFailure(QString, QString)));
connect(BTSession, SIGNAL(deletedTorrent(QString)), this, SLOT(deleteTorrent(QString)));
connect(BTSession, SIGNAL(torrentPaused(QTorrentHandle&)), this, SLOT(setPaused(QTorrentHandle&)));
qDebug("create tabWidget");
tabs = new QTabWidget();
// Download torrents tab
@@ -163,7 +160,7 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
// Search engine tab
searchEngine = new SearchEngine(BTSession, myTrayIcon, systrayIntegration);
tabs->addTab(searchEngine, tr("Search"));
tabs->setTabIcon(2, QIcon(QString::fromUtf8(":/Icons/oxygen/edit-find.png")));
tabs->setTabIcon(2, QIcon(QString::fromUtf8(":/Icons/skin/search.png")));
readSettings();
// RSS Tab
rssWidget = 0;
@@ -174,7 +171,7 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
// Configure BT session according to options
configureSession(true);
// Resume unfinished torrents
BTSession->startUpTorrents();
BTSession->resumeUnfinishedTorrents();
downloadingTorrentTab->loadLastSortedColumn();
finishedTorrentTab->loadLastSortedColumn();
// Add torrent given on command line
@@ -252,9 +249,6 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
if(!settings.value(QString::fromUtf8("Preferences/General/StartMinimized"), false).toBool()) {
show();
}
scrapeTimer = new QTimer(this);
connect(scrapeTimer, SIGNAL(timeout()), this, SLOT(scrapeTrackers()));
scrapeTimer->start(20000);
qDebug("GUI Built");
}
@@ -266,8 +260,6 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
BTSession->saveDHTEntry();
BTSession->saveSessionState();
BTSession->saveFastResumeData();
scrapeTimer->stop();
delete scrapeTimer;
delete dlSpeedLbl;
delete upSpeedLbl;
delete ratioLbl;
@@ -315,7 +307,7 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
if(enable) {
// RSS tab
if(rssWidget == 0) {
rssWidget = new RSSImp(BTSession);
rssWidget = new RSSImp();
tabs->addTab(rssWidget, tr("RSS"));
tabs->setTabIcon(3, QIcon(QString::fromUtf8(":/Icons/rss32.png")));
}
@@ -327,16 +319,6 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
}
}
void GUI::scrapeTrackers() {
std::vector<torrent_handle> torrents = BTSession->getTorrents();
std::vector<torrent_handle>::iterator torrentIT;
for(torrentIT = torrents.begin(); torrentIT != torrents.end(); torrentIT++) {
QTorrentHandle h = QTorrentHandle(*torrentIT);
if(!h.is_valid()) continue;
h.scrape_tracker();
}
}
void GUI::updateRatio() {
// Update ratio info
float ratio = 1.;
@@ -381,7 +363,7 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
qDebug("In GUI, a torrent has finished");
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
bool show_msg = true;
if(TorrentPersistentData::isSeed(h.hash()))
if(QFile::exists(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+h.hash()+".finished"))
show_msg = false;
QString fileName = h.name();
bool useNotificationBalloons = settings.value(QString::fromUtf8("Preferences/General/NotificationBaloons"), true).toBool();
@@ -427,8 +409,8 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
finishedTorrentTab->addTorrent(h.hash());
} else {
// Move torrent back to download list (if necessary)
if(TorrentPersistentData::isSeed(h.hash())) {
TorrentPersistentData::saveSeedStatus(h);
if(QFile::exists(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+h.hash()+".finished")) {
QFile::remove(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+h.hash()+".finished");
finishedTorrentTab->deleteTorrent(h.hash());
downloadingTorrentTab->addTorrent(h.hash());
}
@@ -436,29 +418,23 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
}
// Notification when disk is full
void GUI::fullDiskError(QTorrentHandle& h, QString msg) const {
void GUI::fullDiskError(QTorrentHandle& h) const {
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
bool useNotificationBalloons = settings.value(QString::fromUtf8("Preferences/General/NotificationBaloons"), true).toBool();
if(systrayIntegration && useNotificationBalloons) {
myTrayIcon->showMessage(tr("I/O Error", "i.e: Input/Output Error"), tr("An I/O error occured for torrent %1.\n Reason: %2", "e.g: An error occured for torrent xxx.avi.\n Reason: disk is full.").arg(h.name()).arg(msg), QSystemTrayIcon::Critical, TIME_TRAY_BALLOON);
myTrayIcon->showMessage(tr("I/O Error", "i.e: Input/Output Error"), tr("An error occured when trying to read or write %1. The disk is probably full, download has been paused", "e.g: An error occured when trying to read or write xxx.avi. The disk is probably full, download has been paused").arg(h.name()), QSystemTrayIcon::Critical, TIME_TRAY_BALLOON);
}
// Download will be paused by libtorrent. Updating GUI information accordingly
QString hash = h.hash();
qDebug("Full disk error, pausing torrent %s", hash.toLocal8Bit().data());
setPaused(h);
BTSession->addConsoleMessage(tr("An error occured (full disk?), '%1' paused.", "e.g: An error occured (full disk?), 'xxx.avi' paused.").arg(h.name()));
}
void GUI::setPaused(QTorrentHandle &h) const {
if(!h.is_paused()) return;
qDebug("Marking torrent %s as paused", h.hash().toLocal8Bit().data());
qDebug("Full disk error, pausing torrent %s", hash.toUtf8().data());
if(h.is_seed()) {
// In finished list
qDebug("Automatically paused torrent was in finished list");
finishedTorrentTab->pauseTorrent(h.hash());
finishedTorrentTab->pauseTorrent(hash);
}else{
downloadingTorrentTab->pauseTorrent(h.hash());
downloadingTorrentTab->pauseTorrent(hash);
}
BTSession->addConsoleMessage(tr("An error occured (full disk?), '%1' paused.", "e.g: An error occured (full disk?), 'xxx.avi' paused.").arg(h.name()));
}
void GUI::createKeyboardShortcuts() {
@@ -599,28 +575,6 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
}
}
void GUI::copyMagnetURI() const {
QStringList hashes;
switch(tabs->currentIndex()){
case 0:
hashes = downloadingTorrentTab->getSelectedTorrents();
break;
case 1:
hashes = finishedTorrentTab->getSelectedTorrents();
break;
default:
return;
}
QStringList magnet_uris;
foreach(QString hash, hashes) {
QTorrentHandle h = BTSession->getTorrentHandle(hash);
if(h.is_valid()) {
magnet_uris << misc::toQString(make_magnet_uri(h.get_torrent_info()));
}
}
qApp->clipboard()->setText(magnet_uris.join("\n"));
}
void GUI::goBuyPage() const {
QStringList hashes;
switch(tabs->currentIndex()){
@@ -716,8 +670,7 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
bool goToSystrayOnExit = settings.value(QString::fromUtf8("Preferences/General/CloseToTray"), false).toBool();
if(!force_exit && systrayIntegration && goToSystrayOnExit && !this->isHidden()) {
hide();
//e->ignore();
e->accept();
e->ignore();
return;
}
if(settings.value(QString::fromUtf8("Preferences/General/ExitConfirm"), true).toBool() && downloadingTorrentTab->getNbTorrentsInList()) {
@@ -776,7 +729,8 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
if(event->mimeData()->hasUrls()) {
QList<QUrl> urls = event->mimeData()->urls();
foreach(const QUrl &url, urls) {
QString tmp = url.toString().trimmed();
QString tmp = url.toString();
tmp.trimmed();
if(!tmp.isEmpty())
files << url.toString();
}
@@ -788,16 +742,11 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
bool useTorrentAdditionDialog = settings.value(QString::fromUtf8("Preferences/Downloads/AdditionDialog"), true).toBool();
foreach(QString file, files) {
file = file.trimmed().replace(QString::fromUtf8("file://"), QString::fromUtf8(""), Qt::CaseInsensitive);
qDebug("Dropped file %s on download list", file.toLocal8Bit().data());
qDebug("Dropped file %s on download list", file.toUtf8().data());
if(file.startsWith(QString::fromUtf8("http://"), Qt::CaseInsensitive) || file.startsWith(QString::fromUtf8("ftp://"), Qt::CaseInsensitive) || file.startsWith(QString::fromUtf8("https://"), Qt::CaseInsensitive)) {
BTSession->downloadFromUrl(file);
continue;
}
if(file.startsWith("magnet:", Qt::CaseInsensitive)) {
// FIXME: Possibly skipped torrent addition dialog
BTSession->addMagnetUri(file);
continue;
}
if(useTorrentAdditionDialog) {
torrentAdditionDialog *dialog = new torrentAdditionDialog(this, BTSession);
dialog->showLoad(file);
@@ -810,7 +759,7 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
// Decode if we accept drag 'n drop or not
void GUI::dragEnterEvent(QDragEnterEvent *event) {
foreach(const QString &mime, event->mimeData()->formats()){
qDebug("mimeData: %s", mime.toLocal8Bit().data());
qDebug("mimeData: %s", mime.toUtf8().data());
}
if (event->mimeData()->hasFormat(QString::fromUtf8("text/plain")) || event->mimeData()->hasFormat(QString::fromUtf8("text/uri-list"))) {
event->acceptProposedAction();
@@ -911,7 +860,7 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
inDownloadList = false;
break;
case 3: //RSSImp
rssWidget->deleteSelectedItems();
rssWidget->on_delStream_button_clicked();
return;
default:
return;
@@ -955,10 +904,6 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
param = param.trimmed();
if(param.startsWith(QString::fromUtf8("http://"), Qt::CaseInsensitive) || param.startsWith(QString::fromUtf8("ftp://"), Qt::CaseInsensitive) || param.startsWith(QString::fromUtf8("https://"), Qt::CaseInsensitive)) {
BTSession->downloadFromUrl(param);
}else{
if(param.startsWith("magnet:", Qt::CaseInsensitive)) {
// FIXME: Possibily skipped torrent addition dialog
BTSession->addMagnetUri(param);
}else{
if(useTorrentAdditionDialog) {
torrentAdditionDialog *dialog = new torrentAdditionDialog(this, BTSession);
@@ -969,7 +914,6 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
}
}
}
}
void GUI::addTorrent(QString path) {
BTSession->addTorrent(path);
@@ -1010,11 +954,6 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
// Downloads
// * Save path
BTSession->setDefaultSavePath(options->getSavePath());
if(options->isTempPathEnabled()) {
BTSession->setDefaultTempPath(options->getTempPath());
} else {
BTSession->setDefaultTempPath(QString::null);
}
BTSession->preAllocateAllFiles(options->preAllocateAllFiles());
BTSession->startTorrentsInPause(options->addTorrentsInPause());
// * Scan dir
@@ -1027,10 +966,10 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
// Connection
// * Ports binding
unsigned short old_listenPort = BTSession->getListenPort();
BTSession->setListeningPort(options->getPort());
BTSession->setListeningPortsRange(options->getPorts());
unsigned short new_listenPort = BTSession->getListenPort();
if(new_listenPort != old_listenPort) {
BTSession->addConsoleMessage(tr("qBittorrent is bound to port: TCP/%1", "e.g: qBittorrent is bound to port: 6881").arg( misc::toQString(new_listenPort)));
BTSession->addConsoleMessage(tr("qBittorrent is bind to port: %1", "e.g: qBittorrent is bind to port: 1666").arg( misc::toQString(new_listenPort)));
}
// * Global download limit
QPair<int, int> limits = options->getGlobalBandwidthLimits();
@@ -1119,12 +1058,9 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
// * DHT
if(options->isDHTEnabled()) {
// Set DHT Port
BTSession->setDHTPort(options->getDHTPort());
BTSession->setDHTPort(new_listenPort);
if(BTSession->enableDHT(true)) {
int dht_port = new_listenPort;
if(options->getDHTPort())
dht_port = options->getDHTPort();
BTSession->addConsoleMessage(tr("DHT support [ON], port: UDP/%1").arg(dht_port), QString::fromUtf8("blue"));
BTSession->addConsoleMessage(tr("DHT support [ON], port: %1").arg(new_listenPort), QString::fromUtf8("blue"));
} else {
BTSession->addConsoleMessage(tr("DHT support [OFF]"), QString::fromUtf8("red"));
}
@@ -1234,11 +1170,11 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
// We need this for urllib in search engine plugins
#ifdef Q_WS_WIN
char proxystr[512];
snprintf(proxystr, 512, "http_proxy=%s", proxy_str.toLocal8Bit().data());
snprintf(proxystr, 512, "http_proxy=%s", proxy_str.toUtf8().data());
putenv(proxystr);
#else
qDebug("HTTP: proxy string: %s", proxy_str.toLocal8Bit().data());
setenv("http_proxy", proxy_str.toLocal8Bit().data(), 1);
qDebug("HTTP: proxy string: %s", proxy_str.toUtf8().data());
setenv("http_proxy", proxy_str.toUtf8().data(), 1);
#endif
} else {
qDebug("Disabling search proxy");
@@ -1374,7 +1310,6 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
} else {
hashes = finishedTorrentTab->getSelectedTorrents();
}
qDebug("nb hashes: %d", hashes.size());
foreach(const QString &hash, hashes) {
QTorrentHandle h = BTSession->getTorrentHandle(hash);
if(!h.is_paused()){
@@ -1462,7 +1397,6 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
for(torrentIT = torrents.begin(); torrentIT != torrents.end(); torrentIT++) {
QTorrentHandle h = QTorrentHandle(*torrentIT);
if(!h.is_valid()) continue;
try {
if(h.is_seed()) {
// Update in finished list
finishedTorrentTab->updateTorrent(h);
@@ -1471,12 +1405,9 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
if(downloadingTorrentTab->updateTorrent(h)) {
// Torrent was added, we may need to remove it from finished tab
finishedTorrentTab->deleteTorrent(h.hash());
TorrentPersistentData::saveSeedStatus(h);
QFile::remove(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+h.hash()+".finished");
}
}
} catch(invalid_handle e) {
qDebug("Caught Invalid handle exception, lucky us.");
}
}
}
if(displaySpeedInTitle) {
@@ -1536,14 +1467,8 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
* *
*****************************************************/
void GUI::downloadFromURLList(const QStringList& url_list) {
foreach(const QString url, url_list) {
if(url.startsWith("magnet:", Qt::CaseInsensitive)) {
BTSession->addMagnetUri(url);
} else {
BTSession->downloadFromUrl(url);
}
}
void GUI::downloadFromURLList(const QStringList& urls) {
BTSession->downloadFromURLList(urls);
}
/*****************************************************
@@ -1576,10 +1501,10 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
void GUI::createTrayIcon() {
// Tray icon
#ifdef Q_WS_WIN
myTrayIcon = new QSystemTrayIcon(QIcon(QString::fromUtf8(":/Icons/skin/qbittorrent16.png")), this);
myTrayIcon = new QSystemTrayIcon(QIcon(QString::fromUtf8(":/Icons/qbittorrent16.png")), this);
#endif
#ifndef Q_WS_WIN
myTrayIcon = new QSystemTrayIcon(QIcon(QString::fromUtf8(":/Icons/skin/qbittorrent22.png")), this);
myTrayIcon = new QSystemTrayIcon(QIcon(QString::fromUtf8(":/Icons/qbittorrent22.png")), this);
#endif
// Tray icon Menu
myTrayIconMenu = new QMenu(this);
@@ -1661,4 +1586,3 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
downloadFromURL *downloadFromURLDialog = new downloadFromURL(this);
connect(downloadFromURLDialog, SIGNAL(urlsReadyToBeDownloaded(const QStringList&)), BTSession, SLOT(downloadFromURLList(const QStringList&)));
}

View File

@@ -70,7 +70,6 @@ class GUI : public QMainWindow, private Ui::MainWindow{
// Bittorrent
bittorrent *BTSession;
QTimer *checkConnect;
QTimer *scrapeTimer;
QList<QPair<QTorrentHandle,QString> > unauthenticated_trackers;
// GUI related
QTabWidget *tabs;
@@ -140,10 +139,9 @@ class GUI : public QMainWindow, private Ui::MainWindow{
void createTrayIcon();
void updateUnfinishedTorrentNumber(unsigned int nb);
void updateFinishedTorrentNumber(unsigned int nb);
void fullDiskError(QTorrentHandle& h, QString msg) const;
void fullDiskError(QTorrentHandle& h) const;
void handleDownloadFromUrlFailure(QString, QString) const;
void createSystrayDelayed();
void setPaused(QTorrentHandle &h) const;
// Keyboard shortcuts
void createKeyboardShortcuts();
void displayDownTab() const;
@@ -179,7 +177,6 @@ class GUI : public QMainWindow, private Ui::MainWindow{
bool initWebUi(QString username, QString password, int port);
void on_actionIncreasePriority_triggered();
void on_actionDecreasePriority_triggered();
void scrapeTrackers();
// Options slots
void on_actionOptions_triggered();
void OptionsSaved(bool deleteOptions);
@@ -192,7 +189,6 @@ class GUI : public QMainWindow, private Ui::MainWindow{
void setTabText(int index, QString text) const;
void openDestinationFolder() const;
void goBuyPage() const;
void copyMagnetURI() const;
void updateRatio();
protected:

BIN
src/Icons/add_file.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1005 B

BIN
src/Icons/add_folder.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
src/Icons/bt_settings.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
src/Icons/button_cancel.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
src/Icons/button_ok.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
src/Icons/configure.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
src/Icons/connection.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 820 B

BIN
src/Icons/description.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 821 B

BIN
src/Icons/download.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

Before

Width:  |  Height:  |  Size: 575 B

After

Width:  |  Height:  |  Size: 575 B

View File

Before

Width:  |  Height:  |  Size: 750 B

After

Width:  |  Height:  |  Size: 750 B

View File

Before

Width:  |  Height:  |  Size: 704 B

After

Width:  |  Height:  |  Size: 704 B

BIN
src/Icons/filter.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 998 B

View File

Before

Width:  |  Height:  |  Size: 449 B

After

Width:  |  Height:  |  Size: 449 B

BIN
src/Icons/gear.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
src/Icons/home.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
src/Icons/log.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 846 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

View File

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

BIN
src/Icons/money.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 813 B

BIN
src/Icons/newmsg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 532 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 743 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 659 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 796 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 733 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 873 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 860 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 892 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 627 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 937 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 885 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 923 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 907 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 498 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 541 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 739 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 752 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 813 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

BIN
src/Icons/password.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

BIN
src/Icons/proxy.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -1,26 +1,19 @@
[Desktop Entry]
Categories=Qt;Network;P2P;
Comment=V1.5.0
Categories=Qt;Network;P2P
Comment=V1.3.4
Exec=qbittorrent %f
GenericName=Bittorrent client
GenericName[bg]=Торент клиент
GenericName[cs]=Bittorrent klient
GenericName[de]=Bittorren Client
GenericName[el]=Bittorrent πελάτης
GenericName[el]=Τορεντ πελάτης
GenericName[es]=Cliente Bittorrent
GenericName[fi]=Bittorrent-ohjelma
GenericName[fr]=Client Bittorrent
GenericName[hu]=Bittorrent kliens
GenericName[it]=Client Bittorrent
GenericName[ja]=Bittorrent クライアント
GenericName[ko]=비토렌트 클라이언트
GenericName[nl]=Bittorrent client
GenericName[pl]=Klient Bittorrent
GenericName[pt]=Cliente Bittorrent
GenericName[pt_BR]=Cliente Bittorrent
GenericName[ro]=Client Bittorrent
GenericName[ru]=клиент Bittorrent
GenericName[sk]=Klient siete Bittorrent
GenericName[sv]=Bittorrent-klient
GenericName[tr]=Bittorrent istemcisi
GenericName[uk]=Bittorrent-клієнт

View File

Before

Width:  |  Height:  |  Size: 965 B

After

Width:  |  Height:  |  Size: 965 B

View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
src/Icons/refresh.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 948 B

BIN
src/Icons/skin/add.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 842 B

View File

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
src/Icons/skin/search.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 76 KiB

BIN
src/Icons/star.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
src/Icons/style.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
src/Icons/subscribe.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
src/Icons/subscribe16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 739 B

BIN
src/Icons/systemtray.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

Before

Width:  |  Height:  |  Size: 856 B

After

Width:  |  Height:  |  Size: 856 B

BIN
src/Icons/unavailable.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 888 B

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

Before

Width:  |  Height:  |  Size: 765 B

After

Width:  |  Height:  |  Size: 765 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 722 B

After

Width:  |  Height:  |  Size: 629 B

BIN
src/Icons/wizard.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -1,4 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0" >
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow" >
@@ -25,7 +24,7 @@
<x>0</x>
<y>0</y>
<width>914</width>
<height>23</height>
<height>26</height>
</rect>
</property>
<widget class="QMenu" name="menu_Edit" >
@@ -236,8 +235,7 @@
</action>
<action name="actionDecreasePriority" >
<property name="icon" >
<iconset resource="icons.qrc">
<normaloff>:/Icons/skin/decrease.png</normaloff>:/Icons/skin/decrease.png</iconset>
<iconset resource="icons.qrc" >:/Icons/skin/decrease.png</iconset>
</property>
<property name="text" >
<string>Decrease priority</string>
@@ -248,8 +246,7 @@
</action>
<action name="actionIncreasePriority" >
<property name="icon" >
<iconset resource="icons.qrc">
<normaloff>:/Icons/skin/increase.png</normaloff>:/Icons/skin/increase.png</iconset>
<iconset resource="icons.qrc" >:/Icons/skin/increase.png</iconset>
</property>
<property name="text" >
<string>Increase priority</string>
@@ -260,8 +257,7 @@
</action>
<action name="actionShow_console" >
<property name="icon" >
<iconset resource="icons.qrc">
<normaloff>:/Icons/oxygen/log.png</normaloff>:/Icons/oxygen/log.png</iconset>
<iconset resource="icons.qrc" >:/Icons/log.png</iconset>
</property>
<property name="text" >
<string>Console</string>

View File

@@ -33,7 +33,6 @@
#include <QStandardItemModel>
#include <QHeaderView>
#include <QSettings>
#include <QSortFilterProxyModel>
#include "SearchTab.h"
#include "SearchListDelegate.h"
@@ -46,7 +45,7 @@
#define SEARCH_LEECHERS 3
#define SEARCH_ENGINE 4
SearchTab::SearchTab(SearchEngine *parent) : QWidget(), parent(parent)
SearchTab::SearchTab(SearchEngine *parent) : QWidget()
{
box=new QVBoxLayout();
results_lbl=new QLabel();
@@ -63,67 +62,32 @@ SearchTab::SearchTab(SearchEngine *parent) : QWidget(), parent(parent)
SearchListModel->setHeaderData(SEARCH_SEEDERS, Qt::Horizontal, tr("Seeders", "i.e: Number of full sources"));
SearchListModel->setHeaderData(SEARCH_LEECHERS, Qt::Horizontal, tr("Leechers", "i.e: Number of partial sources"));
SearchListModel->setHeaderData(SEARCH_ENGINE, Qt::Horizontal, tr("Search engine"));
resultsBrowser->setModel(SearchListModel);
resultsBrowser->hideColumn(URL_COLUMN); // Hide url column
proxyModel = new QSortFilterProxyModel();
proxyModel->setDynamicSortFilter(true);
proxyModel->setSourceModel(SearchListModel);
resultsBrowser->setModel(proxyModel);
SearchDelegate = new SearchListDelegate();
resultsBrowser->setItemDelegate(SearchDelegate);
resultsBrowser->setRootIsDecorated(false);
resultsBrowser->setAllColumnsShowFocus(true);
resultsBrowser->setSortingEnabled(true);
// Make search list header clickable for sorting
resultsBrowser->header()->setClickable(true);
resultsBrowser->header()->setSortIndicatorShown(true);
// Connect signals to slots (search part)
connect(resultsBrowser, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(downloadSelectedItem(const QModelIndex&)));
connect(resultsBrowser, SIGNAL(doubleClicked(const QModelIndex&)), parent, SLOT(downloadSelectedItem(const QModelIndex&)));
connect(resultsBrowser->header(), SIGNAL(sectionPressed(int)), this, SLOT(sortSearchList(int)));
// Load last columns width for search results list
if(!loadColWidthResultsList()){
if(!loadColWidthSearchList()){
resultsBrowser->header()->resizeSection(0, 275);
}
// Sort by Seeds
resultsBrowser->sortByColumn(SEEDERS, Qt::DescendingOrder);
}
void SearchTab::downloadSelectedItem(const QModelIndex& index) {
QString engine_url = proxyModel->data(proxyModel->index(index.row(), ENGINE_URL_COLUMN)).toString();
QString torrent_url = proxyModel->data(proxyModel->index(index.row(), URL_COLUMN)).toString();
setRowColor(index.row(), "red");
parent->downloadTorrent(engine_url, torrent_url);
}
SearchTab::~SearchTab() {
delete box;
delete results_lbl;
SearchTab::~SearchTab()
{
saveColWidthSearchList();
delete resultsBrowser;
delete SearchListModel;
delete proxyModel;
delete SearchDelegate;
}
QHeaderView* SearchTab::header() const {
return resultsBrowser->header();
}
bool SearchTab::loadColWidthResultsList() {
QSettings settings("qBittorrent", "qBittorrent");
QString line = settings.value("SearchResultsColsWidth", QString()).toString();
if(line.isEmpty())
return false;
QStringList width_list = line.split(' ');
if(width_list.size() < SearchListModel->columnCount())
return false;
unsigned int listSize = width_list.size();
for(unsigned int i=0; i<listSize; ++i){
resultsBrowser->header()->resizeSection(i, width_list.at(i).toInt());
}
return true;
}
QLabel* SearchTab::getCurrentLabel()
{
return results_lbl;
@@ -141,9 +105,95 @@ QStandardItemModel* SearchTab::getCurrentSearchListModel()
// Set the color of a row in data model
void SearchTab::setRowColor(int row, QString color){
for(int i=0; i<proxyModel->columnCount(); ++i){
proxyModel->setData(proxyModel->index(row, i), QVariant(QColor(color)), Qt::ForegroundRole);
for(int i=0; i<SearchListModel->columnCount(); ++i){
SearchListModel->setData(SearchListModel->index(row, i), QVariant(QColor(color)), Qt::ForegroundRole);
}
}
void SearchTab::sortSearchList(int index){
static Qt::SortOrder sortOrder = Qt::AscendingOrder;
if(resultsBrowser->header()->sortIndicatorSection() == index){
sortOrder = (sortOrder == Qt::DescendingOrder) ? Qt::AscendingOrder : Qt::DescendingOrder; ;
}
resultsBrowser->header()->setSortIndicator(index, sortOrder);
switch(index){
case SEEDERS:
case LEECHERS:
case SIZE:
sortSearchListInt(index, sortOrder);
break;
default:
sortSearchListString(index, sortOrder);
}
}
void SearchTab::sortSearchListInt(int index, Qt::SortOrder sortOrder){
QList<QPair<int, qlonglong> > lines;
// Insertion sorting
for(int i=0; i<SearchListModel->rowCount(); ++i){
misc::insertSort(lines, QPair<int,qlonglong>(i, SearchListModel->data(SearchListModel->index(i, index)).toLongLong()), sortOrder);
}
// Insert items in new model, in correct order
int nbRows_old = lines.size();
for(int row=0; row<lines.size(); ++row){
SearchListModel->insertRow(SearchListModel->rowCount());
int sourceRow = lines[row].first;
for(int col=0; col<6; ++col){
SearchListModel->setData(SearchListModel->index(nbRows_old+row, col), SearchListModel->data(SearchListModel->index(sourceRow, col)));
SearchListModel->setData(SearchListModel->index(nbRows_old+row, col), SearchListModel->data(SearchListModel->index(sourceRow, col), Qt::ForegroundRole), Qt::ForegroundRole);
}
}
// Remove old rows
SearchListModel->removeRows(0, nbRows_old);
}
void SearchTab::sortSearchListString(int index, Qt::SortOrder sortOrder){
QList<QPair<int, QString> > lines;
// Insetion sorting
for(int i=0; i<SearchListModel->rowCount(); ++i){
misc::insertSortString(lines, QPair<int, QString>(i, SearchListModel->data(SearchListModel->index(i, index)).toString()), sortOrder);
}
// Insert items in new model, in correct order
int nbRows_old = lines.size();
for(int row=0; row<nbRows_old; ++row){
SearchListModel->insertRow(SearchListModel->rowCount());
int sourceRow = lines[row].first;
for(int col=0; col<6; ++col){
SearchListModel->setData(SearchListModel->index(nbRows_old+row, col), SearchListModel->data(SearchListModel->index(sourceRow, col)));
SearchListModel->setData(SearchListModel->index(nbRows_old+row, col), SearchListModel->data(SearchListModel->index(sourceRow, col), Qt::ForegroundRole), Qt::ForegroundRole);
}
}
// Remove old rows
SearchListModel->removeRows(0, nbRows_old);
}
// Save columns width in a file to remember them
// (download list)
void SearchTab::saveColWidthSearchList() const{
qDebug("Saving columns width in search list");
QSettings settings("qBittorrent", "qBittorrent");
QStringList width_list;
for(int i=0; i<SearchListModel->columnCount(); ++i){
width_list << misc::toQString(resultsBrowser->columnWidth(i));
}
settings.setValue("SearchListColsWidth", width_list.join(" "));
qDebug("Search list columns width saved");
}
// Load columns width in a file that were saved previously
// (search list)
bool SearchTab::loadColWidthSearchList(){
qDebug("Loading columns width for search list");
QSettings settings("qBittorrent", "qBittorrent");
QString line = settings.value("SearchListColsWidth", QString()).toString();
if(line.isEmpty())
return false;
QStringList width_list = line.split(' ');
if(width_list.size() != SearchListModel->columnCount())
return false;
for(int i=0; i<width_list.size(); ++i){
resultsBrowser->header()->resizeSection(i, width_list.at(i).toInt());
}
qDebug("Search list columns width loaded");
return true;
}

View File

@@ -39,11 +39,10 @@
class SearchListDelegate;
class SearchEngine;
class QTreeView;
class QHeaderView;
class QStandardItemModel;
class QSortFilterProxyModel;
class SearchTab: public QWidget, public Ui::search_engine {
class SearchTab : public QWidget, public Ui::search_engine
{
Q_OBJECT
private:
@@ -51,23 +50,20 @@ private:
QLabel *results_lbl;
QTreeView *resultsBrowser;
QStandardItemModel *SearchListModel;
QSortFilterProxyModel *proxyModel;
SearchListDelegate *SearchDelegate;
SearchEngine *parent;
protected slots:
void downloadSelectedItem(const QModelIndex& index);
public:
SearchTab(SearchEngine *parent);
~SearchTab();
bool loadColWidthResultsList();
bool loadColWidthSearchList();
QLabel * getCurrentLabel();
QStandardItemModel * getCurrentSearchListModel();
QTreeView * getCurrentTreeView();
void setRowColor(int row, QString color);
QHeaderView* header() const;
protected slots:
void sortSearchList(int index);
void sortSearchListInt(int index, Qt::SortOrder sortOrder);
void sortSearchListString(int index, Qt::SortOrder sortOrder);
void saveColWidthSearchList() const;
};

View File

@@ -1,4 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0" >
<author>Christophe Dumez</author>
<class>AboutDlg</class>
@@ -51,13 +50,13 @@
<item>
<widget class="QLabel" name="lb_name" >
<property name="sizePolicy" >
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text" >
<string>&lt;h3&gt;&lt;b&gt;qBittorrent&lt;/b&gt;&lt;/h3&gt;</string>
<string>&lt;h3>&lt;b>qBittorrent&lt;/b>&lt;/h3></string>
</property>
<property name="textFormat" >
<enum>Qt::RichText</enum>
@@ -69,7 +68,7 @@
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
@@ -92,7 +91,7 @@
<property name="geometry" >
<rect>
<x>380</x>
<y>70</y>
<y>50</y>
<width>94</width>
<height>162</height>
</rect>
@@ -105,40 +104,29 @@
<property name="geometry" >
<rect>
<x>0</x>
<y>30</y>
<y>40</y>
<width>481</width>
<height>102</height>
</rect>
</property>
<property name="sizePolicy" >
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text" >
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'DejaVu Sans'; font-size:8pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;A Bittorrent client programmed in C++, based on Qt4 toolkit &lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;and libtorrent-rasterbar. &lt;br /&gt;&lt;br /&gt;Copyright ©2006-2009 Christophe Dumez&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot; text-decoration: underline;&quot;&gt;Home Page:&lt;/span&gt; &lt;a href=&quot;http://www.qbittorrent.org&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0057ae;&quot;&gt;http://www.qbittorrent.org&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>A bittorrent client using Qt4 and libtorrent, programmed in C++.&lt;br>
&lt;br>
Copyright © 2006 by Christophe Dumez&lt;br>
&lt;br> &lt;u>Home Page:&lt;/u> &lt;i>http://www.qbittorrent.org&lt;/i>&lt;br></string>
</property>
<property name="textFormat" >
<enum>Qt::RichText</enum>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
<property name="alignment" >
<set>Qt::AlignCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</widget>
<widget class="QWidget" name="tab3" >
@@ -163,7 +151,7 @@ p, li { white-space: pre-wrap; }
<property name="sizeType" >
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<property name="sizeHint" >
<size>
<width>20</width>
<height>20</height>
@@ -294,7 +282,7 @@ p, li { white-space: pre-wrap; }
<property name="sizeType" >
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<property name="sizeHint" >
<size>
<width>20</width>
<height>20</height>
@@ -356,7 +344,7 @@ p, li { white-space: pre-wrap; }
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>

View File

@@ -46,8 +46,8 @@ class about : public QDialog, private Ui::AboutDlg{
setupUi(this);
setAttribute(Qt::WA_DeleteOnClose);
// Set icons
logo->setPixmap(QPixmap(QString::fromUtf8(":/Icons/skin/qbittorrent22.png")));
mascot_lbl->setPixmap(QPixmap(QString::fromUtf8(":/Icons/skin/mascot.png")));
logo->setPixmap(QPixmap(QString::fromUtf8(":/Icons/qbittorrent22.png")));
mascot_lbl->setPixmap(QPixmap(QString::fromUtf8(":/Icons/mascot.png")));
//Title
lb_name->setText(QString::fromUtf8("<b><h1>")+tr("qBittorrent")+QString::fromUtf8(" "VERSION"</h1></b>"));
// Thanks
@@ -91,19 +91,7 @@ class about : public QDialog, private Ui::AboutDlg{
te_translation->scrollToAnchor(QString::fromUtf8("top"));
// License
te_license->append(QString::fromUtf8("<a name='top'></a>"));
te_license->append(QString::fromUtf8("qBittorrent is licensed under the GNU General Public License version 2 with the\
addition of the following special exception:\
<br><br>\
<i>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.</i>\
<br><br>\
<center><b>GNU GENERAL PUBLIC LICENSE</b></center><br>\
te_license->append(QString::fromUtf8("<center><b>GNU GENERAL PUBLIC LICENSE</b></center><br>\
<center>Version 2, June 1991</center><br>\
Copyright (C) 1989, 1991 Free Software Foundation, Inc.<br>\
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA<br>\

View File

@@ -1,4 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0" >
<class>addTorrentDialog</class>
<widget class="QDialog" name="addTorrentDialog" >
@@ -7,13 +6,13 @@
<x>0</x>
<y>0</y>
<width>511</width>
<height>461</height>
<height>441</height>
</rect>
</property>
<property name="windowTitle" >
<string>Torrent addition dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<layout class="QVBoxLayout" >
<item>
<widget class="QLabel" name="fileNameLbl" >
<property name="text" >
@@ -46,7 +45,16 @@
<property name="spacing" >
<number>6</number>
</property>
<property name="margin">
<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>
@@ -61,75 +69,6 @@
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Torrent size:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lbl_torrent_size">
<property name="text">
<string>Unknown</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Free disk space:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lbl_disk_space">
<property name="text">
<string>Unknown</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_space_msg">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="torrentContentLbl" >
<property name="font" >
@@ -163,7 +102,7 @@
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
@@ -190,7 +129,7 @@
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
@@ -203,7 +142,7 @@
<item>
<widget class="QCheckBox" name="checkIncrementalDL" >
<property name="text" >
<string>Download in sequential order (slower but good for previewing)</string>
<string>Download in correct order (slower but good for previewing)</string>
</property>
</widget>
</item>
@@ -219,7 +158,16 @@
<property name="spacing" >
<number>6</number>
</property>
<property name="margin">
<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>
@@ -227,7 +175,7 @@
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
@@ -254,7 +202,7 @@
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>

View File

@@ -51,8 +51,6 @@ public:
torrent_file(torrent_file *parent, QString path, bool dir, size_type size=0, int index=-1, float progress=0., int priority=1): parent(parent), is_dir(dir), size(size), progress(progress), priority(priority), index(index){
qDebug("created a file with index %d", index);
rel_path = QDir::cleanPath(path);
Q_ASSERT(progress >= 0.);
Q_ASSERT(progress <= 1.);
if(parent) {
parent->updateProgress();
parent->updatePriority(priority);
@@ -77,8 +75,8 @@ public:
progress = 0.;
return;
}
double wanted = 0.;
double done = 0.;
float wanted = 0.;
float done = 0.;
foreach(const torrent_file *child, children) {
wanted += child->getSize();
done += child->getSize()*child->getProgress();
@@ -152,7 +150,7 @@ public:
bool removeFromFS(QString saveDir) const {
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.toLocal8Bit().data());
qDebug("%s does not exist, no need to remove it", full_path.toUtf8().data());
return true;
}
bool success = true;
@@ -162,11 +160,11 @@ public:
success = s && success;
}
if(is_dir) {
qDebug("trying to remove directory: %s", full_path.toLocal8Bit().data());
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.toLocal8Bit().data());
qDebug("trying to remove file: %s", full_path.toUtf8().data());
bool s = QFile::remove(full_path);
success = s && success;
}
@@ -199,7 +197,7 @@ public:
Q_ASSERT(root->getSize() == t->total_size());
}
arborescence(torrent_info const& t, std::vector<size_type> fp, std::vector<int> files_priority) {
arborescence(torrent_info const& t, std::vector<size_type> fp, int *prioritiesTab) {
torrent_info::file_iterator fi = t.begin_files();
if(t.num_files() > 1) {
qDebug("More than one file in the torrent, setting a folder as root");
@@ -207,13 +205,13 @@ public:
} else {
// XXX: Will crash if there is no file in torrent
qDebug("one file in the torrent, setting it as root with index 0");
root = new torrent_file(0, misc::toQString(t.name()), false, fi->size, 0, ((double)fp[0])/t.file_at(0).size, files_priority.at(0));
root = new torrent_file(0, misc::toQString(t.name()), false, fi->size, 0, ((float)fp[0])/t.file_at(0).size, prioritiesTab[0]);
return;
}
int i = 0;
while(fi != t.end_files()) {
QString path = QDir::cleanPath(misc::toQString(fi->path.string()));
addFile(path, fi->size, i, ((double)fp[i])/t.file_at(i).size, files_priority.at(i));
addFile(path, fi->size, i, ((float)fp[i])/t.file_at(i).size, prioritiesTab[i]);
fi++;
++i;
}

File diff suppressed because it is too large Load Diff

View File

@@ -60,7 +60,6 @@ class bittorrent : public QObject {
bool DHTEnabled;
QPointer<downloadThread> downloader;
QString defaultSavePath;
QString defaultTempPath;
QHash<QString, QHash<QString, QString> > trackersErrors;
QStringList consoleMessages;
QStringList peerBanMessages;
@@ -76,7 +75,6 @@ class bittorrent : public QObject {
QString filterPath;
bool queueingEnabled;
QStringList url_skippingDlg;
QHash<QString, QString> savepath_fromurl;
protected:
QString getSavePath(QString hash);
@@ -108,25 +106,19 @@ class bittorrent : public QObject {
QStringList getConsoleMessages() const;
QStringList getPeerBanMessages() const;
qlonglong getETA(QString hash) const;
bool useTemporaryFolder() const;
QString getDefaultSavePath() const;
public slots:
QTorrentHandle addTorrent(QString path, bool fromScanDir = false, QString from_url = QString(), bool resumed = false);
QTorrentHandle addMagnetUri(QString magnet_uri, bool resumed=false);
void importOldTorrents();
void applyFormerAttributeFiles(QTorrentHandle h);
void importOldTempData(QString torrent_path);
void loadSessionState();
void saveSessionState();
void downloadFromUrl(QString url);
void downloadFromURLList(const QStringList& url_list);
void deleteTorrent(QString hash, bool permanent = false);
void startUpTorrents();
/* Needed by Web UI */
void pauseAllTorrents();
void resumeAllTorrents();
void pauseTorrent(QString hash);
void resumeTorrent(QString hash);
void resumeAllTorrents();
/* End Web UI */
void saveDHTEntry();
void preAllocateAllFiles(bool b);
@@ -136,14 +128,17 @@ class bittorrent : public QObject {
void enableIPFilter(QString filter);
void disableIPFilter();
void setQueueingEnabled(bool enable);
void resumeUnfinishedTorrents();
void saveTorrentPriority(QString hash, int prio);
void saveTorrentSpeedLimits(QString hash);
void loadTorrentSpeedLimits(QString hash);
void handleDownloadFailure(QString url, QString reason);
void loadWebSeeds(QString fileHash);
void increaseDlTorrentPriority(QString hash);
void decreaseDlTorrentPriority(QString hash);
void downloadUrlAndSkipDialog(QString url, QString save_path=QString::null);
void downloadUrlAndSkipDialog(QString);
// Session configuration - Setters
void setListeningPort(int port);
void setListeningPortsRange(std::pair<unsigned short, unsigned short> ports);
void setMaxConnections(int maxConnec);
void setMaxConnectionsPerTorrent(int max);
void setMaxUploadsPerTorrent(int max);
@@ -156,7 +151,6 @@ class bittorrent : public QObject {
void setSessionSettings(session_settings sessionSettings);
void startTorrentsInPause(bool b);
void setDefaultSavePath(QString savepath);
void setDefaultTempPath(QString temppath);
void applyEncryptionSettings(pe_settings se);
void loadFilesPriorities(QTorrentHandle& h);
void setDownloadLimit(QString hash, long val);
@@ -168,13 +162,12 @@ class bittorrent : public QObject {
void addConsoleMessage(QString msg, QColor color=QApplication::palette().color(QPalette::WindowText));
void addPeerBanMessage(QString msg, bool from_ipfilter);
void processDownloadedFile(QString, QString);
void saveTrackerFile(QString hash);
void addMagnetSkipAddDlg(QString uri);
protected slots:
void scanDirectory(QString);
void readAlerts();
void loadTrackerFile(QString hash);
bool loadTrackerFile(QString hash);
void saveTrackerFile(QString hash);
void deleteBigRatios();
signals:
@@ -183,15 +176,13 @@ class bittorrent : public QObject {
void pausedTorrent(QTorrentHandle& h);
void resumedTorrent(QTorrentHandle& h);
void finishedTorrent(QTorrentHandle& h);
void fullDiskError(QTorrentHandle& h, QString msg);
void fullDiskError(QTorrentHandle& h);
void trackerError(QString hash, QString time, QString msg);
void trackerAuthenticationRequired(QTorrentHandle& h);
void newDownloadedTorrent(QString path, QString url);
void updateFileSize(QString hash);
void downloadFromUrlFailure(QString url, QString reason);
void torrentFinishedChecking(QTorrentHandle& h);
void metadataReceived(QTorrentHandle &h);
void torrentPaused(QTorrentHandle &h);
};
#endif

View File

@@ -13,7 +13,7 @@
<string>qBittorrent console</string>
</property>
<property name="windowIcon" >
<iconset resource="icons.qrc" >:/Icons/oxygen/log.png</iconset>
<iconset resource="icons.qrc" >:/Icons/log.png</iconset>
</property>
<layout class="QVBoxLayout" >
<item>
@@ -26,7 +26,7 @@
<string>General</string>
</attribute>
<attribute name="icon" >
<iconset resource="icons.qrc" >:/Icons/oxygen/log.png</iconset>
<iconset resource="icons.qrc" >:/Icons/log.png</iconset>
</attribute>
<layout class="QVBoxLayout" >
<item>

View File

@@ -1,4 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0" >
<class>createTorrentDialog</class>
<widget class="QDialog" name="createTorrentDialog" >
@@ -7,7 +6,7 @@
<x>0</x>
<y>0</y>
<width>592</width>
<height>658</height>
<height>655</height>
</rect>
</property>
<property name="windowTitle" >
@@ -62,22 +61,20 @@
<item>
<widget class="QPushButton" name="addFile_button" >
<property name="text" >
<string>Add file</string>
<string>Add a file</string>
</property>
<property name="icon" >
<iconset resource="icons.qrc">
<normaloff>:/Icons/oxygen/document-new.png</normaloff>:/Icons/oxygen/document-new.png</iconset>
<iconset resource="icons.qrc" >:/Icons/add_file.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="addFolder_button" >
<property name="text" >
<string>Add folder</string>
<string>Add a folder</string>
</property>
<property name="icon" >
<iconset resource="icons.qrc">
<normaloff>:/Icons/oxygen/folder-new.png</normaloff>:/Icons/oxygen/folder-new.png</iconset>
<iconset resource="icons.qrc" >:/Icons/add_folder.png</iconset>
</property>
</widget>
</item>
@@ -153,7 +150,16 @@
<property name="spacing" >
<number>6</number>
</property>
<property name="margin">
<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>
@@ -168,7 +174,16 @@
<property name="spacing" >
<number>6</number>
</property>
<property name="margin">
<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>
@@ -176,7 +191,7 @@
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<property name="sizeHint" >
<size>
<width>20</width>
<height>16</height>
@@ -202,14 +217,7 @@
<string/>
</property>
<property name="icon" >
<iconset resource="icons.qrc">
<normaloff>:/Icons/oxygen/list-add.png</normaloff>:/Icons/oxygen/list-add.png</iconset>
</property>
<property name="iconSize">
<size>
<width>18</width>
<height>18</height>
</size>
<iconset resource="icons.qrc" >:/Icons/skin/add.png</iconset>
</property>
</widget>
</item>
@@ -231,14 +239,7 @@
<string/>
</property>
<property name="icon" >
<iconset resource="icons.qrc">
<normaloff>:/Icons/oxygen/list-remove.png</normaloff>:/Icons/oxygen/list-remove.png</iconset>
</property>
<property name="iconSize">
<size>
<width>18</width>
<height>18</height>
</size>
<iconset resource="icons.qrc" >:/Icons/skin/remove.png</iconset>
</property>
</widget>
</item>
@@ -247,7 +248,7 @@
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<property name="sizeHint" >
<size>
<width>20</width>
<height>16</height>
@@ -264,7 +265,16 @@
<property name="spacing" >
<number>6</number>
</property>
<property name="margin">
<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>
@@ -279,7 +289,16 @@
<property name="spacing" >
<number>6</number>
</property>
<property name="margin">
<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>
@@ -287,7 +306,7 @@
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<property name="sizeHint" >
<size>
<width>20</width>
<height>16</height>
@@ -313,14 +332,7 @@
<string/>
</property>
<property name="icon" >
<iconset resource="icons.qrc">
<normaloff>:/Icons/oxygen/list-add.png</normaloff>:/Icons/oxygen/list-add.png</iconset>
</property>
<property name="iconSize">
<size>
<width>18</width>
<height>18</height>
</size>
<iconset resource="icons.qrc" >:/Icons/skin/add.png</iconset>
</property>
</widget>
</item>
@@ -342,14 +354,7 @@
<string/>
</property>
<property name="icon" >
<iconset resource="icons.qrc">
<normaloff>:/Icons/oxygen/list-remove.png</normaloff>:/Icons/oxygen/list-remove.png</iconset>
</property>
<property name="iconSize">
<size>
<width>18</width>
<height>18</height>
</size>
<iconset resource="icons.qrc" >:/Icons/skin/remove.png</iconset>
</property>
</widget>
</item>
@@ -358,7 +363,7 @@
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<property name="sizeHint" >
<size>
<width>20</width>
<height>16</height>
@@ -448,7 +453,7 @@
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
@@ -491,7 +496,16 @@
<property name="spacing" >
<number>6</number>
</property>
<property name="margin">
<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>
@@ -499,7 +513,7 @@
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<property name="sizeHint" >
<size>
<width>131</width>
<height>31</height>
@@ -526,7 +540,7 @@
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>

View File

@@ -166,10 +166,10 @@ void createtorrent::on_createButton_clicked(){
return;
}
QStringList trackers = allItems(trackers_list);
/*if(!trackers.size()){
if(!trackers.size()){
QMessageBox::critical(0, tr("No tracker path set"), tr("Please set at least one tracker"));
return;
}*/
}
QString destination = QFileDialog::getSaveFileName(this, tr("Select destination torrent file"), QDir::homePath(), tr("Torrent Files")+QString::fromUtf8(" (*.torrent)"));
if(!destination.isEmpty()) {
if(!destination.endsWith(QString::fromUtf8(".torrent")))
@@ -184,6 +184,7 @@ void createtorrent::on_createButton_clicked(){
void createtorrent::handleCreationFailure(QString msg) {
QMessageBox::information(0, tr("Torrent creation"), tr("Torrent creation was unsuccessful, reason: %1").arg(msg));
hide();
}
void createtorrent::handleCreationSuccess(QString path, const char* branch_path) {
@@ -191,7 +192,7 @@ void createtorrent::handleCreationSuccess(QString path, const char* branch_path)
// Create save path file
boost::intrusive_ptr<torrent_info> t;
try {
t = new torrent_info(path.toLocal8Bit().data());
t = new torrent_info(path.toUtf8().data());
} catch(std::exception&) {
QMessageBox::critical(0, tr("Torrent creation"), tr("Created torrent file is invalid. It won't be added to download list."));
return;
@@ -204,7 +205,7 @@ void createtorrent::handleCreationSuccess(QString path, const char* branch_path)
emit torrent_to_seed(path);
}
QMessageBox::information(0, tr("Torrent creation"), tr("Torrent was created successfully:")+" "+path);
close();
hide();
}
void createtorrent::updateProgressBar(int progress) {
@@ -227,12 +228,8 @@ void torrentCreatorThread::create(QString _input_path, QString _save_path, QStri
start();
}
void sendProgressUpdateSignal(int i, int num, torrentCreatorThread *parent){
parent->sendProgressSignal((int)(i*100./(float)num));
}
void torrentCreatorThread::sendProgressSignal(int progress) {
emit updateProgress(progress);
void sendProgressUpdateSignal(int i, int num, QDialog *parent){
((createtorrent*)parent)->updateProgressBar((int)(i*100./(float)num));
}
void torrentCreatorThread::run() {
@@ -241,7 +238,7 @@ void torrentCreatorThread::run() {
try {
file_storage fs;
file_pool fp;
path full_path = complete(path(input_path.toLocal8Bit().data()));
path full_path = complete(path(input_path.toUtf8().data()));
// Adding files to the torrent
add_files(fs, full_path, file_filter);
if(abort) return;
@@ -250,23 +247,25 @@ void torrentCreatorThread::run() {
// Add url seeds
QString seed;
foreach(seed, url_seeds){
t.add_url_seed(seed.toLocal8Bit().data());
t.add_url_seed(seed.toUtf8().data());
}
for(int i=0; i<trackers.size(); ++i){
t.add_tracker(trackers.at(i).toLocal8Bit().data());
t.add_tracker(trackers.at(i).toUtf8().data());
}
if(abort) return;
// calculate the hash for all pieces
set_piece_hashes(t, full_path.branch_path(), boost::bind<void>(&sendProgressUpdateSignal, _1, t.num_pieces(), this));
set_piece_hashes(t, full_path.branch_path(), boost::bind<void>(&sendProgressUpdateSignal, _1, t.num_pieces(), parent));
// Set qBittorrent as creator and add user comment to
// torrent_info structure
t.set_creator(creator_str);
t.set_comment((const char*)comment.toLocal8Bit());
t.set_comment((const char*)comment.toUtf8());
// Is private ?
t.set_priv(is_private);
if(is_private){
t.set_priv(true);
}
if(abort) return;
// create the torrent and print it to out
ofstream out(complete(path((const char*)save_path.toLocal8Bit())), std::ios_base::binary);
ofstream out(complete(path((const char*)save_path.toUtf8())), std::ios_base::binary);
bencode(std::ostream_iterator<char>(out), t.generate());
emit updateProgress(100);
emit creationSuccess(save_path, full_path.branch_path().string().c_str());

Some files were not shown because too many files have changed in this diff Show More