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

Last change on this file since 12550 was 12550, checked in by jordan, 10 years ago

(trunk gtk, qt) "It is unobvious if test port feature tests UDP port status as well" -- fixed.

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