Transmission: update to 2.82
[tomato.git] / release / src / router / transmission / qt / prefs-dialog.cc
blob6bd8076036b0c5c44db0e34de3e3eaad494906dc
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: prefs-dialog.cc 14150 2013-07-27 21:58:14Z jordan $
13 #include <cassert>
14 #include <iostream>
16 #include <QCheckBox>
17 #include <QComboBox>
18 #include <QCoreApplication>
19 #include <QDialogButtonBox>
20 #include <QDoubleSpinBox>
21 #include <QFileIconProvider>
22 #include <QFileInfo>
23 #include <QHBoxLayout>
24 #include <QIcon>
25 #include <QLabel>
26 #include <QLineEdit>
27 #include <QList>
28 #include <QMessageBox>
29 #include <QPushButton>
30 #include <QSpinBox>
31 #include <QStyle>
32 #include <QTabWidget>
33 #include <QTime>
34 #include <QTimeEdit>
35 #include <QTimer>
36 #include <QVBoxLayout>
38 #include "freespace-label.h"
39 #include "formatter.h"
40 #include "hig.h"
41 #include "prefs.h"
42 #include "prefs-dialog.h"
43 #include "session.h"
44 #include "utils.h"
46 /***
47 ****
48 ***/
50 namespace
52 const char * PREF_KEY( "pref-key" );
55 void
56 PrefsDialog :: checkBoxToggled( bool checked )
58 const int key( sender( )->property( PREF_KEY ).toInt( ) );
59 setPref( key, checked );
62 QCheckBox *
63 PrefsDialog :: checkBoxNew( const QString& text, int key )
65 QCheckBox * box = new QCheckBox( text );
66 box->setChecked( myPrefs.getBool( key ) );
67 box->setProperty( PREF_KEY, key );
68 connect( box, SIGNAL(toggled(bool)), this, SLOT(checkBoxToggled(bool)));
69 myWidgets.insert( key, box );
70 return box;
73 void
74 PrefsDialog :: enableBuddyWhenChecked( QCheckBox * box, QWidget * buddy )
76 connect( box, SIGNAL(toggled(bool)), buddy, SLOT(setEnabled(bool)) );
77 buddy->setEnabled( box->isChecked( ) );
80 void
81 PrefsDialog :: spinBoxEditingFinished()
83 const QObject * spin = sender();
84 const int key = spin->property( PREF_KEY ).toInt( );
85 const QDoubleSpinBox * d = qobject_cast<const QDoubleSpinBox*>( spin );
86 if( d )
87 setPref( key, d->value( ) );
88 else
89 setPref( key, qobject_cast<const QSpinBox*>(spin)->value( ) );
92 QSpinBox *
93 PrefsDialog :: spinBoxNew( int key, int low, int high, int step )
95 QSpinBox * spin = new QSpinBox( );
96 spin->setRange( low, high );
97 spin->setSingleStep( step );
98 spin->setValue( myPrefs.getInt( key ) );
99 spin->setProperty( PREF_KEY, key );
100 connect( spin, SIGNAL(editingFinished()), this, SLOT(spinBoxEditingFinished()));
101 myWidgets.insert( key, spin );
102 return spin;
105 QDoubleSpinBox *
106 PrefsDialog :: doubleSpinBoxNew( int key, double low, double high, double step, int decimals )
108 QDoubleSpinBox * spin = new QDoubleSpinBox( );
109 spin->setRange( low, high );
110 spin->setSingleStep( step );
111 spin->setDecimals( decimals );
112 spin->setValue( myPrefs.getDouble( key ) );
113 spin->setProperty( PREF_KEY, key );
114 connect( spin, SIGNAL(editingFinished()), this, SLOT(spinBoxEditingFinished()));
115 myWidgets.insert( key, spin );
116 return spin;
119 void
120 PrefsDialog :: timeEditingFinished( )
122 QTimeEdit * e = qobject_cast<QTimeEdit*>(sender());
123 if( e )
125 const int key( e->property( PREF_KEY ).toInt( ) );
126 const QTime time( e->time( ) );
127 const int seconds( QTime().secsTo( time ) );
128 std::cerr << "setPref to " << (seconds/60) << " minutes" << std::endl;
129 setPref( key, seconds / 60 );
132 QTimeEdit*
133 PrefsDialog :: timeEditNew( int key )
135 const int minutes( myPrefs.getInt( key ) );
136 QTimeEdit * e = new QTimeEdit( );
137 e->setDisplayFormat( QString::fromUtf8( "hh:mm" ) );
138 e->setProperty( PREF_KEY, key );
139 e->setTime( QTime().addSecs( minutes * 60 ) );
140 myWidgets.insert( key, e );
141 connect( e, SIGNAL(editingFinished()), this, SLOT(timeEditingFinished()) );
142 return e;
145 void
146 PrefsDialog :: lineEditingFinished( )
148 QLineEdit * e = qobject_cast<QLineEdit*>(sender());
149 if( e && e->isModified( ) )
151 const int key( e->property( PREF_KEY ).toInt( ) );
152 const QString text( e->text() );
153 setPref( key, text );
156 QLineEdit*
157 PrefsDialog :: lineEditNew( int key, int echoMode )
159 QLineEdit * e = new QLineEdit( myPrefs.getString( key ) );
160 e->setProperty( PREF_KEY, key );
161 e->setEchoMode( QLineEdit::EchoMode( echoMode ) );
162 myWidgets.insert( key, e );
163 connect( e, SIGNAL(editingFinished()), this, SLOT(lineEditingFinished()) );
164 return e;
167 /***
168 ****
169 ***/
171 QWidget *
172 PrefsDialog :: createRemoteTab( Session& session )
174 HIG * hig = new HIG( this );
175 hig->addSectionTitle( tr( "Remote Control" ) );
176 QWidget * w;
177 QHBoxLayout * h = new QHBoxLayout( );
178 QPushButton * b = new QPushButton( tr( "&Open web client" ) );
179 connect( b, SIGNAL(clicked()), &session, SLOT(launchWebInterface()) );
180 h->addWidget( b, 0, Qt::AlignRight );
181 QWidget * l = checkBoxNew( tr( "Allow &remote access" ), Prefs::RPC_ENABLED );
182 myUnsupportedWhenRemote << l;
183 hig->addRow( l, h, 0 );
184 l = hig->addRow( tr( "HTTP &port:" ), w = spinBoxNew( Prefs::RPC_PORT, 0, 65535, 1 ) );
185 myWebWidgets << l << w;
186 hig->addWideControl( w = checkBoxNew( tr( "Use &authentication" ), Prefs::RPC_AUTH_REQUIRED ) );
187 myWebWidgets << w;
188 l = hig->addRow( tr( "&Username:" ), w = lineEditNew( Prefs::RPC_USERNAME ) );
189 myWebAuthWidgets << l << w;
190 l = hig->addRow( tr( "Pass&word:" ), w = lineEditNew( Prefs::RPC_PASSWORD, QLineEdit::Password ) );
191 myWebAuthWidgets << l << w;
192 hig->addWideControl( w = checkBoxNew( tr( "Only allow these IP a&ddresses:" ), Prefs::RPC_WHITELIST_ENABLED ) );
193 myWebWidgets << w;
194 l = hig->addRow( tr( "Addresses:" ), w = lineEditNew( Prefs::RPC_WHITELIST ) );
195 myWebWhitelistWidgets << l << w;
196 myUnsupportedWhenRemote << myWebWidgets << myWebAuthWidgets << myWebWhitelistWidgets;
197 hig->finish( );
198 return hig;
201 /***
202 ****
203 ***/
205 void
206 PrefsDialog :: altSpeedDaysEdited( int i )
208 const int value = qobject_cast<QComboBox*>(sender())->itemData(i).toInt();
209 setPref( Prefs::ALT_SPEED_LIMIT_TIME_DAY, value );
213 QWidget *
214 PrefsDialog :: createSpeedTab( )
216 QWidget *l, *r;
217 HIG * hig = new HIG( this );
218 hig->addSectionTitle( tr( "Speed Limits" ) );
219 const QString speed_K_str = Formatter::unitStr( Formatter::SPEED, Formatter::KB );
221 l = checkBoxNew( tr( "&Upload (%1):" ).arg( speed_K_str ), Prefs::USPEED_ENABLED );
222 r = spinBoxNew( Prefs::USPEED, 0, INT_MAX, 5 );
223 hig->addRow( l, r );
224 enableBuddyWhenChecked( qobject_cast<QCheckBox*>(l), r );
226 l = checkBoxNew( tr( "&Download (%1):" ).arg( speed_K_str ), Prefs::DSPEED_ENABLED );
227 r = spinBoxNew( Prefs::DSPEED, 0, INT_MAX, 5 );
228 hig->addRow( l, r );
229 enableBuddyWhenChecked( qobject_cast<QCheckBox*>(l), r );
231 hig->addSectionDivider( );
232 QHBoxLayout * h = new QHBoxLayout;
233 h->setSpacing( HIG :: PAD );
234 QLabel * label = new QLabel;
235 label->setPixmap( QPixmap( QString::fromUtf8( ":/icons/alt-limit-off.png" ) ) );
236 label->setAlignment( Qt::AlignLeft|Qt::AlignVCenter );
237 h->addWidget( label );
238 label = new QLabel( tr( "Alternative Speed Limits" ) );
239 label->setStyleSheet( QString::fromUtf8( "font: bold" ) );
240 label->setAlignment( Qt::AlignLeft|Qt::AlignVCenter );
241 h->addWidget( label );
242 hig->addSectionTitle( h );
244 QString s = tr( "<small>Override normal speed limits manually or at scheduled times</small>" );
245 hig->addWideControl( new QLabel( s ) );
247 s = tr( "U&pload (%1):" ).arg( speed_K_str );
248 r = spinBoxNew( Prefs :: ALT_SPEED_LIMIT_UP, 0, INT_MAX, 5 );
249 hig->addRow( s, r );
251 s = tr( "Do&wnload (%1):" ).arg( speed_K_str );
252 r = spinBoxNew( Prefs :: ALT_SPEED_LIMIT_DOWN, 0, INT_MAX, 5 );
253 hig->addRow( s, r );
255 QCheckBox * c = checkBoxNew( tr( "&Scheduled times:" ), Prefs::ALT_SPEED_LIMIT_TIME_ENABLED );
256 h = new QHBoxLayout( );
257 h->setSpacing( HIG::PAD );
258 QWidget * w = timeEditNew( Prefs :: ALT_SPEED_LIMIT_TIME_BEGIN );
259 h->addWidget( w, 1 );
260 mySchedWidgets << w;
261 QLabel * nd = new QLabel( tr("&to") );
262 h->addWidget( nd );
263 mySchedWidgets << nd;
264 w = timeEditNew( Prefs :: ALT_SPEED_LIMIT_TIME_END );
265 nd->setBuddy( w );
266 h->addWidget( w, 1 );
267 mySchedWidgets << w;
268 hig->addRow( c, h, 0 );
270 s = tr( "&On days:" );
271 QComboBox * box = new QComboBox;
272 const QIcon noIcon;
273 box->addItem( noIcon, tr( "Every Day" ), QVariant( TR_SCHED_ALL ) );
274 box->addItem( noIcon, tr( "Weekdays" ), QVariant( TR_SCHED_WEEKDAY ) );
275 box->addItem( noIcon, tr( "Weekends" ), QVariant( TR_SCHED_WEEKEND ) );
276 box->addItem( noIcon, tr( "Sunday" ), QVariant( TR_SCHED_SUN ) );
277 box->addItem( noIcon, tr( "Monday" ), QVariant( TR_SCHED_MON ) );
278 box->addItem( noIcon, tr( "Tuesday" ), QVariant( TR_SCHED_TUES ) );
279 box->addItem( noIcon, tr( "Wednesday" ), QVariant( TR_SCHED_WED ) );
280 box->addItem( noIcon, tr( "Thursday" ), QVariant( TR_SCHED_THURS ) );
281 box->addItem( noIcon, tr( "Friday" ), QVariant( TR_SCHED_FRI ) );
282 box->addItem( noIcon, tr( "Saturday" ), QVariant( TR_SCHED_SAT ) );
283 box->setCurrentIndex( box->findData( myPrefs.getInt( Prefs :: ALT_SPEED_LIMIT_TIME_DAY ) ) );
284 connect( box, SIGNAL(activated(int)), this, SLOT(altSpeedDaysEdited(int)) );
285 w = hig->addRow( s, box );
286 mySchedWidgets << w << box;
288 hig->finish( );
289 return hig;
292 /***
293 ****
294 ***/
296 QWidget *
297 PrefsDialog :: createDesktopTab( )
299 HIG * hig = new HIG( this );
300 hig->addSectionTitle( tr( "Desktop" ) );
302 hig->addWideControl( checkBoxNew( tr( "Show Transmission icon in the &notification area" ), Prefs::SHOW_TRAY_ICON ) );
303 hig->addWideControl( checkBoxNew( tr( "Start &minimized in notification area" ), Prefs::START_MINIMIZED ) );
305 hig->addSectionDivider( );
306 hig->addSectionTitle( tr ("Notification") );
308 hig->addWideControl( checkBoxNew( tr( "Show a notification when torrents are a&dded" ), Prefs::SHOW_NOTIFICATION_ON_ADD ) );
309 hig->addWideControl( checkBoxNew( tr( "Show a notification when torrents &finish" ), Prefs::SHOW_NOTIFICATION_ON_COMPLETE ) );
310 hig->addWideControl( checkBoxNew( tr( "Play a &sound when torrents finish" ), Prefs::COMPLETE_SOUND_ENABLED ) );
312 hig->finish( );
313 return hig;
316 /***
317 ****
318 ***/
320 void
321 PrefsDialog :: onPortTested( bool isOpen )
323 myPortButton->setEnabled( true );
324 myWidgets[Prefs::PEER_PORT]->setEnabled( true );
325 myPortLabel->setText( isOpen ? tr( "Port is <b>open</b>" )
326 : tr( "Port is <b>closed</b>" ) );
329 void
330 PrefsDialog :: onPortTest( )
332 myPortLabel->setText( tr( "Testing TCP Port..." ) );
333 myPortButton->setEnabled( false );
334 myWidgets[Prefs::PEER_PORT]->setEnabled( false );
335 mySession.portTest( );
338 QWidget *
339 PrefsDialog :: createNetworkTab( )
341 HIG * hig = new HIG( this );
342 hig->addSectionTitle( tr( "Incoming Peers" ) );
344 QSpinBox * s = spinBoxNew( Prefs::PEER_PORT, 1, 65535, 1 );
345 QHBoxLayout * h = new QHBoxLayout( );
346 QPushButton * b = myPortButton = new QPushButton( tr( "Te&st Port" ) );
347 QLabel * l = myPortLabel = new QLabel( tr( "Status unknown" ) );
348 h->addWidget( l );
349 h->addSpacing( HIG :: PAD_BIG );
350 h->addWidget( b );
351 h->setStretchFactor( l, 1 );
352 connect( b, SIGNAL(clicked(bool)), this, SLOT(onPortTest()));
353 connect( &mySession, SIGNAL(portTested(bool)), this, SLOT(onPortTested(bool)));
355 hig->addRow( tr( "&Port for incoming connections:" ), s );
356 hig->addRow( QString(), h, 0 );
357 hig->addWideControl( checkBoxNew( tr( "Pick a &random port every time Transmission is started" ), Prefs :: PEER_PORT_RANDOM_ON_START ) );
358 hig->addWideControl( checkBoxNew( tr( "Use UPnP or NAT-PMP port &forwarding from my router" ), Prefs::PORT_FORWARDING ) );
360 hig->addSectionDivider( );
361 hig->addSectionTitle( tr( "Peer Limits" ) );
362 hig->addRow( tr( "Maximum peers per &torrent:" ), spinBoxNew( Prefs::PEER_LIMIT_TORRENT, 1, FD_SETSIZE, 5 ) );
363 hig->addRow( tr( "Maximum peers &overall:" ), spinBoxNew( Prefs::PEER_LIMIT_GLOBAL, 1, FD_SETSIZE, 5 ) );
365 hig->addSectionDivider( );
366 hig->addSectionTitle( tr( "Options" ) );
368 QWidget * w;
369 hig->addWideControl( w = checkBoxNew( tr( "Enable &uTP for peer connections" ), Prefs::UTP_ENABLED ) );
370 w->setToolTip( tr( "uTP is a tool for reducing network congestion." ) );
371 hig->addWideControl( w = checkBoxNew( tr( "Use PE&X to find more peers" ), Prefs::PEX_ENABLED ) );
372 w->setToolTip( tr( "PEX is a tool for exchanging peer lists with the peers you're connected to." ) );
373 hig->addWideControl( w = checkBoxNew( tr( "Use &DHT to find more peers" ), Prefs::DHT_ENABLED ) );
374 w->setToolTip( tr( "DHT is a tool for finding peers without a tracker." ) );
375 hig->addWideControl( w = checkBoxNew( tr( "Use &Local Peer Discovery to find more peers" ), Prefs::LPD_ENABLED ) );
376 w->setToolTip( tr( "LPD is a tool for finding peers on your local network." ) );
378 hig->finish( );
379 return hig;
382 /***
383 ****
384 ***/
386 void
387 PrefsDialog :: onBlocklistDialogDestroyed( QObject * o )
389 Q_UNUSED( o );
391 myBlocklistDialog = 0;
394 void
395 PrefsDialog :: onUpdateBlocklistCancelled( )
397 disconnect( &mySession, SIGNAL(blocklistUpdated(int)), this, SLOT(onBlocklistUpdated(int))) ;
398 myBlocklistDialog->deleteLater( );
401 void
402 PrefsDialog :: onBlocklistUpdated( int n )
404 myBlocklistDialog->setText( tr( "<b>Update succeeded!</b><p>Blocklist now has %Ln rules.", 0, n ) );
405 myBlocklistDialog->setTextFormat( Qt::RichText );
408 void
409 PrefsDialog :: onUpdateBlocklistClicked( )
411 myBlocklistDialog = new QMessageBox( QMessageBox::Information,
412 QString(),
413 tr( "<b>Update Blocklist</b><p>Getting new blocklist..." ),
414 QMessageBox::Close,
415 this );
416 connect( myBlocklistDialog, SIGNAL(rejected()), this, SLOT(onUpdateBlocklistCancelled()) );
417 connect( &mySession, SIGNAL(blocklistUpdated(int)), this, SLOT(onBlocklistUpdated(int))) ;
418 myBlocklistDialog->show( );
419 mySession.updateBlocklist( );
422 void
423 PrefsDialog :: encryptionEdited( int i )
425 const int value( qobject_cast<QComboBox*>(sender())->itemData(i).toInt( ) );
426 setPref( Prefs::ENCRYPTION, value );
429 QWidget *
430 PrefsDialog :: createPrivacyTab( )
432 QWidget * w;
433 HIG * hig = new HIG( this );
435 hig->addSectionTitle( tr( "Encryption" ) );
437 QComboBox * box = new QComboBox( );
438 box->addItem( tr( "Allow encryption" ), 0 );
439 box->addItem( tr( "Prefer encryption" ), 1 );
440 box->addItem( tr( "Require encryption" ), 2 );
441 myWidgets.insert( Prefs :: ENCRYPTION, box );
442 connect( box, SIGNAL(activated(int)), this, SLOT(encryptionEdited(int)));
444 hig->addRow( tr( "&Encryption mode:" ), box );
446 hig->addSectionDivider( );
447 hig->addSectionTitle( tr( "Blocklist" ) );
449 QWidget * l = checkBoxNew( tr("Enable &blocklist:"), Prefs::BLOCKLIST_ENABLED );
450 QWidget * e = lineEditNew( Prefs::BLOCKLIST_URL );
451 myBlockWidgets << e;
452 hig->addRow( l, e );
454 l = myBlocklistLabel = new QLabel( );
455 myBlockWidgets << l;
456 w = new QPushButton( tr( "&Update" ) );
457 connect( w, SIGNAL(clicked(bool)), this, SLOT(onUpdateBlocklistClicked()));
458 myBlockWidgets << w;
459 QHBoxLayout * h = new QHBoxLayout( );
460 h->addWidget( l );
461 h->addStretch( 1 );
462 h->addWidget( w );
463 hig->addWideControl( h );
465 l = checkBoxNew( tr( "Enable &automatic updates" ), Prefs::BLOCKLIST_UPDATES_ENABLED );
466 myBlockWidgets << l;
467 hig->addWideControl( l );
469 hig->finish( );
470 updateBlocklistLabel( );
471 return hig;
474 /***
475 ****
476 ***/
478 void
479 PrefsDialog :: onScriptClicked( void )
481 const QString title = tr( "Select \"Torrent Done\" Script" );
482 const QString myPath = myPrefs.getString( Prefs::SCRIPT_TORRENT_DONE_FILENAME );
483 const QString path = Utils::remoteFileChooser( this, title, myPath, false, mySession.isServer() );
485 if( !path.isEmpty() )
486 onLocationSelected( path, Prefs::SCRIPT_TORRENT_DONE_FILENAME );
489 void
490 PrefsDialog :: onIncompleteClicked( void )
492 const QString title = tr( "Select Incomplete Directory" );
493 const QString myPath = myPrefs.getString( Prefs::INCOMPLETE_DIR );
494 const QString path = Utils::remoteFileChooser( this, title, myPath, true, mySession.isServer() );
496 if( !path.isEmpty() )
497 onLocationSelected( path, Prefs::INCOMPLETE_DIR );
500 void
501 PrefsDialog :: onWatchClicked( void )
503 const QString title = tr( "Select Watch Directory" );
504 const QString myPath = myPrefs.getString( Prefs::DIR_WATCH );
505 const QString path = Utils::remoteFileChooser( this, title, myPath, true, true );
507 if( !path.isEmpty() )
508 onLocationSelected( path, Prefs::DIR_WATCH );
511 void
512 PrefsDialog :: onDestinationClicked( void )
514 const QString title = tr( "Select Destination" );
515 const QString myPath = myPrefs.getString( Prefs::DOWNLOAD_DIR );
516 const QString path = Utils::remoteFileChooser( this, title, myPath, true, mySession.isServer() );
518 if( !path.isEmpty() )
519 onLocationSelected( path, Prefs::DOWNLOAD_DIR );
522 void
523 PrefsDialog :: onLocationSelected( const QString& path, int key )
525 setPref( key, path );
528 QWidget *
529 PrefsDialog :: createSeedingTab( )
531 const int iconSize( style( )->pixelMetric( QStyle :: PM_SmallIconSize ) );
532 const QFileIconProvider iconProvider;
533 const QIcon folderIcon = iconProvider.icon( QFileIconProvider::Folder );
534 const QPixmap folderPixmap = folderIcon.pixmap( iconSize );
535 const QIcon fileIcon = iconProvider.icon( QFileIconProvider::File );
536 const QPixmap filePixmap = fileIcon.pixmap( iconSize );
538 QWidget *l, *r;
539 HIG * hig = new HIG( this );
540 hig->addSectionTitle( tr( "Limits" ) );
542 l = checkBoxNew( tr( "Stop seeding at &ratio:" ), Prefs::RATIO_ENABLED );
543 r = doubleSpinBoxNew( Prefs::RATIO, 0, INT_MAX, 0.5, 2 );
544 hig->addRow( l, r );
545 enableBuddyWhenChecked( qobject_cast<QCheckBox*>(l), r );
547 l = checkBoxNew( tr( "Stop seeding if idle for &N minutes:" ), Prefs::IDLE_LIMIT_ENABLED );
548 r = spinBoxNew( Prefs::IDLE_LIMIT, 1, INT_MAX, 5 );
549 hig->addRow( l, r );
550 enableBuddyWhenChecked( qobject_cast<QCheckBox*>(l), r );
552 hig->finish( );
553 return hig;
556 QWidget *
557 PrefsDialog :: createDownloadingTab( )
559 const int iconSize( style( )->pixelMetric( QStyle :: PM_SmallIconSize ) );
560 const QFileIconProvider iconProvider;
561 const QIcon folderIcon = iconProvider.icon( QFileIconProvider::Folder );
562 const QPixmap folderPixmap = folderIcon.pixmap( iconSize );
563 const QIcon fileIcon = iconProvider.icon( QFileIconProvider::File );
564 const QPixmap filePixmap = fileIcon.pixmap( iconSize );
566 QWidget * l;
567 QPushButton * b;
568 HIG * hig = new HIG( this );
569 hig->addSectionTitle( tr( "Adding" ) );
571 l = checkBoxNew( tr( "Automatically add .torrent files &from:" ), Prefs::DIR_WATCH_ENABLED );
572 b = myWatchButton = new QPushButton;
573 b->setIcon( folderPixmap );
574 b->setStyleSheet( QString::fromUtf8( "text-align: left; padding-left: 5; padding-right: 5" ) );
575 connect( b, SIGNAL(clicked(bool)), this, SLOT(onWatchClicked(void)) );
576 hig->addRow( l, b );
577 enableBuddyWhenChecked( qobject_cast<QCheckBox*>(l), b );
579 hig->addWideControl( checkBoxNew( tr( "Show the Torrent Options &dialog" ), Prefs::OPTIONS_PROMPT ) );
581 hig->addWideControl( checkBoxNew( tr( "&Start added torrents" ), Prefs::START ) );
583 hig->addWideControl( checkBoxNew( tr( "Mo&ve the .torrent file to the trash" ), Prefs::TRASH_ORIGINAL ) );
585 b = myDestinationButton = new QPushButton;
586 b->setIcon( folderPixmap );
587 b->setStyleSheet( QString::fromUtf8( "text-align: left; padding-left: 5; padding-right: 5" ) );
588 connect( b, SIGNAL(clicked(bool)), this, SLOT(onDestinationClicked(void)) );
589 hig->addRow( tr( "Save to &Location:" ), b );
591 const QString downloadDir (myPrefs.getString(Prefs::DOWNLOAD_DIR));
592 l = myFreespaceLabel = new FreespaceLabel (mySession, downloadDir, this);
593 QHBoxLayout * h = new QHBoxLayout ();
594 h->addStretch (1);
595 h->addWidget (l);
596 hig->addWideControl (h);
598 hig->addSectionDivider( );
599 hig->addSectionTitle( tr( "Download Queue" ) );
601 hig->addRow( tr( "Ma&ximum active downloads:" ), spinBoxNew( Prefs::DOWNLOAD_QUEUE_SIZE, 1, INT_MAX, 1 ) );
602 hig->addRow( tr( "Downloads sharing data in the last &N minutes are active:" ), spinBoxNew( Prefs::QUEUE_STALLED_MINUTES, 1, INT_MAX, 10 ) );
604 hig->addSectionDivider( );
605 hig->addSectionTitle( tr( "Incomplete" ) );
607 hig->addWideControl( checkBoxNew( tr( "Append \".&part\" to incomplete files' names" ), Prefs::RENAME_PARTIAL_FILES ) );
609 l = myIncompleteCheckbox = checkBoxNew( tr( "Keep &incomplete files in:" ), Prefs::INCOMPLETE_DIR_ENABLED );
610 b = myIncompleteButton = new QPushButton;
611 b->setIcon( folderPixmap );
612 b->setStyleSheet( QString::fromUtf8( "text-align: left; padding-left: 5; padding-right: 5" ) );
613 connect( b, SIGNAL(clicked(bool)), this, SLOT(onIncompleteClicked(void)) );
614 hig->addRow( myIncompleteCheckbox, b );
615 enableBuddyWhenChecked( qobject_cast<QCheckBox*>(l), b );
617 l = myTorrentDoneScriptCheckbox = checkBoxNew( tr( "Call scrip&t when torrent is completed:" ), Prefs::SCRIPT_TORRENT_DONE_ENABLED );
618 b = myTorrentDoneScriptButton = new QPushButton;
619 b->setIcon( filePixmap );
620 b->setStyleSheet( QString::fromUtf8( "text-align: left; padding-left: 5; padding-right: 5" ) );
621 connect( b, SIGNAL(clicked(bool)), this, SLOT(onScriptClicked(void)) );
622 hig->addRow( myTorrentDoneScriptCheckbox, b );
623 enableBuddyWhenChecked( qobject_cast<QCheckBox*>(l), b );
625 hig->finish( );
626 return hig;
629 /***
630 ****
631 ***/
633 PrefsDialog :: PrefsDialog( Session& session, Prefs& prefs, QWidget * parent ):
634 QDialog( parent ),
635 myIsServer( session.isServer( ) ),
636 mySession( session ),
637 myPrefs( prefs ),
638 myLayout( new QVBoxLayout( this ) )
640 setWindowTitle( tr( "Transmission Preferences" ) );
642 QTabWidget * t = new QTabWidget( this );
643 t->addTab( createSpeedTab( ), tr( "Speed" ) );
644 t->addTab( createDownloadingTab( ), tr( "Downloading" ) );
645 t->addTab( createSeedingTab( ), tr( "Seeding" ) );
646 t->addTab( createPrivacyTab( ), tr( "Privacy" ) );
647 t->addTab( createNetworkTab( ), tr( "Network" ) );
648 t->addTab( createDesktopTab( ), tr( "Desktop" ) );
649 t->addTab( createRemoteTab(session), tr( "Remote" ) );
650 myLayout->addWidget( t );
652 QDialogButtonBox * buttons = new QDialogButtonBox( QDialogButtonBox::Close, Qt::Horizontal, this );
653 connect( buttons, SIGNAL(rejected()), this, SLOT(close()) ); // "close" triggers rejected
654 myLayout->addWidget( buttons );
655 QWidget::setAttribute( Qt::WA_DeleteOnClose, true );
657 connect( &mySession, SIGNAL(sessionUpdated()), this, SLOT(sessionUpdated()));
659 QList<int> keys;
660 keys << Prefs :: RPC_ENABLED
661 << Prefs :: ALT_SPEED_LIMIT_ENABLED
662 << Prefs :: ALT_SPEED_LIMIT_TIME_ENABLED
663 << Prefs :: ENCRYPTION
664 << Prefs :: BLOCKLIST_ENABLED
665 << Prefs :: DIR_WATCH
666 << Prefs :: DOWNLOAD_DIR
667 << Prefs :: INCOMPLETE_DIR
668 << Prefs :: INCOMPLETE_DIR_ENABLED
669 << Prefs :: SCRIPT_TORRENT_DONE_FILENAME;
670 foreach( int key, keys )
671 refreshPref( key );
673 // if it's a remote session, disable the preferences
674 // that don't work in remote sessions
675 if( !myIsServer ) {
676 foreach( QWidget * w, myUnsupportedWhenRemote ) {
677 w->setToolTip( tr( "Not supported by remote sessions" ) );
678 w->setEnabled( false );
683 PrefsDialog :: ~PrefsDialog( )
687 void
688 PrefsDialog :: setPref( int key, const QVariant& v )
690 myPrefs.set( key, v );
691 refreshPref( key );
694 /***
695 ****
696 ***/
698 void
699 PrefsDialog :: sessionUpdated( )
701 updateBlocklistLabel( );
704 void
705 PrefsDialog :: updateBlocklistLabel( )
707 const int n = mySession.blocklistSize( );
708 myBlocklistLabel->setText( tr( "<i>Blocklist contains %Ln rules</i>", 0, n ) );
711 void
712 PrefsDialog :: refreshPref( int key )
714 switch( key )
716 case Prefs :: RPC_ENABLED:
717 case Prefs :: RPC_WHITELIST_ENABLED:
718 case Prefs :: RPC_AUTH_REQUIRED: {
719 const bool enabled( myPrefs.getBool( Prefs::RPC_ENABLED ) );
720 const bool whitelist( myPrefs.getBool( Prefs::RPC_WHITELIST_ENABLED ) );
721 const bool auth( myPrefs.getBool( Prefs::RPC_AUTH_REQUIRED ) );
722 foreach( QWidget * w, myWebWhitelistWidgets ) w->setEnabled( enabled && whitelist );
723 foreach( QWidget * w, myWebAuthWidgets ) w->setEnabled( enabled && auth );
724 foreach( QWidget * w, myWebWidgets ) w->setEnabled( enabled );
725 break;
728 case Prefs :: ALT_SPEED_LIMIT_TIME_ENABLED: {
729 const bool enabled = myPrefs.getBool( key );
730 foreach( QWidget * w, mySchedWidgets ) w->setEnabled( enabled );
731 break;
734 case Prefs :: BLOCKLIST_ENABLED: {
735 const bool enabled = myPrefs.getBool( key );
736 foreach( QWidget * w, myBlockWidgets ) w->setEnabled( enabled );
737 break;
740 case Prefs :: DIR_WATCH:
741 myWatchButton->setText( QFileInfo(myPrefs.getString(Prefs::DIR_WATCH)).fileName() );
742 break;
744 case Prefs :: SCRIPT_TORRENT_DONE_FILENAME: {
745 const QString path( myPrefs.getString( key ) );
746 myTorrentDoneScriptButton->setText( QFileInfo(path).fileName() );
747 break;
750 case Prefs :: PEER_PORT:
751 myPortLabel->setText( tr( "Status unknown" ) );
752 myPortButton->setEnabled( true );
753 break;
755 case Prefs :: DOWNLOAD_DIR: {
756 const QString path( myPrefs.getString( key ) );
757 myDestinationButton->setText( QFileInfo(path).fileName() );
758 myFreespaceLabel->setPath (path);
759 break;
762 case Prefs :: INCOMPLETE_DIR: {
763 QString path( myPrefs.getString( key ) );
764 myIncompleteButton->setText( QFileInfo(path).fileName() );
765 break;
768 case Prefs :: INCOMPLETE_DIR_ENABLED: {
769 const bool enabled = myPrefs.getBool( key );
770 myIncompleteButton->setEnabled( enabled );
771 break;
774 default:
775 break;
778 key2widget_t::iterator it( myWidgets.find( key ) );
779 if( it != myWidgets.end( ) )
781 QWidget * w( it.value( ) );
782 QCheckBox * checkBox;
783 QSpinBox * spin;
784 QDoubleSpinBox * doubleSpin;
785 QTimeEdit * timeEdit;
786 QLineEdit * lineEdit;
788 if(( checkBox = qobject_cast<QCheckBox*>(w)))
790 checkBox->setChecked( myPrefs.getBool( key ) );
792 else if(( spin = qobject_cast<QSpinBox*>(w)))
794 spin->setValue( myPrefs.getInt( key ) );
796 else if(( doubleSpin = qobject_cast<QDoubleSpinBox*>(w)))
798 doubleSpin->setValue( myPrefs.getDouble( key ) );
800 else if(( timeEdit = qobject_cast<QTimeEdit*>(w)))
802 const int minutes( myPrefs.getInt( key ) );
803 timeEdit->setTime( QTime().addSecs( minutes * 60 ) );
805 else if(( lineEdit = qobject_cast<QLineEdit*>(w)))
807 lineEdit->setText( myPrefs.getString( key ) );
809 else if( key == Prefs::ENCRYPTION )
811 QComboBox * comboBox( qobject_cast<QComboBox*>( w ) );
812 const int index = comboBox->findData( myPrefs.getInt( key ) );
813 comboBox->setCurrentIndex( index );
818 bool
819 PrefsDialog :: isAllowed( int key ) const
821 Q_UNUSED( key );
823 return true;