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

Last change on this file since 10722 was 10722, checked in by Longinus00, 12 years ago

(qt) #3255: Don't use filebrowser in remote sessions

  • Property svn:keywords set to Date Rev Author Id
File size: 26.7 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 10722 2010-06-04 01:00:27Z Longinus00 $
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 Torrents" ) );
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        hig->addWideControl( checkBoxNew( tr( "Append \".&part\" to incomplete files' names" ), Prefs::RENAME_PARTIAL_FILES ) );
569
570        l = myIncompleteCheckbox = checkBoxNew( tr( "Keep &incomplete files in:" ), Prefs::INCOMPLETE_DIR_ENABLED );
571        b = myIncompleteButton = new QPushButton;
572        b->setIcon( folderPixmap );
573        b->setStyleSheet( "text-align: left; padding-left: 5; padding-right: 5" );
574        connect( b, SIGNAL(clicked(bool)), this, SLOT(onIncompleteClicked(void)) );
575        hig->addRow( myIncompleteCheckbox, b );
576        enableBuddyWhenChecked( qobject_cast<QCheckBox*>(l), b );
577
578        l = myTorrentDoneScriptCheckbox = checkBoxNew( tr( "Call scrip&t when torrent is completed" ), Prefs::SCRIPT_TORRENT_DONE_ENABLED );
579        b = myTorrentDoneScriptButton = new QPushButton;
580        b->setIcon( filePixmap );
581        b->setStyleSheet( "text-align: left; padding-left: 5; padding-right: 5" );
582        connect( b, SIGNAL(clicked(bool)), this, SLOT(onScriptClicked(void)) );
583        hig->addRow( myTorrentDoneScriptCheckbox, b );
584        enableBuddyWhenChecked( qobject_cast<QCheckBox*>(l), b );
585
586        b = myDestinationButton = new QPushButton;
587        b->setIcon( folderPixmap );
588        b->setStyleSheet( "text-align: left; padding-left: 5; padding-right: 5" );
589        connect( b, SIGNAL(clicked(bool)), this, SLOT(onDestinationClicked(void)) );
590        hig->addRow( tr( "Save to &Location:" ), b );
591
592    hig->addSectionDivider( );
593    hig->addSectionTitle( tr( "Limits" ) );
594
595        l = checkBoxNew( tr( "&Seed torrent until its ratio reaches:" ), Prefs::RATIO_ENABLED );
596        r = doubleSpinBoxNew( Prefs::RATIO, 0, INT_MAX, 0.5, 2 );
597        hig->addRow( l, r );
598        enableBuddyWhenChecked( qobject_cast<QCheckBox*>(l), r );
599
600    hig->finish( );
601    return hig;
602}
603
604/***
605****
606***/
607
608PrefsDialog :: PrefsDialog( Session& session, Prefs& prefs, QWidget * parent ):
609    QDialog( parent ),
610    myIsServer( session.isServer( ) ),
611    mySession( session ),
612    myPrefs( prefs ),
613    myLayout( new QVBoxLayout( this ) )
614{
615    setWindowTitle( tr( "Transmission Preferences" ) );
616
617    QTabWidget * t = new QTabWidget( this );
618    t->addTab( createTorrentsTab( ),     tr( "Torrents" ) );
619    t->addTab( createSpeedTab( ),        tr( "Speed" ) );
620    t->addTab( createPrivacyTab( ),      tr( "Privacy" ) );
621    t->addTab( createNetworkTab( ),      tr( "Network" ) );
622    t->addTab( createWebTab( session ),  tr( "Web" ) );
623    //t->addTab( createTrackerTab( ),    tr( "Trackers" ) );
624    myLayout->addWidget( t );
625
626    QDialogButtonBox * buttons = new QDialogButtonBox( QDialogButtonBox::Close, Qt::Horizontal, this );
627    connect( buttons, SIGNAL(rejected()), this, SLOT(close()) ); // "close" triggers rejected
628    myLayout->addWidget( buttons );
629    QWidget::setAttribute( Qt::WA_DeleteOnClose, true );
630
631    connect( &mySession, SIGNAL(sessionUpdated()), this, SLOT(sessionUpdated()));
632
633    QList<int> keys;
634    keys << Prefs :: RPC_ENABLED
635         << Prefs :: PROXY_ENABLED
636         << Prefs :: ALT_SPEED_LIMIT_ENABLED
637         << Prefs :: ALT_SPEED_LIMIT_TIME_ENABLED
638         << Prefs :: ENCRYPTION
639         << Prefs :: BLOCKLIST_ENABLED
640         << Prefs :: DIR_WATCH
641         << Prefs :: DOWNLOAD_DIR
642         << Prefs :: INCOMPLETE_DIR
643         << Prefs :: INCOMPLETE_DIR_ENABLED;
644    foreach( int key, keys )
645        updatePref( key );
646
647    // if it's a remote session, disable the preferences
648    // that don't work in remote sessions
649    if( !myIsServer )  {
650        foreach( QWidget * w, myUnsupportedWhenRemote ) {
651            w->setToolTip( tr( "Not supported by remote sessions" ) );
652            w->setEnabled( false );
653        }
654    }
655}
656
657PrefsDialog :: ~PrefsDialog( )
658{
659}
660
661/***
662****
663***/
664
665void
666PrefsDialog :: sessionUpdated( )
667{
668    updateBlocklistCheckBox( );
669}
670
671void
672PrefsDialog :: updateBlocklistCheckBox( )
673{
674    QCheckBox * box = qobject_cast<QCheckBox*>( myWidgets[Prefs::BLOCKLIST_ENABLED] );
675    const int n = mySession.blocklistSize( );
676    if( n < 0 ) // unknown
677        box->setText( tr( "Enable &blocklist" ) );
678    else
679        box->setText( tr( "Enable &blocklist (%Ln rules)", 0, n ) );
680}
681
682void
683PrefsDialog :: updatePref( int key )
684{
685    switch( key )
686    {
687        case Prefs :: RPC_ENABLED:
688        case Prefs :: RPC_WHITELIST_ENABLED:
689        case Prefs :: RPC_AUTH_REQUIRED: {
690            const bool enabled( myPrefs.getBool( Prefs::RPC_ENABLED ) );
691            const bool whitelist( myPrefs.getBool( Prefs::RPC_WHITELIST_ENABLED ) );
692            const bool auth( myPrefs.getBool( Prefs::RPC_AUTH_REQUIRED ) );
693            foreach( QWidget * w, myWebWhitelistWidgets ) w->setEnabled( enabled && whitelist );
694            foreach( QWidget * w, myWebAuthWidgets ) w->setEnabled( enabled && auth );
695            foreach( QWidget * w, myWebWidgets ) w->setEnabled( enabled );
696            break;
697        }
698
699        case Prefs :: PROXY_ENABLED:
700        case Prefs :: PROXY_AUTH_ENABLED: {
701            const bool enabled( myPrefs.getBool( Prefs::PROXY_ENABLED ) );
702            const bool auth( myPrefs.getBool( Prefs::PROXY_AUTH_ENABLED ) );
703            foreach( QWidget * w, myProxyAuthWidgets ) w->setEnabled( enabled && auth );
704            foreach( QWidget * w, myProxyWidgets ) w->setEnabled( enabled );
705            break;
706        }
707
708        case Prefs :: ALT_SPEED_LIMIT_TIME_ENABLED: {
709            const bool enabled = myPrefs.getBool( key );
710            foreach( QWidget * w, mySchedWidgets ) w->setEnabled( enabled );
711            break;
712        }
713
714        case Prefs :: BLOCKLIST_ENABLED: {
715            const bool enabled = myPrefs.getBool( key );
716            foreach( QWidget * w, myBlockWidgets ) w->setEnabled( enabled );
717            break;
718        }
719
720        case Prefs :: DIR_WATCH:
721            myWatchButton->setText( QFileInfo(myPrefs.getString(Prefs::DIR_WATCH)).fileName() );
722            break;
723
724        case Prefs :: PEER_PORT:
725            myPortLabel->setText( tr( "Status unknown" ) );
726            myPortButton->setEnabled( true );
727            break;
728
729        case Prefs :: DOWNLOAD_DIR: {
730            QString path( myPrefs.getString( key ) );
731            myDestinationButton->setText( QFileInfo(path).fileName() );
732            break;
733        }
734
735        case Prefs :: INCOMPLETE_DIR: {
736            QString path( myPrefs.getString( key ) );
737            myIncompleteButton->setText( QFileInfo(path).fileName() );
738            break;
739        }
740
741        case Prefs :: INCOMPLETE_DIR_ENABLED: {
742            const bool enabled = myPrefs.getBool( key );
743            myIncompleteButton->setEnabled( enabled );
744            break;
745        }
746
747        default:
748            break;
749    }
750
751    key2widget_t::iterator it( myWidgets.find( key ) );
752    if( it != myWidgets.end( ) )
753    {
754        QWidget * w( it.value( ) );
755        QCheckBox * checkBox;
756        QSpinBox * spin;
757        QDoubleSpinBox * doubleSpin;
758        QTimeEdit * timeEdit;
759        QLineEdit * lineEdit;
760
761        if(( checkBox = qobject_cast<QCheckBox*>(w)))
762        {
763            checkBox->setChecked( myPrefs.getBool( key ) );
764        }
765        else if(( spin = qobject_cast<QSpinBox*>(w)))
766        {
767            spin->setValue( myPrefs.getInt( key ) );
768        }
769        else if(( doubleSpin = qobject_cast<QDoubleSpinBox*>(w)))
770        {
771            doubleSpin->setValue( myPrefs.getDouble( key ) );
772        }
773        else if(( timeEdit = qobject_cast<QTimeEdit*>(w)))
774        {
775            const int minutes( myPrefs.getInt( key ) );
776            timeEdit->setTime( QTime().addSecs( minutes * 60 ) );
777        }
778        else if(( lineEdit = qobject_cast<QLineEdit*>(w)))
779        {
780            lineEdit->setText( myPrefs.getString( key ) );
781        }
782        else if( key == Prefs::ENCRYPTION )
783        {
784            QComboBox * comboBox( qobject_cast<QComboBox*>( w ) );
785            const int index = comboBox->findData( myPrefs.getInt( key ) );
786            comboBox->setCurrentIndex( index );
787        }
788    }
789}
790
791bool
792PrefsDialog :: isAllowed( int key ) const
793{
794    Q_UNUSED( key );
795
796    return true;
797}
Note: See TracBrowser for help on using the repository browser.