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

Last change on this file since 13991 was 13991, checked in by jordan, 9 years ago

(trunk) first draft of changing the FreeSpace? API to behave as https://trac.transmissionbt.com/ticket/4076#comment:25 -- libT, rpc, qt, and gtk implementations.

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