Browse Source

FEATURE: Added a torrent import assistant to seed or keep downloading outside torrents

adaptive-webui-19844
Christophe Dumez 14 years ago
parent
commit
90dd337069
  1. 1
      Changelog
  2. 6
      src/GUI.cpp
  3. 1
      src/GUI.h
  4. 1
      src/misc.cpp
  5. 8
      src/misc.h
  6. 2
      src/previewselect.h
  7. 2
      src/properties/propertieswidget.cpp
  8. 73
      src/qtlibtorrent/qbtsession.cpp
  9. 2
      src/qtlibtorrent/qtorrenthandle.cpp
  10. 2
      src/qtlibtorrent/qtorrenthandle.h
  11. 9
      src/src.pro
  12. 259
      src/torrentimportdlg.cpp
  13. 81
      src/torrentimportdlg.h
  14. 9
      src/torrentpersistentdata.h
  15. 18
      src/ui/mainwindow.ui
  16. 133
      src/ui/torrentimportdlg.ui

1
Changelog

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
* Unreleased - Christophe Dumez <chris@qbittorrent.org> - v2.5.0
- FEATURE: qBittorrent can now act as a tracker
- FEATURE: Added feature to shutdown qbittorrent on torrents completion
- FEATURE: Added a torrent import assistant to seed or keep downloading outside torrents
- FEATURE: Added a transfer list column to display the current tracker
- COSMETIC: Replaced message box by on-screen notification for download errors

6
src/GUI.cpp

