1
0
Fork 0
mirror of https://github.com/transmission/transmission synced 2024-12-27 18:18:10 +00:00
transmission/qt/MakeDialog.cc

309 lines
8 KiB
C++

// This file Copyright © 2009-2022 Mnemosyne LLC.
// It may be used under GPLv2 (SPDX: GPL-2.0), GPLv3 (SPDX: GPL-3.0),
// or any future license endorsed by Mnemosyne LLC.
// License text can be found in the licenses/ folder.
#include "MakeDialog.h"
#include <vector>
#include <QDir>
#include <QFileInfo>
#include <QMimeData>
#include <QPushButton>
#include <QTimer>
#include <libtransmission/makemeta.h>
#include <libtransmission/transmission.h>
#include <libtransmission/utils.h>
#include "ColumnResizer.h"
#include "Formatter.h"
#include "Session.h"
#include "Utils.h"
#include "ui_MakeProgressDialog.h"
namespace
{
class MakeProgressDialog : public BaseDialog
{
Q_OBJECT
public:
MakeProgressDialog(Session& session, tr_metainfo_builder& builder, QWidget* parent = nullptr);
private slots:
void onButtonBoxClicked(QAbstractButton* button);
void onProgress();
private:
Session& session_;
tr_metainfo_builder& builder_;
Ui::MakeProgressDialog ui_ = {};
QTimer timer_;
};
} // namespace
MakeProgressDialog::MakeProgressDialog(Session& session, tr_metainfo_builder& builder, QWidget* parent)
: BaseDialog(parent)
, session_(session)
, builder_(builder)
{
ui_.setupUi(this);
connect(ui_.dialogButtons, &QDialogButtonBox::clicked, this, &MakeProgressDialog::onButtonBoxClicked);
connect(&timer_, &QTimer::timeout, this, &MakeProgressDialog::onProgress);
timer_.start(100);
onProgress();
}
void MakeProgressDialog::onButtonBoxClicked(QAbstractButton* button)
{
switch (ui_.dialogButtons->standardButton(button))
{
case QDialogButtonBox::Open:
session_.addNewlyCreatedTorrent(
QString::fromUtf8(builder_.outputFile),
QFileInfo(QString::fromUtf8(builder_.top)).dir().path());
break;
case QDialogButtonBox::Abort:
builder_.abortFlag = true;
break;
default: // QDialogButtonBox::Ok:
break;
}
close();
}
void MakeProgressDialog::onProgress()
{
// progress bar
tr_metainfo_builder const& b = builder_;
double const denom = b.pieceCount != 0 ? b.pieceCount : 1;
ui_.progressBar->setValue(static_cast<int>((100.0 * b.pieceIndex) / denom));
// progress label
QString const top = QString::fromUtf8(b.top);
QString const base(QFileInfo(top).completeBaseName());
QString str;
if (!b.isDone)
{
str = tr("Creating \"%1\"").arg(base);
}
else if (b.result == TR_MAKEMETA_OK)
{
str = tr("Created \"%1\"!").arg(base);
}
else if (b.result == TR_MAKEMETA_URL)
{
str = tr("Error: invalid announce URL \"%1\"").arg(QString::fromUtf8(b.errfile));
}
else if (b.result == TR_MAKEMETA_CANCELLED)
{
str = tr("Cancelled");
}
else if (b.result == TR_MAKEMETA_IO_READ)
{
str = tr("Error reading \"%1\": %2").arg(QString::fromUtf8(b.errfile)).arg(QString::fromUtf8(tr_strerror(b.my_errno)));
}
else if (b.result == TR_MAKEMETA_IO_WRITE)
{
str = tr("Error writing \"%1\": %2").arg(QString::fromUtf8(b.errfile)).arg(QString::fromUtf8(tr_strerror(b.my_errno)));
}
ui_.progressLabel->setText(str);
// buttons
ui_.dialogButtons->button(QDialogButtonBox::Abort)->setEnabled(!b.isDone);
ui_.dialogButtons->button(QDialogButtonBox::Ok)->setEnabled(b.isDone);
ui_.dialogButtons->button(QDialogButtonBox::Open)->setEnabled(b.isDone && b.result == TR_MAKEMETA_OK);
}
#include "MakeDialog.moc"
/***
****
***/
void MakeDialog::makeTorrent()
{
if (builder_ == nullptr)
{
return;
}
// get the tiers
int tier = 0;
std::vector<tr_tracker_info> trackers;
for (QString const& line : ui_.trackersEdit->toPlainText().split(QLatin1Char('\n')))
{
QString const announce_url = line.trimmed();
if (announce_url.isEmpty())
{
++tier;
}
else
{
auto tmp = tr_tracker_info{};
tmp.announce = tr_strdup(announce_url.toUtf8().constData());
tmp.tier = tier;
trackers.push_back(tmp);
}
}
// the file to create
QString const path = QString::fromUtf8(builder_->top);
auto const torrent_name = QFileInfo(path).completeBaseName() + QStringLiteral(".torrent");
QString const target = QDir(ui_.destinationButton->path()).filePath(torrent_name);
// comment
QString comment;
if (ui_.commentCheck->isChecked())
{
comment = ui_.commentEdit->text();
}
// source
QString source;
if (ui_.sourceCheck->isChecked())
{
source = ui_.sourceEdit->text();
}
// start making the torrent
tr_makeMetaInfo(
builder_.get(),
target.toUtf8().constData(),
trackers.empty() ? nullptr : trackers.data(),
trackers.size(),
comment.isEmpty() ? nullptr : comment.toUtf8().constData(),
ui_.privateCheck->isChecked(),
source.isNull() ? nullptr : source.toUtf8().constData());
// pop up the dialog
auto* dialog = new MakeProgressDialog(session_, *builder_, this);
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->open();
}
/***
****
***/
QString MakeDialog::getSource() const
{
return (ui_.sourceFileRadio->isChecked() ? ui_.sourceFileButton : ui_.sourceFolderButton)->path();
}
/***
****
***/
void MakeDialog::onSourceChanged()
{
builder_.reset();
QString const filename = getSource();
if (!filename.isEmpty())
{
builder_.reset(tr_metaInfoBuilderCreate(filename.toUtf8().constData()));
}
QString text;
if (builder_ == nullptr)
{
text = tr("<i>No source selected</i>");
}
else
{
QString files = tr("%Ln File(s)", nullptr, builder_->fileCount);
QString pieces = tr("%Ln Piece(s)", nullptr, builder_->pieceCount);
text = tr("%1 in %2; %3 @ %4")
.arg(Formatter::get().sizeToString(builder_->totalSize))
.arg(files)
.arg(pieces)
.arg(Formatter::get().sizeToString(static_cast<uint64_t>(builder_->pieceSize)));
}
ui_.sourceSizeLabel->setText(text);
}
MakeDialog::MakeDialog(Session& session, QWidget* parent)
: BaseDialog(parent)
, session_(session)
, builder_(nullptr, &tr_metaInfoBuilderFree)
{
ui_.setupUi(this);
ui_.destinationButton->setMode(PathButton::DirectoryMode);
ui_.destinationButton->setPath(QDir::homePath());
ui_.sourceFolderButton->setMode(PathButton::DirectoryMode);
ui_.sourceFileButton->setMode(PathButton::FileMode);
auto* cr = new ColumnResizer(this);
cr->addLayout(ui_.filesSectionLayout);
cr->addLayout(ui_.propertiesSectionLayout);
cr->update();
resize(minimumSizeHint());
connect(ui_.sourceFolderRadio, &QAbstractButton::toggled, this, &MakeDialog::onSourceChanged);
connect(ui_.sourceFolderButton, &PathButton::pathChanged, this, &MakeDialog::onSourceChanged);
connect(ui_.sourceFileRadio, &QAbstractButton::toggled, this, &MakeDialog::onSourceChanged);
connect(ui_.sourceFileButton, &PathButton::pathChanged, this, &MakeDialog::onSourceChanged);
connect(ui_.dialogButtons, &QDialogButtonBox::accepted, this, &MakeDialog::makeTorrent);
connect(ui_.dialogButtons, &QDialogButtonBox::rejected, this, &MakeDialog::close);
onSourceChanged();
}
/***
****
***/
void MakeDialog::dragEnterEvent(QDragEnterEvent* event)
{
QMimeData const* mime = event->mimeData();
if (!mime->urls().isEmpty() && QFileInfo(mime->urls().front().path()).exists())
{
event->acceptProposedAction();
}
}
void MakeDialog::dropEvent(QDropEvent* event)
{
QString const filename = event->mimeData()->urls().front().path();
QFileInfo const file_info(filename);
if (file_info.exists())
{
if (file_info.isDir())
{
ui_.sourceFolderRadio->setChecked(true);
ui_.sourceFolderButton->setPath(filename);
}
else // it's a file
{
ui_.sourceFileRadio->setChecked(true);
ui_.sourceFileButton->setPath(filename);
}
}
}