mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2025-12-20 15:37:26 -06:00
Compare commits
17 Commits
release-1.
...
release-1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d02298c7d2 | ||
|
|
e5f9c5b746 | ||
|
|
96f9add49a | ||
|
|
2b9f0ae94f | ||
|
|
76c5c63b50 | ||
|
|
aed4c1f5a4 | ||
|
|
d4fe27e436 | ||
|
|
14567b85bd | ||
|
|
1a5cd45dfc | ||
|
|
a7850a4305 | ||
|
|
02c9b06c77 | ||
|
|
94a8c88bd9 | ||
|
|
7a7fca0d0c | ||
|
|
9dbc3a1540 | ||
|
|
407c384494 | ||
|
|
833f1d8c6a | ||
|
|
51dcd6c93c |
16
Changelog
16
Changelog
@@ -1,3 +1,19 @@
|
|||||||
|
* Tue Nov 17 2009 - Christophe Dumez <chris@qbittorrent.org> - v1.5.6
|
||||||
|
- BUGFIX: RSS feed articles can now be displayed using keyboard arrows
|
||||||
|
- BUGFIX: RSS feed downloader can only process unread articles now
|
||||||
|
- BUGFIX: Fixed memory leak in RSS parser
|
||||||
|
- BUGFIX: Fixed possible crash in search autocompletion
|
||||||
|
- BUGFIX: Improved ETA calculation for big torrents
|
||||||
|
- BUGFIX: Fixed per-torrent speed limiting
|
||||||
|
|
||||||
|
* Wed Nov 4 2009 - Christophe Dumez <chris@qbittorrent.org> - v1.5.5
|
||||||
|
- BUGFIX: Fixed man page
|
||||||
|
- BUGFIX: Fix crash on torrent addition (if libtorrent-rasterbar has debug enabled)
|
||||||
|
- BUGFIX: Fix trackers addition to torrents (bug introduced in v1.5.4)
|
||||||
|
- BUGFIX: Suppress compilation warning regarding sortNewsList() not being used
|
||||||
|
- BUGFIX: Make sure scan folder is different than qBittorrent backup directory to avoid torrents deletion
|
||||||
|
- BUGFIX: Added safety mecanism which adds the torrents back to the list in case qbittorrent-resume.conf gets deleted or corrupted.
|
||||||
|
|
||||||
* Sun Oct 25 2009 - Christophe Dumez <chris@qbittorrent.org> - v1.5.4
|
* Sun Oct 25 2009 - Christophe Dumez <chris@qbittorrent.org> - v1.5.4
|
||||||
- BUGFIX: Updated man page
|
- BUGFIX: Updated man page
|
||||||
- BUGFIX: Fixed possible crash with torrents containing unicode characters
|
- BUGFIX: Fixed possible crash with torrents containing unicode characters
|
||||||
|
|||||||
9
INSTALL
9
INSTALL
@@ -1,12 +1,6 @@
|
|||||||
qBittorrent - A BitTorrent client in C++ / Qt4
|
qBittorrent - A BitTorrent client in C++ / Qt4
|
||||||
------------------------------------------
|
------------------------------------------
|
||||||
|
|
||||||
*** Necessary if qt3 is default on your system ***
|
|
||||||
export QTDIR=/usr/include/qt4
|
|
||||||
export PATH=$QTDIR/bin:$PATH
|
|
||||||
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$QTDIR/lib
|
|
||||||
*** End ***
|
|
||||||
|
|
||||||
./configure
|
./configure
|
||||||
make && make install
|
make && make install
|
||||||
qbittorrent
|
qbittorrent
|
||||||
@@ -28,9 +22,6 @@ Dependencies:
|
|||||||
|
|
||||||
- python >= 2.3 (needed by search engine)
|
- python >= 2.3 (needed by search engine)
|
||||||
|
|
||||||
- libmagick++ (advised, not required)
|
|
||||||
* Needed for favicons support (RSS / Search plugins)
|
|
||||||
|
|
||||||
- libzzip (advised, not required)
|
- libzzip (advised, not required)
|
||||||
* Needed for zip support (Search plugins)
|
* Needed for zip support (Search plugins)
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ qBittorrent \- a Bittorrent client written in C++ / Qt4
|
|||||||
|
|
||||||
.SH "SYNOPSIS"
|
.SH "SYNOPSIS"
|
||||||
|
|
||||||
\fBqbittorrent\fR [--no-splash] [TORRENT_FILE | URL]...
|
\fBqbittorrent\fR [\-\-no-splash] [TORRENT_FILE | URL]...
|
||||||
|
|
||||||
\fBqbittorrent\fR \-\-help
|
\fBqbittorrent\fR \-\-help
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[Desktop Entry]
|
[Desktop Entry]
|
||||||
Categories=Qt;Network;P2P;
|
Categories=Qt;Network;P2P;
|
||||||
Comment=V1.5.4
|
Comment=V1.5.6
|
||||||
Exec=qbittorrent %f
|
Exec=qbittorrent %f
|
||||||
GenericName=Bittorrent client
|
GenericName=Bittorrent client
|
||||||
GenericName[bg]=Торент клиент
|
GenericName[bg]=Торент клиент
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 76 KiB |
@@ -114,6 +114,8 @@ bittorrent::~bittorrent() {
|
|||||||
delete FSWatcher;
|
delete FSWatcher;
|
||||||
delete FSMutex;
|
delete FSMutex;
|
||||||
}
|
}
|
||||||
|
if(timerETA)
|
||||||
|
delete timerETA;
|
||||||
// Delete BT session
|
// Delete BT session
|
||||||
qDebug("Deleting session");
|
qDebug("Deleting session");
|
||||||
delete s;
|
delete s;
|
||||||
@@ -215,21 +217,64 @@ int bittorrent::getUpTorrentPriority(QString hash) const {
|
|||||||
return h.queue_position();
|
return h.queue_position();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate the ETA using GASA
|
void bittorrent::takeETASamples() {
|
||||||
// GASA: global Average Speed Algorithm
|
bool change = false;;
|
||||||
qlonglong bittorrent::getETA(QString hash) const {
|
foreach(const QString &hash, ETA_samples.keys()) {
|
||||||
QTorrentHandle h = getTorrentHandle(hash);
|
QTorrentHandle h = getTorrentHandle(hash);
|
||||||
if(!h.is_valid()) return -1;
|
if(h.is_valid() && !h.is_paused() && !h.is_seed()) {
|
||||||
switch(h.state()) {
|
QList<int> samples = ETA_samples.value(h.hash(), QList<int>());
|
||||||
case torrent_status::downloading: {
|
if(samples.size() >= MAX_SAMPLES)
|
||||||
if(h.active_time() == 0)
|
samples.removeFirst();
|
||||||
return -1;
|
samples.append(h.download_payload_rate());
|
||||||
double avg_speed = (double)h.all_time_download() / h.active_time();
|
ETA_samples[h.hash()] = samples;
|
||||||
return (qlonglong) floor((double) (h.actual_size() - h.total_wanted_done()) / avg_speed);
|
change = true;
|
||||||
|
} else {
|
||||||
|
ETA_samples.remove(hash);
|
||||||
}
|
}
|
||||||
default:
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
if(!change && timerETA) {
|
||||||
|
delete timerETA;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This algorithm was inspired from KTorrent - http://www.ktorrent.org
|
||||||
|
// Calculate the ETA using a combination of several algorithms:
|
||||||
|
// GASA: Global Average Speed Algorithm
|
||||||
|
// CSA: Current Speed Algorithm
|
||||||
|
// WINX: Window of X Algorithm
|
||||||
|
qlonglong bittorrent::getETA(QString hash) {
|
||||||
|
QTorrentHandle h = getTorrentHandle(hash);
|
||||||
|
if(!h.is_valid() || h.state() != torrent_status::downloading || !h.active_time())
|
||||||
|
return -1;
|
||||||
|
// See if the torrent is going to be completed soon
|
||||||
|
qulonglong bytes_left = h.actual_size() - h.total_wanted_done();
|
||||||
|
if(h.actual_size() > 10485760L) { // Size > 10MiB
|
||||||
|
if(h.progress() >= (float)0.99 && bytes_left < 10485760L) { // Progress>99% but less than 10MB left.
|
||||||
|
// Compute by taking samples
|
||||||
|
if(!ETA_samples.contains(h.hash())) {
|
||||||
|
ETA_samples[h.hash()] = QList<int>();
|
||||||
|
}
|
||||||
|
if(!timerETA) {
|
||||||
|
timerETA = new QTimer(this);
|
||||||
|
connect(timerETA, SIGNAL(timeout()), this, SLOT(takeETASamples()));
|
||||||
|
timerETA->start();
|
||||||
|
} else {
|
||||||
|
QList<int> samples = ETA_samples.value(h.hash(), QList<int>());
|
||||||
|
int nb_samples = samples.size();
|
||||||
|
if(nb_samples > 3) {
|
||||||
|
long sum_samples = 0;
|
||||||
|
foreach(int val, samples) {
|
||||||
|
sum_samples += val;
|
||||||
|
}
|
||||||
|
// Use WINX
|
||||||
|
return (qlonglong)(((double)bytes_left) / (((double)sum_samples) / ((double)nb_samples)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Normal case: Use GASA
|
||||||
|
double avg_speed = (double)h.all_time_download() / h.active_time();
|
||||||
|
return (qlonglong) floor((double) (bytes_left) / avg_speed);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<torrent_handle> bittorrent::getTorrents() const {
|
std::vector<torrent_handle> bittorrent::getTorrents() const {
|
||||||
@@ -448,6 +493,10 @@ QTorrentHandle bittorrent::addMagnetUri(QString magnet_uri, bool resumed) {
|
|||||||
h.set_max_connections(maxConnecsPerTorrent);
|
h.set_max_connections(maxConnecsPerTorrent);
|
||||||
// Uploads limit per torrent
|
// Uploads limit per torrent
|
||||||
h.set_max_uploads(maxUploadsPerTorrent);
|
h.set_max_uploads(maxUploadsPerTorrent);
|
||||||
|
if(TorrentPersistentData::isKnownTorrent(h.hash())) {
|
||||||
|
h.set_download_limit(TorrentPersistentData::getDownloadLimit(h.hash()));
|
||||||
|
h.set_upload_limit(TorrentPersistentData::getUploadLimit(h.hash()));
|
||||||
|
}
|
||||||
// Load filtered files
|
// Load filtered files
|
||||||
if(resumed) {
|
if(resumed) {
|
||||||
// Load custom url seeds
|
// Load custom url seeds
|
||||||
@@ -612,6 +661,10 @@ QTorrentHandle bittorrent::addTorrent(QString path, bool fromScanDir, QString fr
|
|||||||
h.set_max_connections(maxConnecsPerTorrent);
|
h.set_max_connections(maxConnecsPerTorrent);
|
||||||
// Uploads limit per torrent
|
// Uploads limit per torrent
|
||||||
h.set_max_uploads(maxUploadsPerTorrent);
|
h.set_max_uploads(maxUploadsPerTorrent);
|
||||||
|
if(TorrentPersistentData::isKnownTorrent(h.hash())) {
|
||||||
|
h.set_download_limit(TorrentPersistentData::getDownloadLimit(h.hash()));
|
||||||
|
h.set_upload_limit(TorrentPersistentData::getUploadLimit(h.hash()));
|
||||||
|
}
|
||||||
// Load filtered files
|
// Load filtered files
|
||||||
loadFilesPriorities(h);
|
loadFilesPriorities(h);
|
||||||
if(resumed) {
|
if(resumed) {
|
||||||
@@ -856,7 +909,8 @@ void bittorrent::loadFilesPriorities(QTorrentHandle &h) {
|
|||||||
qDebug("Setting file piority to %d", priority);
|
qDebug("Setting file piority to %d", priority);
|
||||||
v.push_back(priority);
|
v.push_back(priority);
|
||||||
}
|
}
|
||||||
h.prioritize_files(v);
|
if(v.size() == (unsigned int)h.num_files())
|
||||||
|
h.prioritize_files(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
float bittorrent::getRealRatio(QString hash) const{
|
float bittorrent::getRealRatio(QString hash) const{
|
||||||
@@ -981,6 +1035,12 @@ void bittorrent::scanDirectory(QString scan_dir) {
|
|||||||
FSMutex->lock();
|
FSMutex->lock();
|
||||||
qDebug("Scanning directory: %s", scan_dir.toLocal8Bit().data());
|
qDebug("Scanning directory: %s", scan_dir.toLocal8Bit().data());
|
||||||
QDir dir(scan_dir);
|
QDir dir(scan_dir);
|
||||||
|
QDir torrentBackup(misc::qBittorrentPath() + "BT_backup");
|
||||||
|
// Check that scan dir is not BT_backup (silly but who knows...)
|
||||||
|
if(dir == torrentBackup) {
|
||||||
|
std::cerr << "Scan directory cannot be qBittorrent backup folder!" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
QStringList filters;
|
QStringList filters;
|
||||||
filters << "*.torrent";
|
filters << "*.torrent";
|
||||||
QStringList files = dir.entryList(filters, QDir::Files, QDir::Unsorted);
|
QStringList files = dir.entryList(filters, QDir::Files, QDir::Unsorted);
|
||||||
@@ -1520,14 +1580,31 @@ void bittorrent::applyEncryptionSettings(pe_settings se) {
|
|||||||
// backup directory
|
// backup directory
|
||||||
void bittorrent::startUpTorrents() {
|
void bittorrent::startUpTorrents() {
|
||||||
qDebug("Resuming unfinished torrents");
|
qDebug("Resuming unfinished torrents");
|
||||||
|
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
||||||
QDir torrentBackup(misc::qBittorrentPath() + "BT_backup");
|
QDir torrentBackup(misc::qBittorrentPath() + "BT_backup");
|
||||||
QStringList fileNames;
|
QStringList fileNames;
|
||||||
QStringList known_torrents = TorrentPersistentData::knownTorrents();
|
QStringList known_torrents = TorrentPersistentData::knownTorrents();
|
||||||
if(known_torrents.empty()) {
|
|
||||||
|
if(known_torrents.empty() && !settings.value("v1_4_x_torrent_imported", false).toBool()) {
|
||||||
qDebug("No known torrent, importing old torrents");
|
qDebug("No known torrent, importing old torrents");
|
||||||
importOldTorrents();
|
importOldTorrents();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Safety measure because some people reported torrent loss since
|
||||||
|
// we switch the v1.5 way of resuming torrents on startup
|
||||||
|
QStringList filters;
|
||||||
|
filters << "*.torrent";
|
||||||
|
QStringList torrents_on_hd = torrentBackup.entryList(filters, QDir::Files, QDir::Unsorted);
|
||||||
|
foreach(QString hash, torrents_on_hd) {
|
||||||
|
hash.chop(8); // remove trailing .torrent
|
||||||
|
if(!known_torrents.contains(hash)) {
|
||||||
|
std::cerr << "ERROR Detected!!! Adding back torrent " << hash.toLocal8Bit().data() << " which got lost for some reason." << std::endl;
|
||||||
|
addTorrent(torrentBackup.path()+QDir::separator()+hash+".torrent", false, QString(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// End of safety measure
|
||||||
|
|
||||||
qDebug("Starting up torrents");
|
qDebug("Starting up torrents");
|
||||||
if(isQueueingEnabled()) {
|
if(isQueueingEnabled()) {
|
||||||
QList<QPair<int, QString> > hashes;
|
QList<QPair<int, QString> > hashes;
|
||||||
@@ -1688,79 +1765,78 @@ void bittorrent::applyFormerAttributeFiles(QTorrentHandle h) {
|
|||||||
// TODO: Remove in qBittorrent v1.6.0
|
// TODO: Remove in qBittorrent v1.6.0
|
||||||
void bittorrent::importOldTorrents() {
|
void bittorrent::importOldTorrents() {
|
||||||
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
||||||
if(!settings.value("v1_4_x_torrent_imported", false).toBool()) {
|
Q_ASSERT(!settings.value("v1_4_x_torrent_imported", false).toBool());
|
||||||
// Import old torrent
|
// Import old torrent
|
||||||
QDir torrentBackup(misc::qBittorrentPath() + "BT_backup");
|
QDir torrentBackup(misc::qBittorrentPath() + "BT_backup");
|
||||||
QStringList fileNames;
|
QStringList fileNames;
|
||||||
QStringList filters;
|
QStringList filters;
|
||||||
filters << "*.torrent";
|
filters << "*.torrent";
|
||||||
fileNames = torrentBackup.entryList(filters, QDir::Files, QDir::Unsorted);
|
fileNames = torrentBackup.entryList(filters, QDir::Files, QDir::Unsorted);
|
||||||
if(isQueueingEnabled()) {
|
if(isQueueingEnabled()) {
|
||||||
QList<QPair<int, QString> > filePaths;
|
QList<QPair<int, QString> > filePaths;
|
||||||
foreach(const QString &fileName, fileNames) {
|
foreach(const QString &fileName, fileNames) {
|
||||||
QString filePath = torrentBackup.path()+QDir::separator()+fileName;
|
QString filePath = torrentBackup.path()+QDir::separator()+fileName;
|
||||||
int prio = 99999;
|
int prio = 99999;
|
||||||
// Get priority
|
// Get priority
|
||||||
QString prioPath = filePath;
|
QString prioPath = filePath;
|
||||||
prioPath.replace(".torrent", ".prio");
|
prioPath.replace(".torrent", ".prio");
|
||||||
if(QFile::exists(prioPath)) {
|
if(QFile::exists(prioPath)) {
|
||||||
QFile prio_file(prioPath);
|
QFile prio_file(prioPath);
|
||||||
if(prio_file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
if(prio_file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
prio = prio_file.readAll().toInt(&ok);
|
prio = prio_file.readAll().toInt(&ok);
|
||||||
if(!ok)
|
if(!ok)
|
||||||
prio = 99999;
|
prio = 99999;
|
||||||
prio_file.close();
|
prio_file.close();
|
||||||
}
|
|
||||||
}
|
|
||||||
misc::insertSort2<QString>(filePaths, qMakePair(prio, filePath));
|
|
||||||
}
|
|
||||||
// Resume downloads
|
|
||||||
QPair<int, QString> fileName;
|
|
||||||
foreach(fileName, filePaths) {
|
|
||||||
importOldTempData(fileName.second);
|
|
||||||
QTorrentHandle h = addTorrent(fileName.second, false, QString(), true);
|
|
||||||
// Sequential download
|
|
||||||
if(TorrentTempData::hasTempData(h.hash())) {
|
|
||||||
qDebug("addTorrent: Setting download as sequential (from tmp data)");
|
|
||||||
h.set_sequential_download(TorrentTempData::isSequential(h.hash()));
|
|
||||||
}
|
|
||||||
applyFormerAttributeFiles(h);
|
|
||||||
QString savePath = TorrentTempData::getSavePath(h.hash());
|
|
||||||
// Save persistent data for new torrent
|
|
||||||
TorrentPersistentData::saveTorrentPersistentData(h);
|
|
||||||
// Save save_path
|
|
||||||
if(!defaultTempPath.isEmpty() && !savePath.isNull()) {
|
|
||||||
qDebug("addTorrent: Saving save_path in persistent data: %s", savePath.toLocal8Bit().data());
|
|
||||||
TorrentPersistentData::saveSavePath(h.hash(), savePath);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
misc::insertSort2<QString>(filePaths, qMakePair(prio, filePath));
|
||||||
QStringList filePaths;
|
}
|
||||||
foreach(const QString &fileName, fileNames) {
|
// Resume downloads
|
||||||
filePaths.append(torrentBackup.path()+QDir::separator()+fileName);
|
QPair<int, QString> fileName;
|
||||||
|
foreach(fileName, filePaths) {
|
||||||
|
importOldTempData(fileName.second);
|
||||||
|
QTorrentHandle h = addTorrent(fileName.second, false, QString(), true);
|
||||||
|
// Sequential download
|
||||||
|
if(TorrentTempData::hasTempData(h.hash())) {
|
||||||
|
qDebug("addTorrent: Setting download as sequential (from tmp data)");
|
||||||
|
h.set_sequential_download(TorrentTempData::isSequential(h.hash()));
|
||||||
}
|
}
|
||||||
// Resume downloads
|
applyFormerAttributeFiles(h);
|
||||||
foreach(const QString &fileName, filePaths) {
|
QString savePath = TorrentTempData::getSavePath(h.hash());
|
||||||
importOldTempData(fileName);
|
// Save persistent data for new torrent
|
||||||
QTorrentHandle h = addTorrent(fileName, false, QString(), true);
|
TorrentPersistentData::saveTorrentPersistentData(h);
|
||||||
// Sequential download
|
// Save save_path
|
||||||
if(TorrentTempData::hasTempData(h.hash())) {
|
if(!defaultTempPath.isEmpty() && !savePath.isNull()) {
|
||||||
qDebug("addTorrent: Setting download as sequential (from tmp data)");
|
qDebug("addTorrent: Saving save_path in persistent data: %s", savePath.toLocal8Bit().data());
|
||||||
h.set_sequential_download(TorrentTempData::isSequential(h.hash()));
|
TorrentPersistentData::saveSavePath(h.hash(), savePath);
|
||||||
}
|
}
|
||||||
applyFormerAttributeFiles(h);
|
}
|
||||||
QString savePath = TorrentTempData::getSavePath(h.hash());
|
} else {
|
||||||
// Save persistent data for new torrent
|
QStringList filePaths;
|
||||||
TorrentPersistentData::saveTorrentPersistentData(h);
|
foreach(const QString &fileName, fileNames) {
|
||||||
// Save save_path
|
filePaths.append(torrentBackup.path()+QDir::separator()+fileName);
|
||||||
if(!defaultTempPath.isEmpty() && !savePath.isNull()) {
|
}
|
||||||
qDebug("addTorrent: Saving save_path in persistent data: %s", savePath.toLocal8Bit().data());
|
// Resume downloads
|
||||||
TorrentPersistentData::saveSavePath(h.hash(), savePath);
|
foreach(const QString &fileName, filePaths) {
|
||||||
}
|
importOldTempData(fileName);
|
||||||
|
QTorrentHandle h = addTorrent(fileName, false, QString(), true);
|
||||||
|
// Sequential download
|
||||||
|
if(TorrentTempData::hasTempData(h.hash())) {
|
||||||
|
qDebug("addTorrent: Setting download as sequential (from tmp data)");
|
||||||
|
h.set_sequential_download(TorrentTempData::isSequential(h.hash()));
|
||||||
|
}
|
||||||
|
applyFormerAttributeFiles(h);
|
||||||
|
QString savePath = TorrentTempData::getSavePath(h.hash());
|
||||||
|
// Save persistent data for new torrent
|
||||||
|
TorrentPersistentData::saveTorrentPersistentData(h);
|
||||||
|
// Save save_path
|
||||||
|
if(!defaultTempPath.isEmpty() && !savePath.isNull()) {
|
||||||
|
qDebug("addTorrent: Saving save_path in persistent data: %s", savePath.toLocal8Bit().data());
|
||||||
|
TorrentPersistentData::saveSavePath(h.hash(), savePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
settings.setValue("v1_4_x_torrent_imported", true);
|
|
||||||
std::cout << "Successfully imported torrents from v1.4.x (or previous) instance" << std::endl;
|
|
||||||
}
|
}
|
||||||
|
settings.setValue("v1_4_x_torrent_imported", true);
|
||||||
|
std::cout << "Successfully imported torrents from v1.4.x (or previous) instance" << std::endl;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,6 +42,8 @@
|
|||||||
|
|
||||||
using namespace libtorrent;
|
using namespace libtorrent;
|
||||||
|
|
||||||
|
#define MAX_SAMPLES 20
|
||||||
|
|
||||||
class downloadThread;
|
class downloadThread;
|
||||||
class QTimer;
|
class QTimer;
|
||||||
class QFileSystemWatcher;
|
class QFileSystemWatcher;
|
||||||
@@ -77,6 +79,8 @@ class bittorrent : public QObject {
|
|||||||
bool queueingEnabled;
|
bool queueingEnabled;
|
||||||
QStringList url_skippingDlg;
|
QStringList url_skippingDlg;
|
||||||
QHash<QString, QString> savepath_fromurl;
|
QHash<QString, QString> savepath_fromurl;
|
||||||
|
QPointer<QTimer> timerETA;
|
||||||
|
QHash<QString, QList<int> > ETA_samples;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QString getSavePath(QString hash);
|
QString getSavePath(QString hash);
|
||||||
@@ -107,7 +111,7 @@ class bittorrent : public QObject {
|
|||||||
int loadTorrentPriority(QString hash);
|
int loadTorrentPriority(QString hash);
|
||||||
QStringList getConsoleMessages() const;
|
QStringList getConsoleMessages() const;
|
||||||
QStringList getPeerBanMessages() const;
|
QStringList getPeerBanMessages() const;
|
||||||
qlonglong getETA(QString hash) const;
|
qlonglong getETA(QString hash);
|
||||||
bool useTemporaryFolder() const;
|
bool useTemporaryFolder() const;
|
||||||
QString getDefaultSavePath() const;
|
QString getDefaultSavePath() const;
|
||||||
|
|
||||||
@@ -177,6 +181,7 @@ class bittorrent : public QObject {
|
|||||||
void readAlerts();
|
void readAlerts();
|
||||||
void loadTrackerFile(QString hash);
|
void loadTrackerFile(QString hash);
|
||||||
void deleteBigRatios();
|
void deleteBigRatios();
|
||||||
|
void takeETASamples();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void addedTorrent(QTorrentHandle& h);
|
void addedTorrent(QTorrentHandle& h);
|
||||||
|
|||||||
@@ -605,10 +605,10 @@ bool DownloadingTorrents::updateTorrent(QTorrentHandle h) {
|
|||||||
}
|
}
|
||||||
if(!downloadList->isColumnHidden(SEEDSLEECH)) {
|
if(!downloadList->isColumnHidden(SEEDSLEECH)) {
|
||||||
QString tmp = misc::toQString(h.num_seeds(), true);
|
QString tmp = misc::toQString(h.num_seeds(), true);
|
||||||
if(h.num_complete() >= 0)
|
if(h.num_complete() >= h.num_seeds())
|
||||||
tmp.append(QString("(")+misc::toQString(h.num_complete())+QString(")"));
|
tmp.append(QString("(")+misc::toQString(h.num_complete())+QString(")"));
|
||||||
tmp.append(QString("/")+misc::toQString(h.num_peers() - h.num_seeds(), true));
|
tmp.append(QString("/")+misc::toQString(h.num_peers() - h.num_seeds(), true));
|
||||||
if(h.num_incomplete() >= 0)
|
if(h.num_incomplete() >= (h.num_peers()-h.num_seeds()))
|
||||||
tmp.append(QString("(")+misc::toQString(h.num_incomplete())+QString(")"));
|
tmp.append(QString("(")+misc::toQString(h.num_incomplete())+QString(")"));
|
||||||
DLListModel->setData(DLListModel->index(row, SEEDSLEECH), QVariant(tmp));
|
DLListModel->setData(DLListModel->index(row, SEEDSLEECH), QVariant(tmp));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -163,11 +163,6 @@ QString QTorrentHandle::save_path() const {
|
|||||||
return misc::toQString(h.save_path().string());
|
return misc::toQString(h.save_path().string());
|
||||||
}
|
}
|
||||||
|
|
||||||
fs::path QTorrentHandle::save_path_boost() const {
|
|
||||||
Q_ASSERT(h.is_valid());
|
|
||||||
return h.save_path();
|
|
||||||
}
|
|
||||||
|
|
||||||
QStringList QTorrentHandle::url_seeds() const {
|
QStringList QTorrentHandle::url_seeds() const {
|
||||||
Q_ASSERT(h.is_valid());
|
Q_ASSERT(h.is_valid());
|
||||||
QStringList res;
|
QStringList res;
|
||||||
@@ -234,9 +229,9 @@ size_type QTorrentHandle::filesize_at(unsigned int index) const {
|
|||||||
return h.get_torrent_info().file_at(index).size;
|
return h.get_torrent_info().file_at(index).size;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<announce_entry> const& QTorrentHandle::trackers() const {
|
std::vector<announce_entry> QTorrentHandle::trackers() const {
|
||||||
Q_ASSERT(h.is_valid());
|
Q_ASSERT(h.is_valid());
|
||||||
return h.get_torrent_info().trackers();
|
return h.trackers();
|
||||||
}
|
}
|
||||||
|
|
||||||
torrent_status::state_t QTorrentHandle::state() const {
|
torrent_status::state_t QTorrentHandle::state() const {
|
||||||
|
|||||||
@@ -81,7 +81,6 @@ class QTorrentHandle {
|
|||||||
int num_incomplete() const;
|
int num_incomplete() const;
|
||||||
void scrape_tracker() const;
|
void scrape_tracker() const;
|
||||||
QString save_path() const;
|
QString save_path() const;
|
||||||
fs::path save_path_boost() const;
|
|
||||||
QStringList url_seeds() const;
|
QStringList url_seeds() const;
|
||||||
size_type actual_size() const;
|
size_type actual_size() const;
|
||||||
int download_limit() const;
|
int download_limit() const;
|
||||||
@@ -93,7 +92,7 @@ class QTorrentHandle {
|
|||||||
bool is_queued() const;
|
bool is_queued() const;
|
||||||
QString file_at(unsigned int index) const;
|
QString file_at(unsigned int index) const;
|
||||||
size_type filesize_at(unsigned int index) const;
|
size_type filesize_at(unsigned int index) const;
|
||||||
std::vector<announce_entry> const& trackers() const;
|
std::vector<announce_entry> trackers() const;
|
||||||
torrent_status::state_t state() const;
|
torrent_status::state_t state() const;
|
||||||
QString creator() const;
|
QString creator() const;
|
||||||
QString comment() const;
|
QString comment() const;
|
||||||
|
|||||||
47
src/rss.cpp
47
src/rss.cpp
@@ -561,29 +561,38 @@ short RssStream::readDoc(const QDomDocument& doc) {
|
|||||||
image = property.text();
|
image = property.text();
|
||||||
else if(property.tagName() == "item") {
|
else if(property.tagName() == "item") {
|
||||||
RssItem * item = new RssItem(this, property);
|
RssItem * item = new RssItem(this, property);
|
||||||
if(item->isValid() && !itemAlreadyExists(item->getTitle())) {
|
if(item->isValid()) {
|
||||||
(*this)[item->getTitle()] = item;
|
QString title = item->getTitle();
|
||||||
|
bool already_exists = itemAlreadyExists(title);
|
||||||
|
if(!already_exists) {
|
||||||
|
(*this)[title] = item;
|
||||||
|
} else {
|
||||||
|
delete item;
|
||||||
|
item = this->value(title);
|
||||||
|
}
|
||||||
if(item->has_attachment()) {
|
if(item->has_attachment()) {
|
||||||
has_attachments = true;
|
has_attachments = true;
|
||||||
// Check if the item should be automatically downloaded
|
// Check if the item should be automatically downloaded
|
||||||
FeedFilter * matching_filter = FeedFilters::getFeedFilters(url).matches(item->getTitle());
|
if(!already_exists || !(*this)[item->getTitle()]->isRead()) {
|
||||||
if(matching_filter != 0) {
|
FeedFilter * matching_filter = FeedFilters::getFeedFilters(url).matches(item->getTitle());
|
||||||
// Download the torrent
|
if(matching_filter != 0) {
|
||||||
BTSession->addConsoleMessage(tr("Automatically downloading %1 torrent from %2 RSS feed...").arg(item->getTitle()).arg(getName()));
|
// Download the torrent
|
||||||
if(matching_filter->isValid()) {
|
BTSession->addConsoleMessage(tr("Automatically downloading %1 torrent from %2 RSS feed...").arg(item->getTitle()).arg(getName()));
|
||||||
QString save_path = matching_filter->getSavePath();
|
if(matching_filter->isValid()) {
|
||||||
if(save_path.isEmpty())
|
QString save_path = matching_filter->getSavePath();
|
||||||
|
if(save_path.isEmpty())
|
||||||
|
BTSession->downloadUrlAndSkipDialog(item->getTorrentUrl());
|
||||||
|
else
|
||||||
|
BTSession->downloadUrlAndSkipDialog(item->getTorrentUrl(), save_path);
|
||||||
|
} else {
|
||||||
|
// All torrents are downloaded from this feed
|
||||||
BTSession->downloadUrlAndSkipDialog(item->getTorrentUrl());
|
BTSession->downloadUrlAndSkipDialog(item->getTorrentUrl());
|
||||||
else
|
}
|
||||||
BTSession->downloadUrlAndSkipDialog(item->getTorrentUrl(), save_path);
|
// Item was downloaded, consider it as Read
|
||||||
} else {
|
(*this)[item->getTitle()]->setRead();
|
||||||
// All torrents are downloaded from this feed
|
// Clean up
|
||||||
BTSession->downloadUrlAndSkipDialog(item->getTorrentUrl());
|
delete matching_filter;
|
||||||
}
|
}
|
||||||
// Item was downloaded, consider it as Read
|
|
||||||
item->setRead();
|
|
||||||
// Clean up
|
|
||||||
delete matching_filter;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -604,7 +613,7 @@ void RssStream::resizeList() {
|
|||||||
unsigned int max_articles = settings.value(QString::fromUtf8("Preferences/RSS/RSSMaxArticlesPerFeed"), 100).toInt();
|
unsigned int max_articles = settings.value(QString::fromUtf8("Preferences/RSS/RSSMaxArticlesPerFeed"), 100).toInt();
|
||||||
unsigned int nb_articles = this->size();
|
unsigned int nb_articles = this->size();
|
||||||
if(nb_articles > max_articles) {
|
if(nb_articles > max_articles) {
|
||||||
QList<RssItem*> listItem = sortNewsList(this->values());
|
QList<RssItem*> listItem = RssManager::sortNewsList(this->values());
|
||||||
int excess = nb_articles - max_articles;
|
int excess = nb_articles - max_articles;
|
||||||
for(int i=0; i<excess; ++i){
|
for(int i=0; i<excess; ++i){
|
||||||
RssItem *lastItem = listItem.takeLast();
|
RssItem *lastItem = listItem.takeLast();
|
||||||
|
|||||||
30
src/rss.h
30
src/rss.h
@@ -492,23 +492,25 @@ public slots:
|
|||||||
public:
|
public:
|
||||||
RssManager(bittorrent *BTSession);
|
RssManager(bittorrent *BTSession);
|
||||||
~RssManager();
|
~RssManager();
|
||||||
|
static void insertSortElem(QList<RssItem*> &list, RssItem *item) {
|
||||||
|
int i = 0;
|
||||||
|
while(i < list.size() && item->getDate() < list.at(i)->getDate()) {
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
list.insert(i, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
static QList<RssItem*> sortNewsList(QList<RssItem*> news_list) {
|
||||||
|
QList<RssItem*> new_list;
|
||||||
|
foreach(RssItem *item, news_list) {
|
||||||
|
insertSortElem(new_list, item);
|
||||||
|
}
|
||||||
|
return new_list;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static void insertSortElem(QList<RssItem*> &list, RssItem *item) {
|
|
||||||
int i = 0;
|
|
||||||
while(i < list.size() && item->getDate() < list.at(i)->getDate()) {
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
list.insert(i, item);
|
|
||||||
}
|
|
||||||
|
|
||||||
static QList<RssItem*> sortNewsList(QList<RssItem*> news_list) {
|
|
||||||
QList<RssItem*> new_list;
|
|
||||||
foreach(RssItem *item, news_list) {
|
|
||||||
insertSortElem(new_list, item);
|
|
||||||
}
|
|
||||||
return new_list;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -431,9 +431,9 @@ void RSSImp::refreshNewsList(QTreeWidgetItem* item) {
|
|||||||
qDebug("Getting the list of news");
|
qDebug("Getting the list of news");
|
||||||
QList<RssItem*> news;
|
QList<RssItem*> news;
|
||||||
if(rss_item == rssmanager)
|
if(rss_item == rssmanager)
|
||||||
news = sortNewsList(rss_item->getUnreadNewsList());
|
news = RssManager::sortNewsList(rss_item->getUnreadNewsList());
|
||||||
else
|
else
|
||||||
news = sortNewsList(rss_item->getNewsList());
|
news = RssManager::sortNewsList(rss_item->getNewsList());
|
||||||
// Clear the list first
|
// Clear the list first
|
||||||
textBrowser->clear();
|
textBrowser->clear();
|
||||||
previous_news = 0;
|
previous_news = 0;
|
||||||
@@ -460,8 +460,11 @@ void RSSImp::refreshNewsList(QTreeWidgetItem* item) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// display a news
|
// display a news
|
||||||
void RSSImp::refreshTextBrowser(QTreeWidgetItem *item) {
|
void RSSImp::refreshTextBrowser() {
|
||||||
if(!item || item == previous_news) return;
|
QList<QTreeWidgetItem*> selection = listNews->selectedItems();
|
||||||
|
if(selection.empty()) return;
|
||||||
|
QTreeWidgetItem *item = selection.first();
|
||||||
|
if(item == previous_news) return;
|
||||||
// Stop displaying previous news if necessary
|
// Stop displaying previous news if necessary
|
||||||
if(listStreams->currentFeed() == listStreams->getUnreadItem()) {
|
if(listStreams->currentFeed() == listStreams->getUnreadItem()) {
|
||||||
if(previous_news) {
|
if(previous_news) {
|
||||||
@@ -596,7 +599,7 @@ RSSImp::RSSImp(bittorrent *BTSession) : QWidget(), BTSession(BTSession){
|
|||||||
connect(listStreams, SIGNAL(foldersAltered(QList<QTreeWidgetItem*>)), this, SLOT(updateItemsInfos(QList<QTreeWidgetItem*>)));
|
connect(listStreams, SIGNAL(foldersAltered(QList<QTreeWidgetItem*>)), this, SLOT(updateItemsInfos(QList<QTreeWidgetItem*>)));
|
||||||
connect(listStreams, SIGNAL(overwriteAttempt(QString)), this, SLOT(displayOverwriteError(QString)));
|
connect(listStreams, SIGNAL(overwriteAttempt(QString)), this, SLOT(displayOverwriteError(QString)));
|
||||||
|
|
||||||
connect(listNews, SIGNAL(itemClicked(QTreeWidgetItem*, int)), this, SLOT(refreshTextBrowser(QTreeWidgetItem *)));
|
connect(listNews, SIGNAL(itemSelectionChanged()), this, SLOT(refreshTextBrowser()));
|
||||||
connect(listNews, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, SLOT(downloadTorrent()));
|
connect(listNews, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, SLOT(downloadTorrent()));
|
||||||
|
|
||||||
// Refresh all feeds
|
// Refresh all feeds
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ protected slots:
|
|||||||
void refreshSelectedItems();
|
void refreshSelectedItems();
|
||||||
void copySelectedFeedsURL();
|
void copySelectedFeedsURL();
|
||||||
void refreshNewsList(QTreeWidgetItem* item);
|
void refreshNewsList(QTreeWidgetItem* item);
|
||||||
void refreshTextBrowser(QTreeWidgetItem *);
|
void refreshTextBrowser();
|
||||||
void updateFeedIcon(QString url, QString icon_path);
|
void updateFeedIcon(QString url, QString icon_path);
|
||||||
void updateFeedInfos(QString url, QString aliasOrUrl, unsigned int nbUnread);
|
void updateFeedInfos(QString url, QString aliasOrUrl, unsigned int nbUnread);
|
||||||
void updateItemsInfos(QList<QTreeWidgetItem*> items);
|
void updateItemsInfos(QList<QTreeWidgetItem*> items);
|
||||||
|
|||||||
@@ -57,7 +57,6 @@ SearchEngine::SearchEngine(bittorrent *BTSession, QSystemTrayIcon *myTrayIcon, b
|
|||||||
setupUi(this);
|
setupUi(this);
|
||||||
// new qCompleter to the search pattern
|
// new qCompleter to the search pattern
|
||||||
startSearchHistory();
|
startSearchHistory();
|
||||||
searchCompleter = 0;
|
|
||||||
createCompleter();
|
createCompleter();
|
||||||
// Add close tab button
|
// Add close tab button
|
||||||
closeTab_button = new QPushButton();
|
closeTab_button = new QPushButton();
|
||||||
@@ -142,8 +141,7 @@ void SearchEngine::displayPatternContextMenu(QPoint) {
|
|||||||
QAction *act = myMenu.exec(QCursor::pos());
|
QAction *act = myMenu.exec(QCursor::pos());
|
||||||
if(act != 0) {
|
if(act != 0) {
|
||||||
if(act == &clearHistoryAct) {
|
if(act == &clearHistoryAct) {
|
||||||
searchHistory.clear();
|
searchHistory.setStringList(QStringList());
|
||||||
createCompleter();
|
|
||||||
} else if (act == &pasteAct) {
|
} else if (act == &pasteAct) {
|
||||||
} else if (act == &pasteAct) {
|
} else if (act == &pasteAct) {
|
||||||
search_pattern->paste();
|
search_pattern->paste();
|
||||||
@@ -181,18 +179,13 @@ void SearchEngine::on_enginesButton_clicked() {
|
|||||||
// get the last searchs from a QSettings to a QStringList
|
// get the last searchs from a QSettings to a QStringList
|
||||||
void SearchEngine::startSearchHistory(){
|
void SearchEngine::startSearchHistory(){
|
||||||
QSettings settings("qBittorrent", "qBittorrent");
|
QSettings settings("qBittorrent", "qBittorrent");
|
||||||
settings.beginGroup("Search");
|
searchHistory.setStringList(settings.value("Search/searchHistory",QStringList()).toStringList());
|
||||||
searchHistory = settings.value("searchHistory",-1).toStringList();
|
|
||||||
settings.endGroup();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save the history list into the QSettings for the next session
|
// Save the history list into the QSettings for the next session
|
||||||
void SearchEngine::saveSearchHistory()
|
void SearchEngine::saveSearchHistory() {
|
||||||
{
|
|
||||||
QSettings settings("qBittorrent", "qBittorrent");
|
QSettings settings("qBittorrent", "qBittorrent");
|
||||||
settings.beginGroup("Search");
|
settings.setValue("Search/searchHistory",searchHistory.stringList());
|
||||||
settings.setValue("searchHistory",searchHistory);
|
|
||||||
settings.endGroup();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function called when we click on search button
|
// Function called when we click on search button
|
||||||
@@ -220,13 +213,14 @@ void SearchEngine::on_search_button_clicked(){
|
|||||||
tabWidget->setCurrentWidget(currentSearchTab);
|
tabWidget->setCurrentWidget(currentSearchTab);
|
||||||
closeTab_button->setEnabled(true);
|
closeTab_button->setEnabled(true);
|
||||||
// if the pattern is not in the pattern
|
// if the pattern is not in the pattern
|
||||||
if(searchHistory.indexOf(pattern) == -1){
|
QStringList wordList = searchHistory.stringList();
|
||||||
|
if(wordList.indexOf(pattern) == -1){
|
||||||
//update the searchHistory list
|
//update the searchHistory list
|
||||||
searchHistory.append(pattern);
|
wordList.append(pattern);
|
||||||
// verify the max size of the history
|
// verify the max size of the history
|
||||||
if(searchHistory.size() > SEARCHHISTORY_MAXSIZE)
|
if(wordList.size() > SEARCHHISTORY_MAXSIZE)
|
||||||
searchHistory = searchHistory.mid(searchHistory.size()/2,searchHistory.size()/2);
|
wordList = wordList.mid(wordList.size()/2);
|
||||||
createCompleter();
|
searchHistory.setStringList(wordList);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Getting checked search engines
|
// Getting checked search engines
|
||||||
@@ -252,7 +246,7 @@ void SearchEngine::on_search_button_clicked(){
|
|||||||
void SearchEngine::createCompleter() {
|
void SearchEngine::createCompleter() {
|
||||||
if(searchCompleter)
|
if(searchCompleter)
|
||||||
delete searchCompleter;
|
delete searchCompleter;
|
||||||
searchCompleter = new QCompleter(searchHistory, this);
|
searchCompleter = new QCompleter(&searchHistory);
|
||||||
searchCompleter->setCaseSensitivity(Qt::CaseInsensitive);
|
searchCompleter->setCaseSensitivity(Qt::CaseInsensitive);
|
||||||
search_pattern->setCompleter(searchCompleter);
|
search_pattern->setCompleter(searchCompleter);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QPair>
|
#include <QPair>
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
|
#include <QStringListModel>
|
||||||
#include "ui_search.h"
|
#include "ui_search.h"
|
||||||
#include "engineSelectDlg.h"
|
#include "engineSelectDlg.h"
|
||||||
#include "SearchTab.h"
|
#include "SearchTab.h"
|
||||||
@@ -60,7 +61,7 @@ private:
|
|||||||
QByteArray search_result_line_truncated;
|
QByteArray search_result_line_truncated;
|
||||||
unsigned long nb_search_results;
|
unsigned long nb_search_results;
|
||||||
QPointer<QCompleter> searchCompleter;
|
QPointer<QCompleter> searchCompleter;
|
||||||
QStringList searchHistory;
|
QStringListModel searchHistory;
|
||||||
bittorrent *BTSession;
|
bittorrent *BTSession;
|
||||||
QSystemTrayIcon *myTrayIcon;
|
QSystemTrayIcon *myTrayIcon;
|
||||||
bool systrayIntegration;
|
bool systrayIntegration;
|
||||||
|
|||||||
@@ -14,10 +14,10 @@ CONFIG += qt \
|
|||||||
network
|
network
|
||||||
|
|
||||||
# Update this VERSION for each release
|
# Update this VERSION for each release
|
||||||
DEFINES += VERSION=\\\"v1.5.4\\\"
|
DEFINES += VERSION=\\\"v1.5.6\\\"
|
||||||
DEFINES += VERSION_MAJOR=1
|
DEFINES += VERSION_MAJOR=1
|
||||||
DEFINES += VERSION_MINOR=5
|
DEFINES += VERSION_MINOR=5
|
||||||
DEFINES += VERSION_BUGFIX=4
|
DEFINES += VERSION_BUGFIX=6
|
||||||
!mac:QMAKE_LFLAGS += -Wl,--as-needed
|
!mac:QMAKE_LFLAGS += -Wl,--as-needed
|
||||||
contains(DEBUG_MODE, 1) {
|
contains(DEBUG_MODE, 1) {
|
||||||
CONFIG += debug
|
CONFIG += debug
|
||||||
|
|||||||
Reference in New Issue
Block a user