@ -67,6 +67,7 @@ @@ -67,6 +67,7 @@
#include "statusbar.h"
#include "hidabletabwidget.h"
#include "qinisettings.h"
#include "torrentimportdlg.h"
#ifdef Q_WS_MAC
#include "qmacapplication.h"
void qt_mac_set_dock_menu(QMenu *menu);
@ -1195,6 +1196,11 @@ void GUI::on_actionSearch_engine_triggered() { @@ -1195,6 +1196,11 @@ void GUI::on_actionSearch_engine_triggered() {
displaySearchTab(actionSearch_engine->isChecked());
}
void GUI::on_action_Import_Torrent_triggered()
{
TorrentImportDlg::importTorrent(BTSession);
}
/*****************************************************
* *
* HTTP Downloader *

1
src/GUI.h

@ -184,6 +184,7 @@ private slots: @@ -184,6 +184,7 @@ private slots:
void on_actionTop_tool_bar_triggered();
void on_actionShutdown_when_downloads_complete_triggered();
void on_actionShutdown_qBittorrent_when_downloads_complete_triggered();
void on_action_Import_Torrent_triggered();
};
#endif

1
src/misc.cpp

@ -512,6 +512,7 @@ QString misc::friendlyUnit(double val) { @@ -512,6 +512,7 @@ QString misc::friendlyUnit(double val) {
}
bool misc::isPreviewable(QString extension){
if(extension.isEmpty()) return false;
extension = extension.toUpper();
if(extension == "AVI") return true;
if(extension == "MP3") return true;

8
src/misc.h

@ -98,6 +98,14 @@ public: @@ -98,6 +98,14 @@ public:
return x;
}
static inline QString file_extension(const QString &filename) {
QString extension;
if(filename.contains(".")) {
extension = filename.mid(filename.lastIndexOf(".")+1);
}
return extension;
}
static void shutdownComputer();
static bool safeRemove(QString file_path) {

2
src/previewselect.h

@ -109,7 +109,7 @@ public: @@ -109,7 +109,7 @@ public:
h.file_progress(fp);
unsigned int nbFiles = h.num_files();
for(unsigned int i=0; i<nbFiles; ++i){
QString fileName = h.file_at(i);
QString fileName = h.filename_at(i);
QString extension = fileName.split(QString::fromUtf8(".")).last().toUpper();
if(misc::isPreviewable(extension)) {
int row = previewListModel->rowCount();

2
src/properties/propertieswidget.cpp

@ -730,7 +730,7 @@ void PropertiesWidget::renameSelectedFile() { @@ -730,7 +730,7 @@ void PropertiesWidget::renameSelectedFile() {
#if defined(Q_WS_WIN) || defined(Q_OS_OS2)
if(h.file_at(0).compare(new_file_name, Qt::CaseInsensitive) != 0) {
#else
if(h.file_at(0).compare(new_file_name, Qt::CaseSensitive) != 0) {
if(h.filename_at(0).compare(new_file_name, Qt::CaseSensitive) != 0) {
#endif
qDebug("Renaming single file to %s", qPrintable(new_file_name));
h.rename_file(0, new_file_name);

73
src/qtlibtorrent/qbtsession.cpp

@ -1107,6 +1107,7 @@ QTorrentHandle QBtSession::addTorrent(QString path, bool fromScanDir, QString fr @@ -1107,6 +1107,7 @@ QTorrentHandle QBtSession::addTorrent(QString path, bool fromScanDir, QString fr
loadTorrentSettings(h);
if(!resumed) {
qDebug("This is a NEW torrent (first time)...");
loadTorrentTempData(h, savePath, false);
#if LIBTORRENT_VERSION_MINOR > 14
@ -1191,45 +1192,48 @@ add_torrent_params QBtSession::initializeAddTorrentParams(QString hash) { @@ -1191,45 +1192,48 @@ add_torrent_params QBtSession::initializeAddTorrentParams(QString hash) {
}
void QBtSession::loadTorrentTempData(QTorrentHandle h, QString savePath, bool magnet) {
qDebug("loadTorrentTempdata() - ENTER");
const QString hash = h.hash();
// Sequential download
if(!TorrentTempData::hasTempData(hash)) return;
// sequential download
h.set_sequential_download(TorrentTempData::isSequential(hash));
// The following is useless for newly added magnet
if(!magnet) {
// Files priorities
vector<int> fp;
TorrentTempData::getFilesPriority(hash, fp);
h.prioritize_files(fp);
// Update file names
const QStringList files_path = TorrentTempData::getFilesPath(hash);
bool force_recheck = false;
if(files_path.size() == h.num_files()) {
for(int i=0; i<h.num_files(); ++i) {
QString old_path = h.files_path().at(i);
old_path = old_path.replace("\\", "/");
if(!QFile::exists(old_path)) {
// Remove old parent folder manually since we will
// not get a file_renamed alert
QStringList parts = old_path.split("/", QString::SkipEmptyParts);
parts.removeLast();
if(!parts.empty())
QDir().rmpath(parts.join("/"));
if(TorrentTempData::hasTempData(hash)) {
// sequential download
h.set_sequential_download(TorrentTempData::isSequential(hash));
// The following is useless for newly added magnet
if(!magnet) {
// Files priorities
vector<int> fp;
TorrentTempData::getFilesPriority(hash, fp);
h.prioritize_files(fp);
// Update file names
const QStringList files_path = TorrentTempData::getFilesPath(hash);
bool force_recheck = false;
if(files_path.size() == h.num_files()) {
for(int i=0; i<h.num_files(); ++i) {
QString old_path = h.files_path().at(i);
old_path = old_path.replace("\\", "/");
if(!QFile::exists(old_path)) {
// Remove old parent folder manually since we will
// not get a file_renamed alert
QStringList parts = old_path.split("/", QString::SkipEmptyParts);
parts.removeLast();
if(!parts.empty())
QDir().rmpath(parts.join("/"));
}
const QString &path = files_path.at(i);
if(!force_recheck && QDir(h.save_path()).exists(path))
force_recheck = true;
qDebug("Renaming file to %s", qPrintable(path));
h.rename_file(i, path);
}
const QString &path = files_path.at(i);
if(!force_recheck && QDir(h.save_path()).exists(path))
force_recheck = true;
qDebug("Renaming file to %s", qPrintable(path));
h.rename_file(i, path);
// Force recheck
if(force_recheck) h.force_recheck();
}
// Force recheck
if(force_recheck) h.force_recheck();
}
}
// Save persistent data for new torrent
qDebug("Saving torrent persistant data");
if(defaultTempPath.isEmpty())
TorrentPersistentData::saveTorrentPersistentData(h, QString::null, magnet);
else
@ -1632,7 +1636,7 @@ bool QBtSession::isFilePreviewPossible(QString hash) const{ @@ -1632,7 +1636,7 @@ bool QBtSession::isFilePreviewPossible(QString hash) const{
}
const unsigned int nbFiles = h.num_files();
for(unsigned int i=0; i<nbFiles; ++i) {
QString extension = h.file_at(i).split('.').last();
const QString extension = misc::file_extension(h.filename_at(i));
if(misc::isPreviewable(extension))
return true;
}
@ -2165,7 +2169,7 @@ void QBtSession::readAlerts() { @@ -2165,7 +2169,7 @@ void QBtSession::readAlerts() {
if(h.is_valid()) {
// Attempt to remove old folder if empty
const QString& old_save_path = TorrentPersistentData::getPreviousPath(h.hash());
const QString new_save_path = QString::fromLocal8Bit(p->path.c_str());
const QString new_save_path = misc::toQStringU(p->path.c_str());
qDebug("Torrent moved from %s to %s", qPrintable(old_save_path), qPrintable(new_save_path));
QDir old_save_dir(old_save_path);
if(old_save_dir != QDir(defaultSavePath) && old_save_dir != QDir(defaultTempPath)) {
@ -2173,6 +2177,7 @@ void QBtSession::readAlerts() { @@ -2173,6 +2177,7 @@ void QBtSession::readAlerts() {
misc::removeEmptyTree(old_save_path);
}
if(defaultTempPath.isEmpty() || !new_save_path.startsWith(defaultTempPath)) {
qDebug("Storage has been moved, updating save path to %s", qPrintable(new_save_path));
TorrentPersistentData::saveSavePath(h.hash(), new_save_path);
}
emit savePathChanged(h);

2
src/qtlibtorrent/qtorrenthandle.cpp

@ -232,7 +232,7 @@ int QTorrentHandle::num_files() const { @@ -232,7 +232,7 @@ int QTorrentHandle::num_files() const {
return torrent_handle::get_torrent_info().num_files();
}
QString QTorrentHandle::file_at(unsigned int index) const {
QString QTorrentHandle::filename_at(unsigned int index) const {
Q_ASSERT(torrent_handle::is_valid());
Q_ASSERT(index < (unsigned int)torrent_handle::get_torrent_info().num_files());
return misc::toQStringU(torrent_handle::get_torrent_info().file_at(index).path.leaf());

2
src/qtlibtorrent/qtorrenthandle.h

@ -81,7 +81,7 @@ class QTorrentHandle : public torrent_handle { @@ -81,7 +81,7 @@ class QTorrentHandle : public torrent_handle {
int num_files() const;
int queue_position() const;
bool is_queued() const;
QString file_at(unsigned int index) const;
QString filename_at(unsigned int index) const;
size_type filesize_at(unsigned int index) const;
torrent_status::state_t state() const;
QString creator() const;

9
src/src.pro

@ -309,7 +309,8 @@ contains(DEFINES, DISABLE_GUI) { @@ -309,7 +309,8 @@ contains(DEFINES, DISABLE_GUI) {
cookiesdlg.h \
hidabletabwidget.h \
sessionapplication.h \
torrentcreatordlg.h
torrentcreatordlg.h \
torrentimportdlg.h
macx {
HEADERS += qmacapplication.h
@ -360,7 +361,8 @@ include(tracker/tracker.pri) @@ -360,7 +361,8 @@ include(tracker/tracker.pri)
ui/console.ui \
ui/peer.ui \
ui/confirmdeletiondlg.ui \
ui/cookiesdlg.ui
ui/cookiesdlg.ui \
ui/torrentimportdlg.ui
}
SOURCES += main.cpp \
@ -377,7 +379,8 @@ SOURCES += main.cpp \ @@ -377,7 +379,8 @@ SOURCES += main.cpp \
cookiesdlg.cpp \
torrentadditiondlg.cpp \
sessionapplication.cpp \
torrentcreatordlg.cpp
torrentcreatordlg.cpp \
torrentimportdlg.cpp
macx {
SOURCES += qmacapplication.cpp

259
src/torrentimportdlg.cpp

@ -0,0 +1,259 @@ @@ -0,0 +1,259 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2010 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
*/
#include <QFileDialog>
#include <QMessageBox>
#include "torrentimportdlg.h"
#include "ui_torrentimportdlg.h"
#include "qinisettings.h"
#include "qbtsession.h"
#include "torrentpersistentdata.h"
#include "misc.h"
using namespace libtorrent;
TorrentImportDlg::TorrentImportDlg(QWidget *parent) :
QDialog(parent),
ui(new Ui::TorrentImportDlg)
{
ui->setupUi(this);
// Libtorrent < 0.15 does not support skipping file checking
#if LIBTORRENT_VERSION_MINOR < 15
ui->checkSkipCheck->setVisible(false);
#endif
}
TorrentImportDlg::~TorrentImportDlg()
{
delete ui;
}
void TorrentImportDlg::on_browseTorrentBtn_clicked()
{
QIniSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
const QString default_dir = settings.value(QString::fromUtf8("MainWindowLastDir"), QDir::homePath()).toString();
// Ask for a torrent file
m_torrentPath = QFileDialog::getOpenFileName(this, tr("Torrent file to import"), default_dir, tr("Torrent files (*.torrent)"));
if(!m_torrentPath.isEmpty()) {
loadTorrent(m_torrentPath);
} else {
ui->lineTorrent->clear();
}
}
void TorrentImportDlg::on_browseContentBtn_clicked()
{
QIniSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
const QString default_dir = settings.value(QString::fromUtf8("TorrentImport/LastContentDir"), QDir::homePath()).toString();
if(t->num_files() == 1) {
// Single file torrent
const QString file_name = misc::toQStringU(t->file_at(0).path.leaf());
qDebug("Torrent has only one file: %s", qPrintable(file_name));
QString extension = misc::file_extension(file_name);
qDebug("File extension is : %s", qPrintable(extension));
QString filter;
if(!extension.isEmpty()) {
extension = extension.toUpper();
filter = tr("%1 Files", "%1 is a file extension (e.g. PDF)").arg(extension)+" (*."+extension+")";
}
m_contentPath = QFileDialog::getOpenFileName(this, tr("Please provide the location of %1", "%1 is a file name").arg(file_name), default_dir, filter);
if(m_contentPath.isEmpty() || !QFile(m_contentPath).exists()) {
m_contentPath = QString::null;
ui->importBtn->setEnabled(false);
ui->checkSkipCheck->setEnabled(false);
return;
}
// Update display
#if defined(Q_WS_WIN) || defined(Q_OS_OS2)
ui->lineContent->setText(m_contentPath.replace("/", "\\");
#else
ui->lineContent->setText(m_contentPath);
#endif
#if LIBTORRENT_VERSION_MINOR >= 15
// Check file size
const qint64 file_size = QFile(m_contentPath).size();
if(t->file_at(0).size == file_size) {
qDebug("The file size matches, allowing fast seeding...");
ui->checkSkipCheck->setEnabled(true);
} else {
qDebug("The file size does not match, forbidding fast seeding...");
ui->checkSkipCheck->setChecked(false);
ui->checkSkipCheck->setEnabled(false);
}
#endif
// Handle file renaming
QStringList parts = m_contentPath.replace("\\", "/").split("/");
QString new_file_name = parts.takeLast();
if(new_file_name != file_name) {
qDebug("The file has been renamed");
QStringList new_parts = m_filesPath.first().split("/");
new_parts.replace(new_parts.count()-1, new_file_name);
m_filesPath.replace(0, new_parts.join("/"));
}
m_contentPath = parts.join("/");
} else {
// multiple files torrent
m_contentPath = QFileDialog::getExistingDirectory(this, tr("Please point to the location of the torrent: %1").arg(misc::toQStringU(t->name())),
default_dir);
if(m_contentPath.isEmpty() || !QDir(m_contentPath).exists()) {
m_contentPath = QString::null;
ui->importBtn->setEnabled(false);
ui->checkSkipCheck->setEnabled(false);
return;
}
// Update the display
#if defined(Q_WS_WIN) || defined(Q_OS_OS2)
ui->lineContent->setText(m_contentPath.replace("/", "\\");
#else
ui->lineContent->setText(m_contentPath);
#endif
#if LIBTORRENT_VERSION_MINOR >= 15
bool size_mismatch = false;
QDir content_dir(m_contentPath);
// Check file sizes
torrent_info::file_iterator it; t->begin_files();
for(it = t->begin_files(); it != t->end_files(); it++) {
if(QFile(QDir::cleanPath(content_dir.absoluteFilePath(misc::toQStringU(it->path.string())))).size() != it->size) {
qDebug("%s is %lld",
qPrintable(QDir::cleanPath(content_dir.absoluteFilePath(misc::toQStringU(it->path.string())))), (long long int) QFile(QDir::cleanPath(content_dir.absoluteFilePath(misc::toQStringU(it->path.string())))).size());
qDebug("%s is %lld",
it->path.string().c_str(), (long long int)it->size);
size_mismatch = true;
break;
}
}
if(size_mismatch) {
qDebug("The file size does not match, forbidding fast seeding...");
ui->checkSkipCheck->setChecked(false);
ui->checkSkipCheck->setEnabled(false);
} else {
qDebug("The file size matches, allowing fast seeding...");
ui->checkSkipCheck->setEnabled(true);
}
#endif
}
// Enable the import button
ui->importBtn->setEnabled(true);
}
void TorrentImportDlg::on_importBtn_clicked()
{
accept();
}
QString TorrentImportDlg::getTorrentPath() const
{
return m_torrentPath;
}
QString TorrentImportDlg::getContentPath() const
{
return m_contentPath;
}
void TorrentImportDlg::importTorrent(QBtSession *BTSession)
{
TorrentImportDlg dlg;
if(dlg.exec()) {
boost::intrusive_ptr<libtorrent::torrent_info> t = dlg.torrent();
if(!t->is_valid())
return;
QString torrent_path = dlg.getTorrentPath();
QString content_path = dlg.getContentPath();
if(torrent_path.isEmpty() || content_path.isEmpty() || !QFile(torrent_path).exists()) return;
const QString hash = misc::toQString(t->info_hash());
TorrentTempData::setSavePath(hash, content_path);
#if LIBTORRENT_VERSION_MINOR >= 15
TorrentTempData::setSeedingMode(hash, dlg.skipFileChecking());
#endif
qDebug("Adding the torrent to the session...");
BTSession->addTorrent(torrent_path);
// Remember the last opened folder
QIniSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
settings.setValue(QString::fromUtf8("MainWindowLastDir"), torrent_path);
settings.setValue("TorrentImport/LastContentDir", content_path);
return;
}
return;
}
void TorrentImportDlg::loadTorrent(const QString &torrent_path)
{
// Load the torrent file
try {
t = new torrent_info(torrent_path.toUtf8().constData());
if(!t->is_valid() || t->num_files() == 0)
throw std::exception();
} catch(std::exception&) {
ui->browseContentBtn->setEnabled(false);
ui->lineTorrent->clear();
QMessageBox::warning(this, tr("Invalid torrent file"), tr("This is not a valid torrent file."));
return;
}
// The torrent file is valid
misc::truncateRootFolder(t);
// Update display
#if defined(Q_WS_WIN) || defined(Q_OS_OS2)
ui->lineTorrent->setText(torrent_path.replace("/", "\\"));
#else
ui->lineTorrent->setText(torrent_path);
#endif
ui->browseContentBtn->setEnabled(true);
// Load the file names
initializeFilesPath();
}
void TorrentImportDlg::initializeFilesPath()
{
m_filesPath.clear();
// Loads files path in the torrent
for(int i=0; i<t->num_files(); ++i) {
m_filesPath << misc::toQStringU(t->file_at(i).path.string()).replace("\\", "/");
}
}
bool TorrentImportDlg::fileRenamed() const
{
return m_fileRenamed;
}
boost::intrusive_ptr<libtorrent::torrent_info> TorrentImportDlg::torrent() const
{
return t;
}
#if LIBTORRENT_VERSION_MINOR >= 15
bool TorrentImportDlg::skipFileChecking() const
{
return ui->checkSkipCheck->isChecked();
}
#endif

81
src/torrentimportdlg.h

@ -0,0 +1,81 @@ @@ -0,0 +1,81 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2010 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 TORRENTIMPORTDLG_H
#define TORRENTIMPORTDLG_H
#include <QDialog>
#include <QStringList>
#include <libtorrent/torrent_info.hpp>
#include <libtorrent/version.hpp>
namespace Ui {
class TorrentImportDlg;
}
class QBtSession;
class TorrentImportDlg : public QDialog
{
Q_OBJECT
public:
explicit TorrentImportDlg(QWidget *parent = 0);
~TorrentImportDlg();
static void importTorrent(QBtSession *BTSession);
QString getTorrentPath() const;
QString getContentPath() const;
bool fileRenamed() const;
boost::intrusive_ptr<libtorrent::torrent_info> torrent() const;
#if LIBTORRENT_VERSION_MINOR >= 15
bool skipFileChecking() const;
#endif
protected slots:
void loadTorrent(const QString &torrent_path);
void initializeFilesPath();
private slots:
void on_browseTorrentBtn_clicked();
void on_browseContentBtn_clicked();
void on_importBtn_clicked();
private:
Ui::TorrentImportDlg *ui;
boost::intrusive_ptr<libtorrent::torrent_info> t;
QStringList m_filesPath;
QString m_contentPath;
QString m_torrentPath;
bool m_fileRenamed;
};
#endif // TORRENTIMPORTDLG_H

9
src/torrentpersistentdata.h

@ -295,10 +295,13 @@ public: @@ -295,10 +295,13 @@ public:
}
data["seed"] = h.is_seed();
data["priority"] = h.queue_position();
if(save_path.isEmpty())
if(save_path.isEmpty()) {
qDebug("TorrentPersistantData: save path is %s", qPrintable(h.save_path()));
data["save_path"] = h.save_path();
else
} else {
qDebug("TorrentPersistantData: overriding save path is %s", qPrintable(save_path));
data["save_path"] = save_path; // Override torrent save path (e.g. because it is a temp dir)
}
// Label
data["label"] = TorrentTempData::getLabel(h.hash());
// Save data
@ -322,7 +325,7 @@ public: @@ -322,7 +325,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.toLocal8Bit().data(), hash.toLocal8Bit().data());
qDebug("TorrentPersistentData: Saving save_path: %s, hash: %s", qPrintable(save_path), qPrintable(hash));
}
static void saveLabel(QString hash, QString label) {

18
src/ui/mainwindow.ui

@ -74,6 +74,7 @@ @@ -74,6 +74,7 @@
</property>
<addaction name="actionOpen"/>
<addaction name="actionDownload_from_URL"/>
<addaction name="action_Import_Torrent"/>
<addaction name="actionExit"/>
</widget>
<widget class="QMenu" name="menuView">
@ -149,7 +150,10 @@ @@ -149,7 +150,10 @@
</action>
<action name="actionExit">
<property name="text">
<string>E&amp;xit</string>
<string>Exit</string>
</property>
<property name="toolTip">
<string>Exit</string>
</property>
</action>
<action name="actionOptions">
@ -357,6 +361,18 @@ @@ -357,6 +361,18 @@
<string>Shutdown qBittorrent when downloads complete</string>
</property>
</action>
<action name="action_Import_Torrent">
<property name="icon">
<iconset resource="../icons.qrc">
<normaloff>:/Icons/oxygen/list-add.png</normaloff>:/Icons/oxygen/list-add.png</iconset>
</property>
<property name="text">
<string>Import torrent...</string>
</property>
<property name="toolTip">
<string>Import torrent...</string>
</property>
</action>
</widget>
<resources>
<include location="../icons.qrc"/>

133
src/ui/torrentimportdlg.ui

@ -0,0 +1,133 @@ @@ -0,0 +1,133 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TorrentImportDlg</class>
<widget class="QDialog" name="TorrentImportDlg">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>199</height>
</rect>
</property>
<property name="windowTitle">
<string>Torrent Import</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="spacing">
<number>15</number>
</property>
<item>
<widget class="QLabel" name="label_5">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="../icons.qrc">:/Icons/skin/info.png</pixmap>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>This assistant will help you share with qBittorrent a torrent that you have already downloaded.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Torrent file to import:</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLineEdit" name="lineTorrent">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="browseTorrentBtn">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Content location:</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLineEdit" name="lineContent">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="browseContentBtn">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="checkSkipCheck">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Skip the data checking stage and start seeding immediately</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="importBtn">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Import</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>
</layout>
</widget>
<resources>
<include location="../icons.qrc"/>
</resources>
<connections/>
</ui>
Loading…
Cancel
Save