Browse Source

Merge pull request #5196 from Chocobo1/creator_pr

Revamp Torrent creator
adaptive-webui-19844
Mike Tzou 8 years ago committed by GitHub
parent
commit
1f9ccb44a3
  1. 1
      src/base/CMakeLists.txt
  2. 3
      src/base/base.pri
  3. 40
      src/base/bittorrent/torrentcreatorthread.cpp
  4. 4
      src/base/bittorrent/torrentcreatorthread.h
  5. 30
      src/base/global.h
  6. 50
      src/base/preferences.cpp
  7. 10
      src/base/preferences.h
  8. 28
      src/base/utils/fs.cpp
  9. 39
      src/gui/mainwindow.cpp
  10. 1
      src/gui/mainwindow.h
  11. 318
      src/gui/torrentcreatordlg.cpp
  12. 70
      src/gui/torrentcreatordlg.h
  13. 542
      src/gui/torrentcreatordlg.ui

1
src/base/CMakeLists.txt

@ -52,6 +52,7 @@ utils/string.h @@ -52,6 +52,7 @@ utils/string.h
utils/version.h
asyncfilestorage.h
filesystemwatcher.h
global.h
iconprovider.h
indexrange.h
logger.h

3
src/base/base.pri

@ -63,7 +63,8 @@ HEADERS += \ @@ -63,7 +63,8 @@ HEADERS += \
$$PWD/torrentfileguard.h \
$$PWD/torrentfilter.h \
$$PWD/scanfoldersmodel.h \
$$PWD/searchengine.h
$$PWD/searchengine.h \
$$PWD/global.h
SOURCES += \
$$PWD/asyncfilestorage.cpp \

40
src/base/bittorrent/torrentcreatorthread.cpp

@ -28,25 +28,21 @@ @@ -28,25 +28,21 @@
* Contact : chris@qbittorrent.org
*/
#include <libtorrent/entry.hpp>
#include "torrentcreatorthread.h"
#include <fstream>
#include <boost/bind.hpp>
#include <libtorrent/bencode.hpp>
#include <libtorrent/create_torrent.hpp>
#include <libtorrent/torrent_info.hpp>
#include <libtorrent/file.hpp>
#include <libtorrent/storage.hpp>
#include <libtorrent/hasher.hpp>
#include <libtorrent/file_pool.hpp>
#include <libtorrent/create_torrent.hpp>
#include <QFile>
#include <QDir>
#include <boost/bind.hpp>
#include <iostream>
#include <fstream>
#include <QFile>
#include "base/utils/fs.h"
#include "base/utils/misc.h"
#include "base/utils/string.h"
#include "torrentcreatorthread.h"
namespace libt = libtorrent;
using namespace BitTorrent;
@ -62,14 +58,13 @@ TorrentCreatorThread::TorrentCreatorThread(QObject *parent) @@ -62,14 +58,13 @@ TorrentCreatorThread::TorrentCreatorThread(QObject *parent)
: QThread(parent)
, m_private(false)
, m_pieceSize(0)
, m_abort(false)
{
}
TorrentCreatorThread::~TorrentCreatorThread()
{
m_abort = true;
wait();
requestInterruption();
wait(1000);
}
void TorrentCreatorThread::create(const QString &inputPath, const QString &savePath, const QStringList &trackers,
@ -84,7 +79,6 @@ void TorrentCreatorThread::create(const QString &inputPath, const QString &saveP @@ -84,7 +79,6 @@ void TorrentCreatorThread::create(const QString &inputPath, const QString &saveP
m_comment = comment;
m_private = isPrivate;
m_pieceSize = pieceSize;
m_abort = false;
start();
}
@ -94,11 +88,6 @@ void TorrentCreatorThread::sendProgressSignal(int numHashes, int numPieces) @@ -94,11 +88,6 @@ void TorrentCreatorThread::sendProgressSignal(int numHashes, int numPieces)
emit updateProgress(static_cast<int>((numHashes * 100.) / numPieces));
}
void TorrentCreatorThread::abortCreation()
{
m_abort = true;
}
void TorrentCreatorThread::run()
{
emit updateProgress(0);
@ -108,7 +97,8 @@ void TorrentCreatorThread::run() @@ -108,7 +97,8 @@ void TorrentCreatorThread::run()
libt::file_storage fs;
// Adding files to the torrent
libt::add_files(fs, Utils::Fs::toNativePath(m_inputPath).toStdString(), fileFilter);
if (m_abort) return;
if (isInterruptionRequested()) return;
libt::create_torrent t(fs, m_pieceSize);
@ -129,7 +119,8 @@ void TorrentCreatorThread::run() @@ -129,7 +119,8 @@ void TorrentCreatorThread::run()
t.add_tracker(tracker.trimmed().toStdString(), tier);
newline = false;
}
if (m_abort) return;
if (isInterruptionRequested()) return;
// calculate the hash for all pieces
const QString parentPath = Utils::Fs::branchPath(m_inputPath) + "/";
@ -140,7 +131,8 @@ void TorrentCreatorThread::run() @@ -140,7 +131,8 @@ void TorrentCreatorThread::run()
t.set_comment(m_comment.toUtf8().constData());
// Is private ?
t.set_priv(m_private);
if (m_abort) return;
if (isInterruptionRequested()) return;
// create the torrent and print it to out
qDebug("Saving to %s", qPrintable(m_savePath));
@ -156,6 +148,8 @@ void TorrentCreatorThread::run() @@ -156,6 +148,8 @@ void TorrentCreatorThread::run()
if (outfile.fail())
throw std::exception();
if (isInterruptionRequested()) return;
libt::bencode(std::ostream_iterator<char>(outfile), t.generate());
outfile.close();

4
src/base/bittorrent/torrentcreatorthread.h

@ -31,8 +31,8 @@ @@ -31,8 +31,8 @@
#ifndef BITTORRENT_TORRENTCREATORTHREAD_H
#define BITTORRENT_TORRENTCREATORTHREAD_H
#include <QThread>
#include <QStringList>
#include <QThread>
namespace BitTorrent
{
@ -46,7 +46,6 @@ namespace BitTorrent @@ -46,7 +46,6 @@ namespace BitTorrent
void create(const QString &inputPath, const QString &savePath, const QStringList &trackers,
const QStringList &urlSeeds, const QString &comment, bool isPrivate, int pieceSize);
void abortCreation();
protected:
void run();
@ -66,7 +65,6 @@ namespace BitTorrent @@ -66,7 +65,6 @@ namespace BitTorrent
QString m_comment;
bool m_private;
int m_pieceSize;
bool m_abort;
};
}

