diff --git a/src/base/CMakeLists.txt b/src/base/CMakeLists.txt index f8bf7f7c5..9ff9521ed 100644 --- a/src/base/CMakeLists.txt +++ b/src/base/CMakeLists.txt @@ -52,6 +52,7 @@ utils/string.h utils/version.h asyncfilestorage.h filesystemwatcher.h +global.h iconprovider.h indexrange.h logger.h diff --git a/src/base/base.pri b/src/base/base.pri index 041e2d4a3..b302c9436 100644 --- a/src/base/base.pri +++ b/src/base/base.pri @@ -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 \ diff --git a/src/base/bittorrent/torrentcreatorthread.cpp b/src/base/bittorrent/torrentcreatorthread.cpp index e4809994d..3a3d7fce9 100644 --- a/src/base/bittorrent/torrentcreatorthread.cpp +++ b/src/base/bittorrent/torrentcreatorthread.cpp @@ -28,25 +28,21 @@ * Contact : chris@qbittorrent.org */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "torrentcreatorthread.h" + +#include #include -#include -#include +#include +#include +#include +#include + +#include #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) : 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 m_comment = comment; m_private = isPrivate; m_pieceSize = pieceSize; - m_abort = false; start(); } @@ -94,11 +88,6 @@ void TorrentCreatorThread::sendProgressSignal(int numHashes, int numPieces) emit updateProgress(static_cast((numHashes * 100.) / numPieces)); } -void TorrentCreatorThread::abortCreation() -{ - m_abort = true; -} - void TorrentCreatorThread::run() { emit updateProgress(0); @@ -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() 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() 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() if (outfile.fail()) throw std::exception(); + if (isInterruptionRequested()) return; + libt::bencode(std::ostream_iterator(outfile), t.generate()); outfile.close(); diff --git a/src/base/bittorrent/torrentcreatorthread.h b/src/base/bittorrent/torrentcreatorthread.h index 3816e3489..d62af8011 100644 --- a/src/base/bittorrent/torrentcreatorthread.h +++ b/src/base/bittorrent/torrentcreatorthread.h @@ -31,8 +31,8 @@ #ifndef BITTORRENT_TORRENTCREATORTHREAD_H #define BITTORRENT_TORRENTCREATORTHREAD_H -#include #include +#include 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 QString m_comment; bool m_private; int m_pieceSize; - bool m_abort; }; } diff --git a/src/base/global.h b/src/base/global.h new file mode 100644 index 000000000..2bfeda9cb --- /dev/null +++ b/src/base/global.h @@ -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"; + diff --git a/src/base/preferences.cpp b/src/base/preferences.cpp index 0d4574a6f..d951db38d 100644 --- a/src/base/preferences.cpp +++ b/src/base/preferences.cpp @@ -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(); diff --git a/src/base/preferences.h b/src/base/preferences.h index 0620f5f48..60a936657 100644 --- a/src/base/preferences.h +++ b/src/base/preferences.h @@ -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; diff --git a/src/base/utils/fs.cpp b/src/base/utils/fs.cpp index 3da759c9f..b10edc241 100644 --- a/src/base/utils/fs.cpp +++ b/src/base/utils/fs.cpp @@ -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) 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) diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp index e9be2b2bb..6d2c79fee 100644 --- a/src/gui/mainwindow.cpp +++ b/src/gui/mainwindow.cpp @@ -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) // 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) void MainWindow::dropEvent(QDropEvent *event) { event->acceptProposedAction(); + + // remove scheme QStringList files; if (event->mimeData()->hasUrls()) { const QList urls = event->mimeData()->urls(); @@ -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() // 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()) { diff --git a/src/gui/mainwindow.h b/src/gui/mainwindow.h index f764bca29..a64af6041 100644 --- a/src/gui/mainwindow.h +++ b/src/gui/mainwindow.h @@ -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; diff --git a/src/gui/torrentcreatordlg.cpp b/src/gui/torrentcreatordlg.cpp index 668ee401a..4eb58966d 100644 --- a/src/gui/torrentcreatordlg.cpp +++ b/src/gui/torrentcreatordlg.cpp @@ -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 * * 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 @@ * 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 #include #include #include +#include +#include -#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" -const uint NB_PIECES_MIN = 1200; -const uint NB_PIECES_MAX = 2200; +#include "ui_torrentcreatordlg.h" -TorrentCreatorDlg::TorrentCreatorDlg(QWidget *parent) +#define SETTINGS_KEY(name) "TorrentCreator/" name + +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(); + input = fi.canonicalFilePath(); - Preferences* const pref = Preferences::instance(); - QString lastPath = pref->getCreateTorLastSavePath(); - - 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()); -} - -void TorrentCreatorDlg::showProgressBar(bool show) -{ - progressLbl->setVisible(show); - progressBar->setVisible(show); -} - -void TorrentCreatorDlg::on_checkAutoPieceSize_clicked(bool checked) -{ - comboPieceSize->setEnabled(!checked); - if (checked) - updateOptimalPieceSize(); -} - -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); -} - -void TorrentCreatorDlg::saveTrackerList() -{ - Preferences::instance()->setCreateTorTrackers(trackers_list->toPlainText()); -} - -void TorrentCreatorDlg::loadTrackerList() -{ - trackers_list->setPlainText(Preferences::instance()->getCreateTorTrackers()); + 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::saveSettings() { - Preferences* const pref = Preferences::instance(); - pref->setCreateTorGeometry(saveGeometry()); - pref->setCreateTorIgnoreRatio(checkIgnoreShareLimits->isChecked()); + m_storeLastAddPath = m_ui->textInputPath->text().trimmed(); + + m_storePieceSize = m_ui->comboPieceSize->currentIndex(); + m_storePrivateTorrent = m_ui->checkPrivate->isChecked(); + m_storeStartSeeding = m_ui->checkStartSeeding->isChecked(); + m_storeIgnoreRatio = m_ui->checkIgnoreShareLimits->isChecked(); + + m_storeTrackerList = m_ui->trackersList->toPlainText(); + m_storeWebSeedList = m_ui->URLSeedsList->toPlainText(); + m_storeComments = m_ui->txtComment->toPlainText(); + + m_storeDialogSize = size(); } void TorrentCreatorDlg::loadSettings() { - const Preferences* const pref = Preferences::instance(); - restoreGeometry(pref->getCreateTorGeometry()); - checkIgnoreShareLimits->setChecked(pref->getCreateTorIgnoreRatio()); -} + m_ui->textInputPath->setText(m_storeLastAddPath); -void TorrentCreatorDlg::closeEvent(QCloseEvent *event) -{ - qDebug() << Q_FUNC_INFO; - saveSettings(); - QDialog::closeEvent(event); + 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()); + + m_ui->trackersList->setPlainText(m_storeTrackerList); + m_ui->URLSeedsList->setPlainText(m_storeWebSeedList); + m_ui->txtComment->setPlainText(m_storeComments); + + if (m_storeDialogSize.value().isValid()) + resize(m_storeDialogSize); } diff --git a/src/gui/torrentcreatordlg.h b/src/gui/torrentcreatordlg.h index d681a90d9..41fd0a8fe 100644 --- a/src/gui/torrentcreatordlg.h +++ b/src/gui/torrentcreatordlg.h @@ -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 * * 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 @@ * 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 "ui_torrentcreatordlg.h" +#include + +#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 m_pieceSizes; + + // settings + CachedSettingValue m_storeDialogSize; + CachedSettingValue m_storePieceSize; + CachedSettingValue m_storePrivateTorrent; + CachedSettingValue m_storeStartSeeding; + CachedSettingValue m_storeIgnoreRatio; + CachedSettingValue m_storeLastAddPath; + CachedSettingValue m_storeTrackerList; + CachedSettingValue m_storeWebSeedList; + CachedSettingValue m_storeComments; + CachedSettingValue m_storeLastSavePath; }; #endif diff --git a/src/gui/torrentcreatordlg.ui b/src/gui/torrentcreatordlg.ui index 524fc2db8..2145bb939 100644 --- a/src/gui/torrentcreatordlg.ui +++ b/src/gui/torrentcreatordlg.ui @@ -1,7 +1,7 @@ - createTorrentDialog - + TorrentCreatorDlg + 0 @@ -10,322 +10,300 @@ 658 + + true + - Torrent Creation Tool + Torrent Creator - - - - 0 - 27 - - - - - 16777215 - 27 - - - - - 75 - true - - - - Torrent file creation - - - Qt::AlignCenter + + + Select file/folder to share + + + + + + + Path: + + + + + + + false + + + + + + + + + + + false + + + + 0 + 0 + + + + [Drag and drop area] + + + Qt::AlignCenter + + + + + + + Select file + + + + + + + Select folder + + + + + + - - - File or folder to add to the torrent: + + + Settings + + + + + + + Piece size: + + + + + + + 0 + + + 7 + + + + Auto + + + + + 16 KiB + + + + + 32 KiB + + + + + 64 KiB + + + + + 128 KiB + + + + + 256 KiB + + + + + 512 KiB + + + + + 1 MiB + + + + + 2 MiB + + + + + 4 MiB + + + + + 8 MiB + + + + + 16 MiB + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Private torrent (Won't distribute on DHT network) + + + + + + + Start seeding immediately + + + true + + + + + + + Ignore share ratio limits for this torrent + + + + - + + + Fields + + + + + + You can separate tracker tiers / groups with an empty line. + + + false + + + + + + + Web seed URLs: + + + + + + + false + + + + + + + false + + + + + + + Tracker URLs: + + + + + + + Comments: + + + + + - + - + - Add file + Progress: - - - Add folder + + + 0 - - - - - Tracker URLs: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Web seeds urls: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Comment: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - false - - - - - - - - 0 - 0 - - - - You can separate tracker tiers / groups with an empty line. - - - false - - - - - - - false - - - - - - - - - - - Piece size: - - - - - - - false - - - false - - - 4 - - - - 16 KiB - - - - - 32 KiB - - - - - 64 KiB - - - - - 128 KiB - - - - - 256 KiB - - - - - 512 KiB - - - - - 1 MiB - - - - - 2 MiB - - - - - 4 MiB - - - - - 8 MiB - - - - - 16 MiB - - - - - - - - Auto - - - true - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Private (won't be distributed on DHT network if enabled) + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - Start seeding after creation - - + true - - - - Ignore share ratio limits for this torrent - - - - - - - Progress: - - - - - - - 0 - - - - - - - - - Qt::Horizontal - - - - 131 - 31 - - - - - - - - Create and save... - - - - - - - Cancel - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - + + textInputPath + addFileButton + addFolderButton + comboPieceSize + checkPrivate + checkStartSeeding + checkIgnoreShareLimits + trackersList + URLSeedsList + txtComment + @@ -344,5 +322,21 @@ + + buttonBox + rejected() + TorrentCreatorDlg + reject() + + + 295 + 635 + + + 295 + 328 + + +