- 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: RSS Feeds can now be copied to the clipboard
This commit is contained in:
Christophe Dumez 2009-08-21 07:40:57 +00:00
parent 2477dc1fc0
commit 0b9c05d41b
79 changed files with 8294 additions and 5496 deletions

View file

@ -1,7 +1,12 @@
* Unknown - Christophe Dumez <chris@qbittorrent.org> - v1.5.0
- FEATURE: Added Magnet URI support
- 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: If a torrent contains a torrent file, process downloaded torrent file too [TODO]
- BUGFIX: torrent resume code rewrited
* Thu Aug 13 2009 - Christophe Dumez <chris@qbittorrent.org> - v1.4.0

View file

@ -23,7 +23,7 @@ public:
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());
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());
return true;
}
};

331
src/FeedDownloader.h Normal file
View file

@ -0,0 +1,331 @@
/*
* 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 "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 tokens = getMatchingTokens();
foreach(const QString& token, tokens) {
QRegExp reg(token, Qt::CaseInsensitive);
if(reg.indexIn(s) < 0) 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 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(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());
// Fill filter list
foreach(QString filter_name, filters.names()) {
new QListWidgetItem(filter_name, filtersList);
}
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 showFilterSettings(QListWidgetItem *item) {
// First, save current filter settings
saveCurrentFilterSettings();
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());
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) {
filters.remove(selected_filter);
selected_filter = QString::null;
QListWidgetItem * item = items.first();
delete item;
// Reset Filter settings view
if(filters.size() == 0) {
clearFields();
filterSettingsBox->setEnabled(false);
}
}
}
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::critical(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(filters.hasFilter(filter_name)) {
// Filter alread exists
QMessageBox::critical(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();
}
};
#endif // FEEDDOWNLOADER_H

377
src/FeedDownloader.ui Normal file
View file

@ -0,0 +1,377 @@
<?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>392</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"/>
</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_6">
<item>
<layout class="QVBoxLayout" name="verticalLayout_5">
<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>
</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>
</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>
</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>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</item>
</layout>
</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>
</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

@ -315,7 +315,7 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
if(enable) {
// RSS tab
if(rssWidget == 0) {
rssWidget = new RSSImp();
rssWidget = new RSSImp(BTSession);
tabs->addTab(rssWidget, tr("RSS"));
tabs->setTabIcon(3, QIcon(QString::fromUtf8(":/Icons/rss32.png")));
}
@ -450,8 +450,8 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
}
void GUI::setPaused(QTorrentHandle &h) const {
Q_ASSERT(h.is_paused());
qDebug("Marking torrent %s as paused", h.hash().toUtf8().data());
if(!h.is_paused()) return;
qDebug("Marking torrent %s as paused", h.hash().toLocal8Bit().data());
if(h.is_seed()) {
// In finished list
qDebug("Automatically paused torrent was in finished list");

Binary file not shown.

After

Width:  |  Height:  |  Size: 907 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 498 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 739 B

After

Width:  |  Height:  |  Size: 752 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 842 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 629 B

After

Width:  |  Height:  |  Size: 722 B

Before After
Before After

View file

@ -179,6 +179,12 @@ void bittorrent::setUploadLimit(QString hash, long val) {
void bittorrent::handleDownloadFailure(QString url, QString reason) {
emit downloadFromUrlFailure(url, reason);
// Clean up
int index = url_skippingDlg.indexOf(url);
if(index >= 0)
url_skippingDlg.removeAt(index);
if(savepath_fromurl.contains(url))
savepath_fromurl.remove(url);
}
void bittorrent::startTorrentsInPause(bool b) {
@ -368,7 +374,7 @@ QTorrentHandle bittorrent::addMagnetUri(QString magnet_uri, bool resumed) {
return h;
}
if(resumed) {
qDebug("Resuming magnet URI: %s", hash.toUtf8().data());
qDebug("Resuming magnet URI: %s", hash.toLocal8Bit().data());
} else {
qDebug("Adding new magnet URI");
}
@ -386,7 +392,7 @@ QTorrentHandle bittorrent::addMagnetUri(QString magnet_uri, bool resumed) {
}
// Check if torrent is already in download list
if(s->find_torrent(sha1_hash(hash.toUtf8().data())).is_valid()) {
if(s->find_torrent(sha1_hash(hash.toLocal8Bit().data())).is_valid()) {
qDebug("/!\\ Torrent is already in download list");
// Update info Bar
addConsoleMessage(tr("'%1' is already in download list.", "e.g: 'xxx.avi' is already in download list.").arg(magnet_uri));
@ -405,7 +411,7 @@ QTorrentHandle bittorrent::addMagnetUri(QString magnet_uri, bool resumed) {
}
}
QString savePath = getSavePath(hash);
qDebug("addMagnetURI: using save_path: %s", savePath.toUtf8().data());
qDebug("addMagnetURI: using save_path: %s", savePath.toLocal8Bit().data());
if(defaultTempPath.isEmpty() || (resumed && TorrentPersistentData::isSeed(hash))) {
p.save_path = savePath.toLocal8Bit().data();
} else {
@ -455,12 +461,12 @@ QTorrentHandle bittorrent::addMagnetUri(QString magnet_uri, bool resumed) {
}
// Save persistent data for new torrent
Q_ASSERT(h.is_valid());
qDebug("addMagnetUri: hash: %s", h.hash().toUtf8().data());
qDebug("addMagnetUri: hash: %s", h.hash().toLocal8Bit().data());
TorrentPersistentData::saveTorrentPersistentData(h, true);
qDebug("Persistent data saved");
// Save save_path
if(!defaultTempPath.isEmpty()) {
qDebug("addMagnetUri: Saving save_path in persistent data: %s", savePath.toUtf8().data());
qDebug("addMagnetUri: Saving save_path in persistent data: %s", savePath.toLocal8Bit().data());
TorrentPersistentData::saveSavePath(hash, savePath);
}
}
@ -555,8 +561,14 @@ QTorrentHandle bittorrent::addTorrent(QString path, bool fromScanDir, QString fr
qDebug("Successfuly loaded");
}
}
QString savePath = getSavePath(hash);
qDebug("addTorrent: using save_path: %s", savePath.toUtf8().data());
QString savePath;
if(!from_url.isEmpty() && savepath_fromurl.contains(from_url)) {
// Enforcing the save path defined before URL download (from RSS for example)
savePath = savepath_fromurl.take(from_url);
} else {
savePath = getSavePath(hash);
}
qDebug("addTorrent: using save_path: %s", savePath.toLocal8Bit().data());
if(defaultTempPath.isEmpty() || (resumed && TorrentPersistentData::isSeed(hash))) {
p.save_path = savePath.toLocal8Bit().data();
} else {
@ -609,7 +621,7 @@ QTorrentHandle bittorrent::addTorrent(QString path, bool fromScanDir, QString fr
TorrentPersistentData::saveTorrentPersistentData(h);
// Save save_path
if(!defaultTempPath.isEmpty()) {
qDebug("addTorrent: Saving save_path in persistent data: %s", savePath.toUtf8().data());
qDebug("addTorrent: Saving save_path in persistent data: %s", savePath.toLocal8Bit().data());
TorrentPersistentData::saveSavePath(hash, savePath);
}
}
@ -1002,6 +1014,10 @@ void bittorrent::setDefaultSavePath(QString savepath) {
defaultSavePath = savepath;
}
QString bittorrent::getDefaultSavePath() const {
return defaultSavePath;
}
bool bittorrent::useTemporaryFolder() const {
return !defaultTempPath.isEmpty();
}
@ -1256,7 +1272,7 @@ void bittorrent::readAlerts() {
else if (metadata_received_alert* p = dynamic_cast<metadata_received_alert*>(a.get())) {
QTorrentHandle h(p->handle);
if(h.is_valid()) {
qDebug("Received metadata for %s", h.hash().toUtf8().data());
qDebug("Received metadata for %s", h.hash().toLocal8Bit().data());
emit metadataReceived(h);
if(h.is_paused()) {
// XXX: Unfortunately libtorrent-rasterbar does not send a torrent_paused_alert
@ -1279,7 +1295,7 @@ void bittorrent::readAlerts() {
}
else if (torrent_paused_alert* p = dynamic_cast<torrent_paused_alert*>(a.get())) {
QTorrentHandle h(p->handle);
qDebug("Received a torrent_paused_alert for %s", h.hash().toUtf8().data());
qDebug("Received a torrent_paused_alert for %s", h.hash().toLocal8Bit().data());
if(h.is_valid()) {
emit torrentPaused(h);
}
@ -1379,14 +1395,14 @@ QString bittorrent::getSavePath(QString hash) {
QString savePath;
if(TorrentTempData::hasTempData(hash)) {
savePath = TorrentTempData::getSavePath(hash);
qDebug("getSavePath, got save_path from temp data: %s", savePath.toUtf8().data());
qDebug("getSavePath, got save_path from temp data: %s", savePath.toLocal8Bit().data());
} else {
savePath = TorrentPersistentData::getSavePath(hash);
qDebug("getSavePath, got save_path from persistent data: %s", savePath.toUtf8().data());
qDebug("getSavePath, got save_path from persistent data: %s", savePath.toLocal8Bit().data());
}
if(savePath.isEmpty()) {
// use default save path if no other can be found
qDebug("Using default save path because none was set: %s", defaultSavePath.toUtf8().data());
qDebug("Using default save path because none was set: %s", defaultSavePath.toLocal8Bit().data());
savePath = defaultSavePath;
}
// Checking if savePath Dir exists
@ -1412,8 +1428,10 @@ void bittorrent::downloadFromUrl(QString url) {
downloader->downloadUrl(url);
}
void bittorrent::downloadUrlAndSkipDialog(QString url) {
void bittorrent::downloadUrlAndSkipDialog(QString url, QString save_path) {
//emit aboutToDownloadFromUrl(url);
if(!save_path.isEmpty())
savepath_fromurl[url] = save_path;
url_skippingDlg << url;
// Launch downloader thread
downloader->downloadUrl(url);
@ -1491,7 +1509,7 @@ void bittorrent::startUpTorrents() {
QPair<int, QString> couple;
foreach(couple, hashes) {
QString hash = couple.second;
qDebug("Starting up torrent %s", hash.toUtf8().data());
qDebug("Starting up torrent %s", hash.toLocal8Bit().data());
if(TorrentPersistentData::isMagnet(hash)) {
addMagnetUri(TorrentPersistentData::getMagnetUri(hash), true);
} else {
@ -1501,7 +1519,7 @@ void bittorrent::startUpTorrents() {
} else {
// Resume downloads
foreach(const QString &hash, known_torrents) {
qDebug("Starting up torrent %s", hash.toUtf8().data());
qDebug("Starting up torrent %s", hash.toLocal8Bit().data());
if(TorrentPersistentData::isMagnet(hash))
addMagnetUri(TorrentPersistentData::getMagnetUri(hash), true);
else

View file

@ -76,6 +76,7 @@ class bittorrent : public QObject {
QString filterPath;
bool queueingEnabled;
QStringList url_skippingDlg;
QHash<QString, QString> savepath_fromurl;
protected:
QString getSavePath(QString hash);
@ -108,6 +109,7 @@ class bittorrent : public QObject {
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);
@ -137,7 +139,7 @@ class bittorrent : public QObject {
void loadWebSeeds(QString fileHash);
void increaseDlTorrentPriority(QString hash);
void decreaseDlTorrentPriority(QString hash);
void downloadUrlAndSkipDialog(QString);
void downloadUrlAndSkipDialog(QString url, QString save_path=QString::null);
// Session configuration - Setters
void setListeningPortsRange(std::pair<unsigned short, unsigned short> ports);
void setMaxConnections(int maxConnec);

View file

@ -1,33 +1,34 @@
<ui version="4.0" >
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>createTorrentDialog</class>
<widget class="QDialog" name="createTorrentDialog" >
<property name="geometry" >
<widget class="QDialog" name="createTorrentDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>592</width>
<height>655</height>
<height>658</height>
</rect>
</property>
<property name="windowTitle" >
<property name="windowTitle">
<string>Torrent Creation Tool</string>
</property>
<layout class="QVBoxLayout" >
<layout class="QVBoxLayout">
<item>
<widget class="QLabel" name="createTorrent_title" >
<property name="minimumSize" >
<widget class="QLabel" name="createTorrent_title">
<property name="minimumSize">
<size>
<width>0</width>
<height>27</height>
</size>
</property>
<property name="maximumSize" >
<property name="maximumSize">
<size>
<width>16777215</width>
<height>27</height>
</size>
</property>
<property name="font" >
<property name="font">
<font>
<family>Sans Serif</family>
<pointsize>14</pointsize>
@ -38,105 +39,107 @@
<strikeout>false</strikeout>
</font>
</property>
<property name="text" >
<property name="text">
<string>Torrent file creation</string>
</property>
<property name="alignment" >
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lbl_input" >
<property name="text" >
<widget class="QLabel" name="lbl_input">
<property name="text">
<string>File or folder to add to the torrent:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="textInputPath" />
<widget class="QLineEdit" name="textInputPath"/>
</item>
<item>
<layout class="QHBoxLayout" >
<layout class="QHBoxLayout">
<item>
<widget class="QPushButton" name="addFile_button" >
<property name="text" >
<widget class="QPushButton" name="addFile_button">
<property name="text">
<string>Add a file</string>
</property>
<property name="icon" >
<iconset resource="icons.qrc" >:/Icons/add_file.png</iconset>
<property name="icon">
<iconset resource="icons.qrc">
<normaloff>:/Icons/add_file.png</normaloff>:/Icons/add_file.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="addFolder_button" >
<property name="text" >
<widget class="QPushButton" name="addFolder_button">
<property name="text">
<string>Add a folder</string>
</property>
<property name="icon" >
<iconset resource="icons.qrc" >:/Icons/add_folder.png</iconset>
<property name="icon">
<iconset resource="icons.qrc">
<normaloff>:/Icons/add_folder.png</normaloff>:/Icons/add_folder.png</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" >
<layout class="QHBoxLayout">
<item>
<layout class="QVBoxLayout" >
<layout class="QVBoxLayout">
<item>
<widget class="QLabel" name="lbl_announce_url" >
<property name="minimumSize" >
<widget class="QLabel" name="lbl_announce_url">
<property name="minimumSize">
<size>
<width>0</width>
<height>102</height>
</size>
</property>
<property name="maximumSize" >
<property name="maximumSize">
<size>
<width>16777215</width>
<height>70</height>
</size>
</property>
<property name="text" >
<property name="text">
<string>Announce urls (trackers):</string>
</property>
<property name="buddy" >
<property name="buddy">
<cstring></cstring>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="urlSeeds_lbl" >
<property name="minimumSize" >
<widget class="QLabel" name="urlSeeds_lbl">
<property name="minimumSize">
<size>
<width>0</width>
<height>101</height>
</size>
</property>
<property name="text" >
<property name="text">
<string>Web seeds urls (optional):</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lbl_comment" >
<property name="minimumSize" >
<widget class="QLabel" name="lbl_comment">
<property name="minimumSize">
<size>
<width>0</width>
<height>102</height>
</size>
</property>
<property name="maximumSize" >
<property name="maximumSize">
<size>
<width>16777215</width>
<height>102</height>
</size>
</property>
<property name="text" >
<property name="text">
<string>Comment (optional):</string>
</property>
<property name="buddy" >
<property name="buddy">
<cstring>txt_comment</cstring>
</property>
</widget>
@ -144,54 +147,36 @@
</layout>
</item>
<item>
<layout class="QVBoxLayout" >
<layout class="QVBoxLayout">
<item>
<layout class="QHBoxLayout" >
<property name="spacing" >
<layout class="QHBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QListWidget" name="trackers_list" >
<property name="selectionMode" >
<widget class="QListWidget" name="trackers_list">
<property name="selectionMode">
<enum>QAbstractItemView::MultiSelection</enum>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" >
<property name="spacing" >
<layout class="QVBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<property name="margin">
<number>0</number>
</property>
<item>
<spacer>
<property name="orientation" >
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" >
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>16</height>
@ -200,55 +185,69 @@
</spacer>
</item>
<item>
<widget class="QPushButton" name="addTracker_button" >
<property name="minimumSize" >
<widget class="QPushButton" name="addTracker_button">
<property name="minimumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="maximumSize" >
<property name="maximumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="text" >
<property name="text">
<string/>
</property>
<property name="icon" >
<iconset resource="icons.qrc" >:/Icons/skin/add.png</iconset>
<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>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="removeTracker_button" >
<property name="minimumSize" >
<widget class="QPushButton" name="removeTracker_button">
<property name="minimumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="maximumSize" >
<property name="maximumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="text" >
<property name="text">
<string/>
</property>
<property name="icon" >
<iconset resource="icons.qrc" >:/Icons/skin/remove.png</iconset>
<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>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" >
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>16</height>
@ -261,52 +260,34 @@
</layout>
</item>
<item>
<layout class="QHBoxLayout" >
<property name="spacing" >
<layout class="QHBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QListWidget" name="URLSeeds_list" >
<property name="selectionMode" >
<widget class="QListWidget" name="URLSeeds_list">
<property name="selectionMode">
<enum>QAbstractItemView::MultiSelection</enum>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" >
<property name="spacing" >
<layout class="QVBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<property name="margin">
<number>0</number>
</property>
<item>
<spacer>
<property name="orientation" >
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" >
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>16</height>
@ -315,55 +296,69 @@
</spacer>
</item>
<item>
<widget class="QPushButton" name="addURLSeed_button" >
<property name="minimumSize" >
<widget class="QPushButton" name="addURLSeed_button">
<property name="minimumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="maximumSize" >
<property name="maximumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="text" >
<property name="text">
<string/>
</property>
<property name="icon" >
<iconset resource="icons.qrc" >:/Icons/skin/add.png</iconset>
<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>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="removeURLSeed_button" >
<property name="minimumSize" >
<widget class="QPushButton" name="removeURLSeed_button">
<property name="minimumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="maximumSize" >
<property name="maximumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="text" >
<property name="text">
<string/>
</property>
<property name="icon" >
<iconset resource="icons.qrc" >:/Icons/skin/remove.png</iconset>
<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>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" >
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>16</height>
@ -376,14 +371,14 @@
</layout>
</item>
<item>
<widget class="QTextEdit" name="txt_comment" >
<property name="maximumSize" >
<widget class="QTextEdit" name="txt_comment">
<property name="maximumSize">
<size>
<width>421</width>
<height>102</height>
</size>
</property>
<property name="acceptRichText" >
<property name="acceptRichText">
<bool>false</bool>
</property>
</widget>
@ -393,56 +388,56 @@
</layout>
</item>
<item>
<layout class="QHBoxLayout" >
<layout class="QHBoxLayout">
<item>
<widget class="QLabel" name="txtPieceSize" >
<property name="text" >
<widget class="QLabel" name="txtPieceSize">
<property name="text">
<string>Piece size:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboPieceSize" >
<property name="currentIndex" >
<widget class="QComboBox" name="comboPieceSize">
<property name="currentIndex">
<number>3</number>
</property>
<item>
<property name="text" >
<property name="text">
<string>32 KiB</string>
</property>
</item>
<item>
<property name="text" >
<property name="text">
<string>64 KiB</string>
</property>
</item>
<item>
<property name="text" >
<property name="text">
<string>128 KiB</string>
</property>
</item>
<item>
<property name="text" >
<property name="text">
<string>256 KiB</string>
</property>
</item>
<item>
<property name="text" >
<property name="text">
<string>512 KiB</string>
</property>
</item>
<item>
<property name="text" >
<property name="text">
<string>1 MiB</string>
</property>
</item>
<item>
<property name="text" >
<property name="text">
<string>2 MiB</string>
</property>
</item>
<item>
<property name="text" >
<property name="text">
<string>4 MiB</string>
</property>
</item>
@ -450,10 +445,10 @@
</item>
<item>
<spacer>
<property name="orientation" >
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
@ -464,56 +459,47 @@
</layout>
</item>
<item>
<widget class="QCheckBox" name="check_private" >
<property name="text" >
<widget class="QCheckBox" name="check_private">
<property name="text">
<string>Private (won't be distributed on DHT network if enabled)</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkStartSeeding" >
<property name="text" >
<widget class="QCheckBox" name="checkStartSeeding">
<property name="text">
<string>Start seeding after creation</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="progressLbl" >
<property name="text" >
<widget class="QLabel" name="progressLbl">
<property name="text">
<string>Progress:</string>
</property>
</widget>
</item>
<item>
<widget class="QProgressBar" name="progressBar" >
<property name="value" >
<widget class="QProgressBar" name="progressBar">
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" >
<property name="spacing" >
<layout class="QHBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<property name="margin">
<number>0</number>
</property>
<item>
<spacer>
<property name="orientation" >
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<property name="sizeHint" stdset="0">
<size>
<width>131</width>
<height>31</height>
@ -522,25 +508,25 @@
</spacer>
</item>
<item>
<widget class="QPushButton" name="createButton" >
<property name="text" >
<widget class="QPushButton" name="createButton">
<property name="text">
<string>Create and save...</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="cancelButton" >
<property name="text" >
<widget class="QPushButton" name="cancelButton">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
@ -553,7 +539,7 @@
</layout>
</widget>
<resources>
<include location="icons.qrc" />
<include location="icons.qrc"/>
</resources>
<connections>
<connection>
@ -562,11 +548,11 @@
<receiver>createTorrentDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel" >
<hint type="sourcelabel">
<x>355</x>
<y>275</y>
</hint>
<hint type="destinationlabel" >
<hint type="destinationlabel">
<x>179</x>
<y>282</y>
</hint>

View file

@ -59,7 +59,7 @@ engineSelectDlg::engineSelectDlg(QWidget *parent) : QDialog(parent) {
pluginsTree->hideColumn(ENGINE_ID);
actionEnable->setIcon(QIcon(QString::fromUtf8(":/Icons/oxygen/button_ok.png")));
actionDisable->setIcon(QIcon(QString::fromUtf8(":/Icons/oxygen/button_cancel.png")));
actionUninstall->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/remove.png")));
actionUninstall->setIcon(QIcon(QString::fromUtf8(":/Icons/oxygen/list-remove.png")));
connect(actionEnable, SIGNAL(triggered()), this, SLOT(enableSelection()));
connect(actionDisable, SIGNAL(triggered()), this, SLOT(disableSelection()));
connect(pluginsTree, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayContextMenu(const QPoint&)));

View file

@ -19,7 +19,6 @@
<file>Icons/skin/qbittorrent22.png</file>
<file>Icons/skin/new.png</file>
<file>Icons/skin/preview.png</file>
<file>Icons/skin/add.png</file>
<file>Icons/skin/stalled.png</file>
<file>Icons/skin/delete.png</file>
<file>Icons/skin/url.png</file>
@ -31,7 +30,6 @@
<file>Icons/skin/paused.png</file>
<file>Icons/skin/qb_question.png</file>
<file>Icons/skin/open.png</file>
<file>Icons/skin/remove.png</file>
<file>Icons/skin/qbittorrent16.png</file>
<file>Icons/skin/downloading.png</file>
<file>Icons/skin/search.png</file>
@ -96,8 +94,10 @@
<file>Icons/oxygen/edit-copy.png</file>
<file>Icons/oxygen/bt_settings.png</file>
<file>Icons/oxygen/webui.png</file>
<file>Icons/oxygen/list-remove.png</file>
<file>Icons/oxygen/connection.png</file>
<file>Icons/oxygen/bug.png</file>
<file>Icons/oxygen/list-add.png</file>
<file>Icons/oxygen/folder.png</file>
<file>Icons/oxygen/configure.png</file>
<file>Icons/oxygen/edit-cut.png</file>

Binary file not shown.

File diff suppressed because it is too large Load diff

Binary file not shown.

File diff suppressed because it is too large Load diff

Binary file not shown.

File diff suppressed because it is too large Load diff

Binary file not shown.

File diff suppressed because it is too large Load diff

Binary file not shown.

File diff suppressed because it is too large Load diff

Binary file not shown.

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

Binary file not shown.

File diff suppressed because it is too large Load diff

Binary file not shown.

File diff suppressed because it is too large Load diff

Binary file not shown.

File diff suppressed because it is too large Load diff

Binary file not shown.

File diff suppressed because it is too large Load diff

Binary file not shown.

File diff suppressed because it is too large Load diff

Binary file not shown.

File diff suppressed because it is too large Load diff

Binary file not shown.

File diff suppressed because it is too large Load diff

Binary file not shown.

File diff suppressed because it is too large Load diff

Binary file not shown.

File diff suppressed because it is too large Load diff

Binary file not shown.

File diff suppressed because it is too large Load diff

Binary file not shown.

View file

@ -649,7 +649,7 @@ p, li { white-space: pre-wrap; }
<message>
<source>Transfer lists double-click</source>
<comment>qBittorrent will watch a directory and automatically download torrents present in it</comment>
<translation>Duplo clique na lista de transferência
<translation type="obsolete">Duplo clique na lista de transferência
qBittorrent irá procurar no diretório e baixará automaticamente torrents present</translation>
</message>
<message>
@ -910,6 +910,11 @@ qBittorrent irá procurar no diretório e baixará automaticamente torrents pres
<source>Spoof µtorrent to avoid ban (requires restart)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Transfer lists double-click action</source>
<comment>Action executed when doucle-clicking on an item in transfer (download/upload) list</comment>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>DownloadingTorrents</name>
@ -2252,7 +2257,7 @@ Deseja mesmo sair do qBittorrent?</translation>
</message>
<message>
<source>&lt;b&gt;News:&lt;/b&gt; &lt;i&gt;(double-click to open the link in your web browser)&lt;/i&gt;</source>
<translation>&lt;b&gt;Info:&lt;/b&gt; &lt;i&gt;(clique-duplo para abrir o link no seu browser)&lt;/i&gt;</translation>
<translation type="obsolete">&lt;b&gt;Info:&lt;/b&gt; &lt;i&gt;(clique-duplo para abrir o link no seu browser)&lt;/i&gt;</translation>
</message>
<message>
<source>Add RSS stream</source>
@ -2274,6 +2279,22 @@ Deseja mesmo sair do qBittorrent?</translation>
<source>Mark all as read</source>
<translation>Marcar todos como lido</translation>
</message>
<message>
<source>&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:&apos;Sans&apos;; font-size:10pt; 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;&lt;span style=&quot; font-weight:600;&quot;&gt;Torrents:&lt;/span&gt; &lt;span style=&quot; font-style:italic;&quot;&gt;(double-click to download)&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Download torrent</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Open news URL</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>RSSImp</name>
@ -2729,7 +2750,7 @@ Log de mudanças:</translation>
</message>
<message>
<source>Download in correct order (slower but good for previewing)</source>
<translation>Baixar em ordem (lento mas bom para pré-visualizar)</translation>
<translation type="obsolete">Baixar em ordem (lento mas bom para pré-visualizar)</translation>
</message>
<message>
<source>Add to download list in paused state</source>
@ -2775,6 +2796,22 @@ Log de mudanças:</translation>
<source>Expand all</source>
<translation>Expandir todos</translation>
</message>
<message>
<source>Torrent size:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unknown</source>
<translation type="unfinished">Desconhecido</translation>
</message>
<message>
<source>Free disk space:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Download in sequential order (slower but good for previewing)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>authentication</name>
@ -2903,6 +2940,10 @@ Log de mudanças:</translation>
<comment>e.g: Downloading &apos;xxx.torrent&apos;, please wait...</comment>
<translation>baixando &apos;%1&apos;, por favor espere...</translation>
</message>
<message>
<source>&apos;%1&apos; is not a valid magnet URI.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>createTorrentDialog</name>
@ -3300,6 +3341,10 @@ Log de mudanças:</translation>
<source>Force recheck</source>
<translation>Forçar re-checagem</translation>
</message>
<message>
<source>Copy magnet link</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>engineSelect</name>
@ -4218,6 +4263,10 @@ Portanto os plugins foram desabilitados.</translation>
<source>Force recheck</source>
<translation>Forçar re-checagem</translation>
</message>
<message>
<source>Copy magnet link</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>subDownloadThread</name>
@ -4332,5 +4381,19 @@ Portanto os plugins foram desabilitados.</translation>
<source>Priority</source>
<translation>Prioridade</translation>
</message>
<message>
<source>Unknown</source>
<translation type="unfinished">Desconhecido</translation>
</message>
<message>
<source>(%1 left after torrent download)</source>
<comment>e.g. (100MiB left after torrent download)</comment>
<translation type="unfinished"></translation>
</message>
<message>
<source>(%1 more are required to download)</source>
<comment>e.g. (100MiB more are required to download)</comment>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

Binary file not shown.

View file

@ -649,7 +649,7 @@ p, li { white-space: pre-wrap; }
<message>
<source>Transfer lists double-click</source>
<comment>qBittorrent will watch a directory and automatically download torrents present in it</comment>
<translation>Duplo clique na lista de transferência
<translation type="obsolete">Duplo clique na lista de transferência
qBittorrent irá procurar no diretório e baixará automaticamente torrents present</translation>
</message>
<message>
@ -910,6 +910,11 @@ qBittorrent irá procurar no diretório e baixará automaticamente torrents pres
<source>Spoof µtorrent to avoid ban (requires restart)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Transfer lists double-click action</source>
<comment>Action executed when doucle-clicking on an item in transfer (download/upload) list</comment>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>DownloadingTorrents</name>
@ -2252,7 +2257,7 @@ Deseja mesmo sair do qBittorrent?</translation>
</message>
<message>
<source>&lt;b&gt;News:&lt;/b&gt; &lt;i&gt;(double-click to open the link in your web browser)&lt;/i&gt;</source>
<translation>&lt;b&gt;Info:&lt;/b&gt; &lt;i&gt;(clique-duplo para abrir o link no seu browser)&lt;/i&gt;</translation>
<translation type="obsolete">&lt;b&gt;Info:&lt;/b&gt; &lt;i&gt;(clique-duplo para abrir o link no seu browser)&lt;/i&gt;</translation>
</message>
<message>
<source>Add RSS stream</source>
@ -2274,6 +2279,22 @@ Deseja mesmo sair do qBittorrent?</translation>
<source>Mark all as read</source>
<translation>Marcar todos como lido</translation>
</message>
<message>
<source>&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:&apos;Sans&apos;; font-size:10pt; 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;&lt;span style=&quot; font-weight:600;&quot;&gt;Torrents:&lt;/span&gt; &lt;span style=&quot; font-style:italic;&quot;&gt;(double-click to download)&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Download torrent</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Open news URL</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>RSSImp</name>
@ -2729,7 +2750,7 @@ Log de mudanças:</translation>
</message>
<message>
<source>Download in correct order (slower but good for previewing)</source>
<translation>Baixar em ordem (lento mas bom para pré-visualizar)</translation>
<translation type="obsolete">Baixar em ordem (lento mas bom para pré-visualizar)</translation>
</message>
<message>
<source>Add to download list in paused state</source>
@ -2775,6 +2796,22 @@ Log de mudanças:</translation>
<source>Expand all</source>
<translation>Expandir todos</translation>
</message>
<message>
<source>Torrent size:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unknown</source>
<translation type="unfinished">Desconhecido</translation>
</message>
<message>
<source>Free disk space:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Download in sequential order (slower but good for previewing)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>authentication</name>
@ -2903,6 +2940,10 @@ Log de mudanças:</translation>
<comment>e.g: Downloading &apos;xxx.torrent&apos;, please wait...</comment>
<translation>baixando &apos;%1&apos;, por favor espere...</translation>
</message>
<message>
<source>&apos;%1&apos; is not a valid magnet URI.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>createTorrentDialog</name>
@ -3300,6 +3341,10 @@ Log de mudanças:</translation>
<source>Force recheck</source>
<translation>Forçar re-checagem</translation>
</message>
<message>
<source>Copy magnet link</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>engineSelect</name>
@ -4218,6 +4263,10 @@ Portanto os plugins foram desabilitados.</translation>
<source>Force recheck</source>
<translation>Forçar re-checagem</translation>
</message>
<message>
<source>Copy magnet link</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>subDownloadThread</name>
@ -4332,5 +4381,19 @@ Portanto os plugins foram desabilitados.</translation>
<source>Priority</source>
<translation>Prioridade</translation>
</message>
<message>
<source>Unknown</source>
<translation type="unfinished">Desconhecido</translation>
</message>
<message>
<source>(%1 left after torrent download)</source>
<comment>e.g. (100MiB left after torrent download)</comment>
<translation type="unfinished"></translation>
</message>
<message>
<source>(%1 more are required to download)</source>
<comment>e.g. (100MiB more are required to download)</comment>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

Binary file not shown.

View file

@ -657,7 +657,7 @@ p, li { white-space: pre-wrap; }
<message>
<source>Transfer lists double-click</source>
<comment>qBittorrent will watch a directory and automatically download torrents present in it</comment>
<translation>Lista cu transferuri dublu-click
<translation type="obsolete">Lista cu transferuri dublu-click
qBittorrent va monitoriza directoriul și va adăuga în lista de descărcare a torentelor din directoriu</translation>
</message>
<message>
@ -918,6 +918,11 @@ qBittorrent va monitoriza directoriul și va adăuga în lista de descărcare a
<source>Spoof µtorrent to avoid ban (requires restart)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Transfer lists double-click action</source>
<comment>Action executed when doucle-clicking on an item in transfer (download/upload) list</comment>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>DownloadingTorrents</name>
@ -2181,7 +2186,7 @@ Motivul : %2</translation>
</message>
<message>
<source>&lt;b&gt;News:&lt;/b&gt; &lt;i&gt;(double-click to open the link in your web browser)&lt;/i&gt;</source>
<translation>&lt;b&gt;Noutăţi:&lt;/b&gt; &lt;i&gt;(dubli click pentru a deschide)&lt;/i&gt;</translation>
<translation type="obsolete">&lt;b&gt;Noutăţi:&lt;/b&gt; &lt;i&gt;(dubli click pentru a deschide)&lt;/i&gt;</translation>
</message>
<message>
<source>Add RSS stream</source>
@ -2203,6 +2208,22 @@ Motivul : %2</translation>
<source>Mark all as read</source>
<translation>Marchează toate ca citite</translation>
</message>
<message>
<source>&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:&apos;Sans&apos;; font-size:10pt; 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;&lt;span style=&quot; font-weight:600;&quot;&gt;Torrents:&lt;/span&gt; &lt;span style=&quot; font-style:italic;&quot;&gt;(double-click to download)&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Download torrent</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Open news URL</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>RSSImp</name>
@ -2568,7 +2589,7 @@ Changelog:
</message>
<message>
<source>Download in correct order (slower but good for previewing)</source>
<translation>Descarcă în ordine corectă (mai încet dar bun pentru preview)</translation>
<translation type="obsolete">Descarcă în ordine corectă (mai încet dar bun pentru preview)</translation>
</message>
<message>
<source>Add to download list in paused state</source>
@ -2614,6 +2635,22 @@ Changelog:
<source>Expand all</source>
<translation>Deschide toate</translation>
</message>
<message>
<source>Torrent size:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unknown</source>
<translation type="unfinished">Necunoscut</translation>
</message>
<message>
<source>Free disk space:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Download in sequential order (slower but good for previewing)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>authentication</name>
@ -2742,6 +2779,10 @@ Changelog:
<comment>e.g: Downloading &apos;xxx.torrent&apos;, please wait...</comment>
<translation>Descarc &apos;%1&apos;, rugăm aşteptaţi...</translation>
</message>
<message>
<source>&apos;%1&apos; is not a valid magnet URI.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>createTorrentDialog</name>
@ -3139,6 +3180,10 @@ Changelog:
<source>Force recheck</source>
<translation>Reverificarea forţată</translation>
</message>
<message>
<source>Copy magnet link</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>engineSelect</name>
@ -4065,6 +4110,10 @@ Numai acele adăugate de dvs. pot fi dezinstalate.
<source>Force recheck</source>
<translation>Reverificarea forţată</translation>
</message>
<message>
<source>Copy magnet link</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>subDownloadThread</name>
@ -4179,5 +4228,19 @@ Numai acele adăugate de dvs. pot fi dezinstalate.
<source>Priority</source>
<translation>Prioritate</translation>
</message>
<message>
<source>Unknown</source>
<translation type="unfinished">Necunoscut</translation>
</message>
<message>
<source>(%1 left after torrent download)</source>
<comment>e.g. (100MiB left after torrent download)</comment>
<translation type="unfinished"></translation>
</message>
<message>
<source>(%1 more are required to download)</source>
<comment>e.g. (100MiB more are required to download)</comment>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

Binary file not shown.

View file

@ -704,7 +704,7 @@ p, li { white-space: pre-wrap; }
<message>
<source>Transfer lists double-click</source>
<comment>qBittorrent will watch a directory and automatically download torrents present in it</comment>
<translation>Двойной щелчок по списку закачек</translation>
<translation type="obsolete">Двойной щелчок по списку закачек</translation>
</message>
<message>
<source>Download list:</source>
@ -964,6 +964,11 @@ p, li { white-space: pre-wrap; }
<source>Spoof µtorrent to avoid ban (requires restart)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Transfer lists double-click action</source>
<comment>Action executed when doucle-clicking on an item in transfer (download/upload) list</comment>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>DownloadingTorrents</name>
@ -2354,7 +2359,7 @@ Are you sure you want to quit qBittorrent?</source>
</message>
<message>
<source>&lt;b&gt;News:&lt;/b&gt; &lt;i&gt;(double-click to open the link in your web browser)&lt;/i&gt;</source>
<translation>&lt;b&gt;Новости:&lt;/b&gt; &lt;i&gt;(двойной клик откроет ссылку в вашем браузере)&lt;/i&gt;</translation>
<translation type="obsolete">&lt;b&gt;Новости:&lt;/b&gt; &lt;i&gt;(двойной клик откроет ссылку в вашем браузере)&lt;/i&gt;</translation>
</message>
<message>
<source>Add RSS stream</source>
@ -2376,6 +2381,22 @@ Are you sure you want to quit qBittorrent?</source>
<source>Mark all as read</source>
<translation>Отметить все как прочитанное</translation>
</message>
<message>
<source>&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:&apos;Sans&apos;; font-size:10pt; 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;&lt;span style=&quot; font-weight:600;&quot;&gt;Torrents:&lt;/span&gt; &lt;span style=&quot; font-style:italic;&quot;&gt;(double-click to download)&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Download torrent</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Open news URL</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>RSSImp</name>
@ -2753,7 +2774,7 @@ Changelog:
</message>
<message>
<source>Download in correct order (slower but good for previewing)</source>
<translation>Загрузить в правильном порядке (медленнее, но удобнее для предпросмотра)</translation>
<translation type="obsolete">Загрузить в правильном порядке (медленнее, но удобнее для предпросмотра)</translation>
</message>
<message>
<source>Add to download list in paused state</source>
@ -2803,6 +2824,22 @@ Changelog:
<source>Expand all</source>
<translation>Развернуть все</translation>
</message>
<message>
<source>Torrent size:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unknown</source>
<translation type="unfinished">Неизвестно</translation>
</message>
<message>
<source>Free disk space:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Download in sequential order (slower but good for previewing)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>authentication</name>
@ -2931,6 +2968,10 @@ Changelog:
<comment>e.g: Downloading &apos;xxx.torrent&apos;, please wait...</comment>
<translation>Скачивание &apos;%1&apos;, подождите...</translation>
</message>
<message>
<source>&apos;%1&apos; is not a valid magnet URI.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>createTorrentDialog</name>
@ -3320,6 +3361,10 @@ Changelog:
<source>Force recheck</source>
<translation>Проверить принудительно</translation>
</message>
<message>
<source>Copy magnet link</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>engineSelect</name>
@ -4275,6 +4320,10 @@ However, those plugins were disabled.</source>
<source>Force recheck</source>
<translation>Проверить принудительно</translation>
</message>
<message>
<source>Copy magnet link</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>subDownloadThread</name>
@ -4389,5 +4438,19 @@ However, those plugins were disabled.</source>
<source>Priority</source>
<translation>Приоритет</translation>
</message>
<message>
<source>Unknown</source>
<translation type="unfinished">Неизвестно</translation>
</message>
<message>
<source>(%1 left after torrent download)</source>
<comment>e.g. (100MiB left after torrent download)</comment>
<translation type="unfinished"></translation>
</message>
<message>
<source>(%1 more are required to download)</source>
<comment>e.g. (100MiB more are required to download)</comment>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

Binary file not shown.

View file

@ -665,7 +665,7 @@ p, li { white-space: pre-wrap; }
<message>
<source>Transfer lists double-click</source>
<comment>qBittorrent will watch a directory and automatically download torrents present in it</comment>
<translation>Dvojité kliknutie v zozname prenosov</translation>
<translation type="obsolete">Dvojité kliknutie v zozname prenosov</translation>
</message>
<message>
<source>Download list:</source>
@ -925,6 +925,11 @@ p, li { white-space: pre-wrap; }
<source>Spoof µtorrent to avoid ban (requires restart)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Transfer lists double-click action</source>
<comment>Action executed when doucle-clicking on an item in transfer (download/upload) list</comment>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>DownloadingTorrents</name>
@ -2256,7 +2261,7 @@ Ste si istý, že chcete ukončiť qBittorrent?</translation>
</message>
<message>
<source>&lt;b&gt;News:&lt;/b&gt; &lt;i&gt;(double-click to open the link in your web browser)&lt;/i&gt;</source>
<translation>&lt;b&gt;Novinky:&lt;/b&gt; &lt;i&gt;(dvojitým kliknutím otvoríte odkaz vo webovom prehliadači)&lt;/i&gt;</translation>
<translation type="obsolete">&lt;b&gt;Novinky:&lt;/b&gt; &lt;i&gt;(dvojitým kliknutím otvoríte odkaz vo webovom prehliadači)&lt;/i&gt;</translation>
</message>
<message>
<source>Delete</source>
@ -2290,6 +2295,22 @@ Ste si istý, že chcete ukončiť qBittorrent?</translation>
<source>Mark all as read</source>
<translation>Označiť všetky ako prečítané</translation>
</message>
<message>
<source>&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:&apos;Sans&apos;; font-size:10pt; 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;&lt;span style=&quot; font-weight:600;&quot;&gt;Torrents:&lt;/span&gt; &lt;span style=&quot; font-style:italic;&quot;&gt;(double-click to download)&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Download torrent</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Open news URL</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>RSSImp</name>
@ -2666,7 +2687,7 @@ Záznam zmien:</translation>
</message>
<message>
<source>Download in correct order (slower but good for previewing)</source>
<translation>Stiahnuť v správnom poradí (pomalšie ale lepšie pre náhľad)</translation>
<translation type="obsolete">Stiahnuť v správnom poradí (pomalšie ale lepšie pre náhľad)</translation>
</message>
<message>
<source>Add to download list in paused state</source>
@ -2720,6 +2741,22 @@ Záznam zmien:</translation>
<source>Expand all</source>
<translation>Rozbaliť všetko</translation>
</message>
<message>
<source>Torrent size:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unknown</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Free disk space:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Download in sequential order (slower but good for previewing)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>authentication</name>
@ -2848,6 +2885,10 @@ Záznam zmien:</translation>
<comment>e.g: Downloading &apos;xxx.torrent&apos;, please wait...</comment>
<translation>Sťahuje sa %1, čakajte prosím...</translation>
</message>
<message>
<source>&apos;%1&apos; is not a valid magnet URI.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>createTorrentDialog</name>
@ -3249,6 +3290,10 @@ Záznam zmien:</translation>
<source>Force recheck</source>
<translation>Vynútiť opätovnú kontrolu</translation>
</message>
<message>
<source>Copy magnet link</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>engineSelect</name>
@ -4243,6 +4288,10 @@ Tieto moduly však boli vypnuté.</translation>
<source>Force recheck</source>
<translation>Vynútiť opätovnú kontrolu</translation>
</message>
<message>
<source>Copy magnet link</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>subDownloadThread</name>
@ -4357,5 +4406,19 @@ Tieto moduly však boli vypnuté.</translation>
<source>Priority</source>
<translation>Priorita</translation>
</message>
<message>
<source>Unknown</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>(%1 left after torrent download)</source>
<comment>e.g. (100MiB left after torrent download)</comment>
<translation type="unfinished"></translation>
</message>
<message>
<source>(%1 more are required to download)</source>
<comment>e.g. (100MiB more are required to download)</comment>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

Binary file not shown.

View file

@ -339,7 +339,7 @@ p, li { white-space: pre-wrap; }
<message>
<source>Transfer lists double-click</source>
<comment>qBittorrent will watch a directory and automatically download torrents present in it</comment>
<translation>Dubbelklick i överföringslistan</translation>
<translation type="obsolete">Dubbelklick i överföringslistan</translation>
</message>
<message>
<source>Download list:</source>
@ -607,6 +607,11 @@ p, li { white-space: pre-wrap; }
<source>Spoof µtorrent to avoid ban (requires restart)</source>
<translation>Simulera µtorrent för att undvika bannlysning (kräver omstart)</translation>
</message>
<message>
<source>Transfer lists double-click action</source>
<comment>Action executed when doucle-clicking on an item in transfer (download/upload) list</comment>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>DownloadingTorrents</name>
@ -1175,7 +1180,7 @@ Are you sure you want to quit qBittorrent?</source>
</message>
<message>
<source>&lt;b&gt;News:&lt;/b&gt; &lt;i&gt;(double-click to open the link in your web browser)&lt;/i&gt;</source>
<translation>&lt;b&gt;Nyheter:&lt;/b&gt; &lt;i&gt;(dubbelklicka för att öppna länken i din webbläsare)&lt;/i&gt;</translation>
<translation type="obsolete">&lt;b&gt;Nyheter:&lt;/b&gt; &lt;i&gt;(dubbelklicka för att öppna länken i din webbläsare)&lt;/i&gt;</translation>
</message>
<message>
<source>Add RSS stream</source>
@ -1197,6 +1202,22 @@ Are you sure you want to quit qBittorrent?</source>
<source>Mark all as read</source>
<translation>Markera alla som lästa</translation>
</message>
<message>
<source>&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:&apos;Sans&apos;; font-size:10pt; 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;&lt;span style=&quot; font-weight:600;&quot;&gt;Torrents:&lt;/span&gt; &lt;span style=&quot; font-style:italic;&quot;&gt;(double-click to download)&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Download torrent</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Open news URL</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>RSSImp</name>
@ -1421,7 +1442,7 @@ Are you sure you want to quit qBittorrent?</source>
</message>
<message>
<source>Download in correct order (slower but good for previewing)</source>
<translation>Hämta i korrekt ordning (långsammare men bra för förhandsvisning)</translation>
<translation type="obsolete">Hämta i korrekt ordning (långsammare men bra för förhandsvisning)</translation>
</message>
<message>
<source>Add to download list in paused state</source>
@ -1463,6 +1484,22 @@ Are you sure you want to quit qBittorrent?</source>
<source>Expand all</source>
<translation>Fäll ut alla</translation>
</message>
<message>
<source>Torrent size:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unknown</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Free disk space:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Download in sequential order (slower but good for previewing)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>authentication</name>
@ -1591,6 +1628,10 @@ Are you sure you want to quit qBittorrent?</source>
<comment>e.g: Downloading &apos;xxx.torrent&apos;, please wait...</comment>
<translation>Hämtar &quot;%1&quot;, vänta...</translation>
</message>
<message>
<source>&apos;%1&apos; is not a valid magnet URI.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>createTorrentDialog</name>
@ -1876,6 +1917,10 @@ Are you sure you want to quit qBittorrent?</source>
<source>Force recheck</source>
<translation>Tvinga återkontroll</translation>
</message>
<message>
<source>Copy magnet link</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>engineSelect</name>
@ -2503,6 +2548,10 @@ Dock har dessa insticksmoduler blivit inaktiverade.</translation>
<source>Force recheck</source>
<translation>Tvinga återkontroll</translation>
</message>
<message>
<source>Copy magnet link</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>subDownloadThread</name>
@ -2597,5 +2646,19 @@ Dock har dessa insticksmoduler blivit inaktiverade.</translation>
<source>Priority</source>
<translation>Prioritet</translation>
</message>
<message>
<source>Unknown</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>(%1 left after torrent download)</source>
<comment>e.g. (100MiB left after torrent download)</comment>
<translation type="unfinished"></translation>
</message>
<message>
<source>(%1 more are required to download)</source>
<comment>e.g. (100MiB more are required to download)</comment>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

Binary file not shown.

View file

@ -690,7 +690,7 @@ p, li { white-space: pre-wrap; }
<message>
<source>Transfer lists double-click</source>
<comment>qBittorrent will watch a directory and automatically download torrents present in it</comment>
<translation>Aktarım listesinde çift-tıklamada yapılacak </translation>
<translation type="obsolete">Aktarım listesinde çift-tıklamada yapılacak </translation>
</message>
<message>
<source>Download list:</source>
@ -950,6 +950,11 @@ p, li { white-space: pre-wrap; }
<source>Spoof µtorrent to avoid ban (requires restart)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Transfer lists double-click action</source>
<comment>Action executed when doucle-clicking on an item in transfer (download/upload) list</comment>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>DownloadingTorrents</name>
@ -2340,7 +2345,7 @@ qBittorrent&apos;ten çıkmak istediğinize emin misiniz?</translation>
</message>
<message>
<source>&lt;b&gt;News:&lt;/b&gt; &lt;i&gt;(double-click to open the link in your web browser)&lt;/i&gt;</source>
<translation>&lt;b&gt;Haberler:&lt;/b&gt; &lt;i&gt;(bağlantıyı tarayıcınızda açmak için çift tıklayın)&lt;/i&gt;</translation>
<translation type="obsolete">&lt;b&gt;Haberler:&lt;/b&gt; &lt;i&gt;(bağlantıyı tarayıcınızda açmak için çift tıklayın)&lt;/i&gt;</translation>
</message>
<message>
<source>Add RSS stream</source>
@ -2362,6 +2367,22 @@ qBittorrent&apos;ten çıkmak istediğinize emin misiniz?</translation>
<source>Mark all as read</source>
<translation>Tümünü okunmuş olarak işaretle</translation>
</message>
<message>
<source>&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:&apos;Sans&apos;; font-size:10pt; 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;&lt;span style=&quot; font-weight:600;&quot;&gt;Torrents:&lt;/span&gt; &lt;span style=&quot; font-style:italic;&quot;&gt;(double-click to download)&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Download torrent</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Open news URL</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>RSSImp</name>
@ -2735,7 +2756,7 @@ Changelog:
</message>
<message>
<source>Download in correct order (slower but good for previewing)</source>
<translation>Doğru düzende indir (yavaş ama önizleme için iyi)</translation>
<translation type="obsolete">Doğru düzende indir (yavaş ama önizleme için iyi)</translation>
</message>
<message>
<source>Add to download list in paused state</source>
@ -2785,6 +2806,22 @@ Changelog:
<source>Expand all</source>
<translation>Tümünü genişlet</translation>
</message>
<message>
<source>Torrent size:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unknown</source>
<translation type="unfinished">Bilinmeyen</translation>
</message>
<message>
<source>Free disk space:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Download in sequential order (slower but good for previewing)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>authentication</name>
@ -2913,6 +2950,10 @@ Changelog:
<comment>e.g: Downloading &apos;xxx.torrent&apos;, please wait...</comment>
<translation>&apos;%1&apos; indiriliyor, lütfen bekleyin...</translation>
</message>
<message>
<source>&apos;%1&apos; is not a valid magnet URI.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>createTorrentDialog</name>
@ -3298,6 +3339,10 @@ Changelog:
<source>Force recheck</source>
<translation>Yeniden denetlemeye çalış</translation>
</message>
<message>
<source>Copy magnet link</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>engineSelect</name>
@ -4229,6 +4274,10 @@ Bununla birlikte, o eklentiler devre dışı.</translation>
<source>Force recheck</source>
<translation>Yeniden denetlemeye çalış</translation>
</message>
<message>
<source>Copy magnet link</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>subDownloadThread</name>
@ -4343,5 +4392,19 @@ Bununla birlikte, o eklentiler devre dışı.</translation>
<source>Priority</source>
<translation>Öncelik</translation>
</message>
<message>
<source>Unknown</source>
<translation type="unfinished">Bilinmeyen</translation>
</message>
<message>
<source>(%1 left after torrent download)</source>
<comment>e.g. (100MiB left after torrent download)</comment>
<translation type="unfinished"></translation>
</message>
<message>
<source>(%1 more are required to download)</source>
<comment>e.g. (100MiB more are required to download)</comment>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

Binary file not shown.

View file

@ -697,11 +697,6 @@ p, li { white-space: pre-wrap; }
<comment>qBittorrent will watch a directory and automatically download torrents present in it</comment>
<translation>Спостерігати за папкою</translation>
</message>
<message>
<source>Transfer lists double-click</source>
<comment>qBittorrent will watch a directory and automatically download torrents present in it</comment>
<translation type="unfinished"></translation>
</message>
<message>
<source>Download list:</source>
<translation type="unfinished"></translation>
@ -935,6 +930,11 @@ p, li { white-space: pre-wrap; }
<source>Spoof µtorrent to avoid ban (requires restart)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Transfer lists double-click action</source>
<comment>Action executed when doucle-clicking on an item in transfer (download/upload) list</comment>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>DownloadingTorrents</name>
@ -2320,7 +2320,7 @@ Are you sure you want to quit qBittorrent?</source>
</message>
<message>
<source>&lt;b&gt;News:&lt;/b&gt; &lt;i&gt;(double-click to open the link in your web browser)&lt;/i&gt;</source>
<translation>&lt;b&gt;Новини:&lt;/b&gt; &lt;i&gt;(подвійний клік відкриє посилання у вашому броузері)&lt;/i&gt;</translation>
<translation type="obsolete">&lt;b&gt;Новини:&lt;/b&gt; &lt;i&gt;(подвійний клік відкриє посилання у вашому броузері)&lt;/i&gt;</translation>
</message>
<message>
<source>Add RSS stream</source>
@ -2342,6 +2342,22 @@ Are you sure you want to quit qBittorrent?</source>
<source>Mark all as read</source>
<translation>Позначити всі як прочитані</translation>
</message>
<message>
<source>&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:&apos;Sans&apos;; font-size:10pt; 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;&lt;span style=&quot; font-weight:600;&quot;&gt;Torrents:&lt;/span&gt; &lt;span style=&quot; font-style:italic;&quot;&gt;(double-click to download)&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Download torrent</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Open news URL</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>RSSImp</name>
@ -2719,7 +2735,7 @@ Changelog:
</message>
<message>
<source>Download in correct order (slower but good for previewing)</source>
<translation>Завантажувати в правильному порядку (повільніше, але краще для перегляду)</translation>
<translation type="obsolete">Завантажувати в правильному порядку (повільніше, але краще для перегляду)</translation>
</message>
<message>
<source>Add to download list in paused state</source>
@ -2769,6 +2785,22 @@ Changelog:
<source>Expand all</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Torrent size:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unknown</source>
<translation type="unfinished">Невідомо</translation>
</message>
<message>
<source>Free disk space:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Download in sequential order (slower but good for previewing)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>authentication</name>
@ -2897,6 +2929,10 @@ Changelog:
<comment>e.g: Downloading &apos;xxx.torrent&apos;, please wait...</comment>
<translation type="unfinished"></translation>
</message>
<message>
<source>&apos;%1&apos; is not a valid magnet URI.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>createTorrentDialog</name>
@ -3294,6 +3330,10 @@ Changelog:
<source>Force recheck</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Copy magnet link</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>engineSelect</name>
@ -4227,6 +4267,10 @@ However, those plugins were disabled.</source>
<source>Force recheck</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Copy magnet link</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>subDownloadThread</name>
@ -4341,5 +4385,19 @@ However, those plugins were disabled.</source>
<source>Priority</source>
<translation>Пріоритет</translation>
</message>
<message>
<source>Unknown</source>
<translation type="unfinished">Невідомо</translation>
</message>
<message>
<source>(%1 left after torrent download)</source>
<comment>e.g. (100MiB left after torrent download)</comment>
<translation type="unfinished"></translation>
</message>
<message>
<source>(%1 more are required to download)</source>
<comment>e.g. (100MiB more are required to download)</comment>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

Binary file not shown.

View file

@ -771,7 +771,7 @@ folder:</source>
<message>
<source>Transfer lists double-click</source>
<comment>qBittorrent will watch a directory and automatically download torrents present in it</comment>
<translation></translation>
<translation type="obsolete"></translation>
</message>
<message>
<source>Download list:</source>
@ -997,6 +997,11 @@ folder:</source>
<source>Spoof µtorrent to avoid ban (requires restart)</source>
<translation>µtorrent名义避免被阻止()</translation>
</message>
<message>
<source>Transfer lists double-click action</source>
<comment>Action executed when doucle-clicking on an item in transfer (download/upload) list</comment>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>DownloadingTorrents</name>
@ -2506,7 +2511,23 @@ link in your web browser)&lt;/i&gt;</source>
</message>
<message>
<source>&lt;b&gt;News:&lt;/b&gt; &lt;i&gt;(double-click to open the link in your web browser)&lt;/i&gt;</source>
<translation>&lt;b&gt;:&lt;/b&gt; &lt;i&gt;(双击以连接到网页浏览器)&lt;/i&gt;</translation>
<translation type="obsolete">&lt;b&gt;:&lt;/b&gt; &lt;i&gt;(双击以连接到网页浏览器)&lt;/i&gt;</translation>
</message>
<message>
<source>&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:&apos;Sans&apos;; font-size:10pt; 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;&lt;span style=&quot; font-weight:600;&quot;&gt;Torrents:&lt;/span&gt; &lt;span style=&quot; font-style:italic;&quot;&gt;(double-click to download)&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Download torrent</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Open news URL</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
@ -2962,7 +2983,7 @@ previewing)</source>
</message>
<message>
<source>Download in correct order (slower but good for previewing)</source>
<translation>()</translation>
<translation type="obsolete">()</translation>
</message>
<message>
<source>Collapse all</source>
@ -2976,6 +2997,22 @@ previewing)</source>
<source>Expand all</source>
<translation></translation>
</message>
<message>
<source>Torrent size:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unknown</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Free disk space:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Download in sequential order (slower but good for previewing)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>authentication</name>
@ -3104,6 +3141,10 @@ previewing)</source>
<comment>e.g: Downloading &apos;xxx.torrent&apos;, please wait...</comment>
<translation>&apos;%1&apos;,...</translation>
</message>
<message>
<source>&apos;%1&apos; is not a valid magnet URI.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>createTorrentDialog</name>
@ -3502,6 +3543,10 @@ enabled)</source>
<source>Force recheck</source>
<translation></translation>
</message>
<message>
<source>Copy magnet link</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>engineSelect</name>
@ -4528,6 +4573,10 @@ network.</source>
<source>Force recheck</source>
<translation></translation>
</message>
<message>
<source>Copy magnet link</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>subDownloadThread</name>
@ -4647,5 +4696,19 @@ torrent.</source>
<source>This file is either corrupted or this isn&apos;t a torrent.</source>
<translation type="obsolete">torrent文件或已经损坏.</translation>
</message>
<message>
<source>Unknown</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>(%1 left after torrent download)</source>
<comment>e.g. (100MiB left after torrent download)</comment>
<translation type="unfinished"></translation>
</message>
<message>
<source>(%1 more are required to download)</source>
<comment>e.g. (100MiB more are required to download)</comment>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

Binary file not shown.

View file

@ -337,7 +337,7 @@ p, li { white-space: pre-wrap; }
<message>
<source>Transfer lists double-click</source>
<comment>qBittorrent will watch a directory and automatically download torrents present in it</comment>
<translation></translation>
<translation type="obsolete"></translation>
</message>
<message>
<source>Download list:</source>
@ -609,6 +609,11 @@ p, li { white-space: pre-wrap; }
<source>Spoof µtorrent to avoid ban (requires restart)</source>
<translation> µtorrent ()</translation>
</message>
<message>
<source>Transfer lists double-click action</source>
<comment>Action executed when doucle-clicking on an item in transfer (download/upload) list</comment>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>DownloadingTorrents</name>
@ -1264,7 +1269,7 @@ Are you sure you want to quit qBittorrent?</source>
</message>
<message>
<source>&lt;b&gt;News:&lt;/b&gt; &lt;i&gt;(double-click to open the link in your web browser)&lt;/i&gt;</source>
<translation>&lt;b&gt;:&lt;/b&gt; &lt;i&gt;(雙擊連結從網路瀏覽器打開)&lt;/i&gt;</translation>
<translation type="obsolete">&lt;b&gt;:&lt;/b&gt; &lt;i&gt;(雙擊連結從網路瀏覽器打開)&lt;/i&gt;</translation>
</message>
<message>
<source>Add RSS stream</source>
@ -1286,6 +1291,22 @@ Are you sure you want to quit qBittorrent?</source>
<source>Mark all as read</source>
<translation></translation>
</message>
<message>
<source>&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:&apos;Sans&apos;; font-size:10pt; 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;&lt;span style=&quot; font-weight:600;&quot;&gt;Torrents:&lt;/span&gt; &lt;span style=&quot; font-style:italic;&quot;&gt;(double-click to download)&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Download torrent</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Open news URL</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>RSSImp</name>
@ -1510,7 +1531,7 @@ Are you sure you want to quit qBittorrent?</source>
</message>
<message>
<source>Download in correct order (slower but good for previewing)</source>
<translation> ()</translation>
<translation type="obsolete"> ()</translation>
</message>
<message>
<source>Add to download list in paused state</source>
@ -1552,6 +1573,22 @@ Are you sure you want to quit qBittorrent?</source>
<source>Expand all</source>
<translation></translation>
</message>
<message>
<source>Torrent size:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unknown</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Free disk space:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Download in sequential order (slower but good for previewing)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>authentication</name>
@ -1680,6 +1717,10 @@ Are you sure you want to quit qBittorrent?</source>
<comment>e.g: Downloading &apos;xxx.torrent&apos;, please wait...</comment>
<translation> &apos;%1&apos; , ...</translation>
</message>
<message>
<source>&apos;%1&apos; is not a valid magnet URI.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>createTorrentDialog</name>
@ -1977,6 +2018,10 @@ Are you sure you want to quit qBittorrent?</source>
<source>Force recheck</source>
<translation></translation>
</message>
<message>
<source>Copy magnet link</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>engineSelect</name>
@ -2612,6 +2657,10 @@ However, those plugins were disabled.</source>
<source>Force recheck</source>
<translation></translation>
</message>
<message>
<source>Copy magnet link</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>subDownloadThread</name>
@ -2706,5 +2755,19 @@ However, those plugins were disabled.</source>
<source>Priority</source>
<translation></translation>
</message>
<message>
<source>Unknown</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>(%1 left after torrent download)</source>
<comment>e.g. (100MiB left after torrent download)</comment>
<translation type="unfinished"></translation>
</message>
<message>
<source>(%1 more are required to download)</source>
<comment>e.g. (100MiB more are required to download)</comment>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

View file

@ -103,7 +103,7 @@ public:
#ifndef Q_WS_WIN
unsigned long long available;
struct statfs stats;
int ret = statfs ((path+"/.").toUtf8().data(), &stats) ;
int ret = statfs ((path+"/.").toLocal8Bit().data(), &stats) ;
if(ret == 0) {
available = ((unsigned long long)stats.f_bavail) *
((unsigned long long)stats.f_bsize) ;
@ -293,7 +293,7 @@ public:
sha1.assign(base32decode(reg.cap(1).toStdString()));
hash = misc::toQString(sha1);
}
qDebug("magnetUriToHash: hash: %s", hash.toUtf8().data());
qDebug("magnetUriToHash: hash: %s", hash.toLocal8Bit().data());
return hash;
}

View file

@ -2550,7 +2550,7 @@
<number>9999</number>
</property>
<property name="value">
<number>50</number>
<number>100</number>
</property>
</widget>
</item>

View file

@ -53,12 +53,12 @@ properties::properties(QWidget *parent, bittorrent *BTSession, QTorrentHandle &h
setupUi(this);
lbl_priorities->setText(tr("Priorities:")+"<ul><li>"+tr("Ignored: file is not downloaded at all")+"</li><li>"+tr("Normal: normal priority. Download order is dependent on availability")+"</li><li>"+tr("High: higher than normal priority. Pieces are preferred over pieces with the same availability, but not over pieces with lower availability")+"</li><li>"+tr("Maximum: maximum priority, availability is disregarded, the piece is preferred over any other piece with lower priority")+"</li></ul>");
// set icons
addTracker_button->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/add.png")));
removeTracker_button->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/remove.png")));
addTracker_button->setIcon(QIcon(QString::fromUtf8(":/Icons/oxygen/list-add.png")));
removeTracker_button->setIcon(QIcon(QString::fromUtf8(":/Icons/oxygen/list-remove.png")));
lowerTracker_button->setIcon(QIcon(QString::fromUtf8(":/Icons/downarrow.png")));
riseTracker_button->setIcon(QIcon(QString::fromUtf8(":/Icons/uparrow.png")));
addWS_button->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/add.png")));
deleteWS_button->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/remove.png")));
addWS_button->setIcon(QIcon(QString::fromUtf8(":/Icons/oxygen/list-add.png")));
deleteWS_button->setIcon(QIcon(QString::fromUtf8(":/Icons/oxygen/list-remove.png")));
setAttribute(Qt::WA_DeleteOnClose);
// Set Properties list model
PropListModel = new QStandardItemModel(0,5);

412
src/rss.h
View file

@ -45,6 +45,8 @@
#include <QCryptographicHash>
#include "misc.h"
#include "FeedDownloader.h"
#include "bittorrent.h"
#include "downloadThread.h"
class RssManager;
@ -76,19 +78,21 @@ static const char longMonth[][10] = {
// Item of a rss stream, single information
class RssItem : public QObject {
Q_OBJECT
private:
private:
QString title;
QString link;
QString torrent_url;
QString news_link;
QString description;
QString image;
QString author;
QDateTime date;
QString author;
QString hash;
bool read;
QString downloadLink;
protected:
bool is_valid;
bool read;
protected:
// Ported to Qt4 from KDElibs4
QDateTime parseDate(const QString &string) {
QString str = string.trimmed();
@ -151,9 +155,9 @@ class RssItem : public QObject {
if (dayOfWeek >= 7)
for (dayOfWeek = 0; dayOfWeek < 7 && longDay[dayOfWeek] != parts[nwday]; ++dayOfWeek) ;
}
// if (month >= 12 || dayOfWeek >= 7
// || (dayOfWeek < 0 && format == RFCDateDay))
// return QDateTime;
// if (month >= 12 || dayOfWeek >= 7
// || (dayOfWeek < 0 && format == RFCDateDay))
// return QDateTime;
int i = parts[nyear].size();
if (i < 4) {
// It's an obsolete year specification with less than 4 digits
@ -220,31 +224,84 @@ class RssItem : public QObject {
return result;
}
public:
public:
// public constructor
RssItem(const QDomElement& properties) : read(false), downloadLink("none") {
RssItem(const QDomElement& properties): read(false) {
is_valid = false;
torrent_url = QString::null;
news_link = QString::null;
title = QString::null;
QDomElement property = properties.firstChild().toElement();
while(!property.isNull()) {
if (property.tagName() == "title")
if (property.tagName() == "title") {
title = property.text();
if(title.isEmpty()) {
is_valid = false;
return;
}
if(!torrent_url.isEmpty())
is_valid = true;
}
else if (property.tagName() == "enclosure") {
if(property.attribute("type", "") == "application/x-bittorrent") {
torrent_url = property.attribute("url", QString::null);
if(torrent_url.isNull()) {
qDebug("Error: Torrent URL is null");
return;
}
if(!title.isEmpty())
is_valid = true;
}
}
else if (property.tagName() == "link")
link = property.text();
news_link = property.text();
else if (property.tagName() == "description")
description = property.text();
else if (property.tagName() == "image")
image = property.text();
else if (property.tagName() == "pubDate")
date = parseDate(property.text());
else if (property.tagName() == "author")
author = property.text();
property = property.nextSibling().toElement();
}
hash = QCryptographicHash::hash(QByteArray(title.toLocal8Bit())+QByteArray(description.toLocal8Bit()), QCryptographicHash::Md5);
hash = QCryptographicHash::hash(QByteArray(title.toLocal8Bit()), QCryptographicHash::Md5);
}
RssItem(QString _title, QString _torrent_url, QString _news_link, QString _description, QDateTime _date, QString _author, bool _read):
title(_title), torrent_url(_torrent_url), news_link(_news_link), description(_description), date(_date), author(_author), read(_read){
if(!title.isEmpty() && !torrent_url.isEmpty()) {
is_valid = true;
} else {
std::cerr << "ERROR: an invalid RSS item was saved" << std::endl;
is_valid = false;
}
hash = QCryptographicHash::hash(QByteArray(title.toLocal8Bit()), QCryptographicHash::Md5);
}
~RssItem(){
}
QHash<QString, QVariant> toHash() const {
QHash<QString, QVariant> item;
item["title"] = title;
item["torrent_url"] = torrent_url;
item["news_link"] = news_link;
item["description"] = description;
item["date"] = date;
item["author"] = author;
item["read"] = read;
return item;
}
static RssItem* fromHash(QHash<QString, QVariant> h) {
RssItem * item = new RssItem(h["title"].toString(), h["torrent_url"].toString(), h["news_link"].toString(),
h["description"].toString(), h["date"].toDateTime(), h["author"].toString(), h["read"].toBool());
return item;
}
bool isValid() const {
return is_valid;
}
QString getTitle() const{
return title;
}
@ -253,32 +310,28 @@ class RssItem : public QObject {
return author;
}
QString getLink() const{
return link;
QString getTorrentUrl() const{
return torrent_url;
}
QString getHash() const {
return hash;
}
QString getLink() const {
return news_link;
}
QString getDescription() const{
if(description.isEmpty())
return tr("No description available");
return description;
}
QString getImage() const{
return image;
}
QDateTime getDate() const {
return date;
}
QString getDownloadLink() const{
return downloadLink;
}
bool isRead() const{
return read;
}
@ -292,7 +345,8 @@ class RssItem : public QObject {
class RssStream : public QObject{
Q_OBJECT
private:
private:
bittorrent *BTSession;
QString title;
QString link;
QString description;
@ -308,7 +362,7 @@ class RssStream : public QObject{
bool downloadFailure;
bool currently_loading;
public slots :
public slots :
// read and store the downloaded rss' informations
void processDownloadedFile(QString file_path) {
filePath = file_path;
@ -316,75 +370,74 @@ class RssStream : public QObject{
openRss();
lastRefresh.start();
refreshed = true;
}
}
void setDownloadFailed(){
void setDownloadFailed(){
downloadFailure = true;
lastRefresh.start();
}
}
public:
RssStream(QString _url): url(_url), alias(""), iconPath(":/Icons/rss16.png"), refreshed(false), downloadFailure(false), currently_loading(false) {
RssStream(bittorrent *BTSession, QString _url): BTSession(BTSession), url(_url), alias(""), iconPath(":/Icons/rss16.png"), refreshed(false), downloadFailure(false), currently_loading(false) {
qDebug("RSSStream constructed");
}
}
~RssStream(){
QSettings qBTRSS("qBittorrent-rss");
qBTRSS.setValue(url, getAllReadHashes());
~RssStream(){
if(refreshed) {
QSettings qBTRSS("qBittorrent", "qBittorrent-rss");
QVariantList old_items;
foreach(RssItem *item, listItem) {
old_items << item->toHash();
}
QHash<QString, QVariant> all_old_items = qBTRSS.value("old_items", QHash<QString, QVariant>()).toHash();
all_old_items[url] = old_items;
qBTRSS.setValue(url, all_old_items);
}
removeAllItems();
if(QFile::exists(filePath))
QFile::remove(filePath);
if(QFile::exists(iconPath) && !iconPath.startsWith(":/"))
QFile::remove(iconPath);
}
}
QStringList getAllReadHashes() {
QStringList hashes;
foreach(RssItem *item, listItem) {
if(item->isRead())
hashes << item->getHash();
}
return hashes;
}
// delete all the items saved
void removeAllItems() {
// delete all the items saved
void removeAllItems() {
qDeleteAll(listItem);
listItem.clear();
}
}
bool itemAlreadyExists(QString hash) {
bool itemAlreadyExists(QString hash) {
RssItem * item;
foreach(item, listItem) {
if(item->getHash() == hash) return true;
}
return false;
}
}
void setLoading(bool val) {
void setLoading(bool val) {
currently_loading = val;
}
}
bool isLoading() {
bool isLoading() {
return currently_loading;
}
}
QString getTitle() const{
QString getTitle() const{
return title;
}
}
QString getAlias() const{
QString getAlias() const{
qDebug("getAlias() returned Alias: %s", (const char*)alias.toLocal8Bit());
return alias;
}
}
void setAlias(QString _alias){
void setAlias(QString _alias){
qDebug("setAlias() to %s", (const char*)_alias.toLocal8Bit());
alias = _alias;
}
}
// Return the alias if the stream has one, the url if it has no alias
QString getAliasOrUrl() const{
// Return the alias if the stream has one, the url if it has no alias
QString getAliasOrUrl() const{
if(!alias.isEmpty()) {
qDebug("getAliasOrUrl() returned alias: %s", (const char*)alias.toLocal8Bit());
return alias;
@ -395,59 +448,59 @@ class RssStream : public QObject{
}
qDebug("getAliasOrUrl() returned url: %s", (const char*)url.toLocal8Bit());
return url;
}
}
QString getLink() const{
QString getLink() const{
return link;
}
}
QString getUrl() const{
QString getUrl() const{
return url;
}
}
QString getDescription() const{
QString getDescription() const{
return description;
}
}
QString getImage() const{
QString getImage() const{
return image;
}
}
QString getFilePath() const{
QString getFilePath() const{
return filePath;
}
}
QString getIconPath() const{
QString getIconPath() const{
if(downloadFailure)
return ":/Icons/oxygen/unavailable.png";
return iconPath;
}
}
bool hasCustomIcon() const{
bool hasCustomIcon() const{
return !iconPath.startsWith(":/");
}
}
void setIconPath(QString path) {
void setIconPath(QString path) {
iconPath = path;
}
}
RssItem* getItem(unsigned int index) const{
RssItem* getItem(unsigned int index) const{
return listItem.at(index);
}
}
unsigned int getNbNews() const{
unsigned int getNbNews() const{
return listItem.size();
}
}
void markAllAsRead() {
void markAllAsRead() {
RssItem *item;
foreach(item, listItem){
if(!item->isRead())
item->setRead();
}
}
}
unsigned int getNbUnRead() const{
unsigned int getNbUnRead() const{
unsigned int nbUnread=0;
RssItem *item;
foreach(item, listItem){
@ -455,37 +508,43 @@ class RssStream : public QObject{
++nbUnread;
}
return nbUnread;
}
}
QList<RssItem*> getNewsList() const{
QList<RssItem*> getNewsList() const{
return listItem;
}
}
QString getLastRefreshElapsedString() const{
QString getLastRefreshElapsedString() const{
if(!refreshed)
return tr("Never");
return tr("%1 ago", "10min ago").arg(misc::userFriendlyDuration((long)(lastRefresh.elapsed()/1000.)).replace("<", "&lt;"));
}
}
int getLastRefreshElapsed() const{
int getLastRefreshElapsed() const{
if(!refreshed)
return -1;
return lastRefresh.elapsed();
}
}
// download the icon from the adress
QString getIconUrl() {
// download the icon from the adress
QString getIconUrl() {
QUrl siteUrl(url);
return QString::fromUtf8("http://")+siteUrl.host()+QString::fromUtf8("/favicon.ico");
}
}
private:
// read and create items from a rss document
short readDoc(const QDomDocument& doc) {
QStringList old_items;
// read and create items from a rss document
short readDoc(const QDomDocument& doc) {
if(!refreshed) {
QSettings qBTRSS("qBittorrent-rss");
old_items = qBTRSS.value(this->url, QVariant()).toStringList();
QSettings qBTRSS("qBittorrent", "qBittorrent-rss");
QHash<QString, QVariant> all_old_items = qBTRSS.value("old_items", QHash<QString, QVariant>()).toHash();
QVariantList old_items = all_old_items.value(url, QVariantList()).toList();
foreach(const QVariant &var_it, old_items) {
QHash<QString, QVariant> item = var_it.toHash();
RssItem *rss_item = RssItem::fromHash(item);
if(rss_item->isValid())
listItem << rss_item;
}
}
// is it a rss file ?
QDomElement root = doc.documentElement();
@ -518,10 +577,26 @@ class RssStream : public QObject{
image = property.text();
else if(property.tagName() == "item") {
RssItem * item = new RssItem(property);
if(!itemAlreadyExists(item->getHash())) {
if(!refreshed && old_items.contains(item->getHash()))
item->setRead();
if(item->isValid() && !itemAlreadyExists(item->getHash())) {
listItem.append(item);
// Check if the item should be automatically downloaded
FeedFilter * matching_filter = FeedFilters::getFeedFilters(url).matches(item->getTitle());
if(matching_filter != 0) {
// Download the torrent
BTSession->addConsoleMessage(tr("Automatically downloading %1 torrent from %2 RSS feed...").arg(item->getTorrentUrl()).arg(getAliasOrUrl()));
if(matching_filter->isValid()) {
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());
}
// Clean up
delete matching_filter;
}
} else {
delete item;
}
@ -534,37 +609,37 @@ class RssStream : public QObject{
sortList();
resizeList();
return 0;
}
}
static void insertSortElem(QList<RssItem*> &list, RssItem *item) {
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);
}
}
void sortList() {
void sortList() {
QList<RssItem*> new_list;
RssItem *item;
foreach(item, listItem) {
insertSortElem(new_list, item);
}
listItem = new_list;
}
}
void resizeList() {
void resizeList() {
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
unsigned int max_articles = settings.value(QString::fromUtf8("Preferences/RSS/RSSMaxArticlesPerFeed"), 50).toInt();
unsigned int max_articles = settings.value(QString::fromUtf8("Preferences/RSS/RSSMaxArticlesPerFeed"), 100).toInt();
int excess = listItem.size() - max_articles;
if(excess <= 0) return;
for(int i=0; i<excess; ++i){
delete listItem.takeLast();
}
}
}
// existing and opening test after download
short openRss(){
// existing and opening test after download
short openRss(){
qDebug("openRss() called");
QDomDocument doc("Rss Seed");
QFile fileRss(filePath);
@ -590,22 +665,23 @@ class RssStream : public QObject{
fileRss.remove();
}
return return_lecture;
}
}
};
// global class, manage the whole rss stream
class RssManager : public QObject{
Q_OBJECT
private :
private :
QHash<QString, RssStream*> streams;
downloadThread *downloader;
QTimer newsRefresher;
unsigned int refreshInterval;
downloadThread *downloader;
QTimer newsRefresher;
unsigned int refreshInterval;
bittorrent *BTSession;
signals:
void feedInfosChanged(QString url, QString aliasOrUrl, unsigned int nbUnread);
void feedIconChanged(QString url, QString icon_path);
void feedInfosChanged(QString url, QString aliasOrUrl, unsigned int nbUnread);
void feedIconChanged(QString url, QString icon_path);
public slots :
@ -681,8 +757,8 @@ class RssManager : public QObject{
}
}
public :
RssManager(){
public :
RssManager(bittorrent *BTSession): BTSession(BTSession){
downloader = new downloadThread(this);
connect(downloader, SIGNAL(downloadFinished(QString, QString)), this, SLOT(processFinishedDownload(QString, QString)));
connect(downloader, SIGNAL(downloadFailure(QString, QString)), this, SLOT(handleDownloadFailure(QString, QString)));
@ -691,9 +767,9 @@ class RssManager : public QObject{
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
refreshInterval = settings.value(QString::fromUtf8("Preferences/RSS/RSSRefresh"), 5).toInt();
newsRefresher.start(refreshInterval*60000);
}
}
~RssManager(){
~RssManager(){
qDebug("Deleting RSSManager");
saveStreamList();
qDebug("Deleting all streams");
@ -701,10 +777,10 @@ class RssManager : public QObject{
qDebug("Deleting downloader thread");
delete downloader;
qDebug("RSSManager deleted");
}
}
// load the list of the rss stream
void loadStreamList(){
// load the list of the rss stream
void loadStreamList(){
QSettings settings("qBittorrent", "qBittorrent");
QStringList streamsUrl = settings.value("Rss/streamList").toStringList();
QStringList aliases = settings.value("Rss/streamAlias").toStringList();
@ -715,7 +791,7 @@ class RssManager : public QObject{
QString url;
unsigned int i = 0;
foreach(url, streamsUrl){
RssStream *stream = new RssStream(url);
RssStream *stream = new RssStream(BTSession, url);
QString alias = aliases.at(i);
if(!alias.isEmpty()) {
stream->setAlias(alias);
@ -724,10 +800,10 @@ class RssManager : public QObject{
++i;
}
qDebug("NB RSS streams loaded: %d", streamsUrl.size());
}
}
// save the list of the rss stream for the next session
void saveStreamList(){
// save the list of the rss stream for the next session
void saveStreamList(){
QList<QPair<QString, QString> > streamsList;
QStringList streamsUrl;
QStringList aliases;
@ -741,10 +817,10 @@ class RssManager : public QObject{
settings.setValue("streamList", streamsUrl);
settings.setValue("streamAlias", aliases);
settings.endGroup();
}
}
// add a stream to the manager
void addStream(RssStream* stream){
// add a stream to the manager
void addStream(RssStream* stream){
QString url = stream->getUrl();
if(streams.contains(url)){
qDebug("Not adding the Rss stream because it is already in the list");
@ -752,28 +828,28 @@ class RssManager : public QObject{
}
streams[url] = stream;
emit feedIconChanged(url, stream->getIconPath());
}
}
// add a stream to the manager
RssStream* addStream(QString url){
// add a stream to the manager
RssStream* addStream(QString url){
if(streams.contains(url)){
qDebug("Not adding the Rss stream because it is already in the list");
return 0;
}
RssStream* stream = new RssStream(url);
RssStream* stream = new RssStream(BTSession, url);
streams[url] = stream;
refresh(url);
return stream;
}
}
// remove a stream from the manager
void removeStream(RssStream* stream){
// remove a stream from the manager
void removeStream(RssStream* stream){
QString url = stream->getUrl();
Q_ASSERT(streams.contains(url));
delete streams.take(url);
}
}
QList<RssStream*> findFeedsWithIcon(QString icon_url){
QList<RssStream*> findFeedsWithIcon(QString icon_url){
QList<RssStream*> res;
RssStream* stream;
foreach(stream, streams){
@ -781,21 +857,21 @@ class RssManager : public QObject{
res << stream;
}
return res;
}
}
void removeStream(QString url){
void removeStream(QString url){
Q_ASSERT(streams.contains(url));
delete streams.take(url);
}
}
// remove all the streams in the manager
void removeAll(){
// remove all the streams in the manager
void removeAll(){
qDeleteAll(streams);
streams.clear();
}
}
// reload all the xml files from the web
void refreshAll(){
// reload all the xml files from the web
void refreshAll(){
qDebug("Refreshing all rss feeds");
RssStream *stream;
foreach(stream, streams){
@ -808,9 +884,9 @@ class RssManager : public QObject{
downloader->downloadUrl(stream->getIconUrl());
}
}
}
}
void refresh(QString url) {
void refresh(QString url) {
Q_ASSERT(streams.contains(url));
RssStream *stream = streams[url];
if(stream->isLoading()) return;
@ -821,31 +897,31 @@ class RssManager : public QObject{
}else{
qDebug("No need to download this feed's icon, it was already downloaded");
}
}
}
// XXX: Used?
unsigned int getNbFeeds() {
// XXX: Used?
unsigned int getNbFeeds() {
return streams.size();
}
}
RssStream* getFeed(QString url){
RssStream* getFeed(QString url){
Q_ASSERT(streams.contains(url));
return streams[url];
}
}
// Set an alias for a stream and save it for later
void setAlias(QString url, QString newAlias) {
// Set an alias for a stream and save it for later
void setAlias(QString url, QString newAlias) {
Q_ASSERT(!newAlias.isEmpty());
RssStream * stream = streams.value(url, 0);
Q_ASSERT(stream != 0);
stream->setAlias(newAlias);
emit feedInfosChanged(url, stream->getAliasOrUrl(), stream->getNbUnRead());
}
}
// Return all the rss feeds we have
QList<RssStream*> getRssFeeds() const {
// Return all the rss feeds we have
QList<RssStream*> getRssFeeds() const {
return streams.values();
}
}
};

View file

@ -1,7 +1,8 @@
<ui version="4.0" >
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>RSS</class>
<widget class="QWidget" name="RSS" >
<property name="geometry" >
<widget class="QWidget" name="RSS">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
@ -9,60 +10,60 @@
<height>447</height>
</rect>
</property>
<property name="windowTitle" >
<property name="windowTitle">
<string>Search</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2" >
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QSplitter" name="splitter_h" >
<property name="orientation" >
<widget class="QSplitter" name="splitter_h">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QWidget" name="layoutWidget" >
<layout class="QVBoxLayout" >
<property name="spacing" >
<widget class="QWidget" name="layoutWidget">
<layout class="QVBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin" >
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QTreeWidget" name="listStreams" >
<property name="contextMenuPolicy" >
<widget class="QTreeWidget" name="listStreams">
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="selectionMode" >
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
<property name="columnCount" >
<property name="columnCount">
<number>2</number>
</property>
<column>
<property name="text" >
<property name="text">
<string>RSS streams:</string>
</property>
</column>
<column>
<property name="text" >
<property name="text">
<string>2</string>
</property>
</column>
</widget>
</item>
<item>
<layout class="QHBoxLayout" >
<property name="spacing" >
<layout class="QHBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin" >
<property name="margin">
<number>0</number>
</property>
<item>
<spacer>
<property name="orientation" >
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0" >
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
@ -71,20 +72,20 @@
</spacer>
</item>
<item>
<widget class="QPushButton" name="delStream_button" >
<property name="minimumSize" >
<widget class="QPushButton" name="delStream_button">
<property name="minimumSize">
<size>
<width>55</width>
<height>32</height>
</size>
</property>
<property name="toolTip" >
<property name="toolTip">
<string>Delete selected streams</string>
</property>
<property name="text" >
<property name="text">
<string/>
</property>
<property name="iconSize" >
<property name="iconSize">
<size>
<width>32</width>
<height>32</height>
@ -93,20 +94,20 @@
</widget>
</item>
<item>
<widget class="QPushButton" name="refreshAll_button" >
<property name="minimumSize" >
<widget class="QPushButton" name="refreshAll_button">
<property name="minimumSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="toolTip" >
<property name="toolTip">
<string>Refresh RSS streams</string>
</property>
<property name="text" >
<property name="text">
<string/>
</property>
<property name="iconSize" >
<property name="iconSize">
<size>
<width>32</width>
<height>32</height>
@ -115,20 +116,20 @@
</widget>
</item>
<item>
<widget class="QPushButton" name="addStream_button" >
<property name="minimumSize" >
<widget class="QPushButton" name="addStream_button">
<property name="minimumSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="toolTip" >
<property name="toolTip">
<string>Add a new RSS stream</string>
</property>
<property name="text" >
<property name="text">
<string/>
</property>
<property name="iconSize" >
<property name="iconSize">
<size>
<width>55</width>
<height>32</height>
@ -138,10 +139,10 @@
</item>
<item>
<spacer>
<property name="orientation" >
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0" >
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
@ -155,28 +156,39 @@
<zorder>listStreams</zorder>
<zorder></zorder>
</widget>
<widget class="QWidget" name="layoutWidget" >
<layout class="QVBoxLayout" name="verticalLayout" >
<widget class="QWidget" name="layoutWidget">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="news_lbl" >
<property name="font" >
<widget class="QLabel" name="news_lbl">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text" >
<string>&lt;b>News:&lt;/b> &lt;i>(double-click to open the link in your web browser)&lt;/i></string>
<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:'Sans'; font-size:10pt; 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;&lt;span style=&quot; font-weight:600;&quot;&gt;Torrents:&lt;/span&gt; &lt;span style=&quot; font-style:italic;&quot;&gt;(double-click to download)&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item>
<widget class="QSplitter" name="splitter_v" >
<property name="orientation" >
<widget class="QSplitter" name="splitter_v">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QListWidget" name="listNews" />
<widget class="QTextBrowser" name="textBrowser" />
<widget class="QListWidget" name="listNews">
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
</widget>
<widget class="QTextBrowser" name="textBrowser"/>
</widget>
</item>
</layout>
@ -184,37 +196,75 @@
</widget>
</item>
</layout>
<action name="actionDelete" >
<property name="text" >
<action name="actionDelete">
<property name="text">
<string>Delete</string>
</property>
</action>
<action name="actionRename" >
<property name="text" >
<action name="actionRename">
<property name="text">
<string>Rename</string>
</property>
</action>
<action name="actionRefresh" >
<property name="text" >
<action name="actionRefresh">
<property name="text">
<string>Refresh</string>
</property>
</action>
<action name="actionCreate" >
<property name="text" >
<action name="actionCreate">
<property name="text">
<string>Add RSS stream</string>
</property>
</action>
<action name="actionRefreshAll" >
<property name="text" >
<action name="actionRefreshAll">
<property name="text">
<string>Refresh all streams</string>
</property>
</action>
<action name="actionMark_all_as_read" >
<property name="text" >
<action name="actionMark_all_as_read">
<property name="text">
<string>Mark all as read</string>
</property>
</action>
<action name="actionDownload_torrent">
<property name="icon">
<iconset resource="icons.qrc">
<normaloff>:/Icons/oxygen/download.png</normaloff>:/Icons/oxygen/download.png</iconset>
</property>
<property name="text">
<string>Download torrent</string>
</property>
</action>
<action name="actionOpen_news_URL">
<property name="icon">
<iconset resource="icons.qrc">
<normaloff>:/Icons/url.png</normaloff>:/Icons/url.png</iconset>
</property>
<property name="text">
<string>Open news URL</string>
</property>
</action>
<action name="actionCopy_feed_URL">
<property name="icon">
<iconset resource="icons.qrc">
<normaloff>:/Icons/oxygen/edit-copy.png</normaloff>:/Icons/oxygen/edit-copy.png</iconset>
</property>
<property name="text">
<string>Copy feed URL</string>
</property>
</action>
<action name="actionRSS_feed_downloader">
<property name="icon">
<iconset resource="icons.qrc">
<normaloff>:/Icons/oxygen/download.png</normaloff>:/Icons/oxygen/download.png</iconset>
</property>
<property name="text">
<string>RSS feed downloader</string>
</property>
</action>
</widget>
<resources/>
<resources>
<include location="icons.qrc"/>
</resources>
<connections/>
</ui>

View file

@ -28,9 +28,6 @@
* Contact : chris@qbittorrent.org arnaud@qbittorrent.org
*/
#include "rss_imp.h"
#include "rss.h"
#include <QDesktopServices>
#include <QInputDialog>
#include <QMenu>
@ -38,32 +35,50 @@
#include <QMessageBox>
#include <QTimer>
#include <QString>
#include <QClipboard>
// display a right-click menu
void RSSImp::displayRSSListMenu(const QPoint& pos){
#include "rss_imp.h"
#include "rss.h"
#include "FeedDownloader.h"
#include "bittorrent.h"
// display a right-click menu
void RSSImp::displayRSSListMenu(const QPoint&){
QMenu myFinishedListMenu(this);
QTreeWidgetItem* item = listStreams->itemAt(pos);
QList<QTreeWidgetItem*> selectedItems = listStreams->selectedItems();
if(item != 0) {
if(selectedItems.size() > 0) {
myFinishedListMenu.addAction(actionMark_all_as_read);
myFinishedListMenu.addAction(actionDelete);
if(selectedItems.size() == 1)
if(selectedItems.size() == 1) {
myFinishedListMenu.addAction(actionRename);
myFinishedListMenu.addAction(actionRSS_feed_downloader);
}
myFinishedListMenu.addAction(actionCopy_feed_URL);
myFinishedListMenu.addAction(actionRefresh);
}else{
myFinishedListMenu.addAction(actionCreate);
myFinishedListMenu.addAction(actionRefreshAll);
}
myFinishedListMenu.exec(mapToGlobal(pos)+QPoint(10,33));
}
myFinishedListMenu.exec(QCursor::pos());
}
// add a stream by a button
void RSSImp::on_addStream_button_clicked() {
void RSSImp::displayItemsListMenu(const QPoint&){
QMenu myItemListMenu(this);
QList<QTreeWidgetItem*> selectedItems = listStreams->selectedItems();
if(selectedItems.size() > 0) {
myItemListMenu.addAction(actionDownload_torrent);
myItemListMenu.addAction(actionOpen_news_URL);
}
myItemListMenu.exec(QCursor::pos());
}
// add a stream by a button
void RSSImp::on_addStream_button_clicked() {
createStream();
}
}
// delete a stream by a button
void RSSImp::on_delStream_button_clicked() {
// delete a stream by a button
void RSSImp::on_delStream_button_clicked() {
QList<QTreeWidgetItem*> selectedItems = listStreams->selectedItems();
QTreeWidgetItem *item;
if(!selectedItems.size()) return;
@ -88,23 +103,34 @@
if(urlsToDelete.size())
rssmanager->saveStreamList();
}
}
}
// refresh all streams by a button
void RSSImp::on_refreshAll_button_clicked() {
// refresh all streams by a button
void RSSImp::on_refreshAll_button_clicked() {
refreshAllStreams();
}
}
// open the url of the news in a browser
void RSSImp::openInBrowser(QListWidgetItem *item) {
void RSSImp::downloadTorrent() {
QList<QListWidgetItem *> selected_items = listNews->selectedItems();
foreach(const QListWidgetItem* item, selected_items) {
RssItem* news = rssmanager->getFeed(selectedFeedUrl)->getItem(listNews->row(item));
BTSession->downloadFromUrl(news->getTorrentUrl());
}
}
// open the url of the news in a browser
void RSSImp::openNewsUrl() {
QList<QListWidgetItem *> selected_items = listNews->selectedItems();
foreach(const QListWidgetItem* item, selected_items) {
RssItem* news = rssmanager->getFeed(selectedFeedUrl)->getItem(listNews->row(item));
QString link = news->getLink();
if(!link.isEmpty())
QDesktopServices::openUrl(QUrl(link));
}
}
//right-click on stream : give him an alias
void RSSImp::renameStream() {
//right-click on stream : give him an alias
void RSSImp::renameStream() {
QList<QTreeWidgetItem*> selectedItems = listStreams->selectedItems();
Q_ASSERT(selectedItems.size() == 1);
QTreeWidgetItem *item = selectedItems.at(0);
@ -114,10 +140,10 @@
if(ok) {
rssmanager->setAlias(url, newAlias);
}
}
}
//right-click on stream : refresh it
void RSSImp::refreshSelectedStreams() {
//right-click on stream : refresh it
void RSSImp::refreshSelectedStreams() {
QList<QTreeWidgetItem*> selectedItems = listStreams->selectedItems();
QTreeWidgetItem* item;
foreach(item, selectedItems){
@ -127,9 +153,24 @@
rssmanager->refresh(url);
item->setData(0,Qt::DecorationRole, QVariant(QIcon(":/Icons/loading.png")));
}
}
}
void RSSImp::on_actionMark_all_as_read_triggered() {
void RSSImp::copySelectedFeedsURL() {
QStringList URLs;
QList<QTreeWidgetItem*> selectedItems = listStreams->selectedItems();
QTreeWidgetItem* item;
foreach(item, selectedItems){
URLs << item->text(1);
}
qApp->clipboard()->setText(URLs.join("\n"));
}
void RSSImp::showFeedDownloader() {
QTreeWidgetItem* item = listStreams->selectedItems()[0];
new FeedDownloaderDlg(this, item->text(1), rssmanager->getFeed(item->text(1))->getAliasOrUrl(), BTSession);
}
void RSSImp::on_actionMark_all_as_read_triggered() {
textBrowser->clear();
listNews->clear();
QList<QTreeWidgetItem*> selectedItems = listStreams->selectedItems();
@ -142,10 +183,10 @@
}
if(selectedItems.size())
refreshNewsList(selectedItems.last(), 0);
}
}
//right-click somewhere, refresh all the streams
void RSSImp::refreshAllStreams() {
//right-click somewhere, refresh all the streams
void RSSImp::refreshAllStreams() {
textBrowser->clear();
listNews->clear();
unsigned int nbFeeds = listStreams->topLevelItemCount();
@ -153,9 +194,9 @@
listStreams->topLevelItem(i)->setData(0,Qt::DecorationRole, QVariant(QIcon(":/Icons/loading.png")));
rssmanager->refreshAll();
updateLastRefreshedTimeForStreams();
}
}
void RSSImp::fillFeedsList() {
void RSSImp::fillFeedsList() {
QList<RssStream*> feeds = rssmanager->getRssFeeds();
RssStream* stream;
foreach(stream, feeds){
@ -165,12 +206,17 @@
item->setData(1, Qt::DisplayRole, stream->getUrl());
item->setToolTip(0, QString::fromUtf8("<b>")+tr("Description:")+QString::fromUtf8("</b> ")+stream->getDescription()+QString::fromUtf8("<br/><b>")+tr("url:")+QString::fromUtf8("</b> ")+stream->getUrl()+QString::fromUtf8("<br/><b>")+tr("Last refresh:")+QString::fromUtf8("</b> ")+stream->getLastRefreshElapsedString());
}
}
}
//right-click, register a new stream
void RSSImp::createStream() {
//right-click, register a new stream
void RSSImp::createStream() {
bool ok;
QString newUrl = QInputDialog::getText(this, tr("Please type a rss stream url"), tr("Stream URL:"), QLineEdit::Normal, "http://", &ok);
QString clip_txt = qApp->clipboard()->text();
QString default_url = "http://";
if(clip_txt.startsWith("http://", Qt::CaseInsensitive) || clip_txt.startsWith("https://", Qt::CaseInsensitive) || clip_txt.startsWith("ftp://", Qt::CaseInsensitive)) {
default_url = clip_txt;
}
QString newUrl = QInputDialog::getText(this, tr("Please type a rss stream url"), tr("Stream URL:"), QLineEdit::Normal, default_url, &ok);
if(ok) {
newUrl = newUrl.trimmed();
if(!newUrl.isEmpty()){
@ -193,27 +239,27 @@
rssmanager->saveStreamList();
}
}
}
}
void RSSImp::updateLastRefreshedTimeForStreams() {
void RSSImp::updateLastRefreshedTimeForStreams() {
unsigned int nbFeeds = listStreams->topLevelItemCount();
for(unsigned int i=0; i<nbFeeds; ++i){
QTreeWidgetItem* item = listStreams->topLevelItem(i);
RssStream* stream = rssmanager->getFeed(item->data(1, Qt::DisplayRole).toString());
item->setToolTip(0, QString::fromUtf8("<b>")+tr("Description:")+QString::fromUtf8("</b> ")+stream->getDescription()+QString::fromUtf8("<br/><b>")+tr("url:")+QString::fromUtf8("</b> ")+stream->getUrl()+QString::fromUtf8("<br/><b>")+tr("Last refresh:")+QString::fromUtf8("</b> ")+stream->getLastRefreshElapsedString());
}
}
}
// fills the newsList
void RSSImp::refreshNewsList(QTreeWidgetItem* item, int) {
// fills the newsList
void RSSImp::refreshNewsList(QTreeWidgetItem* item, int) {
selectedFeedUrl = item->text(1);
RssStream *stream = rssmanager->getFeed(selectedFeedUrl);
listNews->clear();
qDebug("Getting the list of news");
QList<RssItem*> news = stream->getNewsList();
// Clear the list first
listNews->clear();
qDebug("Got the list of news");
RssItem* article;
foreach(article, news){
foreach(RssItem* article, news){
QListWidgetItem* it = new QListWidgetItem(article->getTitle(), listNews);
if(article->isRead()){
it->setData(Qt::ForegroundRole, QVariant(QColor("grey")));
@ -224,12 +270,12 @@
}
}
qDebug("Added all news to the GUI");
selectFirstNews();
//selectFirstNews();
qDebug("First news selected");
}
}
// display a news
void RSSImp::refreshTextBrowser(QListWidgetItem *item) {
// display a news
void RSSImp::refreshTextBrowser(QListWidgetItem *item) {
RssItem* article = rssmanager->getFeed(selectedFeedUrl)->getItem(listNews->row(item));
QString html;
html += "<div style='border: 2px solid red; margin-left: 5px; margin-right: 5px; margin-bottom: 5px;'>";
@ -247,17 +293,17 @@
item->setData(Qt::ForegroundRole, QVariant(QColor("grey")));
item->setData(Qt::DecorationRole, QVariant(QIcon(":/Icons/sphere.png")));
updateFeedNbNews(selectedFeedUrl);
}
}
void RSSImp::saveSlidersPosition() {
void RSSImp::saveSlidersPosition() {
// Remember sliders positions
QSettings settings("qBittorrent", "qBittorrent");
settings.setValue("rss/splitter_h", splitter_h->saveState());
settings.setValue("rss/splitter_v", splitter_v->saveState());
qDebug("Splitters position saved");
}
}
void RSSImp::restoreSlidersPosition() {
void RSSImp::restoreSlidersPosition() {
QSettings settings("qBittorrent", "qBittorrent");
QByteArray pos_h = settings.value("rss/splitter_h", QByteArray()).toByteArray();
if(!pos_h.isNull()) {
@ -267,9 +313,9 @@
if(!pos_v.isNull()) {
splitter_v->restoreState(pos_v);
}
}
}
QTreeWidgetItem* RSSImp::getTreeItemFromUrl(QString url) const{
QTreeWidgetItem* RSSImp::getTreeItemFromUrl(QString url) const{
unsigned int nbItems = listStreams->topLevelItemCount();
for(unsigned int i = 0; i<nbItems; ++i){
QTreeWidgetItem* item = listStreams->topLevelItem(i);
@ -279,20 +325,20 @@
qDebug("Cannot find url %s in feeds list", (const char*)url.toLocal8Bit());
Q_ASSERT(false); // Should never go through here
return (QTreeWidgetItem*)0;
}
}
void RSSImp::updateFeedIcon(QString url, QString icon_path){
void RSSImp::updateFeedIcon(QString url, QString icon_path){
QTreeWidgetItem *item = getTreeItemFromUrl(url);
item->setData(0,Qt::DecorationRole, QVariant(QIcon(icon_path)));
}
}
void RSSImp::updateFeedNbNews(QString url){
void RSSImp::updateFeedNbNews(QString url){
QTreeWidgetItem *item = getTreeItemFromUrl(url);
RssStream *stream = rssmanager->getFeed(url);
item->setText(0, stream->getAliasOrUrl() + QString::fromUtf8(" (") + QString::number(stream->getNbUnRead(), 10)+ QString(")"));
}
}
void RSSImp::updateFeedInfos(QString url, QString aliasOrUrl, unsigned int nbUnread){
void RSSImp::updateFeedInfos(QString url, QString aliasOrUrl, unsigned int nbUnread){
QTreeWidgetItem *item = getTreeItemFromUrl(url);
RssStream *stream = rssmanager->getFeed(url);
item->setText(0, aliasOrUrl + QString::fromUtf8(" (") + QString::number(nbUnread, 10)+ QString(")"));
@ -302,9 +348,9 @@
if(selectedFeedUrl == url){
refreshNewsList(getTreeItemFromUrl(url), 0);
}
}
}
RSSImp::RSSImp() : QWidget(){
RSSImp::RSSImp(bittorrent *BTSession) : QWidget(), BTSession(BTSession){
setupUi(this);
// icons of bottom buttons
addStream_button->setIcon(QIcon(QString::fromUtf8(":/Icons/oxygen/subscribe.png")));
@ -321,20 +367,28 @@
// Hide second column (url)
listStreams->hideColumn(1);
rssmanager = new RssManager();
rssmanager = new RssManager(BTSession);
fillFeedsList();
connect(rssmanager, SIGNAL(feedInfosChanged(QString, QString, unsigned int)), this, SLOT(updateFeedInfos(QString, QString, unsigned int)));
connect(rssmanager, SIGNAL(feedIconChanged(QString, QString)), this, SLOT(updateFeedIcon(QString, QString)));
connect(listStreams, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayRSSListMenu(const QPoint&)));
connect(listNews, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayItemsListMenu(const QPoint&)));
connect(actionDelete, SIGNAL(triggered()), this, SLOT(on_delStream_button_clicked()));
connect(actionRename, SIGNAL(triggered()), this, SLOT(renameStream()));
connect(actionRefresh, SIGNAL(triggered()), this, SLOT(refreshSelectedStreams()));
connect(actionCreate, SIGNAL(triggered()), this, SLOT(createStream()));
connect(actionRefreshAll, SIGNAL(triggered()), this, SLOT(refreshAllStreams()));
connect(actionCopy_feed_URL, SIGNAL(triggered()), this, SLOT(copySelectedFeedsURL()));
connect(actionRSS_feed_downloader, SIGNAL(triggered()), this, SLOT(showFeedDownloader()));
connect(actionOpen_news_URL, SIGNAL(triggered()), this, SLOT(openNewsUrl()));
connect(actionDownload_torrent, SIGNAL(triggered()), this, SLOT(downloadTorrent()));
connect(listStreams, SIGNAL(itemClicked(QTreeWidgetItem*,int)), this, SLOT(refreshNewsList(QTreeWidgetItem*,int)));
connect(listNews, SIGNAL(itemClicked(QListWidgetItem *)), this, SLOT(refreshTextBrowser(QListWidgetItem *)));
connect(listNews, SIGNAL(itemDoubleClicked(QListWidgetItem *)), this, SLOT(openInBrowser(QListWidgetItem *)));
connect(listNews, SIGNAL(itemDoubleClicked(QListWidgetItem *)), this, SLOT(downloadTorrent()));
refreshTimeTimer = new QTimer(this);
connect(refreshTimeTimer, SIGNAL(timeout()), this, SLOT(updateLastRefreshedTimeForStreams()));
refreshTimeTimer->start(60000); // 1min
@ -348,27 +402,27 @@
connect(splitter_v, SIGNAL(splitterMoved(int, int)), this, SLOT(saveSlidersPosition()));
connect(splitter_h, SIGNAL(splitterMoved(int, int)), this, SLOT(saveSlidersPosition()));
qDebug("RSSImp constructed");
}
}
void RSSImp::selectFirstFeed(){
void RSSImp::selectFirstFeed(){
if(listStreams->topLevelItemCount()){
QTreeWidgetItem *first = listStreams->topLevelItem(0);
listStreams->setCurrentItem(first);
selectedFeedUrl = first->text(1);
}
}
}
void RSSImp::selectFirstNews(){
void RSSImp::selectFirstNews(){
if(listNews->count()){
listNews->setCurrentRow(0);
refreshTextBrowser(listNews->currentItem());
}
}
}
RSSImp::~RSSImp(){
RSSImp::~RSSImp(){
qDebug("Deleting RSSImp...");
delete refreshTimeTimer;
delete rssmanager;
qDebug("RSSImp deleted");
}
}

View file

@ -36,6 +36,7 @@
class QTimer;
class RssManager;
class bittorrent;
class RSSImp : public QWidget, public Ui::RSS{
Q_OBJECT
@ -44,6 +45,7 @@ class RSSImp : public QWidget, public Ui::RSS{
RssManager *rssmanager;
QTimer *refreshTimeTimer;
QString selectedFeedUrl;
bittorrent *BTSession;
public slots:
void on_delStream_button_clicked();
@ -52,8 +54,10 @@ class RSSImp : public QWidget, public Ui::RSS{
void on_addStream_button_clicked();
void on_refreshAll_button_clicked();
void displayRSSListMenu(const QPoint&);
void displayItemsListMenu(const QPoint&);
void renameStream();
void refreshSelectedStreams();
void copySelectedFeedsURL();
void createStream();
void refreshAllStreams();
void refreshNewsList(QTreeWidgetItem* item, int);
@ -61,7 +65,8 @@ class RSSImp : public QWidget, public Ui::RSS{
void updateLastRefreshedTimeForStreams();
void updateFeedIcon(QString url, QString icon_path);
void updateFeedInfos(QString url, QString aliasOrUrl, unsigned int nbUnread);
void openInBrowser(QListWidgetItem *);
void openNewsUrl();
void downloadTorrent();
void fillFeedsList();
void selectFirstFeed();
void selectFirstNews();
@ -69,9 +74,10 @@ class RSSImp : public QWidget, public Ui::RSS{
void on_actionMark_all_as_read_triggered();
void saveSlidersPosition();
void restoreSlidersPosition();
void showFeedDownloader();
public:
RSSImp();
RSSImp(bittorrent *BTSession);
~RSSImp();
QTreeWidgetItem* getTreeItemFromUrl(QString url) const;
};

View file

@ -14,7 +14,7 @@ CONFIG += qt \
network
# Update this VERSION for each release
DEFINES += VERSION=\\\"v1.5.0alpha\\\"
DEFINES += VERSION=\\\"v1.5.0beta1\\\"
DEFINES += VERSION_MAJOR=1
DEFINES += VERSION_MINOR=5
DEFINES += VERSION_BUGFIX=0
@ -183,7 +183,8 @@ HEADERS += GUI.h \
console_imp.h \
ico.h \
stacktrace.h \
torrentPersistentData.h
torrentPersistentData.h \
FeedDownloader.h
FORMS += MainWindow.ui \
options.ui \
about.ui \
@ -201,7 +202,8 @@ FORMS += MainWindow.ui \
engineSelect.ui \
pluginSource.ui \
trackersAdd.ui \
console.ui
console.ui \
FeedDownloader.ui
SOURCES += GUI.cpp \
main.cpp \
options_imp.cpp \

View file

@ -145,7 +145,7 @@ public:
static void saveTorrentPersistentData(QTorrentHandle h, bool is_magnet = false) {
Q_ASSERT(h.is_valid());
qDebug("Saving persistent data for %s", h.hash().toUtf8().data());
qDebug("Saving persistent data for %s", h.hash().toLocal8Bit().data());
// First, remove temp data
TorrentTempData::deleteTempData(h.hash());
Q_ASSERT(!TorrentTempData::hasTempData(h.hash()));
@ -187,7 +187,7 @@ public:
// Save data
all_data[h.hash()] = data;
settings.setValue("torrents", all_data);
qDebug("TorrentPersistentData: Saving save_path %s, hash: %s", h.save_path().toUtf8().data(), h.hash().toUtf8().data());
qDebug("TorrentPersistentData: Saving save_path %s, hash: %s", h.save_path().toLocal8Bit().data(), h.hash().toLocal8Bit().data());
}
static void saveTrackers(QTorrentHandle h) {
@ -233,7 +233,7 @@ public:
data["save_path"] = save_path;
all_data[hash] = data;
settings.setValue("torrents", all_data);
qDebug("TorrentPersistentData: Saving save_path: %s, hash: %s", save_path.toUtf8().data(), hash.toUtf8().data());
qDebug("TorrentPersistentData: Saving save_path: %s, hash: %s", save_path.toLocal8Bit().data(), hash.toLocal8Bit().data());
}
static void saveUrlSeeds(QTorrentHandle h) {
@ -295,7 +295,7 @@ public:
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent-resume"));
QHash<QString, QVariant> all_data = settings.value("torrents", QHash<QString, QVariant>()).toHash();
QHash<QString, QVariant> data = all_data[hash].toHash();
qDebug("TorrentPersistentData: getSavePath %s", data["save_path"].toString().toUtf8().data());
qDebug("TorrentPersistentData: getSavePath %s", data["save_path"].toString().toLocal8Bit().data());
return data["save_path"].toString();
}