30
src/base/global.h

@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2016 Mike Tzou
*
* 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.
*/
const char C_TORRENT_FILE_EXTENSION[] = ".torrent";

50
src/base/preferences.cpp

@ -1277,56 +1277,6 @@ void Preferences::setSearchEngDisabled(const QStringList &engines) @@ -1277,56 +1277,6 @@ void Preferences::setSearchEngDisabled(const QStringList &engines)
setValue("SearchEngines/disabledEngines", engines);
}
QString Preferences::getCreateTorLastAddPath() const
{
return value("CreateTorrent/last_add_path", QDir::homePath()).toString();
}
void Preferences::setCreateTorLastAddPath(const QString &path)
{
setValue("CreateTorrent/last_add_path", path);
}
QString Preferences::getCreateTorLastSavePath() const
{
return value("CreateTorrent/last_save_path", QDir::homePath()).toString();
}
void Preferences::setCreateTorLastSavePath(const QString &path)
{
setValue("CreateTorrent/last_save_path", path);
}
QString Preferences::getCreateTorTrackers() const
{
return value("CreateTorrent/TrackerList").toString();
}
void Preferences::setCreateTorTrackers(const QString &path)
{
setValue("CreateTorrent/TrackerList", path);
}
QByteArray Preferences::getCreateTorGeometry() const
{
return value("CreateTorrent/dimensions").toByteArray();
}
void Preferences::setCreateTorGeometry(const QByteArray &geometry)
{
setValue("CreateTorrent/dimensions", geometry);
}
bool Preferences::getCreateTorIgnoreRatio() const
{
return value("CreateTorrent/IgnoreRatio").toBool();
}
void Preferences::setCreateTorIgnoreRatio(const bool ignore)
{
setValue("CreateTorrent/IgnoreRatio", ignore);
}
QString Preferences::getTorImportLastContentDir() const
{
return value("TorrentImport/LastContentDir", QDir::homePath()).toString();

10
src/base/preferences.h

@ -305,16 +305,6 @@ public: @@ -305,16 +305,6 @@ public:
void setSearchTabHeaderState(const QByteArray &state);
QStringList getSearchEngDisabled() const;
void setSearchEngDisabled(const QStringList &engines);
QString getCreateTorLastAddPath() const;
void setCreateTorLastAddPath(const QString &path);
QString getCreateTorLastSavePath() const;
void setCreateTorLastSavePath(const QString &path);
QString getCreateTorTrackers() const;
void setCreateTorTrackers(const QString &path);
QByteArray getCreateTorGeometry() const;
void setCreateTorGeometry(const QByteArray &geometry);
bool getCreateTorIgnoreRatio() const;
void setCreateTorIgnoreRatio(const bool ignore);
QString getTorImportLastContentDir() const;
void setTorImportLastContentDir(const QString &path);
QByteArray getTorImportGeometry() const;

28
src/base/utils/fs.cpp

@ -180,14 +180,13 @@ qint64 Utils::Fs::computePathSize(const QString& path) @@ -180,14 +180,13 @@ qint64 Utils::Fs::computePathSize(const QString& path)
QFileInfo fi(path);
if (!fi.exists()) return -1;
if (fi.isFile()) return fi.size();
// Compute folder size based on its content
qint64 size = 0;
foreach (const QFileInfo &subfi, QDir(path).entryInfoList(QDir::Dirs|QDir::Files)) {
if (subfi.fileName().startsWith(".")) continue;
if (subfi.isDir())
size += computePathSize(subfi.absoluteFilePath());
else
size += subfi.size();
QDirIterator iter(path, QDir::Files | QDir::Hidden | QDir::NoSymLinks, QDirIterator::Subdirectories);
while (iter.hasNext()) {
iter.next();
size += iter.fileInfo().size();
}
return size;
}
@ -201,19 +200,14 @@ bool Utils::Fs::sameFiles(const QString& path1, const QString& path2) @@ -201,19 +200,14 @@ bool Utils::Fs::sameFiles(const QString& path1, const QString& path2)
if (!f1.exists() || !f2.exists()) return false;
if (f1.size() != f2.size()) return false;
if (!f1.open(QIODevice::ReadOnly)) return false;
if (!f2.open(QIODevice::ReadOnly)) {
f1.close();
return false;
}
bool same = true;
if (!f2.open(QIODevice::ReadOnly)) return false;
const int readSize = 1024 * 1024; // 1 MiB
while(!f1.atEnd() && !f2.atEnd()) {
if (f1.read(1024) != f2.read(1024)) {
same = false;
break;
}
if (f1.read(readSize) != f2.read(readSize))
return false;
}
f1.close(); f2.close();
return same;
return true;
}
QString Utils::Fs::toValidFileSystemName(const QString &name, bool allowSeparators, const QString &pad)

