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 $
18 #include <QCoreApplication>
19 #include <QDialogButtonBox>
20 #include <QDoubleSpinBox>
21 #include <QFileIconProvider>
23 #include <QHBoxLayout>
28 #include <QMessageBox>
29 #include <QPushButton>
36 #include <QVBoxLayout>
38 #include "freespace-label.h"
39 #include "formatter.h"
42 #include "prefs-dialog.h"
52 const char * PREF_KEY( "pref-key" );
56 PrefsDialog :: checkBoxToggled( bool checked
)
58 const int key( sender( )->property( PREF_KEY
).toInt( ) );
59 setPref( key
, checked
);
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
);
74 PrefsDialog :: enableBuddyWhenChecked( QCheckBox
* box
, QWidget
* buddy
)
76 connect( box
, SIGNAL(toggled(bool)), buddy
, SLOT(setEnabled(bool)) );
77 buddy
->setEnabled( box
->isChecked( ) );
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
);
87 setPref( key
, d
->value( ) );
89 setPref( key
, qobject_cast
<const QSpinBox
*>(spin
)->value( ) );
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
);
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
);
120 PrefsDialog :: timeEditingFinished( )
122 QTimeEdit
* e
= qobject_cast
<QTimeEdit
*>(sender());
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 );
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()) );
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
);
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()) );
172 PrefsDialog :: createRemoteTab( Session
& session
)
174 HIG
* hig
= new HIG( this );
175 hig
->addSectionTitle( tr( "Remote Control" ) );
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
) );
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
) );
194 l
= hig
->addRow( tr( "Addresses:" ), w
= lineEditNew( Prefs::RPC_WHITELIST
) );
195 myWebWhitelistWidgets
<< l
<< w
;
196 myUnsupportedWhenRemote
<< myWebWidgets
<< myWebAuthWidgets
<< myWebWhitelistWidgets
;
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
);
214 PrefsDialog :: createSpeedTab( )
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 );
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 );
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 );
251 s
= tr( "Do&wnload (%1):" ).arg( speed_K_str
);
252 r
= spinBoxNew( Prefs :: ALT_SPEED_LIMIT_DOWN
, 0, INT_MAX
, 5 );
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 );
261 QLabel
* nd
= new QLabel( tr("&to") );
263 mySchedWidgets
<< nd
;
264 w
= timeEditNew( Prefs :: ALT_SPEED_LIMIT_TIME_END
);
266 h
->addWidget( w
, 1 );
268 hig
->addRow( c
, h
, 0 );
270 s
= tr( "&On days:" );
271 QComboBox
* box
= new QComboBox
;
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
;
297 PrefsDialog :: createDesktopTab( )
299 HIG
* hig
= new HIG( this );
300 hig
->addSectionTitle( tr( "Desktop" ) );
302 hig
->addWideControl( checkBoxNew( tr( "Show Transmission icon in the ¬ification 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
) );
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>" ) );
330 PrefsDialog :: onPortTest( )
332 myPortLabel
->setText( tr( "Testing TCP Port..." ) );
333 myPortButton
->setEnabled( false );
334 myWidgets
[Prefs::PEER_PORT
]->setEnabled( false );
335 mySession
.portTest( );
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" ) );
349 h
->addSpacing( HIG :: PAD_BIG
);
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" ) );
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." ) );
387 PrefsDialog :: onBlocklistDialogDestroyed( QObject
* o
)
391 myBlocklistDialog
= 0;
395 PrefsDialog :: onUpdateBlocklistCancelled( )
397 disconnect( &mySession
, SIGNAL(blocklistUpdated(int)), this, SLOT(onBlocklistUpdated(int))) ;
398 myBlocklistDialog
->deleteLater( );
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
);
409 PrefsDialog :: onUpdateBlocklistClicked( )
411 myBlocklistDialog
= new QMessageBox( QMessageBox::Information
,
413 tr( "<b>Update Blocklist</b><p>Getting new blocklist..." ),
416 connect( myBlocklistDialog
, SIGNAL(rejected()), this, SLOT(onUpdateBlocklistCancelled()) );
417 connect( &mySession
, SIGNAL(blocklistUpdated(int)), this, SLOT(onBlocklistUpdated(int))) ;
418 myBlocklistDialog
->show( );
419 mySession
.updateBlocklist( );
423 PrefsDialog :: encryptionEdited( int i
)
425 const int value( qobject_cast
<QComboBox
*>(sender())->itemData(i
).toInt( ) );
426 setPref( Prefs::ENCRYPTION
, value
);
430 PrefsDialog :: createPrivacyTab( )
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
);
454 l
= myBlocklistLabel
= new QLabel( );
456 w
= new QPushButton( tr( "&Update" ) );
457 connect( w
, SIGNAL(clicked(bool)), this, SLOT(onUpdateBlocklistClicked()));
459 QHBoxLayout
* h
= new QHBoxLayout( );
463 hig
->addWideControl( h
);
465 l
= checkBoxNew( tr( "Enable &automatic updates" ), Prefs::BLOCKLIST_UPDATES_ENABLED
);
467 hig
->addWideControl( l
);
470 updateBlocklistLabel( );
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
);
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
);
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
);
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
);
523 PrefsDialog :: onLocationSelected( const QString
& path
, int key
)
525 setPref( key
, path
);
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
);
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 );
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 );
550 enableBuddyWhenChecked( qobject_cast
<QCheckBox
*>(l
), r
);
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
);
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)) );
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 ();
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
);
633 PrefsDialog :: PrefsDialog( Session
& session
, Prefs
& prefs
, QWidget
* parent
):
635 myIsServer( session
.isServer( ) ),
636 mySession( session
),
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()));
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
)
673 // if it's a remote session, disable the preferences
674 // that don't work in remote sessions
676 foreach( QWidget
* w
, myUnsupportedWhenRemote
) {
677 w
->setToolTip( tr( "Not supported by remote sessions" ) );
678 w
->setEnabled( false );
683 PrefsDialog :: ~PrefsDialog( )
688 PrefsDialog :: setPref( int key
, const QVariant
& v
)
690 myPrefs
.set( key
, v
);
699 PrefsDialog :: sessionUpdated( )
701 updateBlocklistLabel( );
705 PrefsDialog :: updateBlocklistLabel( )
707 const int n
= mySession
.blocklistSize( );
708 myBlocklistLabel
->setText( tr( "<i>Blocklist contains %Ln rules</i>", 0, n
) );
712 PrefsDialog :: refreshPref( int 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
);
728 case Prefs :: ALT_SPEED_LIMIT_TIME_ENABLED
: {
729 const bool enabled
= myPrefs
.getBool( key
);
730 foreach( QWidget
* w
, mySchedWidgets
) w
->setEnabled( enabled
);
734 case Prefs :: BLOCKLIST_ENABLED
: {
735 const bool enabled
= myPrefs
.getBool( key
);
736 foreach( QWidget
* w
, myBlockWidgets
) w
->setEnabled( enabled
);
740 case Prefs :: DIR_WATCH
:
741 myWatchButton
->setText( QFileInfo(myPrefs
.getString(Prefs::DIR_WATCH
)).fileName() );
744 case Prefs :: SCRIPT_TORRENT_DONE_FILENAME
: {
745 const QString
path( myPrefs
.getString( key
) );
746 myTorrentDoneScriptButton
->setText( QFileInfo(path
).fileName() );
750 case Prefs :: PEER_PORT
:
751 myPortLabel
->setText( tr( "Status unknown" ) );
752 myPortButton
->setEnabled( true );
755 case Prefs :: DOWNLOAD_DIR
: {
756 const QString
path( myPrefs
.getString( key
) );
757 myDestinationButton
->setText( QFileInfo(path
).fileName() );
758 myFreespaceLabel
->setPath (path
);
762 case Prefs :: INCOMPLETE_DIR
: {
763 QString
path( myPrefs
.getString( key
) );
764 myIncompleteButton
->setText( QFileInfo(path
).fileName() );
768 case Prefs :: INCOMPLETE_DIR_ENABLED
: {
769 const bool enabled
= myPrefs
.getBool( key
);
770 myIncompleteButton
->setEnabled( enabled
);
778 key2widget_t::iterator
it( myWidgets
.find( key
) );
779 if( it
!= myWidgets
.end( ) )
781 QWidget
* w( it
.value( ) );
782 QCheckBox
* checkBox
;
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
);
819 PrefsDialog :: isAllowed( int key
) const