You've already forked qBittorrent
mirror of
https://github.com/qbittorrent/qBittorrent
synced 2025-10-12 03:12:18 +02:00
Compare commits
14 Commits
release-2.
...
release-2.
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a4f62b4e18 | ||
![]() |
2f291daefa | ||
![]() |
722f2aeb5d | ||
![]() |
d5b9598b5b | ||
![]() |
cc7d74b67c | ||
![]() |
e853b0b736 | ||
![]() |
5e395b24a9 | ||
![]() |
9c3789f83f | ||
![]() |
758595dc8c | ||
![]() |
01f9e989ef | ||
![]() |
eb9f0cb559 | ||
![]() |
2592948182 | ||
![]() |
6f6ab1c439 | ||
![]() |
b10e606dda |
12
Changelog
12
Changelog
@@ -1,3 +1,15 @@
|
||||
* Sat Mar 20 2010 - Christophe Dumez <chris@qbittorrent.org> - v2.2.1
|
||||
- FEATURE: Display pieces that are being downloaded
|
||||
- FEATURE: Added back folder watching in Web UI
|
||||
- FEATURE: Added back file prioritizing in Web UI
|
||||
- BUGFIX: Fix compilation with Qt 4.4
|
||||
- BUGFIX: Fix Web UI compatibility with Safari
|
||||
- BUGFIX: Fix progress display with cleanlook style
|
||||
- BUGFIX: Fix file filtering in complex torrents
|
||||
- BUGFIX: Ask for user confirmation for recursive torrent download
|
||||
- BUGFIX: Fix "add file" dialog in torrent creation tool
|
||||
- BUGFIX: Fix "Ctrl+A" in Web UI
|
||||
|
||||
* Sun Mar 14 2010 - Christophe Dumez <chris@qbittorrent.org> - v2.2.0
|
||||
- FEATURE: User can set alternative speed limits for fast toggling
|
||||
- FEATURE: Bandwidth scheduler (automatically use alternative speed limits for a given period)
|
||||
|
@@ -117,6 +117,7 @@ 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(alternativeSpeedsModeChanged(bool)), this, SLOT(updateAltSpeedsBtn(bool)));
|
||||
connect(BTSession, SIGNAL(recursiveTorrentDownloadPossible(QTorrentHandle&)), this, SLOT(askRecursiveTorrentDownloadConfirmation(QTorrentHandle&)));
|
||||
|
||||
qDebug("create tabWidget");
|
||||
tabs = new QTabWidget();
|
||||
@@ -413,6 +414,12 @@ void GUI::readParamsOnSocket() {
|
||||
}
|
||||
}
|
||||
|
||||
void GUI::askRecursiveTorrentDownloadConfirmation(QTorrentHandle &h) {
|
||||
if(QMessageBox::question(this, tr("Recursive download confirmation"), tr("The torrent %1 contains torrent files, do you want to proceed with their download?").arg(h.name()), QMessageBox::Yes|QMessageBox::No) == QMessageBox::Yes) {
|
||||
BTSession->recursiveTorrentDownload(h);
|
||||
}
|
||||
}
|
||||
|
||||
void GUI::handleDownloadFromUrlFailure(QString url, QString reason) const{
|
||||
// Display a message box
|
||||
QMessageBox::critical(0, tr("Url download error"), tr("Couldn't download file at url: %1, reason: %2.").arg(url).arg(reason));
|
||||
|
@@ -116,6 +116,7 @@ protected slots:
|
||||
void addUnauthenticatedTracker(const QPair<QTorrentHandle,QString> &tracker);
|
||||
void processDownloadedFiles(QString path, QString url);
|
||||
void finishedTorrent(QTorrentHandle& h) const;
|
||||
void askRecursiveTorrentDownloadConfirmation(QTorrentHandle &h);
|
||||
// Options slots
|
||||
void on_actionOptions_triggered();
|
||||
void optionsSaved();
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[Desktop Entry]
|
||||
Categories=Qt;Network;P2P;
|
||||
Comment=V2.2.0
|
||||
Comment=V2.2.1
|
||||
Exec=qbittorrent %f
|
||||
GenericName=Bittorrent client
|
||||
GenericName[bg]=Торент клиент
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 79 KiB |
@@ -70,13 +70,13 @@ enum VersionType { NORMAL,ALPHA,BETA,RELEASE_CANDIDATE,DEVEL };
|
||||
|
||||
// Main constructor
|
||||
Bittorrent::Bittorrent()
|
||||
: m_scanFolders(ScanFoldersModel::instance(this)),
|
||||
preAllocateAll(false), addInPause(false), ratio_limit(-1),
|
||||
UPnPEnabled(false), NATPMPEnabled(false), LSDEnabled(false),
|
||||
DHTEnabled(false), current_dht_port(0), queueingEnabled(false),
|
||||
torrentExport(false), exiting(false)
|
||||
: m_scanFolders(ScanFoldersModel::instance(this)),
|
||||
preAllocateAll(false), addInPause(false), ratio_limit(-1),
|
||||
UPnPEnabled(false), NATPMPEnabled(false), LSDEnabled(false),
|
||||
DHTEnabled(false), current_dht_port(0), queueingEnabled(false),
|
||||
torrentExport(false), exiting(false)
|
||||
#ifndef DISABLE_GUI
|
||||
, geoipDBLoaded(false), resolve_countries(false)
|
||||
, geoipDBLoaded(false), resolve_countries(false)
|
||||
#endif
|
||||
{
|
||||
// To avoid some exceptions
|
||||
@@ -197,6 +197,10 @@ void Bittorrent::preAllocateAllFiles(bool b) {
|
||||
}
|
||||
}
|
||||
|
||||
ScanFoldersModel* Bittorrent::getScanFoldersModel() const {
|
||||
return m_scanFolders;
|
||||
}
|
||||
|
||||
void Bittorrent::deleteBigRatios() {
|
||||
if(ratio_limit == -1) return;
|
||||
std::vector<torrent_handle> torrents = getTorrents();
|
||||
@@ -1810,6 +1814,26 @@ void Bittorrent::addConsoleMessage(QString msg, QString) {
|
||||
#endif
|
||||
}
|
||||
|
||||
void Bittorrent::recursiveTorrentDownload(const QTorrentHandle &h) {
|
||||
for(int i=0; i<h.get_torrent_info().num_files(); ++i) {
|
||||
const QString &torrent_relpath = misc::toQString(h.get_torrent_info().file_at(i).path.string());
|
||||
if(torrent_relpath.endsWith(".torrent")) {
|
||||
addConsoleMessage(tr("Recursive download of file %1 embedded in torrent %2", "Recursive download of test.torrent embedded in torrent test2").arg(torrent_relpath).arg(h.name()));
|
||||
const QString &torrent_fullpath = h.save_path()+QDir::separator()+torrent_relpath;
|
||||
try {
|
||||
boost::intrusive_ptr<torrent_info> t = new torrent_info(torrent_fullpath.toLocal8Bit().constData());
|
||||
const QString &sub_hash = misc::toQString(t->info_hash());
|
||||
// Passing the save path along to the sub torrent file
|
||||
TorrentTempData::setSavePath(sub_hash, h.save_path());
|
||||
addTorrent(torrent_fullpath);
|
||||
} catch(std::exception&) {
|
||||
qDebug("Caught error loading torrent");
|
||||
addConsoleMessage(tr("Unable to decode %1 torrent file.").arg(torrent_fullpath), QString::fromUtf8("red"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Read alerts sent by the Bittorrent session
|
||||
void Bittorrent::readAlerts() {
|
||||
// look at session alerts and display some infos
|
||||
@@ -1837,18 +1861,21 @@ void Bittorrent::addConsoleMessage(QString msg, QString) {
|
||||
const bool was_already_seeded = TorrentPersistentData::isSeed(hash);
|
||||
if(!was_already_seeded) {
|
||||
h.save_resume_data();
|
||||
qDebug("Checking if the torrent contains torrent files to download");
|
||||
// Check if there are torrent files inside
|
||||
for(int i=0; i<h.get_torrent_info().num_files(); ++i) {
|
||||
const QString &torrent_relpath = misc::toQString(h.get_torrent_info().file_at(i).path.string());
|
||||
if(torrent_relpath.endsWith(".torrent")) {
|
||||
addConsoleMessage(tr("Recursive download of file %1 embedded in torrent %2", "Recursive download of test.torrent embedded in torrent test2").arg(torrent_relpath).arg(h.name()));
|
||||
qDebug("Found possible recursive torrent download.");
|
||||
const QString &torrent_fullpath = h.save_path()+QDir::separator()+torrent_relpath;
|
||||
qDebug("Full subtorrent path is %s", qPrintable(torrent_fullpath));
|
||||
try {
|
||||
boost::intrusive_ptr<torrent_info> t = new torrent_info(torrent_fullpath.toLocal8Bit().constData());
|
||||
const QString &sub_hash = misc::toQString(t->info_hash());
|
||||
// Passing the save path along to the sub torrent file
|
||||
TorrentTempData::setSavePath(sub_hash, h.save_path());
|
||||
addTorrent(torrent_fullpath);
|
||||
if(t->is_valid()) {
|
||||
qDebug("emitting recursiveTorrentDownloadPossible()");
|
||||
emit recursiveTorrentDownloadPossible(h);
|
||||
break;
|
||||
}
|
||||
} catch(std::exception&) {
|
||||
qDebug("Caught error loading torrent");
|
||||
addConsoleMessage(tr("Unable to decode %1 torrent file.").arg(torrent_fullpath), QString::fromUtf8("red"));
|
||||
@@ -2274,10 +2301,7 @@ void Bittorrent::addConsoleMessage(QString msg, QString) {
|
||||
torrent_queue.push(qMakePair(prio, hash));
|
||||
}
|
||||
// Resume downloads
|
||||
int prio = -1;
|
||||
while(!torrent_queue.empty()) {
|
||||
int new_prio = torrent_queue.top().first;
|
||||
Q_ASSERT(new_prio >= prio);
|
||||
const QString &hash = torrent_queue.top().second;
|
||||
torrent_queue.pop();
|
||||
qDebug("Starting up torrent %s", qPrintable(hash));
|
||||
|
@@ -115,6 +115,7 @@ public:
|
||||
qlonglong getETA(QString hash);
|
||||
bool useTemporaryFolder() const;
|
||||
QString getDefaultSavePath() const;
|
||||
ScanFoldersModel* getScanFoldersModel() const;
|
||||
|
||||
public slots:
|
||||
QTorrentHandle addTorrent(QString path, bool fromScanDir = false, QString from_url = QString(), bool resumed = false);
|
||||
@@ -181,6 +182,7 @@ public slots:
|
||||
void downloadFromURLList(const QStringList& urls);
|
||||
void configureSession();
|
||||
void banIP(QString ip);
|
||||
void recursiveTorrentDownload(const QTorrentHandle &h);
|
||||
|
||||
protected:
|
||||
QString getSavePath(QString hash, bool fromScanDir = false, QString filePath = QString());
|
||||
@@ -210,6 +212,7 @@ signals:
|
||||
void savePathChanged(QTorrentHandle &h);
|
||||
void newConsoleMessage(QString msg);
|
||||
void alternativeSpeedsModeChanged(bool alternative);
|
||||
void recursiveTorrentDownloadPossible(QTorrentHandle &h);
|
||||
|
||||
private:
|
||||
// Bittorrent
|
||||
|
@@ -85,7 +85,7 @@ void createtorrent::on_addFolder_button_clicked(){
|
||||
}
|
||||
|
||||
void createtorrent::on_addFile_button_clicked(){
|
||||
QString file = QFileDialog::getOpenFileName(this, tr("Select a file to add to the torrent"), QDir::homePath(), QString(), 0, QFileDialog::ShowDirsOnly);
|
||||
QString file = QFileDialog::getOpenFileName(this, tr("Select a file to add to the torrent"), QDir::homePath());
|
||||
if(!file.isEmpty())
|
||||
textInputPath->setText(file);
|
||||
}
|
||||
|
@@ -53,34 +53,49 @@ public:
|
||||
setFixedHeight(BAR_HEIGHT);
|
||||
}
|
||||
|
||||
void setProgress(bitfield pieces) {
|
||||
void setProgress(const bitfield &pieces, const bitfield &downloading_pieces) {
|
||||
if(pieces.empty()) {
|
||||
// Empty bar
|
||||
QPixmap pix = QPixmap(1, 1);
|
||||
pix.fill();
|
||||
pixmap = pix;
|
||||
} else {
|
||||
int nb_pieces = pieces.size();
|
||||
const int nb_pieces = pieces.size();
|
||||
// Reduce the number of pieces before creating the pixmap
|
||||
// otherwise it can crash when there are too many pieces
|
||||
if(nb_pieces > width()) {
|
||||
int ratio = floor(nb_pieces/(double)width());
|
||||
QVector<bool> scaled_pieces;
|
||||
const int ratio = floor(nb_pieces/(double)width());
|
||||
std::vector<bool> scaled_pieces;
|
||||
std::vector<bool> scaled_downloading;
|
||||
for(int i=0; i<nb_pieces; i+= ratio) {
|
||||
bool have = true;
|
||||
for(int j=i; j<qMin(i+ratio, nb_pieces); ++j) {
|
||||
if(!pieces[i]) { have = false; break; }
|
||||
}
|
||||
scaled_pieces << have;
|
||||
scaled_pieces.push_back(have);
|
||||
if(have) {
|
||||
scaled_downloading.push_back(false);
|
||||
} else {
|
||||
bool downloading = false;
|
||||
for(int j=i; j<qMin(i+ratio, nb_pieces); ++j) {
|
||||
if(downloading_pieces[i]) { downloading = true; break; }
|
||||
}
|
||||
scaled_downloading.push_back(downloading);
|
||||
}
|
||||
}
|
||||
QPixmap pix = QPixmap(scaled_pieces.size(), 1);
|
||||
pix.fill();
|
||||
QPainter painter(&pix);
|
||||
for(int i=0; i<scaled_pieces.size(); ++i) {
|
||||
if(scaled_pieces[i])
|
||||
for(uint i=0; i<scaled_pieces.size(); ++i) {
|
||||
if(scaled_pieces[i]) {
|
||||
painter.setPen(Qt::blue);
|
||||
else
|
||||
painter.setPen(Qt::white);
|
||||
} else {
|
||||
if(scaled_downloading[i]) {
|
||||
painter.setPen(Qt::yellow);
|
||||
} else {
|
||||
painter.setPen(Qt::white);
|
||||
}
|
||||
}
|
||||
painter.drawPoint(i,0);
|
||||
}
|
||||
pixmap = pix;
|
||||
@@ -89,10 +104,15 @@ public:
|
||||
pix.fill();
|
||||
QPainter painter(&pix);
|
||||
for(uint i=0; i<pieces.size(); ++i) {
|
||||
if(pieces[i])
|
||||
if(pieces[i]) {
|
||||
painter.setPen(Qt::blue);
|
||||
else
|
||||
painter.setPen(Qt::white);
|
||||
} else {
|
||||
if(downloading_pieces[i]) {
|
||||
painter.setPen(Qt::yellow);
|
||||
} else {
|
||||
painter.setPen(Qt::white);
|
||||
}
|
||||
}
|
||||
painter.drawPoint(i,0);
|
||||
}
|
||||
pixmap = pix;
|
||||
|
@@ -31,6 +31,7 @@
|
||||
|
||||
#include "eventmanager.h"
|
||||
#include "bittorrent.h"
|
||||
#include "scannedfoldersmodel.h"
|
||||
#include "misc.h"
|
||||
#include "preferences.h"
|
||||
//#include "proplistdelegate.h"
|
||||
@@ -129,8 +130,23 @@ void EventManager::setGlobalPreferences(QVariantMap m) const {
|
||||
Preferences::setTempPathEnabled(m["temp_path_enabled"].toBool());
|
||||
if(m.contains("temp_path"))
|
||||
Preferences::setTempPath(m["temp_path"].toString());
|
||||
if(m.contains("scan_dirs"))
|
||||
Preferences::setScanDirs(m["scan_dirs"].toStringList());
|
||||
if(m.contains("scan_dirs")) {
|
||||
QStringList old_folders = Preferences::getScanDirs();
|
||||
QStringList new_folders = m["scan_dirs"].toStringList();
|
||||
foreach(const QString &old_folder, old_folders) {
|
||||
// Update deleted folders
|
||||
if(!new_folders.contains(old_folder)) {
|
||||
BTSession->getScanFoldersModel()->removePath(old_folder);
|
||||
}
|
||||
}
|
||||
foreach(const QString &new_folder, new_folders) {
|
||||
// Update new folders
|
||||
if(!old_folders.contains(new_folder)) {
|
||||
BTSession->getScanFoldersModel()->addPath(new_folder);
|
||||
}
|
||||
}
|
||||
Preferences::setScanDirs(new_folders);
|
||||
}
|
||||
if(m.contains("download_in_scan_dirs"))
|
||||
Preferences::setDownloadInScanDirs(m["download_in_scan_dirs"].toList());
|
||||
if(m.contains("export_dir"))
|
||||
|
@@ -104,7 +104,7 @@ void HttpConnection::write()
|
||||
}
|
||||
|
||||
QString HttpConnection::translateDocument(QString data) {
|
||||
std::string contexts[] = {"TransferListFiltersWidget", "TransferListWidget", "PropertiesWidget", "GUI", "MainWindow", "HttpServer", "confirmDeletionDlg", "TrackerList", "TorrentFilesModel", "options_imp", "Preferences", "TrackersAdditionDlg"};
|
||||
std::string contexts[] = {"TransferListFiltersWidget", "TransferListWidget", "PropertiesWidget", "GUI", "MainWindow", "HttpServer", "confirmDeletionDlg", "TrackerList", "TorrentFilesModel", "options_imp", "Preferences", "TrackersAdditionDlg", "ScanFoldersModel"};
|
||||
int i=0;
|
||||
bool found = false;
|
||||
do {
|
||||
@@ -119,7 +119,7 @@ QString HttpConnection::translateDocument(QString data) {
|
||||
do {
|
||||
translation = qApp->translate(contexts[context_index].c_str(), word.toLocal8Bit().constData(), 0, QCoreApplication::UnicodeUTF8, 1);
|
||||
++context_index;
|
||||
}while(translation == word && context_index < 12);
|
||||
}while(translation == word && context_index < 13);
|
||||
//qDebug("Translation is %s", translation.toUtf8().data());
|
||||
data = data.replace(i, regex.matchedLength(), translation);
|
||||
i += translation.length();
|
||||
@@ -140,6 +140,14 @@ void HttpConnection::respond() {
|
||||
return;
|
||||
}
|
||||
QString auth = parser.value("Authorization");
|
||||
if(auth.isEmpty()) {
|
||||
// Return unauthorized header
|
||||
qDebug("Auth is Empty...");
|
||||
generator.setStatusLine(401, "Unauthorized");
|
||||
generator.setValue("WWW-Authenticate", "Digest realm=\""+QString(QBT_REALM)+"\", nonce=\""+parent->generateNonce()+"\", opaque=\""+parent->generateNonce()+"\", stale=\"false\", algorithm=\"MD5\", qop=\"auth\"");
|
||||
write();
|
||||
return;
|
||||
}
|
||||
qDebug("Auth: %s", qPrintable(auth.split(" ").first()));
|
||||
if (QString::compare(auth.split(" ").first(), "Digest", Qt::CaseInsensitive) != 0 || !parent->isAuthorized(auth.toLocal8Bit(), parser.method())) {
|
||||
// Update failed attempt counter
|
||||
|
@@ -259,7 +259,7 @@ bool HttpServer::isAuthorized(QByteArray auth, QString method) const {
|
||||
md5_ha.addData(password_ha1+":"+prop_nonce+":"+ha2);
|
||||
response = md5_ha.result().toHex();
|
||||
}
|
||||
qDebug("AUTH: comparing reponses");
|
||||
qDebug("AUTH: comparing reponses: (%d)", static_cast<int>(prop_response == response));
|
||||
return prop_response == response;
|
||||
}
|
||||
|
||||
|
44
src/json.h
44
src/json.h
@@ -113,7 +113,24 @@ namespace json {
|
||||
if(json.startsWith("{") && json.endsWith("}")) {
|
||||
json.chop(1);
|
||||
json = json.replace(0, 1, "");
|
||||
QStringList couples = json.split(",");
|
||||
QStringList couples;
|
||||
QString tmp = "";
|
||||
bool in_list = false;
|
||||
foreach(QChar c, json) {
|
||||
if(c == ',' && !in_list) {
|
||||
couples << tmp;
|
||||
tmp = "";
|
||||
} else {
|
||||
if(c == '[') {
|
||||
in_list = true;
|
||||
} else {
|
||||
if(c == ']') {
|
||||
in_list = false;
|
||||
}
|
||||
}
|
||||
tmp += c;
|
||||
}
|
||||
}
|
||||
foreach(QString couple, couples) {
|
||||
QStringList parts = couple.split(":");
|
||||
if(parts.size() != 2) continue;
|
||||
@@ -124,12 +141,29 @@ namespace json {
|
||||
}
|
||||
QString value_str = parts.last();
|
||||
QVariant value;
|
||||
if(value_str.startsWith("\"") && value_str.endsWith("\"")) {
|
||||
if(value_str.startsWith("[") && value_str.endsWith("]")) {
|
||||
value_str.chop(1);
|
||||
value_str = value_str.replace(0, 1, "");
|
||||
value = value_str;
|
||||
value_str.replace(0, 1, "");
|
||||
QStringList list_elems = value_str.split(",");
|
||||
QVariantList varlist;
|
||||
foreach(QString list_val, list_elems) {
|
||||
if(list_val.startsWith("\"") && list_val.endsWith("\"")) {
|
||||
list_val.chop(1);
|
||||
list_val = list_val.replace(0, 1, "");
|
||||
varlist << list_val;
|
||||
} else {
|
||||
varlist << list_val.toInt();
|
||||
}
|
||||
}
|
||||
value = varlist;
|
||||
} else {
|
||||
value = value_str.toInt();
|
||||
if(value_str.startsWith("\"") && value_str.endsWith("\"")) {
|
||||
value_str.chop(1);
|
||||
value_str = value_str.replace(0, 1, "");
|
||||
value = value_str;
|
||||
} else {
|
||||
value = value_str.toInt();
|
||||
}
|
||||
}
|
||||
m.insert(key,value);
|
||||
qDebug("%s:%s", key.toLocal8Bit().data(), value_str.toLocal8Bit().data());
|
||||
|
@@ -36,8 +36,10 @@
|
||||
#include <QApplication>
|
||||
#include <QMessageBox>
|
||||
#include <QStyleFactory>
|
||||
#include <QStyle>
|
||||
#include <QSplashScreen>
|
||||
#include <QPushButton>
|
||||
#include "qgnomelook.h"
|
||||
#include "GUI.h"
|
||||
#include "ico.h"
|
||||
#else
|
||||
@@ -158,6 +160,11 @@ void useStyle(QApplication *app, QString style){
|
||||
if(!style.isEmpty()) {
|
||||
QApplication::setStyle(QStyleFactory::create(style));
|
||||
}
|
||||
if(app->style()->objectName() == "cleanlooks") {
|
||||
// Force our own cleanlooks style
|
||||
qDebug("Forcing our own cleanlooks style");
|
||||
app->setStyle(new QGnomeLookStyle());
|
||||
}
|
||||
Preferences::setStyle(app->style()->objectName());
|
||||
}
|
||||
#endif
|
||||
|
@@ -34,6 +34,7 @@
|
||||
#include <QSystemTrayIcon>
|
||||
#include <QApplication>
|
||||
#include <QSettings>
|
||||
#include "qgnomelook.h"
|
||||
#include <QDialogButtonBox>
|
||||
#include <QCloseEvent>
|
||||
#include <QDesktopWidget>
|
||||
@@ -307,6 +308,11 @@ void options_imp::changePage(QListWidgetItem *current, QListWidgetItem *previous
|
||||
|
||||
void options_imp::useStyle() {
|
||||
QApplication::setStyle(QStyleFactory::create(comboStyle->itemText(comboStyle->currentIndex())));
|
||||
if(QApplication::style()->objectName() == "cleanlooks") {
|
||||
// Force our own cleanlooks style
|
||||
qDebug("Forcing our own cleanlooks style");
|
||||
QApplication::setStyle(new QGnomeLookStyle());
|
||||
}
|
||||
}
|
||||
|
||||
void options_imp::loadWindowState() {
|
||||
|
@@ -51,7 +51,7 @@ public:
|
||||
setFixedHeight(BAR_HEIGHT);
|
||||
}
|
||||
|
||||
double setAvailability(std::vector<int>& avail) {
|
||||
double setAvailability(const std::vector<int>& avail) {
|
||||
double average = 0;
|
||||
if(avail.empty()) {
|
||||
// Empty bar
|
||||
@@ -60,12 +60,12 @@ public:
|
||||
pixmap = pix;
|
||||
} else {
|
||||
// Look for maximum value
|
||||
int nb_pieces = avail.size();
|
||||
const int nb_pieces = avail.size();
|
||||
average = std::accumulate(avail.begin(), avail.end(), 0)/(double)nb_pieces;
|
||||
// Reduce the number of pieces before creating the pixmap
|
||||
// otherwise it can crash when there are too many pieces
|
||||
if(nb_pieces > width()) {
|
||||
int ratio = floor(nb_pieces/(double)width());
|
||||
const int ratio = floor(nb_pieces/(double)width());
|
||||
std::vector<int> scaled_avail;
|
||||
for(int i=0; i<nb_pieces; i+= ratio) {
|
||||
int j = i;
|
||||
@@ -113,7 +113,7 @@ protected:
|
||||
QColor getPieceColor(int avail, double average) {
|
||||
if(!avail) return Qt::white;
|
||||
//qDebug("avail: %d/%d", avail, max_avail);
|
||||
QColor color = Qt::blue; // average avail
|
||||
const QColor color = Qt::blue; // average avail
|
||||
double fraction = 100.*average/avail;
|
||||
if(fraction < 100)
|
||||
fraction *= 0.9;
|
||||
|
@@ -338,7 +338,9 @@ void PropertiesWidget::loadDynamicData() {
|
||||
if(!h.is_seed()) {
|
||||
showPiecesDownloaded(true);
|
||||
// Downloaded pieces
|
||||
downloaded_pieces->setProgress(h.pieces());
|
||||
bitfield bf(h.get_torrent_info().num_pieces(), 0);
|
||||
h.downloading_pieces(bf);
|
||||
downloaded_pieces->setProgress(h.pieces(), bf);
|
||||
// Pieces availability
|
||||
if(h.has_metadata() && !h.is_paused() && !h.is_queued() && !h.is_checking()) {
|
||||
showPiecesAvailability(true);
|
||||
|
96
src/qgnomelook.h
Normal file
96
src/qgnomelook.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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 QGNOMELOOK
|
||||
#define QGNOMELOOK
|
||||
|
||||
#include <QCleanlooksStyle>
|
||||
#include <QStyleOption>
|
||||
#include <QStyleOptionProgressBar>
|
||||
#include <QStyleOptionProgressBarV2>
|
||||
#include <QPen>
|
||||
#include <QPainter>
|
||||
|
||||
class QGnomeLookStyle : public QCleanlooksStyle {
|
||||
public:
|
||||
QGnomeLookStyle() : QCleanlooksStyle() {}
|
||||
|
||||
void drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const {
|
||||
switch(element) {
|
||||
case CE_ProgressBarLabel:
|
||||
if (const QStyleOptionProgressBar *pb = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) {
|
||||
bool vertical = false;
|
||||
if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(option)) {
|
||||
vertical = (pb2->orientation == Qt::Vertical);
|
||||
}
|
||||
if (!vertical) {
|
||||
QPalette::ColorRole textRole = QPalette::WindowText;/*
|
||||
if ((pb->textAlignment & Qt::AlignCenter) && pb->textVisible
|
||||
&& ((qint64(pb->progress) - qint64(pb->minimum)) * 2 >= (qint64(pb->maximum) - qint64(pb->minimum)))) {
|
||||
textRole = QPalette::HighlightedText;
|
||||
//Draw text shadow, This will increase readability when the background of same color
|
||||
QRect shadowRect(pb->rect);
|
||||
shadowRect.translate(1,1);
|
||||
QColor shadowColor = (pb->palette.color(textRole).value() <= 128) ? QColor(255,255,255,160) : QColor(0,0,0,160);
|
||||
QPalette shadowPalette = pb->palette;
|
||||
shadowPalette.setColor(textRole, shadowColor);
|
||||
drawItemText(painter, shadowRect, Qt::AlignCenter | Qt::TextSingleLine, shadowPalette, pb->state, pb->text, textRole);
|
||||
}
|
||||
QPalette shadowPalette = pb->palette;
|
||||
shadowPalette.setColor(textRole, QColor(0,0,0,160));*/
|
||||
drawItemText(painter, pb->rect, Qt::AlignCenter | Qt::TextSingleLine, pb->palette, pb->state, pb->text, textRole);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
QCleanlooksStyle::drawControl(element, option, painter, widget);
|
||||
}
|
||||
}
|
||||
|
||||
QRect subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget=0) const
|
||||
{
|
||||
QRect rect;
|
||||
switch (element) {
|
||||
#ifndef QT_NO_PROGRESSBAR
|
||||
case SE_ProgressBarLabel:
|
||||
case SE_ProgressBarContents:
|
||||
case SE_ProgressBarGroove:
|
||||
return option->rect;
|
||||
#endif // QT_NO_PROGRESSBAR
|
||||
default:
|
||||
return QCleanlooksStyle::subElementRect(element, option, widget);
|
||||
}
|
||||
|
||||
return visualRect(option->direction, option->rect, rect);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
@@ -451,6 +451,16 @@ bool QTorrentHandle::has_error() const {
|
||||
return h.status().error.empty();
|
||||
}
|
||||
|
||||
void QTorrentHandle::downloading_pieces(bitfield &bf) const {
|
||||
Q_ASSERT(h.is_valid());
|
||||
std::vector<partial_piece_info> queue;
|
||||
h.get_download_queue(queue);
|
||||
for(std::vector<partial_piece_info>::iterator it=queue.begin(); it!= queue.end(); it++) {
|
||||
bf.set_bit(it->piece_index);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Setters
|
||||
//
|
||||
|
@@ -129,6 +129,7 @@ class QTorrentHandle {
|
||||
bool first_last_piece_first() const;
|
||||
QString root_path() const;
|
||||
bool has_error() const;
|
||||
void downloading_pieces(bitfield &bf) const;
|
||||
|
||||
//
|
||||
// Setters
|
||||
|
@@ -11,10 +11,10 @@ CONFIG += qt \
|
||||
thread
|
||||
|
||||
# Update this VERSION for each release
|
||||
DEFINES += VERSION=\\\"v2.2.0\\\"
|
||||
DEFINES += VERSION=\\\"v2.2.1\\\"
|
||||
DEFINES += VERSION_MAJOR=2
|
||||
DEFINES += VERSION_MINOR=2
|
||||
DEFINES += VERSION_BUGFIX=0
|
||||
DEFINES += VERSION_BUGFIX=1
|
||||
|
||||
# NORMAL,ALPHA,BETA,RELEASE_CANDIDATE,DEVEL
|
||||
DEFINES += VERSION_TYPE=NORMAL
|
||||
@@ -227,6 +227,7 @@ else:HEADERS += GUI.h \
|
||||
ico.h \
|
||||
engineselectdlg.h \
|
||||
pluginsource.h \
|
||||
qgnomelook.h \
|
||||
searchEngine.h \
|
||||
rss.h \
|
||||
rss_imp.h \
|
||||
|
@@ -97,6 +97,7 @@ public:
|
||||
TreeItem(QList<QVariant> data) {
|
||||
parentItem = 0;
|
||||
type = ROOT;
|
||||
Q_ASSERT(data.size() == 4);
|
||||
itemData = data;
|
||||
total_done = 0;
|
||||
}
|
||||
@@ -201,12 +202,13 @@ public:
|
||||
return itemData.value(3).toInt();
|
||||
}
|
||||
|
||||
void setPriority(int new_prio, bool update_children=true) {
|
||||
void setPriority(int new_prio, bool update_children=true, bool update_parent=true) {
|
||||
int old_prio = getPriority();
|
||||
if(old_prio != new_prio) {
|
||||
qDebug("setPriority(%s, %d)", qPrintable(getName()), new_prio);
|
||||
itemData.replace(3, new_prio);
|
||||
// Update parent
|
||||
if(parentItem) {
|
||||
if(update_parent && parentItem) {
|
||||
parentItem->updateSize();
|
||||
parentItem->updateProgress();
|
||||
parentItem->updatePriority();
|
||||
@@ -215,9 +217,13 @@ public:
|
||||
// Update children
|
||||
if(update_children) {
|
||||
foreach(TreeItem* child, childItems) {
|
||||
child->setPriority(new_prio);
|
||||
child->setPriority(new_prio, true, false);
|
||||
}
|
||||
}
|
||||
if(type==FOLDER) {
|
||||
updateSize();
|
||||
updateProgress();
|
||||
}
|
||||
}
|
||||
|
||||
void updatePriority() {
|
||||
|
@@ -100,12 +100,17 @@
|
||||
<tr>
|
||||
<td style="vertical-align: bottom; text-align: right;"></td><td><input type="text" id="temppath_text"/></td>
|
||||
</tr>
|
||||
<!-- <tr>
|
||||
<td style="vertical-align: bottom; text-align: right;"><input type="checkbox" id="scandir_checkbox" onclick="updateScanDirEnabled();"/></td><td>_(Automatically load .torrent files from:)</td>
|
||||
</tr>
|
||||
<tr><td colspan="2">_(Check Folders for .torrent Files:)</td></tr>
|
||||
<tr>
|
||||
<td style="vertical-align: bottom; text-align: right;"></td><td><input type="text" id="scandir_text"/></td>
|
||||
</tr> -->
|
||||
<td></td>
|
||||
<td>
|
||||
<table style="border: 1px solid black; text-align: center" id="watched_folders_tab">
|
||||
<thead><tr style="border: 1px solid black;"><th>_(Watched Folder)</th><th>_(Download here)</th></tr></thead>
|
||||
<tbody></tbody>
|
||||
<tfoot><tr style="border: 1px solid black;"><td style="padding-top:4px;"><input type="text" id="new_watch_folder_txt"/></td><td style="padding-top:4px;"><input type="checkbox" id="new_watch_folder_dl" style="padding-left:18px;"/><img src="images/oxygen/list-add.png" alt="Add" style="padding-left:2px;width:16px;cursor:pointer;margin-right:-18px;" onclick="javascript:addWatchFolder();"/></td></tr></tfoot>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="vertical-align: bottom; text-align: right;"><input type="checkbox" id="exportdir_checkbox" onclick="updateExportDirEnabled();"/></td><td>_(Copy .torrent files to:)</td>
|
||||
</tr>
|
||||
@@ -229,7 +234,7 @@
|
||||
<option value="ja_JP" title="Icons/flags/japan.png">日本語</option>
|
||||
<option value="zh_CN" title="Icons/flags/china.png">中文 (简体)</option>
|
||||
<option value="zh_TW" title="Icons/flags/taiwan.png">中文 (繁體)</option>
|
||||
<option value="ko_KR" title="Icons/flags/south_korea.png">한글"</option>
|
||||
<option value="ko_KR" title="Icons/flags/south_korea.png">한글</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -266,6 +271,8 @@
|
||||
<center><input type="button" value="_(Apply)" onclick="applyPreferences();"/></center>
|
||||
|
||||
<script type="text/javascript">
|
||||
var WatchedFoldersTable = new HtmlTable($("watched_folders_tab"));
|
||||
|
||||
applyPreferences = function() {
|
||||
// Validate form data
|
||||
// Connection
|
||||
@@ -340,12 +347,7 @@
|
||||
if($defined($('temppath_checkbox').get('checked')) && $('temppath_checkbox').get('checked'))
|
||||
temp_path_enabled = 1;
|
||||
var temp_path = $('temppath_text').get('value');
|
||||
/*var scandir_enabled = 0;
|
||||
if($defined($('scandir_checkbox').get('checked')) && $('scandir_checkbox').get('checked'))
|
||||
scandir_enabled = 1;
|
||||
var scandir_path = '';
|
||||
if(scandir_enabled)
|
||||
scandir_path = $('scandir_text').get('value');*/
|
||||
var watched_folders = getWatchedFolders();
|
||||
var exportdir_enabled = 0;
|
||||
if($defined($('exportdir_checkbox').get('checked')) && $('exportdir_checkbox').get('checked'))
|
||||
exportdir_enabled = 1;
|
||||
@@ -467,7 +469,8 @@
|
||||
dict.set('save_path', save_path);
|
||||
dict.set('temp_path_enabled', temp_path_enabled);
|
||||
dict.set('temp_path', temp_path);
|
||||
//dict.set('scan_dir', scandir_path);
|
||||
dict.set('scan_dirs', watched_folders[0]);
|
||||
dict.set('download_in_scan_dirs', watched_folders[1]);
|
||||
dict.set('export_dir', exportdir_path);
|
||||
dict.set('preallocate_all', preallocate_all);
|
||||
if(!$('appendexttr').hasClass('invisible')) {
|
||||
@@ -686,6 +689,47 @@ updatePeerProxyAuthSettings = function() {
|
||||
}
|
||||
}
|
||||
|
||||
getWatchedFolders = function() {
|
||||
var nb_folders = $("watched_folders_tab").getChildren("tbody")[0].getChildren("tr").length;
|
||||
var folders = Array();
|
||||
var download_in_place = Array();
|
||||
for(var i=0; i<nb_folders; i+=1) {
|
||||
var folder_path = $('text_watch_'+i).get('value').trim();
|
||||
if(folder_path.length > 0) {
|
||||
folders[folders.length] = folder_path;
|
||||
if($defined($("cb_watch_"+i).get('checked')) && $("cb_watch_"+i).get('checked')) {
|
||||
download_in_place[download_in_place.length] = 1;
|
||||
} else {
|
||||
download_in_place[download_in_place.length] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return [folders, download_in_place];
|
||||
}
|
||||
|
||||
addWatchFolder = function() {
|
||||
var new_folder = $("new_watch_folder_txt").get('value').trim();
|
||||
if(new_folder.length <= 0) return;
|
||||
var download_here = ($defined($("new_watch_folder_dl").get('checked')) && $("new_watch_folder_dl").get('checked'));
|
||||
var myinput = new Element("input");
|
||||
var i = $("watched_folders_tab").getChildren("tbody")[0].getChildren("tr").length;
|
||||
myinput.set('id', 'text_watch_'+i);
|
||||
myinput.set('type', 'text');
|
||||
myinput.set('value', new_folder);
|
||||
var mycb = new Element("input");
|
||||
mycb.set("type", "checkbox");
|
||||
mycb.set("id", "cb_watch_"+i);
|
||||
if(download_here) {
|
||||
mycb.set("checked", "checked");
|
||||
} else {
|
||||
mycb.removeProperty('checked');
|
||||
}
|
||||
WatchedFoldersTable.push([myinput, mycb]);
|
||||
// Clear fields
|
||||
$("new_watch_folder_txt").set('value', '');
|
||||
$("new_watch_folder_dl").removeProperty('checked');
|
||||
}
|
||||
|
||||
loadPreferences = function() {
|
||||
var url = 'json/preferences';
|
||||
var request = new Request.JSON({
|
||||
@@ -793,15 +837,23 @@ loadPreferences = function() {
|
||||
var temp_path = pref.temp_path;
|
||||
$('temppath_text').set('value', temp_path);
|
||||
updateTempDirEnabled();
|
||||
/*var scan_dir_enabled = pref.scan_dir_enabled;
|
||||
if(scan_dir_enabled) {
|
||||
$('scandir_text').set('value', pref.scan_dir);
|
||||
$('scandir_checkbox').set('checked', 'checked');
|
||||
} else {
|
||||
$('scandir_text').set('value', '');
|
||||
$('scandir_checkbox').removeProperty('checked');
|
||||
var i = 0;
|
||||
for(i=0; i<pref.scan_dirs.length; i+=1) {
|
||||
var myinput = new Element("input");
|
||||
myinput.set('id', 'text_watch_'+i);
|
||||
myinput.set('type', 'text');
|
||||
myinput.set('value', pref.scan_dirs[i]);
|
||||
var mycb = new Element("input");
|
||||
mycb.set("type", "checkbox");
|
||||
mycb.set("id", "cb_watch_"+i);
|
||||
if(pref.download_in_scan_dirs[i] == "true" || pref.download_in_scan_dirs[i] == 1) {
|
||||
mycb.set("checked", "checked");
|
||||
} else {
|
||||
mycb.removeProperty('checked');
|
||||
}
|
||||
WatchedFoldersTable.push([myinput, mycb]);
|
||||
}
|
||||
updateScanDirEnabled();*/
|
||||
|
||||
var export_dir_enabled = pref.export_dir_enabled;
|
||||
if(export_dir_enabled) {
|
||||
$('exportdir_text').set('value', pref.export_dir);
|
||||
@@ -905,4 +957,4 @@ loadPreferences = function() {
|
||||
}
|
||||
|
||||
loadPreferences();
|
||||
</script>
|
||||
</script>
|
||||
|
@@ -2,10 +2,11 @@
|
||||
<table class="torrentTable" cellpadding="0" cellspacing="0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>_(Downloaded)</th>
|
||||
<th>_(Name)</th>
|
||||
<th>_(Size)</th>
|
||||
<th style="width: 90px;">_(Progress)</th>
|
||||
<th>_(Downloaded)</th>
|
||||
<th>_(Priority)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="filesTable"></tbody>
|
||||
@@ -32,10 +33,50 @@ var createDownloadedCB = function(id, downloaded) {
|
||||
if($defined($('cbPrio'+id).get('checked')) && $('cbPrio'+id).get('checked'))
|
||||
checked = 1;
|
||||
setFilePriority(id, checked);
|
||||
// Display or add combobox
|
||||
if(checked) {
|
||||
$('comboPrio'+id).set("value", 1);
|
||||
$('comboPrio'+id).removeClass("invisible");
|
||||
} else {
|
||||
$('comboPrio'+id).addClass("invisible");
|
||||
}
|
||||
});
|
||||
return CB;
|
||||
}
|
||||
|
||||
var createPriorityCombo = function(id, selected_prio) {
|
||||
var select = new Element('select');
|
||||
select.set('id', 'comboPrio'+id);
|
||||
select.addEvent('change', function(e){
|
||||
var new_prio = $('comboPrio'+id).get('value');
|
||||
setFilePriority(id, new_prio);
|
||||
});
|
||||
var opt = new Element("option");
|
||||
opt.set('value', '1')
|
||||
opt.set('html', "_(Normal)");
|
||||
if(selected_prio <= 1)
|
||||
opt.setAttribute('selected', '');
|
||||
opt.injectInside(select);
|
||||
opt = new Element("option");
|
||||
opt.set('value', '2')
|
||||
opt.set('html', "_(High)");
|
||||
if(selected_prio == 2)
|
||||
opt.setAttribute('selected', '');
|
||||
opt.injectInside(select);
|
||||
opt = new Element("option");
|
||||
opt.set('value', '7')
|
||||
opt.set('html', "_(Maximum)");
|
||||
if(selected_prio == 7)
|
||||
opt.setAttribute('selected', '');
|
||||
opt.injectInside(select);
|
||||
if(selected_prio < 1) {
|
||||
select.addClass("invisible");
|
||||
} else {
|
||||
select.removeClass("invisible");
|
||||
}
|
||||
return select;
|
||||
}
|
||||
|
||||
var filesDynTable = new Class ({
|
||||
|
||||
initialize: function(){
|
||||
@@ -65,16 +106,26 @@ var createDownloadedCB = function(id, downloaded) {
|
||||
updateRow: function(tr, row, id){
|
||||
var tds = tr.getElements('td');
|
||||
for(var i=0; i<row.length; i++) {
|
||||
if(i==2) {
|
||||
if(i==3) {
|
||||
$('pbf_'+id).setValue(row[i].toFloat());
|
||||
} else {
|
||||
if(i==3) {
|
||||
} else {
|
||||
if(i==0) {
|
||||
if(row[i] > 0)
|
||||
tds[i].getChildren('input')[0].set('checked', 'checked');
|
||||
else
|
||||
tds[i].removeProperty('checked')
|
||||
} else {
|
||||
tds[i].set('html', row[i]);
|
||||
if(i == 4) {
|
||||
if(row[i] > 0) {
|
||||
tds[i].getChildren('select').set('value', row[i]);
|
||||
$('comboPrio'+id).removeClass("invisible");
|
||||
} else {
|
||||
if(!$('comboPrio'+id).hasClass("invisible"))
|
||||
$('comboPrio'+id).addClass("invisible");
|
||||
}
|
||||
} else {
|
||||
tds[i].set('html', row[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -93,13 +144,17 @@ var createDownloadedCB = function(id, downloaded) {
|
||||
for(var i=0; i<row.length; i++)
|
||||
{
|
||||
var td = new Element('td');
|
||||
if(i==2) {
|
||||
td.adopt(new ProgressBar(row[i].toFloat(), {'id': 'pbf_'+id, 'width':80}));
|
||||
} else {
|
||||
if(i == 3) {
|
||||
if(i==3) {
|
||||
td.adopt(new ProgressBar(row[i].toFloat(), {'id': 'pbf_'+id, 'width':80}));
|
||||
} else {
|
||||
if(i == 0) {
|
||||
td.adopt(createDownloadedCB(id,row[i]));
|
||||
} else {
|
||||
td.set('html', row[i]);
|
||||
if(i == 4) {
|
||||
td.adopt(createPriorityCombo(id,row[i]));
|
||||
} else {
|
||||
td.set('html', row[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
td.injectInside(tr);
|
||||
@@ -143,10 +198,11 @@ var createDownloadedCB = function(id, downloaded) {
|
||||
files.each(function(file){
|
||||
var row = new Array();
|
||||
row.length = 4;
|
||||
row[0] = file.name;
|
||||
row[1] = file.size;
|
||||
row[2] = (file.progress*100).round(1);
|
||||
row[3] = file.priority;
|
||||
row[0] = file.priority;
|
||||
row[1] = file.name;
|
||||
row[2] = file.size;
|
||||
row[3] = (file.progress*100).round(1);
|
||||
row[4] = file.priority;
|
||||
fTable.insertRow(i, row);
|
||||
i++;
|
||||
}.bind(this));
|
||||
@@ -164,4 +220,4 @@ var createDownloadedCB = function(id, downloaded) {
|
||||
fTable.setup($('filesTable'));
|
||||
// Initial loading
|
||||
loadTorrentFilesData();
|
||||
</script>
|
||||
</script>
|
||||
|
@@ -22,6 +22,116 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
// Debug
|
||||
//alert(navigator.userAgent);
|
||||
|
||||
// From http://www.quirksmode.org/js/detect.html
|
||||
var BrowserDetect = {
|
||||
init: function () {
|
||||
this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
|
||||
//this.version = this.searchVersion(navigator.userAgent)
|
||||
// || this.searchVersion(navigator.appVersion)
|
||||
// || "an unknown version";
|
||||
//this.OS = this.searchString(this.dataOS) || "an unknown OS";
|
||||
},
|
||||
searchString: function (data) {
|
||||
for (var i=0;i<data.length;i++) {
|
||||
var dataString = data[i].string;
|
||||
var dataProp = data[i].prop;
|
||||
this.versionSearchString = data[i].versionSearch || data[i].identity;
|
||||
if (dataString) {
|
||||
if (dataString.indexOf(data[i].subString) != -1)
|
||||
return data[i].identity;
|
||||
}
|
||||
else if (dataProp)
|
||||
return data[i].identity;
|
||||
}
|
||||
},
|
||||
dataBrowser: [
|
||||
{
|
||||
string: navigator.userAgent,
|
||||
subString: "Chrome",
|
||||
identity: "Chrome"
|
||||
},
|
||||
{
|
||||
string: navigator.userAgent,
|
||||
subString: "Epiphany",
|
||||
identity: "Epiphany"
|
||||
},
|
||||
{
|
||||
string: navigator.userAgent,
|
||||
subString: "Arora",
|
||||
identity: "Arora"
|
||||
},
|
||||
{
|
||||
string: navigator.userAgent,
|
||||
subString: "midori",
|
||||
identity: "Midori"
|
||||
},
|
||||
{
|
||||
string: navigator.userAgent,
|
||||
subString: "OmniWeb",
|
||||
versionSearch: "OmniWeb/",
|
||||
identity: "OmniWeb"
|
||||
},
|
||||
{
|
||||
string: navigator.vendor,
|
||||
subString: "Apple",
|
||||
identity: "Safari",
|
||||
versionSearch: "Version"
|
||||
},
|
||||
{
|
||||
prop: window.opera,
|
||||
identity: "Opera"
|
||||
},
|
||||
{
|
||||
string: navigator.vendor,
|
||||
subString: "iCab",
|
||||
identity: "iCab"
|
||||
},
|
||||
{
|
||||
string: navigator.vendor,
|
||||
subString: "KDE",
|
||||
identity: "Konqueror"
|
||||
},
|
||||
{
|
||||
string: navigator.userAgent,
|
||||
subString: "Firefox",
|
||||
identity: "Firefox"
|
||||
},
|
||||
{
|
||||
string: navigator.vendor,
|
||||
subString: "Camino",
|
||||
identity: "Camino"
|
||||
},
|
||||
{ // for newer Netscapes (6+)
|
||||
string: navigator.userAgent,
|
||||
subString: "Netscape",
|
||||
identity: "Netscape"
|
||||
},
|
||||
{
|
||||
string: navigator.userAgent,
|
||||
subString: "MSIE",
|
||||
identity: "Explorer",
|
||||
versionSearch: "MSIE"
|
||||
},
|
||||
{
|
||||
string: navigator.userAgent,
|
||||
subString: "Gecko",
|
||||
identity: "Mozilla",
|
||||
versionSearch: "rv"
|
||||
},
|
||||
{ // for older Netscapes (4-)
|
||||
string: navigator.userAgent,
|
||||
subString: "Mozilla",
|
||||
identity: "Netscape",
|
||||
versionSearch: "Mozilla"
|
||||
}
|
||||
]
|
||||
|
||||
};
|
||||
BrowserDetect.init();
|
||||
|
||||
myTable = new dynamicTable();
|
||||
ajaxfn = function(){};
|
||||
setSortedColumn = function(index){
|
||||
@@ -206,8 +316,10 @@ window.addEvent('load', function(){
|
||||
}
|
||||
};
|
||||
ajaxfn();
|
||||
loadTransferInfo();
|
||||
// ajaxfn.periodical(5000);
|
||||
if(BrowserDetect.browser != "Safari") {
|
||||
// Safari has trouble with this
|
||||
loadTransferInfo();
|
||||
}
|
||||
|
||||
setFilter = function(f) {
|
||||
// Visually Select the right filter
|
||||
@@ -229,14 +341,6 @@ function closeWindows() {
|
||||
MochaUI.closeAll();
|
||||
}
|
||||
|
||||
// This runs when a person leaves your page.
|
||||
|
||||
//window.addEvent('unload', function(){
|
||||
// if (MochaUI && Browser.Engine.trident != true) {
|
||||
// MochaUI.garbageCleanUp();
|
||||
// }
|
||||
//});
|
||||
|
||||
window.addEvent('keydown', function(event){
|
||||
if (event.key == 'a' && event.control) {
|
||||
event.stop();
|
||||
|
@@ -358,7 +358,7 @@ var dynamicTable = new Class ({
|
||||
if(!tr.hasClass('selected')) {
|
||||
tr.addClass('selected');
|
||||
}
|
||||
});
|
||||
}, this);
|
||||
},
|
||||
|
||||
updateRow: function(id, row, status){
|
||||
|
Reference in New Issue
Block a user