39
src/gui/mainwindow.cpp

@ -64,6 +64,7 @@ @@ -64,6 +64,7 @@
#include "base/bittorrent/session.h"
#include "base/bittorrent/sessionstatus.h"
#include "base/bittorrent/torrenthandle.h"
#include "base/global.h"
#include "base/rss/rss_folder.h"
#include "base/rss/rss_session.h"
@ -1069,10 +1070,17 @@ void MainWindow::closeEvent(QCloseEvent *e) @@ -1069,10 +1070,17 @@ void MainWindow::closeEvent(QCloseEvent *e)
// Display window to create a torrent
void MainWindow::on_actionCreateTorrent_triggered()
{
if (m_createTorrentDlg)
createTorrentTriggered();
}
void MainWindow::createTorrentTriggered(const QString &path)
{
if (m_createTorrentDlg) {
m_createTorrentDlg->updateInputPath(path);
m_createTorrentDlg->setFocus();
}
else
m_createTorrentDlg = new TorrentCreatorDlg(this);
m_createTorrentDlg = new TorrentCreatorDlg(this, path);
}
bool MainWindow::event(QEvent *e)
@ -1126,6 +1134,8 @@ bool MainWindow::event(QEvent *e) @@ -1126,6 +1134,8 @@ bool MainWindow::event(QEvent *e)
void MainWindow::dropEvent(QDropEvent *event)
{
event->acceptProposedAction();
// remove scheme
QStringList files;
if (event->mimeData()->hasUrls()) {
const QList<QUrl> urls = event->mimeData()->urls();
@ -1142,15 +1152,34 @@ void MainWindow::dropEvent(QDropEvent *event) @@ -1142,15 +1152,34 @@ void MainWindow::dropEvent(QDropEvent *event)
files = event->mimeData()->text().split('\n');
}
// Add file to download list
// differentiate ".torrent" files and others
QStringList torrentFiles, otherFiles;
foreach (const QString &file, files) {
if (file.endsWith(C_TORRENT_FILE_EXTENSION, Qt::CaseInsensitive))
torrentFiles << file;
else
otherFiles << file;
}
// Download torrents
const bool useTorrentAdditionDialog = AddNewTorrentDialog::isEnabled();
foreach (QString file, files) {
foreach (const QString &file, torrentFiles) {
qDebug("Dropped file %s on download list", qPrintable(file));
if (useTorrentAdditionDialog)
AddNewTorrentDialog::show(file, this);
else
BitTorrent::Session::instance()->addTorrent(file);
}
if (!torrentFiles.isEmpty()) return;
// Create torrent
foreach (const QString &file, otherFiles) {
createTorrentTriggered(file);
// currently only hande the first entry
// this is a stub that can be expanded later to create many torrents at once
break;
}
}
// Decode if we accept drag 'n drop or not
@ -1177,7 +1206,7 @@ void MainWindow::on_actionOpen_triggered() @@ -1177,7 +1206,7 @@ void MainWindow::on_actionOpen_triggered()
// Note: it is possible to select more than one file
const QStringList pathsList =
QFileDialog::getOpenFileNames(this, tr("Open Torrent Files"), pref->getMainLastDir(),
tr("Torrent Files") + " (*.torrent)");
tr("Torrent Files") + " (*" + C_TORRENT_FILE_EXTENSION + ')');
const bool useTorrentAdditionDialog = AddNewTorrentDialog::isEnabled();
if (!pathsList.isEmpty()) {

1
src/gui/mainwindow.h

@ -202,6 +202,7 @@ private: @@ -202,6 +202,7 @@ private:
bool event(QEvent *e) override;
void displayRSSTab(bool enable);
void displaySearchTab(bool enable);
void createTorrentTriggered(const QString &path = QString());
Ui::MainWindow *m_ui;

318
src/gui/torrentcreatordlg.cpp

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2010 Christophe Dumez
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2017 Mike Tzou (Chocobo1)
* Copyright (C) 2010 Christophe Dumez <chris@qbittorrent.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -24,258 +25,233 @@ @@ -24,258 +25,233 @@
* 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 "torrentcreatordlg.h"
#include <QCloseEvent>
#include <QDebug>
#include <QFileDialog>
#include <QMessageBox>
#include <QMimeData>
#include <QUrl>
#include "torrentcreatordlg.h"
#include "base/utils/fs.h"
#include "base/utils/misc.h"
#include "base/preferences.h"
#include "guiiconprovider.h"
#include "base/bittorrent/session.h"
#include "base/bittorrent/torrentinfo.h"
#include "base/bittorrent/torrentcreatorthread.h"
#include "base/bittorrent/torrentinfo.h"
#include "base/global.h"
#include "base/utils/fs.h"
#include "ui_torrentcreatordlg.h"
const uint NB_PIECES_MIN = 1200;
const uint NB_PIECES_MAX = 2200;
#define SETTINGS_KEY(name) "TorrentCreator/" name
TorrentCreatorDlg::TorrentCreatorDlg(QWidget *parent)
TorrentCreatorDlg::TorrentCreatorDlg(QWidget *parent, const QString &defaultPath)
: QDialog(parent)
, m_creatorThread(0)
, m_ui(new Ui::TorrentCreatorDlg)
, m_creatorThread(new BitTorrent::TorrentCreatorThread(this))
, m_storeDialogSize(SETTINGS_KEY("Dimension"))
, m_storePieceSize(SETTINGS_KEY("PieceSize"))
, m_storePrivateTorrent(SETTINGS_KEY("PrivateTorrent"))
, m_storeStartSeeding(SETTINGS_KEY("StartSeeding"))
, m_storeIgnoreRatio(SETTINGS_KEY("IgnoreRatio"))
, m_storeLastAddPath(SETTINGS_KEY("LastAddPath"), QDir::homePath())
, m_storeTrackerList(SETTINGS_KEY("TrackerList"))
, m_storeWebSeedList(SETTINGS_KEY("WebSeedList"))
, m_storeComments(SETTINGS_KEY("Comments"))
, m_storeLastSavePath(SETTINGS_KEY("LastSavePath"), QDir::homePath())
{
setupUi(this);
// Icons
addFile_button->setIcon(GuiIconProvider::instance()->getIcon("document-new"));
addFolder_button->setIcon(GuiIconProvider::instance()->getIcon("folder-new"));
createButton->setIcon(GuiIconProvider::instance()->getIcon("document-save"));
cancelButton->setIcon(GuiIconProvider::instance()->getIcon("dialog-cancel"));
m_ui->setupUi(this);
setAttribute(Qt::WA_DeleteOnClose);
setModal(true);
showProgressBar(false);
loadTrackerList();
// Piece sizes
m_pieceSizes << 16 << 32 << 64 << 128 << 256 << 512 << 1024 << 2048 << 4096 << 8192 << 16384;
setModal(false);
m_ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Create Torrent"));
connect(m_ui->addFileButton, SIGNAL(clicked(bool)), SLOT(onAddFileButtonClicked()));
connect(m_ui->addFolderButton, SIGNAL(clicked(bool)), SLOT(onAddFolderButtonClicked()));
connect(m_ui->buttonBox, SIGNAL(accepted()), SLOT(onCreateButtonClicked()));
connect(m_creatorThread, SIGNAL(creationSuccess(QString, QString)), this, SLOT(handleCreationSuccess(QString, QString)));
connect(m_creatorThread, SIGNAL(creationFailure(QString)), this, SLOT(handleCreationFailure(QString)));
connect(m_creatorThread, SIGNAL(updateProgress(int)), this, SLOT(updateProgressBar(int)));
loadSettings();
updateInputPath(defaultPath);
show();
}
TorrentCreatorDlg::~TorrentCreatorDlg()
{
saveSettings();
if (m_creatorThread)
delete m_creatorThread;
delete m_ui;
}
void TorrentCreatorDlg::on_addFolder_button_clicked()
void TorrentCreatorDlg::updateInputPath(const QString &path)
{
Preferences* const pref = Preferences::instance();
QString lastPath = pref->getCreateTorLastAddPath();
QString dir = QFileDialog::getExistingDirectory(this, tr("Select a folder to add to the torrent"), lastPath, QFileDialog::ShowDirsOnly);
if (!dir.isEmpty()) {
pref->setCreateTorLastAddPath(dir);
textInputPath->setText(Utils::Fs::toNativePath(dir));
// Update piece size
if (checkAutoPieceSize->isChecked())
updateOptimalPieceSize();
}
if (path.isEmpty()) return;
m_ui->textInputPath->setText(Utils::Fs::toNativePath(path));
updateProgressBar(0);
}
void TorrentCreatorDlg::on_addFile_button_clicked()
void TorrentCreatorDlg::onAddFolderButtonClicked()
{
Preferences* const pref = Preferences::instance();
QString lastPath = pref->getCreateTorLastAddPath();
QString file = QFileDialog::getOpenFileName(this, tr("Select a file to add to the torrent"), lastPath);
if (!file.isEmpty()) {
pref->setCreateTorLastAddPath(Utils::Fs::branchPath(file));
textInputPath->setText(Utils::Fs::toNativePath(file));
// Update piece size
if (checkAutoPieceSize->isChecked())
updateOptimalPieceSize();
}
QString oldPath = m_ui->textInputPath->text();
QString path = QFileDialog::getExistingDirectory(this, tr("Select folder"), oldPath);
updateInputPath(path);
}
void TorrentCreatorDlg::onAddFileButtonClicked()
{
QString oldPath = m_ui->textInputPath->text();
QString path = QFileDialog::getOpenFileName(this, tr("Select file"), oldPath);
updateInputPath(path);
}
int TorrentCreatorDlg::getPieceSize() const
{
return m_pieceSizes.at(comboPieceSize->currentIndex()) * 1024;
const int pieceSizes[] = {0, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384}; // base unit in KiB
return pieceSizes[m_ui->comboPieceSize->currentIndex()] * 1024;
}
void TorrentCreatorDlg::dropEvent(QDropEvent *event)
{
event->acceptProposedAction();
if (event->mimeData()->hasUrls()) {
// only take the first one
QUrl firstItem = event->mimeData()->urls().first();
QString path = (firstItem.scheme().compare("file", Qt::CaseInsensitive) == 0)
? firstItem.toLocalFile() : firstItem.toString();
updateInputPath(path);
}
}
void TorrentCreatorDlg::dragEnterEvent(QDragEnterEvent *event)
{
if (event->mimeData()->hasFormat("text/plain") || event->mimeData()->hasFormat("text/uri-list"))
event->acceptProposedAction();
}
// Main function that create a .torrent file
void TorrentCreatorDlg::on_createButton_clicked()
void TorrentCreatorDlg::onCreateButtonClicked()
{
QString input = Utils::Fs::fromNativePath(textInputPath->text()).trimmed();
if (input.endsWith("/"))
input.chop(1);
if (input.isEmpty()) {
QMessageBox::critical(0, tr("No input path set"), tr("Please type an input path first"));
QString input = Utils::Fs::fromNativePath(m_ui->textInputPath->text()).trimmed();
// test if readable
QFileInfo fi(input);
if (!fi.isReadable()) {
QMessageBox::critical(this, tr("Torrent creator failed"), tr("Reason: Path to file/folder is not readable."));
return;
}
QStringList trackers = trackers_list->toPlainText().split("\n");
if (!trackers_list->toPlainText().trimmed().isEmpty())
saveTrackerList();
Preferences* const pref = Preferences::instance();
QString lastPath = pref->getCreateTorLastSavePath();
input = fi.canonicalFilePath();
QString destination = QFileDialog::getSaveFileName(this, tr("Select destination torrent file"), lastPath, tr("Torrent Files (*.torrent)"));
// get save path
QString lastPath = m_storeLastSavePath;
QString destination = QFileDialog::getSaveFileName(this, tr("Select where to save the new torrent"), lastPath, tr("Torrent Files (*.torrent)"));
if (destination.isEmpty())
return;
if (!destination.endsWith(C_TORRENT_FILE_EXTENSION, Qt::CaseInsensitive))
destination += C_TORRENT_FILE_EXTENSION;
m_storeLastSavePath = Utils::Fs::branchPath(destination);
pref->setCreateTorLastSavePath(Utils::Fs::branchPath(destination));
if (!destination.toUpper().endsWith(".TORRENT"))
destination += QString::fromUtf8(".torrent");
// Disable dialog
// Disable dialog & set busy cursor
setInteractionEnabled(false);
showProgressBar(true);
// Set busy cursor
setCursor(QCursor(Qt::WaitCursor));
// Actually create the torrent
QStringList urlSeeds = URLSeeds_list->toPlainText().split("\n");
QString comment = txt_comment->toPlainText();
// Create the creator thread
m_creatorThread = new BitTorrent::TorrentCreatorThread(this);
connect(m_creatorThread, SIGNAL(creationSuccess(QString, QString)), this, SLOT(handleCreationSuccess(QString, QString)));
connect(m_creatorThread, SIGNAL(creationFailure(QString)), this, SLOT(handleCreationFailure(QString)));
connect(m_creatorThread, SIGNAL(updateProgress(int)), this, SLOT(updateProgressBar(int)));
m_creatorThread->create(input, destination, trackers, urlSeeds, comment, check_private->isChecked(), getPieceSize());
QStringList trackers = m_ui->trackersList->toPlainText().split("\n");
QStringList urlSeeds = m_ui->URLSeedsList->toPlainText().split("\n");
QString comment = m_ui->txtComment->toPlainText();
// run the creator thread
m_creatorThread->create(input, destination, trackers, urlSeeds, comment, m_ui->checkPrivate->isChecked(), getPieceSize());
}
void TorrentCreatorDlg::handleCreationFailure(QString msg)
void TorrentCreatorDlg::handleCreationFailure(const QString &msg)
{
// Remove busy cursor
setCursor(QCursor(Qt::ArrowCursor));
QMessageBox::information(0, tr("Torrent creation"), tr("Torrent creation was unsuccessful, reason: %1").arg(msg));
QMessageBox::information(this, tr("Torrent creator failed"), tr("Reason: %1").arg(msg));
setInteractionEnabled(true);
showProgressBar(false);
}
void TorrentCreatorDlg::handleCreationSuccess(QString path, QString branch_path)
void TorrentCreatorDlg::handleCreationSuccess(const QString &path, const QString &branchPath)
{
// Remove busy cursor
setCursor(QCursor(Qt::ArrowCursor));
if (checkStartSeeding->isChecked()) {
if (m_ui->checkStartSeeding->isChecked()) {
// Create save path temp data
BitTorrent::TorrentInfo t = BitTorrent::TorrentInfo::loadFromFile(Utils::Fs::toNativePath(path));
if (!t.isValid()) {
QMessageBox::critical(0, tr("Torrent creation"), tr("Created torrent file is invalid. It won't be added to download list."));
QMessageBox::critical(this, tr("Torrent creator failed"), tr("Reason: Created torrent is invalid. It won't be added to download list."));
return;
}
BitTorrent::AddTorrentParams params;
params.savePath = branch_path;
params.savePath = branchPath;
params.skipChecking = true;
params.ignoreShareLimits = checkIgnoreShareLimits->isChecked();
params.ignoreShareLimits = m_ui->checkIgnoreShareLimits->isChecked();
BitTorrent::Session::instance()->addTorrent(t, params);
}
QMessageBox::information(0, tr("Torrent creation"), tr("Torrent was created successfully: %1", "%1 is the path of the torrent").arg(Utils::Fs::toNativePath(path)));
close();
}
void TorrentCreatorDlg::on_cancelButton_clicked()
{
// End torrent creation thread
if (m_creatorThread && m_creatorThread->isRunning()) {
m_creatorThread->abortCreation();
m_creatorThread->terminate();
// Wait for termination
m_creatorThread->wait();
}
// Close the dialog
close();
QMessageBox::information(this, tr("Torrent creator"), QString("%1\n%2").arg(tr("Create torrent success:")).arg(Utils::Fs::toNativePath(path)));
setInteractionEnabled(true);
}
void TorrentCreatorDlg::updateProgressBar(int progress)
{
progressBar->setValue(progress);
m_ui->progressBar->setValue(progress);
}
void TorrentCreatorDlg::setInteractionEnabled(bool enabled)
{
textInputPath->setEnabled(enabled);
addFile_button->setEnabled(enabled);
addFolder_button->setEnabled(enabled);
trackers_list->setEnabled(enabled);
URLSeeds_list->setEnabled(enabled);
txt_comment->setEnabled(enabled);
comboPieceSize->setEnabled(enabled);
checkAutoPieceSize->setEnabled(enabled);
check_private->setEnabled(enabled);
checkStartSeeding->setEnabled(enabled);
createButton->setEnabled(enabled);
checkIgnoreShareLimits->setEnabled(enabled && checkStartSeeding->isChecked());
m_ui->textInputPath->setEnabled(enabled);
m_ui->addFileButton->setEnabled(enabled);
m_ui->addFolderButton->setEnabled(enabled);
m_ui->trackersList->setEnabled(enabled);
m_ui->URLSeedsList->setEnabled(enabled);
m_ui->txtComment->setEnabled(enabled);
m_ui->comboPieceSize->setEnabled(enabled);
m_ui->checkPrivate->setEnabled(enabled);
m_ui->checkStartSeeding->setEnabled(enabled);
m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(enabled);
m_ui->checkIgnoreShareLimits->setEnabled(enabled && m_ui->checkStartSeeding->isChecked());
}
void TorrentCreatorDlg::showProgressBar(bool show)
void TorrentCreatorDlg::saveSettings()
{
progressLbl->setVisible(show);
progressBar->setVisible(show);
}
m_storeLastAddPath = m_ui->textInputPath->text().trimmed();
void TorrentCreatorDlg::on_checkAutoPieceSize_clicked(bool checked)
{
comboPieceSize->setEnabled(!checked);
if (checked)
updateOptimalPieceSize();
}
m_storePieceSize = m_ui->comboPieceSize->currentIndex();
m_storePrivateTorrent = m_ui->checkPrivate->isChecked();
m_storeStartSeeding = m_ui->checkStartSeeding->isChecked();
m_storeIgnoreRatio = m_ui->checkIgnoreShareLimits->isChecked();
void TorrentCreatorDlg::updateOptimalPieceSize()
{
qint64 torrentSize = Utils::Fs::computePathSize(textInputPath->text());
qDebug("Torrent size is %lld", torrentSize);
if (torrentSize < 0)
return;
int i = 0;
qulonglong nb_pieces = 0;
do {
nb_pieces = (double)torrentSize/(m_pieceSizes.at(i) * 1024.);
qDebug("nb_pieces=%lld with piece_size=%s", nb_pieces, qPrintable(comboPieceSize->itemText(i)));
if (nb_pieces <= NB_PIECES_MIN) {
if (i > 1)
--i;
break;
}
else if (nb_pieces < NB_PIECES_MAX) {
qDebug("Good, nb_pieces=%lld < %d", nb_pieces + 1, NB_PIECES_MAX);
break;
}
++i;
} while (i < (m_pieceSizes.size() - 1));
comboPieceSize->setCurrentIndex(i);
}
m_storeTrackerList = m_ui->trackersList->toPlainText();
m_storeWebSeedList = m_ui->URLSeedsList->toPlainText();
m_storeComments = m_ui->txtComment->toPlainText();
void TorrentCreatorDlg::saveTrackerList()
{
Preferences::instance()->setCreateTorTrackers(trackers_list->toPlainText());
m_storeDialogSize = size();
}
void TorrentCreatorDlg::loadTrackerList()
void TorrentCreatorDlg::loadSettings()
{
trackers_list->setPlainText(Preferences::instance()->getCreateTorTrackers());
}
m_ui->textInputPath->setText(m_storeLastAddPath);
void TorrentCreatorDlg::saveSettings()
{
Preferences* const pref = Preferences::instance();
pref->setCreateTorGeometry(saveGeometry());
pref->setCreateTorIgnoreRatio(checkIgnoreShareLimits->isChecked());
}
m_ui->comboPieceSize->setCurrentIndex(m_storePieceSize);
m_ui->checkPrivate->setChecked(m_storePrivateTorrent);
m_ui->checkStartSeeding->setChecked(m_storeStartSeeding);
m_ui->checkIgnoreShareLimits->setChecked(m_storeIgnoreRatio);
m_ui->checkIgnoreShareLimits->setEnabled(m_ui->checkStartSeeding->isChecked());
void TorrentCreatorDlg::loadSettings()
{
const Preferences* const pref = Preferences::instance();
restoreGeometry(pref->getCreateTorGeometry());
checkIgnoreShareLimits->setChecked(pref->getCreateTorIgnoreRatio());
}
m_ui->trackersList->setPlainText(m_storeTrackerList);
m_ui->URLSeedsList->setPlainText(m_storeWebSeedList);
m_ui->txtComment->setPlainText(m_storeComments);
void TorrentCreatorDlg::closeEvent(QCloseEvent *event)
{
qDebug() << Q_FUNC_INFO;
saveSettings();
QDialog::closeEvent(event);
if (m_storeDialogSize.value().isValid())
resize(m_storeDialogSize);
}

70
src/gui/torrentcreatordlg.h

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2010 Christophe Dumez
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2017 Mike Tzou (Chocobo1)
* Copyright (C) 2010 Christophe Dumez <chris@qbittorrent.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -24,56 +25,65 @@ @@ -24,56 +25,65 @@
* 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 CREATE_TORRENT_IMP_H
#define CREATE_TORRENT_IMP_H
#ifndef TORRENTCREATORDLG_H
#define TORRENTCREATORDLG_H
#include <QDialog>
#include "ui_torrentcreatordlg.h"
#include "base/settingvalue.h"
namespace Ui
{
class TorrentCreatorDlg;
}
namespace BitTorrent
{
class TorrentCreatorThread;
}
class TorrentCreatorDlg : public QDialog, private Ui::createTorrentDialog
class TorrentCreatorDlg: public QDialog
{
Q_OBJECT
public:
TorrentCreatorDlg(QWidget *parent = 0);
TorrentCreatorDlg(QWidget *parent = 0, const QString &defaultPath = QString());
~TorrentCreatorDlg();
int getPieceSize() const;
void updateInputPath(const QString &path);
public slots:
private slots:
void updateProgressBar(int progress);
void on_cancelButton_clicked();
protected slots:
void on_createButton_clicked();
void on_addFile_button_clicked();
void on_addFolder_button_clicked();
void handleCreationFailure(QString msg);
void handleCreationSuccess(QString path, QString branch_path);
void setInteractionEnabled(bool enabled);
void showProgressBar(bool show);
void on_checkAutoPieceSize_clicked(bool checked);
void updateOptimalPieceSize();
void saveTrackerList();
void loadTrackerList();
protected:
void closeEvent(QCloseEvent *event);
void onCreateButtonClicked();
void onAddFileButtonClicked();
void onAddFolderButtonClicked();
void handleCreationFailure(const QString &msg);
void handleCreationSuccess(const QString &path, const QString &branchPath);
private:
void dropEvent(QDropEvent *event) override;
void dragEnterEvent(QDragEnterEvent *event) override;
void saveSettings();
void loadSettings();
int getPieceSize() const;
void setInteractionEnabled(bool enabled);
private:
Ui::TorrentCreatorDlg *m_ui;
BitTorrent::TorrentCreatorThread *m_creatorThread;
QList<int> m_pieceSizes;
// settings
CachedSettingValue<QSize> m_storeDialogSize;
CachedSettingValue<int> m_storePieceSize;
CachedSettingValue<bool> m_storePrivateTorrent;
CachedSettingValue<bool> m_storeStartSeeding;
CachedSettingValue<bool> m_storeIgnoreRatio;
CachedSettingValue<QString> m_storeLastAddPath;
CachedSettingValue<QString> m_storeTrackerList;
CachedSettingValue<QString> m_storeWebSeedList;
CachedSettingValue<QString> m_storeComments;
CachedSettingValue<QString> m_storeLastSavePath;
};
#endif

542
src/gui/torrentcreatordlg.ui

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>createTorrentDialog</class>
<widget class="QDialog" name="createTorrentDialog">
<class>TorrentCreatorDlg</class>
<widget class="QDialog" name="TorrentCreatorDlg">
<property name="geometry">
<rect>
<x>0</x>
@ -10,322 +10,300 @@ @@ -10,322 +10,300 @@
<height>658</height>
</rect>
</property>
<property name="acceptDrops">
<bool>true</bool>
</property>
<property name="windowTitle">
<string>Torrent Creation Tool</string>
<string>Torrent Creator</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="createTorrent_title">
<property name="minimumSize">
<size>
<width>0</width>
<height>27</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>27</height>
</size>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Torrent file creation</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Select file/folder to share</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Path:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="textInputPath">
<property name="acceptDrops">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label_2">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>[Drag and drop area]</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="addFileButton">
<property name="text">
<string>Select file</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="addFolderButton">
<property name="text">
<string>Select folder</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QLabel" name="lbl_input">
<property name="text">
<string>File or folder to add to the torrent:</string>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Settings</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="textInputPath"/>
</item>
<item>
<layout class="QHBoxLayout">
<item>
<widget class="QPushButton" name="addFile_button">
<property name="text">
<string>Add file</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="addFolder_button">
<property name="text">
<string>Add folder</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="lbl_announce_url">
<property name="text">
<string>Tracker URLs:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="urlSeeds_lbl">
<property name="text">
<string>Web seeds urls:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="lbl_comment">
<property name="text">
<string>Comment:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QTextEdit" name="txt_comment">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="acceptRichText">
<bool>false</bool>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QTextEdit" name="trackers_list">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string comment="A tracker tier is a group of trackers, consisting of a main tracker and its mirrors.">You can separate tracker tiers / groups with an empty line.</string>
</property>
<property name="acceptRichText">
<bool>false</bool>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QTextEdit" name="URLSeeds_list">
<property name="acceptRichText">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout">
<item>
<widget class="QLabel" name="txtPieceSize">
<property name="text">
<string>Piece size:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboPieceSize">
<property name="enabled">
<bool>false</bool>
</property>
<property name="editable">
<bool>false</bool>
</property>
<property name="currentIndex">
<number>4</number>
</property>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QHBoxLayout" name="pieceSizeLayout">
<item>
<widget class="QLabel" name="txtPieceSize">
<property name="text">
<string>Piece size:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboPieceSize">
<property name="currentIndex">
<number>0</number>
</property>
<property name="minimumContentsLength">
<number>7</number>
</property>
<item>
<property name="text">
<string>Auto</string>
</property>
</item>
<item>
<property name="text">
<string>16 KiB</string>
</property>
</item>
<item>
<property name="text">
<string>32 KiB</string>
</property>
</item>
<item>
<property name="text">
<string>64 KiB</string>
</property>
</item>
<item>
<property name="text">
<string>128 KiB</string>
</property>
</item>
<item>
<property name="text">
<string>256 KiB</string>
</property>
</item>
<item>
<property name="text">
<string>512 KiB</string>
</property>
</item>
<item>
<property name="text">
<string>1 MiB</string>
</property>
</item>
<item>
<property name="text">
<string>2 MiB</string>
</property>
</item>
<item>
<property name="text">
<string>4 MiB</string>
</property>
</item>
<item>
<property name="text">
<string>8 MiB</string>
</property>
</item>
<item>
<property name="text">
<string>16 MiB</string>
</property>
</item>
</widget>
</item>
<item>
<spacer name="spacer1">
<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="checkPrivate">
<property name="text">
<string>16 KiB</string>
<string>Private torrent (Won't distribute on DHT network)</string>
</property>
</item>
<item>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkStartSeeding">
<property name="text">
<string>32 KiB</string>
<string>Start seeding immediately</string>
</property>
</item>
<item>
<property name="text">
<string>64 KiB</string>
<property name="checked">
<bool>true</bool>
</property>
</item>
<item>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkIgnoreShareLimits">
<property name="text">
<string>128 KiB</string>
<string>Ignore share ratio limits for this torrent</string>
</property>
</item>
<item>
<property name="text">
<string>256 KiB</string>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>Fields</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="1">
<widget class="QTextEdit" name="trackersList">
<property name="toolTip">
<string comment="A tracker tier is a group of trackers, consisting of a main tracker and its mirrors.">You can separate tracker tiers / groups with an empty line.</string>
</property>
</item>
<item>
<property name="text">
<string>512 KiB</string>
<property name="acceptRichText">
<bool>false</bool>
</property>
</item>
<item>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="urlSeeds_lbl">
<property name="text">
<string>1 MiB</string>
<string>Web seed URLs:</string>
</property>
</item>
<item>
<property name="text">
<string>2 MiB</string>
</widget>
</item>
<item row="1" column="1">
<widget class="QTextEdit" name="URLSeedsList">
<property name="acceptRichText">
<bool>false</bool>
</property>
</item>
<item>
<property name="text">
<string>4 MiB</string>
</widget>
</item>
<item row="2" column="1">
<widget class="QTextEdit" name="txtComment">
<property name="acceptRichText">
<bool>false</bool>
</property>
</item>
<item>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="lbl_announce_url">
<property name="text">
<string>8 MiB</string>
<string>Tracker URLs:</string>
</property>
</item>
<item>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="lbl_comment">
<property name="text">
<string>16 MiB</string>
<string>Comments:</string>
</property>
</item>
</widget>
</item>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QCheckBox" name="checkAutoPieceSize">
<widget class="QLabel" name="progressLbl">
<property name="text">
<string>Auto</string>
</property>
<property name="checked">
<bool>true</bool>
<string>Progress:</string>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
<widget class="QProgressBar" name="progressBar">
<property name="value">
<number>0</number>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="check_private">
<property name="text">
<string>Private (won't be distributed on DHT network if enabled)</string>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkStartSeeding">
<property name="text">
<string>Start seeding after creation</string>
</property>
<property name="checked">
<property name="centerButtons">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkIgnoreShareLimits">
<property name="text">
<string>Ignore share ratio limits for this torrent</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="progressLbl">
<property name="text">
<string>Progress:</string>
</property>
</widget>
</item>
<item>
<widget class="QProgressBar" name="progressBar">
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout">
<item>
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>131</width>
<height>31</height>
</size>
</property>
</spacer>
</item>
<item>
<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">
<string>Cancel</string>
</property>
</widget>
</item>
<item>
<spacer>
<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>
</widget>
<tabstops>
<tabstop>textInputPath</tabstop>
<tabstop>addFileButton</tabstop>
<tabstop>addFolderButton</tabstop>
<tabstop>comboPieceSize</tabstop>
<tabstop>checkPrivate</tabstop>
<tabstop>checkStartSeeding</tabstop>
<tabstop>checkIgnoreShareLimits</tabstop>
<tabstop>trackersList</tabstop>
<tabstop>URLSeedsList</tabstop>
<tabstop>txtComment</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
@ -344,5 +322,21 @@ @@ -344,5 +322,21 @@
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>TorrentCreatorDlg</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>295</x>
<y>635</y>
</hint>
<hint type="destinationlabel">
<x>295</x>
<y>328</y>
</hint>
</hints>
</connection>
</connections>
</ui>

Loading…
Cancel
Save