/release/src/router/transmission/qt/make-dialog.cc
C++ | 460 lines | 371 code | 59 blank | 30 comment | 34 complexity | 7071b717a85caed9c673893c7f421c29 MD5 | raw file
- /*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
- *
- * It may be used under the GNU Public License v2 or v3 licenses,
- * or any future license endorsed by Mnemosyne LLC.
- *
- * $Id: make-dialog.cc 14225 2014-01-19 01:09:44Z jordan $
- */
- #include <cassert>
- #include <iostream>
- #include <QCheckBox>
- #include <QDialogButtonBox>
- #include <QFileDialog>
- #include <QFileIconProvider>
- #include <QHBoxLayout>
- #include <QLabel>
- #include <QLineEdit>
- #include <QList>
- #include <QMimeData>
- #include <QPlainTextEdit>
- #include <QProgressBar>
- #include <QPushButton>
- #include <QRadioButton>
- #include <QSize>
- #include <QStyle>
- #include <QTimer>
- #include <QVBoxLayout>
- #include <libtransmission/transmission.h>
- #include <libtransmission/makemeta.h>
- #include <libtransmission/utils.h>
- #include "formatter.h"
- #include "hig.h"
- #include "make-dialog.h"
- #include "session.h"
- #include "utils.h"
- /***
- ****
- ***/
- void
- MakeDialog :: onNewDialogDestroyed (QObject * o)
- {
- Q_UNUSED (o);
- myTimer.stop ();
- }
- void
- MakeDialog :: onNewButtonBoxClicked (QAbstractButton * button)
- {
- switch (myNewButtonBox->standardButton (button))
- {
- case QDialogButtonBox::Open:
- mySession.addNewlyCreatedTorrent (myTarget, QFileInfo(QString::fromUtf8(myBuilder->top)).dir().path());
- break;
- case QDialogButtonBox::Abort:
- myBuilder->abortFlag = true;
- break;
- default: // QDialogButtonBox::Ok:
- break;
- }
- myNewDialog->deleteLater ();
- }
- void
- MakeDialog :: onProgress ()
- {
- // progress bar
- const tr_metainfo_builder * b = myBuilder;
- const double denom = b->pieceCount ? b->pieceCount : 1;
- myNewProgress->setValue ((int) ((100.0 * b->pieceIndex) / denom));
- // progress label
- const QString top = QString::fromLocal8Bit (myBuilder->top);
- const QString 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::fromLocal8Bit (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::fromLocal8Bit(b->errfile)).arg (QString::fromLocal8Bit(strerror(b->my_errno)));
- else if (b->result == TR_MAKEMETA_IO_WRITE)
- str = tr ("Error writing \"%1\": %2").arg (QString::fromLocal8Bit(b->errfile)).arg (QString::fromLocal8Bit(strerror(b->my_errno)));
- myNewLabel->setText (str);
- // buttons
- (myNewButtonBox->button(QDialogButtonBox::Abort))->setEnabled (!b->isDone);
- (myNewButtonBox->button(QDialogButtonBox::Ok))->setEnabled (b->isDone);
- (myNewButtonBox->button(QDialogButtonBox::Open))->setEnabled (b->isDone && !b->result);
- }
- void
- MakeDialog :: makeTorrent ()
- {
- if (!myBuilder)
- return;
- // get the tiers
- int tier = 0;
- QVector<tr_tracker_info> trackers;
- foreach (QString line, myTrackerEdit->toPlainText().split("\n"))
- {
- line = line.trimmed ();
- if (line.isEmpty ())
- {
- ++tier;
- }
- else
- {
- tr_tracker_info tmp;
- tmp.announce = tr_strdup (line.toUtf8().constData ());
- tmp.tier = tier;
- trackers.append (tmp);
- }
- }
- // pop up the dialog
- QDialog * dialog = new QDialog (this);
- dialog->setWindowTitle (tr ("New Torrent"));
- myNewDialog = dialog;
- QVBoxLayout * top = new QVBoxLayout (dialog);
- top->addWidget( (myNewLabel = new QLabel));
- top->addWidget( (myNewProgress = new QProgressBar));
- QDialogButtonBox * buttons = new QDialogButtonBox (QDialogButtonBox::Ok
- | QDialogButtonBox::Open
- | QDialogButtonBox::Abort);
- myNewButtonBox = buttons;
- connect (buttons, SIGNAL(clicked(QAbstractButton*)),
- this, SLOT(onNewButtonBoxClicked(QAbstractButton*)));
- top->addWidget (buttons);
- onProgress ();
- dialog->show ();
- connect (dialog, SIGNAL(destroyed(QObject*)),
- this, SLOT(onNewDialogDestroyed(QObject*)));
- myTimer.start (100);
- // the file to create
- const QString path = QString::fromUtf8 (myBuilder->top);
- const QString torrentName = QFileInfo(path).completeBaseName() + ".torrent";
- myTarget = QDir (myDestination).filePath (torrentName);
- // comment
- QString comment;
- if (myCommentCheck->isChecked())
- comment = myCommentEdit->text();
- // start making the torrent
- tr_makeMetaInfo (myBuilder,
- myTarget.toUtf8().constData(),
- (trackers.isEmpty() ? NULL : trackers.data()),
- trackers.size(),
- (comment.isEmpty() ? NULL : comment.toUtf8().constData()),
- myPrivateCheck->isChecked());
- }
- /***
- ****
- ***/
- void
- MakeDialog :: onFileClicked ()
- {
- QFileDialog * d = new QFileDialog (this, tr ("Select File"));
- d->setFileMode (QFileDialog::ExistingFile);
- d->setAttribute (Qt::WA_DeleteOnClose);
- connect (d, SIGNAL(filesSelected(const QStringList&)),
- this, SLOT(onFileSelected(const QStringList&)));
- d->show ();
- }
- void
- MakeDialog :: onFileSelected (const QStringList& list)
- {
- if (!list.empty ())
- onFileSelected (list.front ());
- }
- void
- MakeDialog :: onFileSelected (const QString& filename)
- {
- myFile = Utils::removeTrailingDirSeparator (filename);
- myFileButton->setText (QFileInfo(myFile).fileName());
- onSourceChanged ();
- }
- void
- MakeDialog :: onFolderClicked ()
- {
- QFileDialog * d = new QFileDialog (this, tr ("Select Folder"));
- d->setFileMode (QFileDialog::Directory);
- d->setOption (QFileDialog::ShowDirsOnly);
- d->setAttribute (Qt::WA_DeleteOnClose);
- connect (d, SIGNAL(filesSelected(const QStringList&)),
- this, SLOT(onFolderSelected(const QStringList&)));
- d->show ();
- }
- void
- MakeDialog :: onFolderSelected (const QStringList& list)
- {
- if (!list.empty ())
- onFolderSelected (list.front ());
- }
- void
- MakeDialog :: onFolderSelected (const QString& filename)
- {
- myFolder = Utils::removeTrailingDirSeparator (filename);
- myFolderButton->setText (QFileInfo(myFolder).fileName());
- onSourceChanged ();
- }
- void
- MakeDialog :: onDestinationClicked ()
- {
- QFileDialog * d = new QFileDialog (this, tr ("Select Folder"));
- d->setFileMode (QFileDialog::Directory);
- d->setOption (QFileDialog::ShowDirsOnly);
- d->setAttribute (Qt::WA_DeleteOnClose);
- connect (d, SIGNAL(filesSelected(const QStringList&)),
- this, SLOT(onDestinationSelected(const QStringList&)));
- d->show ();
- }
- void
- MakeDialog :: onDestinationSelected (const QStringList& list)
- {
- if (!list.empty ())
- onDestinationSelected (list.front());
- }
- void
- MakeDialog :: onDestinationSelected (const QString& filename)
- {
- myDestination = Utils::removeTrailingDirSeparator (filename);
- myDestinationButton->setText (QFileInfo(myDestination).fileName());
- }
- void
- MakeDialog :: enableBuddyWhenChecked (QRadioButton * box, QWidget * buddy)
- {
- connect (box, SIGNAL(toggled(bool)), buddy, SLOT(setEnabled(bool)));
- buddy->setEnabled (box->isChecked ());
- }
- void
- MakeDialog :: enableBuddyWhenChecked (QCheckBox * box, QWidget * buddy)
- {
- connect (box, SIGNAL(toggled(bool)), buddy, SLOT(setEnabled(bool)));
- buddy->setEnabled (box->isChecked ());
- }
- QString
- MakeDialog :: getSource () const
- {
- return myFileRadio->isChecked () ? myFile : myFolder;
- }
- void
- MakeDialog :: onButtonBoxClicked (QAbstractButton * button)
- {
- switch (myButtonBox->standardButton (button))
- {
- case QDialogButtonBox::Ok:
- makeTorrent ();
- break;
- default: // QDialogButtonBox::Close:
- deleteLater ();
- break;
- }
- }
- /***
- ****
- ***/
- void
- MakeDialog :: onSourceChanged ()
- {
- if (myBuilder)
- {
- tr_metaInfoBuilderFree (myBuilder);
- myBuilder = 0;
- }
- const QString filename = getSource ();
- if (!filename.isEmpty ())
- myBuilder = tr_metaInfoBuilderCreate (filename.toUtf8().constData());
- QString text;
- if (!myBuilder)
- {
- text = tr ("<i>No source selected<i>");
- }
- else
- {
- QString files = tr ("%Ln File(s)", 0, myBuilder->fileCount);
- QString pieces = tr ("%Ln Piece(s)", 0, myBuilder->pieceCount);
- text = tr ("%1 in %2; %3 @ %4")
- .arg (Formatter::sizeToString (myBuilder->totalSize))
- .arg (files)
- .arg (pieces)
- .arg (Formatter::sizeToString (myBuilder->pieceSize));
- }
- mySourceLabel->setText (text);
- }
- // bah, there doesn't seem to be any cleaner way to override
- // QPlainTextEdit's default desire to be 12 lines tall
- class ShortPlainTextEdit: public QPlainTextEdit
- {
- public:
- virtual ~ShortPlainTextEdit () {}
- ShortPlainTextEdit (QWidget * parent = 0): QPlainTextEdit(parent) {}
- virtual QSize sizeHint () const { return QSize (256, 50); }
- };
- MakeDialog :: MakeDialog (Session & session, QWidget * parent):
- QDialog (parent, Qt::Dialog),
- mySession (session),
- myBuilder (0)
- {
- setAcceptDrops (true);
- connect (&myTimer, SIGNAL(timeout()), this, SLOT(onProgress()));
- setWindowTitle (tr ("New Torrent"));
- QVBoxLayout * top = new QVBoxLayout (this);
- top->setSpacing (HIG :: PAD);
- HIG * hig = new HIG;
- hig->setContentsMargins (0, 0, 0, 0);
- hig->addSectionTitle (tr ("Files"));
- QFileIconProvider iconProvider;
- const int iconSize (style()->pixelMetric (QStyle::PM_SmallIconSize));
- const QIcon folderIcon = iconProvider.icon (QFileIconProvider::Folder);
- const QPixmap folderPixmap = folderIcon.pixmap (iconSize);
- QPushButton * b = new QPushButton;
- b->setIcon (folderPixmap);
- b->setStyleSheet (QString::fromUtf8 ("text-align: left; padding-left: 5; padding-right: 5"));
- myDestination = QDir::homePath();
- b->setText (myDestination);
- connect (b, SIGNAL(clicked(bool)),
- this, SLOT(onDestinationClicked(void)));
- myDestinationButton = b;
- hig->addRow (tr ("Sa&ve to:"), b);
- myFolderRadio = new QRadioButton (tr ("Source F&older:"));
- connect (myFolderRadio, SIGNAL(toggled(bool)),
- this, SLOT(onSourceChanged()));
- myFolderButton = new QPushButton;
- myFolderButton->setIcon (folderPixmap);
- myFolderButton->setText (tr ("(None)"));
- myFolderButton->setStyleSheet (QString::fromUtf8 ("text-align: left; padding-left: 5; padding-right: 5"));
- connect (myFolderButton, SIGNAL(clicked(bool)),
- this, SLOT(onFolderClicked(void)));
- hig->addRow (myFolderRadio, myFolderButton);
- enableBuddyWhenChecked (myFolderRadio, myFolderButton);
- const QIcon fileIcon = iconProvider.icon (QFileIconProvider::File);
- const QPixmap filePixmap = fileIcon.pixmap (iconSize);
- myFileRadio = new QRadioButton (tr ("Source &File:"));
- myFileRadio->setChecked (true);
- connect (myFileRadio, SIGNAL(toggled(bool)),
- this, SLOT(onSourceChanged()));
- myFileButton = new QPushButton;
- myFileButton->setText (tr ("(None)"));
- myFileButton->setIcon (filePixmap);
- myFileButton->setStyleSheet (QString::fromUtf8 ("text-align: left; padding-left: 5; padding-right: 5"));
- connect (myFileButton, SIGNAL(clicked(bool)),
- this, SLOT(onFileClicked(void)));
- hig->addRow (myFileRadio, myFileButton);
- enableBuddyWhenChecked (myFileRadio, myFileButton);
- mySourceLabel = new QLabel (this);
- hig->addRow (tr (""), mySourceLabel);
- hig->addSectionDivider ();
- hig->addSectionTitle (tr ("Properties"));
- hig->addWideControl (myTrackerEdit = new ShortPlainTextEdit);
- const int height = fontMetrics().size (0, QString::fromUtf8("\n\n\n\n")).height ();
- myTrackerEdit->setMinimumHeight (height);
- hig->addTallRow (tr ("&Trackers:"), myTrackerEdit);
- QLabel * l = new QLabel (tr ("To add a backup URL, add it on the line after the primary URL.\nTo add another primary URL, add it after a blank line."));
- l->setAlignment (Qt::AlignLeft);
- hig->addRow (tr (""), l);
- myTrackerEdit->resize (500, height);
- myCommentCheck = new QCheckBox (tr ("Co&mment"));
- myCommentEdit = new QLineEdit ();
- hig->addRow (myCommentCheck, myCommentEdit);
- enableBuddyWhenChecked (myCommentCheck, myCommentEdit);
- myPrivateCheck = hig->addWideCheckBox (tr ("&Private torrent"), false);
- hig->finish ();
- top->addWidget (hig, 1);
- myButtonBox = new QDialogButtonBox (QDialogButtonBox::Ok
- | QDialogButtonBox::Close);
- connect (myButtonBox, SIGNAL(clicked(QAbstractButton*)),
- this, SLOT(onButtonBoxClicked(QAbstractButton*)));
- top->addWidget (myButtonBox);
- onSourceChanged ();
- }
- MakeDialog :: ~MakeDialog ()
- {
- if (myBuilder)
- tr_metaInfoBuilderFree (myBuilder);
- }
- /***
- ****
- ***/
- void
- MakeDialog :: dragEnterEvent (QDragEnterEvent * event)
- {
- const QMimeData * mime = event->mimeData ();
- if (mime->urls().size() && QFile(mime->urls().front().path()).exists ())
- event->acceptProposedAction();
- }
- void
- MakeDialog :: dropEvent (QDropEvent * event)
- {
- const QString filename = event->mimeData()->urls().front().path();
- const QFileInfo fileInfo (filename);
- if (fileInfo.exists ())
- {
- if (fileInfo.isDir ())
- {
- myFolderRadio->setChecked (true);
- onFolderSelected (filename );
- }
- else // it's a file
- {
- myFileRadio->setChecked (true);
- onFileSelected (filename);
- }
- }
- }