source: trunk/qt/prefs-dialog.cc @ 10922

Last change on this file since 10922 was 10922, checked in by charles, 12 years ago

(trunk qt) sync the Preference dialog's "Torrents" tab's section names ("Adding", "Downloading", "Seeding") with the GTK+ client's.

  • Property svn:keywords set to Date Rev Author Id
File size: 26.8 KB
Line 
1/*
2 * This file Copyright (C) 2009-2010 Mnemosyne LLC
3 *
4 * This file is licensed by the GPL version 2.  Works owned by the
5 * Transmission project are granted a special exemption to clause 2(b)
6 * so that the bulk of its code can remain under the MIT license.
7 * This exemption does not extend to derived works not owned by
8 * the Transmission project.
9 *
10 * $Id: prefs-dialog.cc 10922 2010-07-01 16:15:08Z charles $
11 */
12
13#include <cassert>
14#include <iostream>
15
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 <QHttp>
25#include <QIcon>
26#include <QLabel>
27#include <QLineEdit>
28#include <QList>
29#include <QMessageBox>
30#include <QPushButton>
31#include <QSpinBox>
32#include <QStyle>
33#include <QTabWidget>
34#include <QTime>
35#include <QTimeEdit>
36#include <QTimer>
37#include <QVBoxLayout>
38
39#include "hig.h"
40#include "prefs.h"
41#include "prefs-dialog.h"
42#include "qticonloader.h"
43#include "session.h"
44#include "utils.h"
45
46/***
47****
48***/
49
50namespace
51{
52    const char * PREF_KEY( "pref-key" );
53};
54
55void
56PrefsDialog :: checkBoxToggled( bool checked )
57{
58    const int key( sender( )->property( PREF_KEY ).toInt( ) );
59    myPrefs.set( key, checked );
60}
61
62QCheckBox *
63PrefsDialog :: checkBoxNew( const QString& text, int key )
64{
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;
71}
72
73void
74PrefsDialog :: enableBuddyWhenChecked( QCheckBox * box, QWidget * buddy )
75{
76    connect( box, SIGNAL(toggled(bool)), buddy, SLOT(setEnabled(bool)) );
77    buddy->setEnabled( box->isChecked( ) );
78}
79
80void
81PrefsDialog :: spinBoxChangedIdle( )
82{
83    const QObject * spin( sender()->property( "SPIN" ).value<QObject*>( ) );
84    const int key( spin->property( PREF_KEY ).toInt( ) );
85
86    const QDoubleSpinBox * d = qobject_cast<const QDoubleSpinBox*>( spin );
87    if( d != 0 )
88        myPrefs.set( key, d->value( ) );
89    else
90        myPrefs.set( key, qobject_cast<const QSpinBox*>(spin)->value( ) );
91}
92
93void
94PrefsDialog :: spinBoxChanged( int value )
95{
96    Q_UNUSED( value );
97
98    static const QString timerName( "TIMER_CHILD" );
99    QObject * o( sender( ) );
100
101    // user may be spinning through many values, so let's hold off
102    // for a moment to kekep from flooding a bunch of prefs changes
103    QTimer * timer( o->findChild<QTimer*>( timerName ) );
104    if( timer == 0 )
105    {
106        timer = new QTimer( o );
107        timer->setObjectName( timerName );
108        timer->setSingleShot( true );
109        timer->setProperty( "SPIN", qVariantFromValue( o ) );
110        connect( timer, SIGNAL(timeout()), this, SLOT(spinBoxChangedIdle()));
111    }
112    timer->start( 200 );
113}
114
115QSpinBox *
116PrefsDialog :: spinBoxNew( int key, int low, int high, int step )
117{
118    QSpinBox * spin = new QSpinBox( );
119    spin->setRange( low, high );
120    spin->setSingleStep( step );
121    spin->setValue( myPrefs.getInt( key ) );
122    spin->setProperty( PREF_KEY, key );
123    connect( spin, SIGNAL(valueChanged(int)), this, SLOT(spinBoxChanged(int)));
124    myWidgets.insert( key, spin );
125    return spin;
126}
127
128void
129PrefsDialog :: doubleSpinBoxChanged( double value )
130{
131    Q_UNUSED( value );
132
133    spinBoxChanged( 0 );
134}
135
136QDoubleSpinBox *
137PrefsDialog :: doubleSpinBoxNew( int key, double low, double high, double step, int decimals )
138{
139    QDoubleSpinBox * spin = new QDoubleSpinBox( );
140    spin->setRange( low, high );
141    spin->setSingleStep( step );
142    spin->setDecimals( decimals );
143    spin->setValue( myPrefs.getDouble( key ) );
144    spin->setProperty( PREF_KEY, key );
145    connect( spin, SIGNAL(valueChanged(double)), this, SLOT(doubleSpinBoxChanged(double)));
146    myWidgets.insert( key, spin );
147    return spin;
148}
149
150void
151PrefsDialog :: timeChanged( const QTime& time )
152{
153    const int key( sender()->property( PREF_KEY ).toInt( ) );
154    const int seconds( QTime().secsTo( time ) );
155    myPrefs.set( key, seconds / 60 );
156}
157
158QTimeEdit*
159PrefsDialog :: timeEditNew( int key )
160{
161    const int minutes( myPrefs.getInt( key ) );
162    QTimeEdit * e = new QTimeEdit( );
163    e->setDisplayFormat( "hh:mm" );
164    e->setProperty( PREF_KEY, key );
165    e->setTime( QTime().addSecs( minutes * 60 ) );
166    myWidgets.insert( key, e );
167    connect( e, SIGNAL(timeChanged(const QTime&)), this, SLOT(timeChanged(const QTime&)) );
168    return e;
169}
170
171void
172PrefsDialog :: textChanged( const QString& text )
173{
174    const int key( sender()->property( PREF_KEY ).toInt( ) );
175    myPrefs.set( key, text );
176}
177
178QLineEdit*
179PrefsDialog :: lineEditNew( int key, int echoMode )
180{
181    QLineEdit * e = new QLineEdit( myPrefs.getString( key ) );
182    e->setProperty( PREF_KEY, key );
183    e->setEchoMode( QLineEdit::EchoMode( echoMode ) );
184    myWidgets.insert( key, e );
185    connect( e, SIGNAL(textChanged(const QString&)), this, SLOT(textChanged(const QString&)) );
186    return e;
187}
188
189/***
190****
191***/
192
193QWidget *
194PrefsDialog :: createTrackerTab( )
195{
196    QWidget *l, *r;
197    HIG * hig = new HIG( );
198    hig->addSectionTitle( tr( "Tracker Proxy" ) );
199    hig->addWideControl( l = checkBoxNew( tr( "Connect to tracker via a pro&xy" ), Prefs::PROXY_ENABLED ) );
200    myUnsupportedWhenRemote << l;
201    l = hig->addRow( tr( "Proxy &server:" ), r = lineEditNew( Prefs::PROXY ) );
202    myProxyWidgets << l << r;
203    l = hig->addRow( tr( "Proxy &port:" ), r = spinBoxNew( Prefs::PROXY_PORT, 1, 65535, 1 ) );
204    myProxyWidgets << l << r;
205    hig->addWideControl( l = checkBoxNew( tr( "Use &authentication" ), Prefs::PROXY_AUTH_ENABLED ) );
206    myProxyWidgets << l;
207    l = hig->addRow( tr( "&Username:" ), r = lineEditNew( Prefs::PROXY_USERNAME ) );
208    myProxyAuthWidgets << l << r;
209    l = hig->addRow( tr( "Pass&word:" ), r = lineEditNew( Prefs::PROXY_PASSWORD, QLineEdit::Password ) );
210    myProxyAuthWidgets << l << r;
211    myUnsupportedWhenRemote << myProxyAuthWidgets;
212    hig->finish( );
213    return hig;
214}
215
216/***
217****
218***/
219
220QWidget *
221PrefsDialog :: createWebTab( Session& session )
222{
223    HIG * hig = new HIG( this );
224    hig->addSectionTitle( tr( "Web Client" ) );
225    QWidget * w;
226    QHBoxLayout * h = new QHBoxLayout( );
227    QIcon i( style()->standardIcon( QStyle::StandardPixmap( QStyle::SP_DirOpenIcon ) ) );
228    QPushButton * b = new QPushButton( i, tr( "&Open web client" ) );
229    connect( b, SIGNAL(clicked()), &session, SLOT(launchWebInterface()) );
230    h->addWidget( b, 0, Qt::AlignRight );
231    QWidget * l = checkBoxNew( tr( "&Enable web client" ), Prefs::RPC_ENABLED );
232    myUnsupportedWhenRemote << l;
233    hig->addRow( l, h, 0 );
234    l = hig->addRow( tr( "Listening &port:" ), w = spinBoxNew( Prefs::RPC_PORT, 0, 65535, 1 ) );
235    myWebWidgets << l << w;
236    hig->addWideControl( w = checkBoxNew( tr( "Use &authentication" ), Prefs::RPC_AUTH_REQUIRED ) );
237    myWebWidgets << w;
238    l = hig->addRow( tr( "&Username:" ), w = lineEditNew( Prefs::RPC_USERNAME ) );
239    myWebAuthWidgets << l << w;
240    l = hig->addRow( tr( "Pass&word:" ), w = lineEditNew( Prefs::RPC_PASSWORD, QLineEdit::Password ) );
241    myWebAuthWidgets << l << w;
242    hig->addWideControl( w = checkBoxNew( tr( "Only allow these IP a&ddresses to connect:" ), Prefs::RPC_WHITELIST_ENABLED ) );
243    myWebWidgets << w;
244    l = hig->addRow( tr( "Addresses:" ), w = lineEditNew( Prefs::RPC_WHITELIST ) );
245    myWebWhitelistWidgets << l << w;
246    myUnsupportedWhenRemote << myWebWidgets << myWebAuthWidgets << myWebWhitelistWidgets;
247    hig->finish( );
248    return hig;
249}
250
251/***
252****
253***/
254
255void
256PrefsDialog :: altSpeedDaysEdited( int i )
257{
258    const int value = qobject_cast<QComboBox*>(sender())->itemData(i).toInt();
259    myPrefs.set( Prefs::ALT_SPEED_LIMIT_TIME_DAY, value );
260}
261
262
263QWidget *
264PrefsDialog :: createSpeedTab( )
265{
266    QWidget *l, *r;
267    HIG * hig = new HIG( this );
268    hig->addSectionTitle( tr( "Speed Limits" ) );
269
270        l = checkBoxNew( tr( "Limit &download speed (KiB/s):" ), Prefs::DSPEED_ENABLED );
271        r = spinBoxNew( Prefs::DSPEED, 0, INT_MAX, 5 );
272        hig->addRow( l, r );
273        enableBuddyWhenChecked( qobject_cast<QCheckBox*>(l), r );
274
275        l = checkBoxNew( tr( "Limit &upload speed (KiB/s):" ), Prefs::USPEED_ENABLED );
276        r = spinBoxNew( Prefs::USPEED, 0, INT_MAX, 5 );
277        hig->addRow( l, r );
278        enableBuddyWhenChecked( qobject_cast<QCheckBox*>(l), r );
279
280    hig->addSectionDivider( );
281    QHBoxLayout * h = new QHBoxLayout;
282    h->setSpacing( HIG :: PAD );
283    QLabel * label = new QLabel;
284    label->setPixmap( QPixmap( ":/icons/alt-limit-off.png" ) );
285    label->setAlignment( Qt::AlignLeft|Qt::AlignVCenter );
286    h->addWidget( label );
287    label = new QLabel( tr( "Temporary Speed Limits" ) );
288    label->setStyleSheet( "font: bold" );
289    label->setAlignment( Qt::AlignLeft|Qt::AlignVCenter );
290    h->addWidget( label );
291    hig->addSectionTitle( h );
292
293        QString s = tr( "<small>Override normal speed limits manually or at scheduled times</small>" );
294        hig->addWideControl( new QLabel( s ) );
295
296        s = tr( "Limit d&ownload speed (KiB/s):" );
297        r = spinBoxNew( Prefs :: ALT_SPEED_LIMIT_DOWN, 0, INT_MAX, 5 );
298        hig->addRow( s, r );
299
300        s = tr( "Limit u&pload speed (KiB/s):" );
301        r = spinBoxNew( Prefs :: ALT_SPEED_LIMIT_UP, 0, INT_MAX, 5 );
302        hig->addRow( s, r );
303
304        QCheckBox * c = checkBoxNew( tr( "&Scheduled times:" ), Prefs::ALT_SPEED_LIMIT_TIME_ENABLED );
305        h = new QHBoxLayout( );
306        h->setSpacing( HIG::PAD );
307        QWidget * w = timeEditNew( Prefs :: ALT_SPEED_LIMIT_TIME_BEGIN );
308        h->addWidget( w, 1 );
309        mySchedWidgets << w;
310        QLabel * nd = new QLabel( "&to" );
311        h->addWidget( nd );
312        mySchedWidgets << nd;
313        w = timeEditNew( Prefs :: ALT_SPEED_LIMIT_TIME_END );
314        nd->setBuddy( w );
315        h->addWidget( w, 1 );
316        mySchedWidgets << w;
317        hig->addRow( c, h, 0 );
318
319        s = tr( "&On days:" );
320        QComboBox * box = new QComboBox;
321        const QIcon noIcon;
322        box->addItem( noIcon, tr( "Every Day" ), QVariant( TR_SCHED_ALL ) );
323        box->addItem( noIcon, tr( "Weekdays" ),  QVariant( TR_SCHED_WEEKDAY ) );
324        box->addItem( noIcon, tr( "Weekends" ),  QVariant( TR_SCHED_WEEKEND ) );
325        box->addItem( noIcon, tr( "Sunday" ),    QVariant( TR_SCHED_SUN ) );
326        box->addItem( noIcon, tr( "Monday" ),    QVariant( TR_SCHED_MON ) );
327        box->addItem( noIcon, tr( "Tuesday" ),   QVariant( TR_SCHED_TUES ) );
328        box->addItem( noIcon, tr( "Wednesday" ), QVariant( TR_SCHED_WED ) );
329        box->addItem( noIcon, tr( "Thursday" ),  QVariant( TR_SCHED_THURS ) );
330        box->addItem( noIcon, tr( "Friday" ),    QVariant( TR_SCHED_FRI ) );
331        box->addItem( noIcon, tr( "Saturday" ),  QVariant( TR_SCHED_SAT ) );
332        box->setCurrentIndex( box->findData( myPrefs.getInt( Prefs :: ALT_SPEED_LIMIT_TIME_DAY ) ) );
333        connect( box, SIGNAL(activated(int)), this, SLOT(altSpeedDaysEdited(int)) );
334        w = hig->addRow( s, box );
335        mySchedWidgets << w << box;
336
337    hig->finish( );
338    return hig;
339}
340
341/***
342****
343***/
344
345void
346PrefsDialog :: onPortTested( bool isOpen )
347{
348    myPortButton->setEnabled( true );
349    myWidgets[Prefs::PEER_PORT]->setEnabled( true );
350    myPortLabel->setText( isOpen ? tr( "Port is <b>open</b>" )
351                                 : tr( "Port is <b>closed</b>" ) );
352}
353
354void
355PrefsDialog :: onPortTest( )
356{
357    myPortLabel->setText( tr( "Testing..." ) );
358    myPortButton->setEnabled( false );
359    myWidgets[Prefs::PEER_PORT]->setEnabled( false );
360    mySession.portTest( );
361}
362
363QWidget *
364PrefsDialog :: createNetworkTab( )
365{
366    HIG * hig = new HIG( this );
367    hig->addSectionTitle( tr( "Incoming Peers" ) );
368
369    QSpinBox * s = spinBoxNew( Prefs::PEER_PORT, 1, 65535, 1 );
370    QHBoxLayout * h = new QHBoxLayout( );
371    QPushButton * b = myPortButton = new QPushButton( tr( "&Test Port" ) );
372    QLabel * l = myPortLabel = new QLabel( tr( "Status unknown" ) );
373    h->addWidget( l );
374    h->addSpacing( HIG :: PAD_BIG );
375    h->addWidget( b );
376    h->setStretchFactor( l, 1 );
377    connect( b, SIGNAL(clicked(bool)), this, SLOT(onPortTest()));
378    connect( &mySession, SIGNAL(portTested(bool)), this, SLOT(onPortTested(bool)));
379
380    hig->addRow( tr( "&Port for incoming connections:" ), s );
381    hig->addRow( "", h, 0 );
382    hig->addWideControl( checkBoxNew( tr( "Use UPnP or NAT-PMP port &forwarding from my router" ), Prefs::PORT_FORWARDING ) );
383    hig->addWideControl( checkBoxNew( tr( "Pick a &random port every time Transmission is started" ), Prefs :: PEER_PORT_RANDOM_ON_START ) );
384
385    hig->addSectionDivider( );
386    hig->addSectionTitle( tr( "Limits" ) );
387    hig->addRow( tr( "Maximum peers per &torrent:" ), spinBoxNew( Prefs::PEER_LIMIT_TORRENT, 1, 300, 5 ) );
388    hig->addRow( tr( "Maximum peers &overall:" ), spinBoxNew( Prefs::PEER_LIMIT_GLOBAL, 1, 3000, 5 ) );
389
390    hig->finish( );
391    return hig;
392}
393
394/***
395****
396***/
397
398void
399PrefsDialog :: onBlocklistDialogDestroyed( QObject * o )
400{
401    Q_UNUSED( o );
402
403    myBlocklistDialog = 0;
404}
405
406void
407PrefsDialog :: onUpdateBlocklistCancelled( )
408{
409    disconnect( &mySession, SIGNAL(blocklistUpdated(int)), this, SLOT(onBlocklistUpdated(int))) ;
410    myBlocklistDialog->deleteLater( );
411}
412
413void
414PrefsDialog :: onBlocklistUpdated( int n )
415{
416    myBlocklistDialog->setText( tr( "<b>Update succeeded!</b><p>Blocklist now has %Ln rules.", 0, n ) );
417    myBlocklistDialog->setTextFormat( Qt::RichText );
418}
419
420void
421PrefsDialog :: onUpdateBlocklistClicked( )
422{
423    myBlocklistDialog = new QMessageBox( QMessageBox::Information,
424                                         "",
425                                         tr( "<b>Update Blocklist</b><p>Getting new blocklist..." ),
426                                         QMessageBox::Close,
427                                         this );
428    QPixmap pixmap;
429    QIcon icon = QtIconLoader :: icon( "dialog-information" );
430    if( !icon.isNull( ) ) {
431        const int size = style()->pixelMetric( QStyle::PM_LargeIconSize );
432        myBlocklistDialog->setIconPixmap( icon.pixmap( size, size ) );
433    }
434    connect( myBlocklistDialog, SIGNAL(rejected()), this, SLOT(onUpdateBlocklistCancelled()) );
435    connect( &mySession, SIGNAL(blocklistUpdated(int)), this, SLOT(onBlocklistUpdated(int))) ;
436    myBlocklistDialog->show( );
437    mySession.updateBlocklist( );
438}
439
440void
441PrefsDialog :: encryptionEdited( int i )
442{
443    const int value( qobject_cast<QComboBox*>(sender())->itemData(i).toInt( ) );
444    myPrefs.set( Prefs::ENCRYPTION, value );
445}
446
447QWidget *
448PrefsDialog :: createPrivacyTab( )
449{
450    HIG * hig = new HIG( this );
451    hig->addSectionTitle( tr( "Blocklist" ) );
452    QHBoxLayout * h = new QHBoxLayout( );
453    QIcon i( style()->standardIcon( QStyle::StandardPixmap( QStyle::SP_BrowserReload ) ) );
454    QWidget * w = new QPushButton( i, tr( "&Update blocklist" ) );
455    connect( w, SIGNAL(clicked(bool)), this, SLOT(onUpdateBlocklistClicked()));
456    myBlockWidgets << w;
457    QWidget * l = checkBoxNew( "", Prefs::BLOCKLIST_ENABLED );
458    h->addWidget( l );
459    h->addStretch( 1 );
460    h->addWidget( w );
461    hig->addWideControl( h );
462    l = checkBoxNew( tr( "Enable &automatic updates" ), Prefs::BLOCKLIST_UPDATES_ENABLED );
463    myBlockWidgets << l;
464    hig->addWideControl( l );
465
466    QComboBox * box = new QComboBox( );
467    box->addItem( tr( "Allow encryption" ), 0 );
468    box->addItem( tr( "Prefer encryption" ), 1 );
469    box->addItem( tr( "Require encryption" ), 2 );
470    myWidgets.insert( Prefs :: ENCRYPTION, box );
471    connect( box, SIGNAL(activated(int)), this, SLOT(encryptionEdited(int)));
472
473    hig->addSectionDivider( );
474    hig->addSectionTitle( tr( "Privacy" ) );
475    hig->addRow( tr( "&Encryption mode:" ), box );
476    hig->addWideControl( w = checkBoxNew( tr( "Use PE&X to find more peers" ), Prefs::PEX_ENABLED ) );
477    w->setToolTip( tr( "PEX is a tool for exchanging peer lists with the peers you're connected to." ) );
478    hig->addWideControl( w = checkBoxNew( tr( "Use &DHT to find more peers" ), Prefs::DHT_ENABLED ) );
479    w->setToolTip( tr( "DHT is a tool for finding peers without a tracker." ) );
480    hig->addWideControl( w = checkBoxNew( tr( "Use &Local Peer Discovery to find more peers" ), Prefs::LPD_ENABLED ) );
481    w->setToolTip( tr( "LPD is a tool for finding peers on your local network." ) );
482
483    hig->finish( );
484    updateBlocklistCheckBox( );
485    return hig;
486}
487
488/***
489****
490***/
491
492void
493PrefsDialog :: onScriptClicked( void )
494{
495    const QString title = tr( "Select \"Torrent Done\" Script" );
496    const QString myPath = myPrefs.getString( Prefs::SCRIPT_TORRENT_DONE_FILENAME );
497    const QString path = Utils::remoteFileChooser( this, title, myPath, false, mySession.isServer() );
498
499    if( !path.isEmpty() )
500        onLocationSelected( path, Prefs::SCRIPT_TORRENT_DONE_FILENAME );
501}
502
503void
504PrefsDialog :: onIncompleteClicked( void )
505{
506    const QString title = tr( "Select Incomplete Directory" );
507    const QString myPath = myPrefs.getString( Prefs::INCOMPLETE_DIR );
508    const QString path = Utils::remoteFileChooser( this, title, myPath, true, mySession.isServer() );
509
510    if( !path.isEmpty() )
511        onLocationSelected( path, Prefs::INCOMPLETE_DIR );
512}
513
514void
515PrefsDialog :: onWatchClicked( void )
516{
517    const QString title = tr( "Select Watch Directory" );
518    const QString myPath = myPrefs.getString( Prefs::DIR_WATCH );
519    const QString path = Utils::remoteFileChooser( this, title, myPath, true, true );
520
521    if( !path.isEmpty() )
522        onLocationSelected( path, Prefs::DIR_WATCH );
523}
524
525void
526PrefsDialog :: onDestinationClicked( void )
527{
528    const QString title = tr( "Select Destination" );
529    const QString myPath = myPrefs.getString( Prefs::DOWNLOAD_DIR );
530    const QString path = Utils::remoteFileChooser( this, title, myPath, true, mySession.isServer() );
531
532    if( !path.isEmpty() )
533        onLocationSelected( path, Prefs::DOWNLOAD_DIR );
534}
535
536void
537PrefsDialog :: onLocationSelected( const QString& path, int key )
538{
539    myPrefs.set( key, path );
540    updatePref( key );
541}
542
543QWidget *
544PrefsDialog :: createTorrentsTab( )
545{
546    const int iconSize( style( )->pixelMetric( QStyle :: PM_SmallIconSize ) );
547    const QFileIconProvider iconProvider;
548    const QIcon folderIcon = iconProvider.icon( QFileIconProvider::Folder );
549    const QPixmap folderPixmap = folderIcon.pixmap( iconSize );
550    const QIcon fileIcon = iconProvider.icon( QFileIconProvider::File );
551    const QPixmap filePixmap = fileIcon.pixmap( iconSize );
552
553    QWidget *l, *r;
554    HIG * hig = new HIG( this );
555    hig->addSectionTitle( tr( "Adding" ) );
556
557        l = checkBoxNew( tr( "Automatically &add torrents from:" ), Prefs::DIR_WATCH_ENABLED );
558        QPushButton * b = myWatchButton = new QPushButton;
559        b->setIcon( folderPixmap );
560        b->setStyleSheet( "text-align: left; padding-left: 5; padding-right: 5" );
561        connect( b, SIGNAL(clicked(bool)), this, SLOT(onWatchClicked(void)) );
562        hig->addRow( l, b );
563        enableBuddyWhenChecked( qobject_cast<QCheckBox*>(l), b );
564
565        hig->addWideControl( checkBoxNew( tr( "Show &options dialog" ), Prefs::OPTIONS_PROMPT ) );
566        hig->addWideControl( checkBoxNew( tr( "&Start when added" ), Prefs::START ) );
567        hig->addWideControl( checkBoxNew( tr( "Mo&ve .torrent file to the trash" ), Prefs::TRASH_ORIGINAL ) );
568
569    hig->addSectionDivider( );
570    hig->addSectionTitle( tr( "Downloading" ) );
571
572        hig->addWideControl( checkBoxNew( tr( "Append \".&part\" to incomplete files' names" ), Prefs::RENAME_PARTIAL_FILES ) );
573
574        l = myIncompleteCheckbox = checkBoxNew( tr( "Keep &incomplete files in:" ), Prefs::INCOMPLETE_DIR_ENABLED );
575        b = myIncompleteButton = new QPushButton;
576        b->setIcon( folderPixmap );
577        b->setStyleSheet( "text-align: left; padding-left: 5; padding-right: 5" );
578        connect( b, SIGNAL(clicked(bool)), this, SLOT(onIncompleteClicked(void)) );
579        hig->addRow( myIncompleteCheckbox, b );
580        enableBuddyWhenChecked( qobject_cast<QCheckBox*>(l), b );
581
582        l = myTorrentDoneScriptCheckbox = checkBoxNew( tr( "Call scrip&t when torrent is completed" ), Prefs::SCRIPT_TORRENT_DONE_ENABLED );
583        b = myTorrentDoneScriptButton = new QPushButton;
584        b->setIcon( filePixmap );
585        b->setStyleSheet( "text-align: left; padding-left: 5; padding-right: 5" );
586        connect( b, SIGNAL(clicked(bool)), this, SLOT(onScriptClicked(void)) );
587        hig->addRow( myTorrentDoneScriptCheckbox, b );
588        enableBuddyWhenChecked( qobject_cast<QCheckBox*>(l), b );
589
590        b = myDestinationButton = new QPushButton;
591        b->setIcon( folderPixmap );
592        b->setStyleSheet( "text-align: left; padding-left: 5; padding-right: 5" );
593        connect( b, SIGNAL(clicked(bool)), this, SLOT(onDestinationClicked(void)) );
594        hig->addRow( tr( "Save to &Location:" ), b );
595
596    hig->addSectionDivider( );
597    hig->addSectionTitle( tr( "Seeding" ) );
598
599        l = checkBoxNew( tr( "&Seed torrent until its ratio reaches:" ), Prefs::RATIO_ENABLED );
600        r = doubleSpinBoxNew( Prefs::RATIO, 0, INT_MAX, 0.5, 2 );
601        hig->addRow( l, r );
602        enableBuddyWhenChecked( qobject_cast<QCheckBox*>(l), r );
603
604    hig->finish( );
605    return hig;
606}
607
608/***
609****
610***/
611
612PrefsDialog :: PrefsDialog( Session& session, Prefs& prefs, QWidget * parent ):
613    QDialog( parent ),
614    myIsServer( session.isServer( ) ),
615    mySession( session ),
616    myPrefs( prefs ),
617    myLayout( new QVBoxLayout( this ) )
618{
619    setWindowTitle( tr( "Transmission Preferences" ) );
620
621    QTabWidget * t = new QTabWidget( this );
622    t->addTab( createTorrentsTab( ),     tr( "Torrents" ) );
623    t->addTab( createSpeedTab( ),        tr( "Speed" ) );
624    t->addTab( createPrivacyTab( ),      tr( "Privacy" ) );
625    t->addTab( createNetworkTab( ),      tr( "Network" ) );
626    t->addTab( createWebTab( session ),  tr( "Web" ) );
627    //t->addTab( createTrackerTab( ),    tr( "Trackers" ) );
628    myLayout->addWidget( t );
629
630    QDialogButtonBox * buttons = new QDialogButtonBox( QDialogButtonBox::Close, Qt::Horizontal, this );
631    connect( buttons, SIGNAL(rejected()), this, SLOT(close()) ); // "close" triggers rejected
632    myLayout->addWidget( buttons );
633    QWidget::setAttribute( Qt::WA_DeleteOnClose, true );
634
635    connect( &mySession, SIGNAL(sessionUpdated()), this, SLOT(sessionUpdated()));
636
637    QList<int> keys;
638    keys << Prefs :: RPC_ENABLED
639         << Prefs :: PROXY_ENABLED
640         << Prefs :: ALT_SPEED_LIMIT_ENABLED
641         << Prefs :: ALT_SPEED_LIMIT_TIME_ENABLED
642         << Prefs :: ENCRYPTION
643         << Prefs :: BLOCKLIST_ENABLED
644         << Prefs :: DIR_WATCH
645         << Prefs :: DOWNLOAD_DIR
646         << Prefs :: INCOMPLETE_DIR
647         << Prefs :: INCOMPLETE_DIR_ENABLED;
648    foreach( int key, keys )
649        updatePref( key );
650
651    // if it's a remote session, disable the preferences
652    // that don't work in remote sessions
653    if( !myIsServer )  {
654        foreach( QWidget * w, myUnsupportedWhenRemote ) {
655            w->setToolTip( tr( "Not supported by remote sessions" ) );
656            w->setEnabled( false );
657        }
658    }
659}
660
661PrefsDialog :: ~PrefsDialog( )
662{
663}
664
665/***
666****
667***/
668
669void
670PrefsDialog :: sessionUpdated( )
671{
672    updateBlocklistCheckBox( );
673}
674
675void
676PrefsDialog :: updateBlocklistCheckBox( )
677{
678    QCheckBox * box = qobject_cast<QCheckBox*>( myWidgets[Prefs::BLOCKLIST_ENABLED] );
679    const int n = mySession.blocklistSize( );
680    if( n < 0 ) // unknown
681        box->setText( tr( "Enable &blocklist" ) );
682    else
683        box->setText( tr( "Enable &blocklist (%Ln rules)", 0, n ) );
684}
685
686void
687PrefsDialog :: updatePref( int key )
688{
689    switch( key )
690    {
691        case Prefs :: RPC_ENABLED:
692        case Prefs :: RPC_WHITELIST_ENABLED:
693        case Prefs :: RPC_AUTH_REQUIRED: {
694            const bool enabled( myPrefs.getBool( Prefs::RPC_ENABLED ) );
695            const bool whitelist( myPrefs.getBool( Prefs::RPC_WHITELIST_ENABLED ) );
696            const bool auth( myPrefs.getBool( Prefs::RPC_AUTH_REQUIRED ) );
697            foreach( QWidget * w, myWebWhitelistWidgets ) w->setEnabled( enabled && whitelist );
698            foreach( QWidget * w, myWebAuthWidgets ) w->setEnabled( enabled && auth );
699            foreach( QWidget * w, myWebWidgets ) w->setEnabled( enabled );
700            break;
701        }
702
703        case Prefs :: PROXY_ENABLED:
704        case Prefs :: PROXY_AUTH_ENABLED: {
705            const bool enabled( myPrefs.getBool( Prefs::PROXY_ENABLED ) );
706            const bool auth( myPrefs.getBool( Prefs::PROXY_AUTH_ENABLED ) );
707            foreach( QWidget * w, myProxyAuthWidgets ) w->setEnabled( enabled && auth );
708            foreach( QWidget * w, myProxyWidgets ) w->setEnabled( enabled );
709            break;
710        }
711
712        case Prefs :: ALT_SPEED_LIMIT_TIME_ENABLED: {
713            const bool enabled = myPrefs.getBool( key );
714            foreach( QWidget * w, mySchedWidgets ) w->setEnabled( enabled );
715            break;
716        }
717
718        case Prefs :: BLOCKLIST_ENABLED: {
719            const bool enabled = myPrefs.getBool( key );
720            foreach( QWidget * w, myBlockWidgets ) w->setEnabled( enabled );
721            break;
722        }
723
724        case Prefs :: DIR_WATCH:
725            myWatchButton->setText( QFileInfo(myPrefs.getString(Prefs::DIR_WATCH)).fileName() );
726            break;
727
728        case Prefs :: PEER_PORT:
729            myPortLabel->setText( tr( "Status unknown" ) );
730            myPortButton->setEnabled( true );
731            break;
732
733        case Prefs :: DOWNLOAD_DIR: {
734            QString path( myPrefs.getString( key ) );
735            myDestinationButton->setText( QFileInfo(path).fileName() );
736            break;
737        }
738
739        case Prefs :: INCOMPLETE_DIR: {
740            QString path( myPrefs.getString( key ) );
741            myIncompleteButton->setText( QFileInfo(path).fileName() );
742            break;
743        }
744
745        case Prefs :: INCOMPLETE_DIR_ENABLED: {
746            const bool enabled = myPrefs.getBool( key );
747            myIncompleteButton->setEnabled( enabled );
748            break;
749        }
750
751        default:
752            break;
753    }
754
755    key2widget_t::iterator it( myWidgets.find( key ) );
756    if( it != myWidgets.end( ) )
757    {
758        QWidget * w( it.value( ) );
759        QCheckBox * checkBox;
760        QSpinBox * spin;
761        QDoubleSpinBox * doubleSpin;
762        QTimeEdit * timeEdit;
763        QLineEdit * lineEdit;
764
765        if(( checkBox = qobject_cast<QCheckBox*>(w)))
766        {
767            checkBox->setChecked( myPrefs.getBool( key ) );
768        }
769        else if(( spin = qobject_cast<QSpinBox*>(w)))
770        {
771            spin->setValue( myPrefs.getInt( key ) );
772        }
773        else if(( doubleSpin = qobject_cast<QDoubleSpinBox*>(w)))
774        {
775            doubleSpin->setValue( myPrefs.getDouble( key ) );
776        }
777        else if(( timeEdit = qobject_cast<QTimeEdit*>(w)))
778        {
779            const int minutes( myPrefs.getInt( key ) );
780            timeEdit->setTime( QTime().addSecs( minutes * 60 ) );
781        }
782        else if(( lineEdit = qobject_cast<QLineEdit*>(w)))
783        {
784            lineEdit->setText( myPrefs.getString( key ) );
785        }
786        else if( key == Prefs::ENCRYPTION )
787        {
788            QComboBox * comboBox( qobject_cast<QComboBox*>( w ) );
789            const int index = comboBox->findData( myPrefs.getInt( key ) );
790            comboBox->setCurrentIndex( index );
791        }
792    }
793}
794
795bool
796PrefsDialog :: isAllowed( int key ) const
797{
798    Q_UNUSED( key );
799
800    return true;
801}
Note: See TracBrowser for help on using the repository browser.