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

Last change on this file since 14329 was 14329, checked in by jordan, 8 years ago

(trunk, qt) #5774 'Alternative Speed Limits Scheduled Times broken in transmission-qt' -- fixed, plus more gratuitous c++11isms

  • Property svn:keywords set to Date Rev Author Id
File size: 25.9 KB
Line 
1/*
2 * This file Copyright (C) 2009-2014 Mnemosyne LLC
3 *
4 * It may be used under the GNU Public License v2 or v3 licenses,
5 * or any future license endorsed by Mnemosyne LLC.
6 *
7 * $Id: prefs-dialog.cc 14329 2014-08-26 23:26:00Z jordan $
8 */
9
10#include <cassert>
11#include <climits> /* INT_MAX */
12#include <iostream>
13
14#include <QCheckBox>
15#include <QComboBox>
16#include <QCoreApplication>
17#include <QDialogButtonBox>
18#include <QDoubleSpinBox>
19#include <QFileIconProvider>
20#include <QFileInfo>
21#include <QHBoxLayout>
22#include <QIcon>
23#include <QLabel>
24#include <QLineEdit>
25#include <QList>
26#include <QMessageBox>
27#include <QPushButton>
28#include <QSpinBox>
29#include <QStyle>
30#include <QTabWidget>
31#include <QTime>
32#include <QTimeEdit>
33#include <QTimer>
34#include <QVBoxLayout>
35
36#include "freespace-label.h"
37#include "formatter.h"
38#include "hig.h"
39#include "prefs.h"
40#include "prefs-dialog.h"
41#include "session.h"
42#include "utils.h"
43
44/***
45****
46***/
47
48namespace
49{
50  const char * PREF_KEY ("pref-key");
51};
52
53void
54PrefsDialog :: checkBoxToggled (bool checked)
55{
56  const int key (sender ()->property (PREF_KEY).toInt ());
57  setPref (key, checked);
58}
59
60QCheckBox *
61PrefsDialog :: checkBoxNew (const QString& text, int key)
62{
63  QCheckBox * box = new QCheckBox (text);
64  box->setChecked (myPrefs.getBool (key));
65  box->setProperty (PREF_KEY, key);
66  connect (box, SIGNAL(toggled(bool)), this, SLOT(checkBoxToggled(bool)));
67  myWidgets.insert (key, box);
68  return box;
69}
70
71void
72PrefsDialog :: enableBuddyWhenChecked (QCheckBox * box, QWidget * buddy)
73{
74  connect (box, SIGNAL(toggled(bool)), buddy, SLOT(setEnabled(bool)));
75  buddy->setEnabled (box->isChecked ());
76}
77
78void
79PrefsDialog :: spinBoxEditingFinished()
80{
81  const QObject * spin = sender();
82  const int key = spin->property (PREF_KEY).toInt ();
83  const QDoubleSpinBox * d = qobject_cast<const QDoubleSpinBox*> (spin);
84
85  if (d)
86    setPref (key, d->value ());
87  else
88    setPref (key, qobject_cast<const QSpinBox*>(spin)->value ());
89}
90
91QSpinBox *
92PrefsDialog :: spinBoxNew (int key, int low, int high, int step)
93{
94  QSpinBox * spin = new QSpinBox ();
95  spin->setRange (low, high);
96  spin->setSingleStep (step);
97  spin->setValue (myPrefs.getInt (key));
98  spin->setProperty (PREF_KEY, key);
99  connect (spin, SIGNAL(editingFinished()), this, SLOT(spinBoxEditingFinished()));
100  myWidgets.insert (key, spin);
101  return spin;
102}
103
104QDoubleSpinBox *
105PrefsDialog :: doubleSpinBoxNew (int key, double low, double high, double step, int decimals)
106{
107  QDoubleSpinBox * spin = new QDoubleSpinBox ();
108  spin->setRange (low, high);
109  spin->setSingleStep (step);
110  spin->setDecimals (decimals);
111  spin->setValue (myPrefs.getDouble (key));
112  spin->setProperty (PREF_KEY, key);
113  connect (spin, SIGNAL(editingFinished()), this, SLOT(spinBoxEditingFinished()));
114  myWidgets.insert (key, spin);
115  return spin;
116}
117
118void
119PrefsDialog::timeEditingFinished()
120{
121  auto e = qobject_cast<QTimeEdit*>(sender());
122  if (e != nullptr)
123    {
124      const int key {e->property(PREF_KEY).toInt()};
125      const QTime t {e->time()};
126      const int minutes_after_midnight {t.hour()*60 + t.minute()};
127      setPref(key, minutes_after_midnight);
128    }
129}
130
131QTimeEdit*
132PrefsDialog::timeEditNew (int key)
133{
134  const int minutes {myPrefs.getInt(key)};
135  auto e = new QTimeEdit{};
136  e->setDisplayFormat(QString::fromUtf8("hh:mm"));
137  e->setProperty(PREF_KEY, key);
138  e->setTime(QTime{minutes/60, minutes%60});
139  myWidgets.insert(key, e);
140  connect(e, SIGNAL(editingFinished()), this, SLOT(timeEditingFinished()));
141  return e;
142}
143
144void
145PrefsDialog :: lineEditingFinished ()
146{
147  QLineEdit * e = qobject_cast<QLineEdit*>(sender());
148  if (e && e->isModified ())
149    {
150      const int key (e->property (PREF_KEY).toInt ());
151      const QString text (e->text());
152      setPref (key, text);
153    }
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 :: createRemoteTab (Session& session)
173{
174  HIG * hig = new HIG (this);
175  hig->addSectionTitle (tr ("Remote Control"));
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 ("Allow &remote access"), Prefs::RPC_ENABLED);
182  myUnsupportedWhenRemote << l;
183  hig->addRow (l, h, 0);
184  l = hig->addRow (tr ("HTTP &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:"), 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 ("&Upload (%1):").arg (speed_K_str), Prefs::USPEED_ENABLED);
222    r = spinBoxNew (Prefs::USPEED, 0, INT_MAX, 5);
223    hig->addRow (l, r);
224    enableBuddyWhenChecked (qobject_cast<QCheckBox*>(l), r);
225
226    l = checkBoxNew (tr ("&Download (%1):").arg (speed_K_str), Prefs::DSPEED_ENABLED);
227    r = spinBoxNew (Prefs::DSPEED, 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 (QString::fromUtf8 (":/icons/alt-limit-off.png")));
236  label->setAlignment (Qt::AlignLeft|Qt::AlignVCenter);
237  h->addWidget (label);
238  label = new QLabel (tr ("Alternative Speed Limits"));
239  label->setStyleSheet (QString::fromUtf8 ("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 ("U&pload (%1):").arg (speed_K_str);
248    r = spinBoxNew (Prefs :: ALT_SPEED_LIMIT_UP, 0, INT_MAX, 5);
249    hig->addRow (s, r);
250
251    s = tr ("Do&wnload (%1):").arg (speed_K_str);
252    r = spinBoxNew (Prefs :: ALT_SPEED_LIMIT_DOWN, 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 ("Start &minimized in notification area"), Prefs::START_MINIMIZED));
304
305  hig->addSectionDivider ();
306  hig->addSectionTitle (tr ("Notification"));
307
308    hig->addWideControl (checkBoxNew (tr ("Show a notification when torrents are a&dded"), Prefs::SHOW_NOTIFICATION_ON_ADD));
309    hig->addWideControl (checkBoxNew (tr ("Show a notification when torrents &finish"), Prefs::SHOW_NOTIFICATION_ON_COMPLETE));
310    hig->addWideControl (checkBoxNew (tr ("Play a &sound when torrents finish"), Prefs::COMPLETE_SOUND_ENABLED));
311
312  hig->finish ();
313  return hig;
314}
315
316/***
317****
318***/
319
320void
321PrefsDialog :: onPortTested (bool isOpen)
322{
323  myPortButton->setEnabled (true);
324  myWidgets[Prefs::PEER_PORT]->setEnabled (true);
325  myPortLabel->setText (isOpen ? tr ("Port is <b>open</b>")
326                               : tr ("Port is <b>closed</b>"));
327}
328
329void
330PrefsDialog :: onPortTest ()
331{
332  myPortLabel->setText (tr ("Testing TCP Port..."));
333  myPortButton->setEnabled (false);
334  myWidgets[Prefs::PEER_PORT]->setEnabled (false);
335  mySession.portTest ();
336}
337
338QWidget *
339PrefsDialog :: createNetworkTab ()
340{
341  HIG * hig = new HIG (this);
342  hig->addSectionTitle (tr ("Incoming Peers"));
343
344  QSpinBox * s = spinBoxNew (Prefs::PEER_PORT, 1, 65535, 1);
345  QHBoxLayout * h = new QHBoxLayout ();
346  QPushButton * b = myPortButton = new QPushButton (tr ("Te&st Port"));
347  QLabel * l = myPortLabel = new QLabel (tr ("Status unknown"));
348  h->addWidget (l);
349  h->addSpacing (HIG :: PAD_BIG);
350  h->addWidget (b);
351  h->setStretchFactor (l, 1);
352  connect (b, SIGNAL(clicked(bool)), this, SLOT(onPortTest()));
353  connect (&mySession, SIGNAL(portTested(bool)), this, SLOT(onPortTested(bool)));
354
355  hig->addRow (tr ("&Port for incoming connections:"), s);
356  hig->addRow (QString(), h, 0);
357  hig->addWideControl (checkBoxNew (tr ("Pick a &random port every time Transmission is started"), Prefs :: PEER_PORT_RANDOM_ON_START));
358  hig->addWideControl (checkBoxNew (tr ("Use UPnP or NAT-PMP port &forwarding from my router"), Prefs::PORT_FORWARDING));
359
360  hig->addSectionDivider ();
361  hig->addSectionTitle (tr ("Peer Limits"));
362  hig->addRow (tr ("Maximum peers per &torrent:"), spinBoxNew (Prefs::PEER_LIMIT_TORRENT, 1, FD_SETSIZE, 5));
363  hig->addRow (tr ("Maximum peers &overall:"), spinBoxNew (Prefs::PEER_LIMIT_GLOBAL, 1, FD_SETSIZE, 5));
364
365  hig->addSectionDivider ();
366  hig->addSectionTitle (tr ("Options"));
367
368  QWidget * w;
369  hig->addWideControl (w = checkBoxNew (tr ("Enable &uTP for peer connections"), Prefs::UTP_ENABLED));
370  w->setToolTip (tr ("uTP is a tool for reducing network congestion."));
371  hig->addWideControl (w = checkBoxNew (tr ("Use PE&X to find more peers"), Prefs::PEX_ENABLED));
372  w->setToolTip (tr ("PEX is a tool for exchanging peer lists with the peers you're connected to."));
373  hig->addWideControl (w = checkBoxNew (tr ("Use &DHT to find more peers"), Prefs::DHT_ENABLED));
374  w->setToolTip (tr ("DHT is a tool for finding peers without a tracker."));
375  hig->addWideControl (w = checkBoxNew (tr ("Use &Local Peer Discovery to find more peers"), Prefs::LPD_ENABLED));
376  w->setToolTip (tr ("LPD is a tool for finding peers on your local network."));
377
378  hig->finish ();
379  return hig;
380}
381
382/***
383****
384***/
385
386void
387PrefsDialog :: onBlocklistDialogDestroyed (QObject * o)
388{
389  Q_UNUSED (o);
390
391  myBlocklistDialog = 0;
392}
393
394void
395PrefsDialog :: onUpdateBlocklistCancelled ()
396{
397  disconnect (&mySession, SIGNAL(blocklistUpdated(int)), this, SLOT(onBlocklistUpdated(int)));
398  myBlocklistDialog->deleteLater ();
399}
400
401void
402PrefsDialog :: onBlocklistUpdated (int n)
403{
404  myBlocklistDialog->setText (tr ("<b>Update succeeded!</b><p>Blocklist now has %Ln rules.", 0, n));
405  myBlocklistDialog->setTextFormat (Qt::RichText);
406}
407
408void
409PrefsDialog :: onUpdateBlocklistClicked ()
410{
411  myBlocklistDialog = new QMessageBox (QMessageBox::Information,
412                                       QString(),
413                                       tr ("<b>Update Blocklist</b><p>Getting new blocklist..."),
414                                       QMessageBox::Close,
415                                       this);
416  connect (myBlocklistDialog, SIGNAL(rejected()), this, SLOT(onUpdateBlocklistCancelled()));
417  connect (&mySession, SIGNAL(blocklistUpdated(int)), this, SLOT(onBlocklistUpdated(int)));
418  myBlocklistDialog->show ();
419  mySession.updateBlocklist ();
420}
421
422void
423PrefsDialog :: encryptionEdited (int i)
424{
425  const int value (qobject_cast<QComboBox*>(sender())->itemData(i).toInt ());
426  setPref (Prefs::ENCRYPTION, value);
427}
428
429QWidget *
430PrefsDialog :: createPrivacyTab ()
431{
432  QWidget * w;
433  HIG * hig = new HIG (this);
434
435  hig->addSectionTitle (tr ("Encryption"));
436
437  QComboBox * box = new QComboBox ();
438  box->addItem (tr ("Allow encryption"), 0);
439  box->addItem (tr ("Prefer encryption"), 1);
440  box->addItem (tr ("Require encryption"), 2);
441  myWidgets.insert (Prefs :: ENCRYPTION, box);
442  connect (box, SIGNAL(activated(int)), this, SLOT(encryptionEdited(int)));
443
444  hig->addRow (tr ("&Encryption mode:"), box);
445
446  hig->addSectionDivider ();
447  hig->addSectionTitle (tr ("Blocklist"));
448
449  QWidget * l = checkBoxNew (tr("Enable &blocklist:"), Prefs::BLOCKLIST_ENABLED);
450  QWidget * e = lineEditNew (Prefs::BLOCKLIST_URL);
451  myBlockWidgets << e;
452  hig->addRow (l, e);
453
454  l = myBlocklistLabel = new QLabel ();
455  myBlockWidgets << l;
456  w = new QPushButton (tr ("&Update"));
457  connect (w, SIGNAL(clicked(bool)), this, SLOT(onUpdateBlocklistClicked()));
458  myBlockWidgets << w;
459  QHBoxLayout * h = new QHBoxLayout ();
460  h->addWidget (l);
461  h->addStretch (1);
462  h->addWidget (w);
463  hig->addWideControl (h);
464
465  l = checkBoxNew (tr ("Enable &automatic updates"), Prefs::BLOCKLIST_UPDATES_ENABLED);
466  myBlockWidgets << l;
467  hig->addWideControl (l);
468
469  hig->finish ();
470  updateBlocklistLabel ();
471  return hig;
472}
473
474/***
475****
476***/
477
478void
479PrefsDialog :: onScriptClicked (void)
480{
481  const QString title = tr ("Select \"Torrent Done\" Script");
482  const QString myPath = myPrefs.getString (Prefs::SCRIPT_TORRENT_DONE_FILENAME);
483  const QString path = Utils::remoteFileChooser (this, title, myPath, false, mySession.isServer());
484
485  if (!path.isEmpty())
486    onLocationSelected (path, Prefs::SCRIPT_TORRENT_DONE_FILENAME);
487}
488
489void
490PrefsDialog :: onIncompleteClicked (void)
491{
492  const QString title = tr ("Select Incomplete Directory");
493  const QString myPath = myPrefs.getString (Prefs::INCOMPLETE_DIR);
494  const QString path = Utils::remoteFileChooser (this, title, myPath, true, mySession.isServer());
495
496  if (!path.isEmpty())
497    onLocationSelected (path, Prefs::INCOMPLETE_DIR);
498}
499
500void
501PrefsDialog :: onWatchClicked (void)
502{
503  const QString title = tr ("Select Watch Directory");
504  const QString myPath = myPrefs.getString (Prefs::DIR_WATCH);
505  const QString path = Utils::remoteFileChooser (this, title, myPath, true, true);
506
507  if (!path.isEmpty())
508    onLocationSelected (path, Prefs::DIR_WATCH);
509}
510
511void
512PrefsDialog :: onDestinationClicked (void)
513{
514  const QString title = tr ("Select Destination");
515  const QString myPath = myPrefs.getString (Prefs::DOWNLOAD_DIR);
516  const QString path = Utils::remoteFileChooser (this, title, myPath, true, mySession.isServer());
517
518  if (!path.isEmpty())
519    onLocationSelected (path, Prefs::DOWNLOAD_DIR);
520}
521
522void
523PrefsDialog :: onLocationSelected (const QString& path, int key)
524{
525  setPref (key, path);
526}
527
528QWidget *
529PrefsDialog :: createSeedingTab ()
530{
531  const int iconSize (style ()->pixelMetric (QStyle :: PM_SmallIconSize));
532  const QFileIconProvider iconProvider;
533  const QIcon folderIcon = iconProvider.icon (QFileIconProvider::Folder);
534  const QPixmap folderPixmap = folderIcon.pixmap (iconSize);
535  const QIcon fileIcon = iconProvider.icon (QFileIconProvider::File);
536  const QPixmap filePixmap = fileIcon.pixmap (iconSize);
537
538  QWidget *l, *r;
539  HIG * hig = new HIG (this);
540  hig->addSectionTitle (tr ("Limits"));
541
542    l = checkBoxNew (tr ("Stop seeding at &ratio:"), Prefs::RATIO_ENABLED);
543    r = doubleSpinBoxNew (Prefs::RATIO, 0, INT_MAX, 0.5, 2);
544    hig->addRow (l, r);
545    enableBuddyWhenChecked (qobject_cast<QCheckBox*>(l), r);
546
547    l = checkBoxNew (tr ("Stop seeding if idle for &N minutes:"), Prefs::IDLE_LIMIT_ENABLED);
548    r = spinBoxNew (Prefs::IDLE_LIMIT, 1, INT_MAX, 5);
549    hig->addRow (l, r);
550    enableBuddyWhenChecked (qobject_cast<QCheckBox*>(l), r);
551
552  hig->finish ();
553  return hig;
554}
555
556QWidget *
557PrefsDialog :: createDownloadingTab ()
558{
559  const int iconSize (style ()->pixelMetric (QStyle :: PM_SmallIconSize));
560  const QFileIconProvider iconProvider;
561  const QIcon folderIcon = iconProvider.icon (QFileIconProvider::Folder);
562  const QPixmap folderPixmap = folderIcon.pixmap (iconSize);
563  const QIcon fileIcon = iconProvider.icon (QFileIconProvider::File);
564  const QPixmap filePixmap = fileIcon.pixmap (iconSize);
565
566  QWidget * l;
567  QPushButton * b;
568  HIG * hig = new HIG (this);
569  hig->addSectionTitle (tr ("Adding"));
570
571    l = checkBoxNew (tr ("Automatically add .torrent files &from:"), Prefs::DIR_WATCH_ENABLED);
572    b = myWatchButton = new QPushButton;
573    b->setIcon (folderPixmap);
574    b->setStyleSheet (QString::fromUtf8 ("text-align: left; padding-left: 5; padding-right: 5"));
575    connect (b, SIGNAL(clicked(bool)), this, SLOT(onWatchClicked(void)));
576    hig->addRow (l, b);
577    enableBuddyWhenChecked (qobject_cast<QCheckBox*>(l), b);
578
579    hig->addWideControl (checkBoxNew (tr ("Show the Torrent Options &dialog"), Prefs::OPTIONS_PROMPT));
580
581    hig->addWideControl (checkBoxNew (tr ("&Start added torrents"), Prefs::START));
582
583    hig->addWideControl (checkBoxNew (tr ("Mo&ve the .torrent file to the trash"), Prefs::TRASH_ORIGINAL));
584
585    b = myDestinationButton = new QPushButton;
586    b->setIcon (folderPixmap);
587    b->setStyleSheet (QString::fromUtf8 ("text-align: left; padding-left: 5; padding-right: 5"));
588    connect (b, SIGNAL(clicked(bool)), this, SLOT(onDestinationClicked(void)));
589    hig->addRow (tr ("Save to &Location:"), b);
590
591    const QString downloadDir (myPrefs.getString(Prefs::DOWNLOAD_DIR));
592    l = myFreespaceLabel = new FreespaceLabel (mySession, downloadDir, this);
593    QHBoxLayout * h = new QHBoxLayout ();
594    h->addStretch (1);
595    h->addWidget (l);
596    hig->addWideControl (h);
597
598  hig->addSectionDivider ();
599  hig->addSectionTitle (tr ("Download Queue"));
600   
601    hig->addRow (tr ("Ma&ximum active downloads:"), spinBoxNew (Prefs::DOWNLOAD_QUEUE_SIZE, 1, INT_MAX, 1));
602    hig->addRow (tr ("Downloads sharing data in the last &N minutes are active:"), spinBoxNew (Prefs::QUEUE_STALLED_MINUTES, 1, INT_MAX, 10));
603
604  hig->addSectionDivider ();
605  hig->addSectionTitle (tr ("Incomplete"));
606
607    hig->addWideControl (checkBoxNew (tr ("Append \".&part\" to incomplete files' names"), Prefs::RENAME_PARTIAL_FILES));
608
609    l = myIncompleteCheckbox = checkBoxNew (tr ("Keep &incomplete files in:"), Prefs::INCOMPLETE_DIR_ENABLED);
610    b = myIncompleteButton = new QPushButton;
611    b->setIcon (folderPixmap);
612    b->setStyleSheet (QString::fromUtf8 ("text-align: left; padding-left: 5; padding-right: 5"));
613    connect (b, SIGNAL(clicked(bool)), this, SLOT(onIncompleteClicked(void)));
614    hig->addRow (myIncompleteCheckbox, b);
615    enableBuddyWhenChecked (qobject_cast<QCheckBox*>(l), b);
616
617    l = myTorrentDoneScriptCheckbox = checkBoxNew (tr ("Call scrip&t when torrent is completed:"), Prefs::SCRIPT_TORRENT_DONE_ENABLED);
618    b = myTorrentDoneScriptButton = new QPushButton;
619    b->setIcon (filePixmap);
620    b->setStyleSheet (QString::fromUtf8 ("text-align: left; padding-left: 5; padding-right: 5"));
621    connect (b, SIGNAL(clicked(bool)), this, SLOT(onScriptClicked(void)));
622    hig->addRow (myTorrentDoneScriptCheckbox, b);
623    enableBuddyWhenChecked (qobject_cast<QCheckBox*>(l), b);
624
625  hig->finish ();
626  return hig;
627}
628
629/***
630****
631***/
632
633PrefsDialog :: PrefsDialog (Session& session, Prefs& prefs, QWidget * parent):
634  QDialog (parent),
635  myIsServer (session.isServer ()),
636  mySession (session),
637  myPrefs (prefs),
638  myLayout (new QVBoxLayout (this))
639{
640  setWindowTitle (tr ("Transmission Preferences"));
641
642  QTabWidget * t = new QTabWidget (this);
643  t->addTab (createSpeedTab (),        tr ("Speed"));
644  t->addTab (createDownloadingTab (),  tr ("Downloading"));
645  t->addTab (createSeedingTab (),      tr ("Seeding"));
646  t->addTab (createPrivacyTab (),      tr ("Privacy"));
647  t->addTab (createNetworkTab (),      tr ("Network"));
648  t->addTab (createDesktopTab (),      tr ("Desktop"));
649  t->addTab (createRemoteTab(session), tr ("Remote"));
650  myLayout->addWidget (t);
651
652  QDialogButtonBox * buttons = new QDialogButtonBox (QDialogButtonBox::Close, Qt::Horizontal, this);
653  connect (buttons, SIGNAL(rejected()), this, SLOT(close())); // "close" triggers rejected
654  myLayout->addWidget (buttons);
655  QWidget::setAttribute (Qt::WA_DeleteOnClose, true);
656
657  connect (&mySession, SIGNAL(sessionUpdated()), this, SLOT(sessionUpdated()));
658
659  QList<int> keys;
660  keys << Prefs :: RPC_ENABLED
661       << Prefs :: ALT_SPEED_LIMIT_ENABLED
662       << Prefs :: ALT_SPEED_LIMIT_TIME_ENABLED
663       << Prefs :: ENCRYPTION
664       << Prefs :: BLOCKLIST_ENABLED
665       << Prefs :: DIR_WATCH
666       << Prefs :: DOWNLOAD_DIR
667       << Prefs :: INCOMPLETE_DIR
668       << Prefs :: INCOMPLETE_DIR_ENABLED
669       << Prefs :: SCRIPT_TORRENT_DONE_FILENAME;
670  foreach (int key, keys)
671    refreshPref (key);
672
673  // if it's a remote session, disable the preferences
674  // that don't work in remote sessions
675  if (!myIsServer)
676    {
677      foreach (QWidget * w, myUnsupportedWhenRemote)
678        {
679          w->setToolTip (tr ("Not supported by remote sessions"));
680          w->setEnabled (false);
681        }
682    }
683}
684
685PrefsDialog :: ~PrefsDialog ()
686{
687}
688
689void
690PrefsDialog :: setPref (int key, const QVariant& v)
691{
692  myPrefs.set (key, v);
693  refreshPref (key);
694}
695
696/***
697****
698***/
699
700void
701PrefsDialog :: sessionUpdated ()
702{
703  updateBlocklistLabel ();
704}
705
706void
707PrefsDialog :: updateBlocklistLabel ()
708{
709  const int n = mySession.blocklistSize ();
710  myBlocklistLabel->setText (tr ("<i>Blocklist contains %Ln rules</i>", 0, n));
711}
712
713void
714PrefsDialog :: refreshPref (int key)
715{
716  switch (key)
717    {
718      case Prefs :: RPC_ENABLED:
719      case Prefs :: RPC_WHITELIST_ENABLED:
720      case Prefs :: RPC_AUTH_REQUIRED:
721        {
722          const bool enabled (myPrefs.getBool (Prefs::RPC_ENABLED));
723          const bool whitelist (myPrefs.getBool (Prefs::RPC_WHITELIST_ENABLED));
724          const bool auth (myPrefs.getBool (Prefs::RPC_AUTH_REQUIRED));
725          foreach (QWidget * w, myWebWhitelistWidgets)w->setEnabled (enabled && whitelist);
726          foreach (QWidget * w, myWebAuthWidgets)w->setEnabled (enabled && auth);
727          foreach (QWidget * w, myWebWidgets)w->setEnabled (enabled);
728          break;
729        }
730
731      case Prefs :: ALT_SPEED_LIMIT_TIME_ENABLED:
732        {
733          const bool enabled = myPrefs.getBool (key);
734          foreach (QWidget * w, mySchedWidgets)w->setEnabled (enabled);
735          break;
736        }
737
738      case Prefs :: BLOCKLIST_ENABLED:
739        {
740          const bool enabled = myPrefs.getBool (key);
741          foreach (QWidget * w, myBlockWidgets)w->setEnabled (enabled);
742          break;
743        }
744
745      case Prefs :: DIR_WATCH:
746        myWatchButton->setText (QFileInfo(myPrefs.getString(Prefs::DIR_WATCH)).fileName());
747        break;
748
749      case Prefs :: SCRIPT_TORRENT_DONE_FILENAME:
750        {
751          const QString path (myPrefs.getString (key));
752          myTorrentDoneScriptButton->setText (QFileInfo(path).fileName());
753          break;
754        }
755
756      case Prefs :: PEER_PORT:
757        myPortLabel->setText (tr ("Status unknown"));
758        myPortButton->setEnabled (true);
759        break;
760
761      case Prefs :: DOWNLOAD_DIR:
762        {
763          const QString path (myPrefs.getString (key));
764          myDestinationButton->setText (QFileInfo(path).fileName());
765          myFreespaceLabel->setPath (path);
766          break;
767        }
768
769      case Prefs :: INCOMPLETE_DIR:
770        {
771          QString path (myPrefs.getString (key));
772          myIncompleteButton->setText (QFileInfo(path).fileName());
773          break;
774        }
775
776      case Prefs :: INCOMPLETE_DIR_ENABLED:
777        {
778          const bool enabled = myPrefs.getBool (key);
779          myIncompleteButton->setEnabled (enabled);
780          break;
781        }
782
783      default:
784        break;
785    }
786
787  key2widget_t::iterator it (myWidgets.find (key));
788  if (it != myWidgets.end ())
789    {
790      QWidget * w (it.value ());
791      QCheckBox * checkBox;
792      QSpinBox * spin;
793      QDoubleSpinBox * doubleSpin;
794      QTimeEdit * timeEdit;
795      QLineEdit * lineEdit;
796
797      if ((checkBox = qobject_cast<QCheckBox*>(w)))
798        {
799          checkBox->setChecked (myPrefs.getBool (key));
800        }
801      else if ((spin = qobject_cast<QSpinBox*>(w)))
802        {
803          spin->setValue (myPrefs.getInt (key));
804        }
805      else if ((doubleSpin = qobject_cast<QDoubleSpinBox*>(w)))
806        {
807          doubleSpin->setValue (myPrefs.getDouble (key));
808        }
809      else if ((timeEdit = qobject_cast<QTimeEdit*>(w)))
810        {
811          const int minutes (myPrefs.getInt (key));
812          timeEdit->setTime (QTime().addSecs (minutes * 60));
813        }
814      else if ((lineEdit = qobject_cast<QLineEdit*>(w)))
815        {
816          lineEdit->setText (myPrefs.getString (key));
817        }
818      else if (key == Prefs::ENCRYPTION)
819        {
820          QComboBox * comboBox (qobject_cast<QComboBox*> (w));
821          const int index = comboBox->findData (myPrefs.getInt (key));
822          comboBox->setCurrentIndex (index);
823        }
824    }
825}
826
827bool
828PrefsDialog :: isAllowed (int key) const
829{
830  Q_UNUSED (key);
831
832  return true;
833}
Note: See TracBrowser for help on using the repository browser.