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

Last change on this file since 8211 was 8211, checked in by charles, 13 years ago

(trunk) have the gtk and qt clients use the same minimum seed ratio in the preferences dialog as the mac uses

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