Revert "transmission: update from 2.13 to 2.22"
[tomato.git] / release / src / router / transmission / qt / make-dialog.cc
blobc146b0471706db9eb4582e2c731ab0ae192d9a30
1 /*
2 * This file Copyright (C) Mnemosyne LLC
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2
6 * as published by the Free Software Foundation.
8 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
10 * $Id: make-dialog.cc 11098 2010-08-02 20:55:11Z charles $
13 #include <cassert>
14 #include <iostream>
16 #include <QCheckBox>
17 #include <QDialogButtonBox>
18 #include <QFileDialog>
19 #include <QFileIconProvider>
20 #include <QHBoxLayout>
21 #include <QLabel>
22 #include <QLineEdit>
23 #include <QList>
24 #include <QPlainTextEdit>
25 #include <QProgressBar>
26 #include <QPushButton>
27 #include <QRadioButton>
28 #include <QSize>
29 #include <QStyle>
30 #include <QTimer>
31 #include <QVBoxLayout>
33 #include <libtransmission/transmission.h>
34 #include <libtransmission/makemeta.h>
35 #include <libtransmission/utils.h>
37 #include "formatter.h"
38 #include "hig.h"
39 #include "make-dialog.h"
40 #include "session.h"
42 /***
43 ****
44 ***/
46 void
47 MakeDialog :: onNewDialogDestroyed( QObject * o )
49 Q_UNUSED( o );
51 myTimer.stop( );
54 void
55 MakeDialog :: onNewButtonBoxClicked( QAbstractButton * button )
57 switch( myNewButtonBox->standardButton( button ) )
59 case QDialogButtonBox::Open:
60 std::cerr << "calling mySession.addTorrent( " << qPrintable(myTarget) << ", " << qPrintable(QFileInfo(myBuilder->top).dir().path()) << ')' << std::endl;
61 mySession.addNewlyCreatedTorrent( myTarget, QFileInfo(myBuilder->top).dir().path() );
62 break;
63 case QDialogButtonBox::Abort:
64 myBuilder->abortFlag = true;
65 break;
66 default: // QDialogButtonBox::Ok:
67 break;
70 myNewDialog->deleteLater( );
73 void
74 MakeDialog :: onProgress( )
76 // progress bar
77 const tr_metainfo_builder * b = myBuilder;
78 const double denom = b->pieceCount ? b->pieceCount : 1;
79 myNewProgress->setValue( (int) ((100.0 * b->pieceIndex) / denom ) );
81 // progress label
82 const QString base( QFileInfo(b->top).baseName() );
83 QString str;
84 if( !b->isDone )
85 str = tr( "Creating \"%1\"" ).arg( base );
86 else if( b->result == TR_MAKEMETA_OK )
87 str = tr( "Created \"%1\"!" ).arg( base );
88 else if( b->result == TR_MAKEMETA_URL )
89 str = tr( "Error: invalid announce URL \"%1\"" ).arg( b->errfile );
90 else if( b->result == TR_MAKEMETA_CANCELLED )
91 str = tr( "Cancelled" );
92 else if( b->result == TR_MAKEMETA_IO_READ )
93 str = tr( "Error reading \"%1\": %2" ).arg( b->errfile ).arg( strerror(b->my_errno) );
94 else if( b->result == TR_MAKEMETA_IO_WRITE )
95 str = tr( "Error writing \"%1\": %2" ).arg( b->errfile ).arg( strerror(b->my_errno) );
96 myNewLabel->setText( str );
98 // buttons
99 (myNewButtonBox->button(QDialogButtonBox::Abort))->setEnabled( !b->isDone );
100 (myNewButtonBox->button(QDialogButtonBox::Ok))->setEnabled( b->isDone );
101 (myNewButtonBox->button(QDialogButtonBox::Open))->setEnabled( b->isDone && !b->result );
105 void
106 MakeDialog :: makeTorrent( )
108 if( !myBuilder )
109 return;
111 // get the tiers
112 int tier = 0;
113 QList<tr_tracker_info> trackers;
114 foreach( QString line, myTrackerEdit->toPlainText().split("\n") ) {
115 line = line.trimmed( );
116 if( line.isEmpty( ) )
117 ++tier;
118 else {
119 tr_tracker_info tmp;
120 tmp.announce = tr_strdup( line.toUtf8().constData( ) );
121 tmp.tier = tier;
122 trackers.append( tmp );
126 // pop up the dialog
127 QDialog * dialog = new QDialog( this );
128 dialog->setWindowTitle( tr( "New Torrent" ) );
129 myNewDialog = dialog;
130 QVBoxLayout * top = new QVBoxLayout( dialog );
131 top->addWidget(( myNewLabel = new QLabel));
132 top->addWidget(( myNewProgress = new QProgressBar ));
133 QDialogButtonBox * buttons = new QDialogButtonBox( QDialogButtonBox::Ok
134 | QDialogButtonBox::Open
135 | QDialogButtonBox::Abort );
136 myNewButtonBox = buttons;
137 connect( buttons, SIGNAL(clicked(QAbstractButton*)),
138 this, SLOT(onNewButtonBoxClicked(QAbstractButton*)) );
139 top->addWidget( buttons );
140 onProgress( );
141 dialog->show( );
142 connect( dialog, SIGNAL(destroyed(QObject*)),
143 this, SLOT(onNewDialogDestroyed(QObject*)) );
144 myTimer.start( 100 );
146 // the file to create
147 myTarget = QDir( myDestination ).filePath( QFileInfo(myBuilder->top).baseName() + ".torrent" );
148 std::cerr << qPrintable(myTarget) << std::endl;
150 // comment
151 QString comment;
152 if( myCommentCheck->isChecked() )
153 comment = myCommentEdit->text().toUtf8().constData();
155 // start making the torrent
156 tr_makeMetaInfo( myBuilder,
157 myTarget.toUtf8().constData(),
158 (trackers.isEmpty() ? 0 : &trackers.front()),
159 trackers.size(),
160 (comment.isEmpty() ? NULL : comment.toUtf8().constData()),
161 myPrivateCheck->isChecked() );
164 /***
165 ****
166 ***/
168 void
169 MakeDialog :: onFileClicked( )
171 QFileDialog * d = new QFileDialog( this, tr( "Select File" ) );
172 d->setFileMode( QFileDialog::ExistingFile );
173 connect( d, SIGNAL(filesSelected(const QStringList&)),
174 this, SLOT(onFileSelected(const QStringList&)) );
175 d->show( );
177 void
178 MakeDialog :: onFileSelected( const QStringList& list )
180 if( !list.empty( ) )
181 onFileSelected( list.front( ) );
183 void
184 MakeDialog :: onFileSelected( const QString& filename )
186 myFile = filename;
187 myFileButton->setText( QFileInfo(myFile).fileName() );
188 onSourceChanged( );
191 void
192 MakeDialog :: onFolderClicked( )
194 QFileDialog * d = new QFileDialog( this, tr( "Select Folder" ) );
195 d->setFileMode( QFileDialog::Directory );
196 connect( d, SIGNAL(filesSelected(const QStringList&)),
197 this, SLOT(onFolderSelected(const QStringList&)) );
198 d->show( );
200 void
201 MakeDialog :: onFolderSelected( const QStringList& list )
203 if( !list.empty( ) )
204 onFolderSelected( list.front( ) );
206 void
207 MakeDialog :: onFolderSelected( const QString& filename )
209 myFolder = filename;
210 myFolderButton->setText( QFileInfo(myFolder).fileName() );
211 onSourceChanged( );
214 void
215 MakeDialog :: onDestinationClicked( )
217 QFileDialog * d = new QFileDialog( this, tr( "Select Folder" ) );
218 d->setFileMode( QFileDialog::Directory );
219 connect( d, SIGNAL(filesSelected(const QStringList&)),
220 this, SLOT(onDestinationSelected(const QStringList&)) );
221 d->show( );
223 void
224 MakeDialog :: onDestinationSelected( const QStringList& list )
226 if( !list.empty( ) )
227 onDestinationSelected( list.front() );
229 void
230 MakeDialog :: onDestinationSelected( const QString& filename )
232 myDestination = filename;
233 myDestinationButton->setText( QFileInfo(myDestination).fileName() );
236 void
237 MakeDialog :: enableBuddyWhenChecked( QRadioButton * box, QWidget * buddy )
239 connect( box, SIGNAL(toggled(bool)), buddy, SLOT(setEnabled(bool)) );
240 buddy->setEnabled( box->isChecked( ) );
242 void
243 MakeDialog :: enableBuddyWhenChecked( QCheckBox * box, QWidget * buddy )
245 connect( box, SIGNAL(toggled(bool)), buddy, SLOT(setEnabled(bool)) );
246 buddy->setEnabled( box->isChecked( ) );
249 QString
250 MakeDialog :: getSource( ) const
252 return myFileRadio->isChecked( ) ? myFile : myFolder;
255 void
256 MakeDialog :: onButtonBoxClicked( QAbstractButton * button )
258 switch( myButtonBox->standardButton( button ) )
260 case QDialogButtonBox::Ok:
261 makeTorrent( );
262 break;
264 default: // QDialogButtonBox::Close:
265 deleteLater( );
266 break;
270 /***
271 ****
272 ***/
274 void
275 MakeDialog :: onSourceChanged( )
277 if( myBuilder )
279 tr_metaInfoBuilderFree( myBuilder );
280 myBuilder = 0;
283 const QString filename = getSource( );
284 if( !filename.isEmpty( ) )
285 myBuilder = tr_metaInfoBuilderCreate( filename.toUtf8().constData() );
287 QString text;
288 if( !myBuilder )
289 text = tr( "<i>No source selected<i>" );
290 else {
291 QString files = tr( "%Ln File(s)", 0, myBuilder->fileCount );
292 QString pieces = tr( "%Ln Piece(s)", 0, myBuilder->pieceCount );
293 text = tr( "%1 in %2; %3 @ %4" )
294 .arg( Formatter::sizeToString( myBuilder->totalSize ) )
295 .arg( files )
296 .arg( pieces )
297 .arg( Formatter::sizeToString( myBuilder->pieceSize ) );
300 mySourceLabel->setText( text );
304 // bah, there doesn't seem to be any cleaner way to override
305 // QPlainTextEdit's default desire to be 12 lines tall
306 class ShortPlainTextEdit: public QPlainTextEdit {
307 public:
308 virtual ~ShortPlainTextEdit( ) { }
309 ShortPlainTextEdit( QWidget * parent = 0 ): QPlainTextEdit(parent) { }
310 virtual QSize sizeHint ( ) const { return QSize( 256, 50 ); }
313 MakeDialog :: MakeDialog( Session & session, QWidget * parent ):
314 QDialog( parent, Qt::Dialog ),
315 mySession( session ),
316 myBuilder( 0 )
318 setAcceptDrops( true );
320 connect( &myTimer, SIGNAL(timeout()), this, SLOT(onProgress()) );
322 setWindowTitle( tr( "New Torrent" ) );
323 QVBoxLayout * top = new QVBoxLayout( this );
324 top->setSpacing( HIG :: PAD );
326 HIG * hig = new HIG;
327 hig->setContentsMargins( 0, 0, 0, 0 );
328 hig->addSectionTitle( tr( "Files" ) );
330 QFileIconProvider iconProvider;
331 const int iconSize( style()->pixelMetric( QStyle::PM_SmallIconSize ) );
332 const QIcon folderIcon = iconProvider.icon( QFileIconProvider::Folder );
333 const QPixmap folderPixmap = folderIcon.pixmap( iconSize );
334 QPushButton * b = new QPushButton;
335 b->setIcon( folderPixmap );
336 b->setStyleSheet( "text-align: left; padding-left: 5; padding-right: 5" );
337 myDestination = QDir::homePath();
338 b->setText( myDestination );
339 connect( b, SIGNAL(clicked(bool)),
340 this, SLOT(onDestinationClicked(void)) );
341 myDestinationButton = b;
342 hig->addRow( tr( "Sa&ve to:" ), b );
344 myFolderRadio = new QRadioButton( tr( "Source F&older:" ) );
345 connect( myFolderRadio, SIGNAL(toggled(bool)),
346 this, SLOT(onSourceChanged()) );
347 myFolderButton = new QPushButton;
348 myFolderButton->setIcon( folderPixmap );
349 myFolderButton->setText( tr( "(None)" ) );
350 myFolderButton->setStyleSheet( "text-align: left; padding-left: 5; padding-right: 5" );
351 connect( myFolderButton, SIGNAL(clicked(bool)),
352 this, SLOT(onFolderClicked(void)) );
353 hig->addRow( myFolderRadio, myFolderButton );
354 enableBuddyWhenChecked( myFolderRadio, myFolderButton );
356 const QIcon fileIcon = iconProvider.icon( QFileIconProvider::File );
357 const QPixmap filePixmap = fileIcon.pixmap( iconSize );
358 myFileRadio = new QRadioButton( tr( "Source &File:" ) );
359 myFileRadio->setChecked( true );
360 connect( myFileRadio, SIGNAL(toggled(bool)),
361 this, SLOT(onSourceChanged()) );
362 myFileButton = new QPushButton;
363 myFileButton->setText( tr( "(None)" ) );
364 myFileButton->setIcon( filePixmap );
365 myFileButton->setStyleSheet( "text-align: left; padding-left: 5; padding-right: 5" );
366 connect( myFileButton, SIGNAL(clicked(bool)),
367 this, SLOT(onFileClicked(void)) );
368 hig->addRow( myFileRadio, myFileButton );
369 enableBuddyWhenChecked( myFileRadio, myFileButton );
371 mySourceLabel = new QLabel( this );
372 hig->addRow( tr( "" ), mySourceLabel );
374 hig->addSectionDivider( );
375 hig->addSectionTitle( tr( "Properties" ) );
377 hig->addWideControl( myTrackerEdit = new ShortPlainTextEdit );
378 const int height = fontMetrics().size( 0, "\n\n\n\n" ).height( );
379 myTrackerEdit->setMinimumHeight( height );
380 hig->addTallRow( tr( "&Trackers:" ), myTrackerEdit );
381 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." ) );
382 l->setAlignment( Qt::AlignLeft );
383 hig->addRow( tr( "" ), l );
384 myTrackerEdit->resize( 500, height );
386 myCommentCheck = new QCheckBox( tr( "Co&mment" ) );
387 myCommentEdit = new QLineEdit( );
388 hig->addRow( myCommentCheck, myCommentEdit );
389 enableBuddyWhenChecked( myCommentCheck, myCommentEdit );
391 myPrivateCheck = hig->addWideCheckBox( tr( "&Private torrent" ), false );
393 hig->finish( );
394 top->addWidget( hig, 1 );
396 myButtonBox = new QDialogButtonBox( QDialogButtonBox::Ok
397 | QDialogButtonBox::Close );
398 connect( myButtonBox, SIGNAL(clicked(QAbstractButton*)),
399 this, SLOT(onButtonBoxClicked(QAbstractButton*)) );
401 top->addWidget( myButtonBox );
402 onSourceChanged( );
405 MakeDialog :: ~MakeDialog( )
407 if( myBuilder )
408 tr_metaInfoBuilderFree( myBuilder );
411 /***
412 ****
413 ***/
415 void
416 MakeDialog :: dragEnterEvent( QDragEnterEvent * event )
418 const QMimeData * mime = event->mimeData( );
420 if( mime->urls().size() && QFile(mime->urls().front().path()).exists( ) )
421 event->acceptProposedAction();
424 void
425 MakeDialog :: dropEvent( QDropEvent * event )
427 const QString filename = event->mimeData()->urls().front().path();
428 const QFileInfo fileInfo( filename );
430 if( fileInfo.exists( ) )
432 if( fileInfo.isDir( ) )
434 myFolderRadio->setChecked( true );
435 onFolderSelected( filename );
437 else // it's a file
439 myFileRadio->setChecked( true );
440 onFileSelected( filename );