Vidalia  0.3.1
ConfigDialog.cpp
Go to the documentation of this file.
1 /*
2 ** This file is part of Vidalia, and is subject to the license terms in the
3 ** LICENSE file, found in the top level directory of this distribution. If you
4 ** did not receive the LICENSE file with this file, you may obtain it from the
5 ** Vidalia source package distributed by the Vidalia Project at
6 ** http://www.torproject.org/projects/vidalia.html. No part of Vidalia,
7 ** including this file, may be copied, modified, propagated, or distributed
8 ** except according to the terms described in the LICENSE file.
9 */
10 
11 /*
12 ** \file ConfigDialog.cpp
13 ** \brief Contains a series of Vidalia and Tor configuration pages
14 */
15 
16 #include "ConfigDialog.h"
17 #include "GeneralPage.h"
18 #include "NetworkPage.h"
19 #include "ServerPage.h"
20 #include "AdvancedPage.h"
21 #include "AppearancePage.h"
22 #include "ServicePage.h"
23 #include "VMessageBox.h"
24 #include "ServerSettings.h"
25 #include "NetworkSettings.h"
26 #include "Vidalia.h"
27 
28 #include "html.h"
29 
30 
31 /* Images for toolbar icons */
32 #define IMAGE_GENERAL ":/images/32x32/preferences-system.png"
33 #define IMAGE_NETWORK ":/images/32x32/preferences-system-network.png"
34 #define IMAGE_SERVER ":/images/32x32/preferences-system-network-sharing.png"
35 #define IMAGE_APPEARANCE ":/images/32x32/preferences-desktop-locale.png"
36 #define IMAGE_ADVANCED ":/images/32x32/applications-system.png"
37 #define IMAGE_HELP ":/images/32x32/system-help.png"
38 #define IMAGE_SERVICE ":/images/32x32/services.png"
39 
40 
41 /** Constructor */
43 : VidaliaWindow("ConfigDialog", parent)
44 {
45  /* Invoke the Qt Designer generated QObject setup routine */
46  ui.setupUi(this);
47 
48  /* Override the QDialogButtonBox button text so we can use our own
49  * translations. */
50  QPushButton *button = ui.buttonBox->button(QDialogButtonBox::Ok);
51  if (button) {
52  Vidalia::createShortcut(QKeySequence(Qt::Key_Return),
53  this, button, SLOT(click()));
54  }
55  button = ui.buttonBox->button(QDialogButtonBox::Cancel);
56  if (button) {
57  Vidalia::createShortcut("Esc", this, button, SLOT(click()));
58  Vidalia::createShortcut("Ctrl+W", this, button, SLOT(click()));
59  }
60 
61  /* Connect the button box signals to the appropriate slots */
62  connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(saveChanges()));
63  connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(close()));
64  connect(ui.buttonBox, SIGNAL(helpRequested()), this, SLOT(help()));
65  connect(Vidalia::torControl(), SIGNAL(authenticated()),
66  this, SLOT(applyChanges()));
67 
68  /* Used to connect restartTor signals */
69  AdvancedPage *advancedPage;
70  /* Create the config pages and actions */
71  QActionGroup *grp = new QActionGroup(this);
72  GeneralPage *generalPage = new GeneralPage(ui.stackPages);
73  ui.stackPages->add(generalPage,
75  tr("General"), "General", grp));
76  connect(generalPage, SIGNAL(checkForUpdates()),
77  this, SLOT(onCheckForUpdates()));
78 
79  ui.stackPages->add(new NetworkPage(ui.stackPages),
81  tr("Network"), "Network", grp));
82 
83  ui.stackPages->add(new ServerPage(ui.stackPages),
85  tr("Sharing"), "Sharing", grp));
86 
87  ui.stackPages->add(new ServicePage(ui.stackPages),
89  tr("Services"), "Services", grp));
90 
91  ui.stackPages->add(new AppearancePage(ui.stackPages),
93  tr("Appearance"), "Appearance", grp));
94 
95  ui.stackPages->add(advancedPage = new AdvancedPage(ui.stackPages),
97  tr("Advanced"), "Advanced", grp));
98 
99  connect(advancedPage, SIGNAL(restartTor()), this, SIGNAL(restartTor()));
100 
101  foreach (ConfigPage *page, ui.stackPages->pages()) {
102  connect(page, SIGNAL(helpRequested(QString)),
103  this, SLOT(help(QString)));
104  }
105 
106  /* Create the toolbar */
107  ui.toolBar->addActions(grp->actions());
108  ui.toolBar->addSeparator();
109  connect(grp, SIGNAL(triggered(QAction *)),
110  ui.stackPages, SLOT(showPage(QAction *)));
111 
112  /* Create and bind the Help button */
113  QAction *helpAct = new QAction(QIcon(IMAGE_HELP), tr("Help"), ui.toolBar);
114  helpAct->setData("Help");
115  addAction(helpAct, SLOT(help()));
116 
117  /* Select the first action */
118  grp->actions()[0]->setChecked(true);
119 
120 #if defined(Q_WS_WIN)
121  helpAct->setShortcut(QString("F1"));
122 #else
123  helpAct->setShortcut(QString("Ctrl+?"));
124 #endif
125 }
126 
127 /** Creates a new action associated with a config page. */
128 QAction*
129 ConfigDialog::createPageAction(const QIcon &img, const QString &text,
130  const QString &data, QActionGroup *group)
131 {
132  QAction *action = new QAction(img, text, group);
133  action->setData(data);
134  action->setCheckable(true);
135  return action;
136 }
137 
138 /** Adds the given action to the toolbar and hooks its triggered() signal to
139  * the specified slot (if given). */
140 void
141 ConfigDialog::addAction(QAction *action, const char *slot)
142 {
143  ui.toolBar->addAction(action);
144  connect(action, SIGNAL(triggered()), this, slot);
145 }
146 
147 /** Shows the config dialog with focus set to the given page. */
148 void
150 {
151  /* Load saved settings */
152  loadSettings();
153  /* Show the dialog. */
155  /* Set the focus to the specified page. */
156  ui.stackPages->setCurrentIndex((int)page);
157 }
158 
159 /** Called when the user changes the UI translation. */
160 void
162 {
163  ui.retranslateUi(this);
164  foreach (ConfigPage *page, ui.stackPages->pages()) {
165  page->retranslateUi();
166  }
167  foreach (QAction *action, ui.toolBar->actions()) {
168  action->setText(tr(qPrintable(action->data().toString()), "ConfigDialog"));
169  }
170  ui.buttonBox->setStandardButtons(ui.buttonBox->standardButtons());
171 }
172 
173 /** Loads the saved ConfigDialog settings. */
174 void
176 {
177  /* Call each config page's load() method to load its data */
178  foreach (ConfigPage *page, ui.stackPages->pages()) {
179  page->load();
180  }
181 }
182 
183 /** Saves changes made to settings. If Tor is running and Vidalia is
184  * connected, we will also attempt to apply the changes to Tor. */
185 void
187 {
188  QString errmsg;
189 
190  /* Call each config page's save() method to save its data */
191  foreach (ConfigPage *page, ui.stackPages->pages()) {
192  if (!page->save(errmsg)) {
193  /* Display the offending page */
194  ui.stackPages->setCurrentPage(page);
195 
196  /* Show the user what went wrong */
197  VMessageBox::warning(this,
198  tr("Error Saving Settings"),
199  p(tr("Vidalia was unable to save your %1 settings.")
200  .arg(tr(qPrintable(page->title()), "ConfigDialog"))) + p(errmsg),
202 
203  /* Don't process the rest of the pages */
204  return;
205  }
206  }
208  applyChanges();
209  else
210  close();
211 }
212 
213 /** Called after Vidalia has authenticated to Tor and applies any changes
214  * made since the last time they were applied. */
215 void
217 {
218  QString errmsg;
219  bool appliedChanges = false;
220 
221  foreach (ConfigPage *page, ui.stackPages->pages()) {
222  if (!page->changedSinceLastApply())
223  continue;
224  if (!page->apply(errmsg)) {
225  /* Failed to apply the changes to Tor */
226  int ret = VMessageBox::warning(this,
227  tr("Error Applying Settings"),
228  p(tr("Vidalia was unable to apply your %1 settings "
229  "to Tor.").arg(page->title()))
230  + p(errmsg),
231  VMessageBox::ShowSettings|VMessageBox::Default,
232  VMessageBox::Cancel|VMessageBox::Escape);
233  if (ret == VMessageBox::ShowSettings) {
234  /* Show the user the page with the bad settings */
235  showWindow();
236  ui.stackPages->setCurrentPage(page);
237  } else {
238  /* The user clicked 'Cancel', so revert the failed settings */
239  page->revert();
240  close();
241  }
242  return;
243  }
244  appliedChanges = true;
245  }
246  if (appliedChanges)
247  saveConf();
248  close();
249 }
250 
251 /** Sends Tor a SAVECONF to write its configuration to disk. If the SAVECONF
252  * is successful, then all settings are considered to be applied. */
253 void
255 {
257  if (tc->saveConf()) {
258  ServerSettings(tc).setChanged(false);
259  NetworkSettings(tc).setChanged(false);
260  TorSettings(tc).setChanged(false);
261  }
262 }
263 
264 /** Shows help information for whichever settings page the user is currently
265  * viewing. */
266 void
268 {
269  Page currentPage = static_cast<Page>(ui.stackPages->currentIndex());
270 
271  switch (currentPage) {
272  case Network:
273  help("config.network"); break;
274  case Server:
275  help("server"); break;
276  case Appearance:
277  help("config.appearance"); break;
278  case Advanced:
279  help("config.advanced"); break;
280  case Service:
281  help("config.services"); break;
282  default:
283  help("config.general"); break;
284  }
285 }
286 
287 /** Stub method that relays the checkForUpdates() signal from the General
288  * settings page to the owner of the config dialog (MainWindow). */
289 void
291 {
292  emit checkForUpdates();
293 }
294 
295 
296 /** Called when a ConfigPage in the dialog requests help on a specific
297  * <b>topic</b>. */
298 void
299 ConfigDialog::help(const QString &topic)
300 {
301  emit helpRequested(topic);
302 }
303 
QString p(QString str)
Definition: html.cpp:22
#define IMAGE_SERVER
Ui::ConfigDialog ui
Definition: ConfigDialog.h:90
#define IMAGE_ADVANCED
virtual void load()=0
Definition: tcglobal.cpp:19
virtual void revert()
Definition: ConfigPage.h:56
virtual bool save(QString &errmsg)=0
virtual bool apply(QString &errmsg)
Definition: ConfigPage.h:50
#define IMAGE_GENERAL
void loadSettings()
void addAction(QAction *action, const char *slot=0)
#define IMAGE_NETWORK
void checkForUpdates()
virtual void retranslateUi()
void restartTor()
void onCheckForUpdates()
void helpRequested(const QString &topic)
void setChanged(bool changed)
virtual void showWindow()
Definition: VidaliaWindow.h:64
QString title() const
Definition: ConfigPage.h:32
ConfigDialog(QWidget *parent=0)
#define IMAGE_HELP
static TorControl * torControl()
Definition: Vidalia.h:76
stop errmsg connect(const QHostAddress &address, quint16 port)
bool saveConf(QString *errmsg=0)
Definition: TorControl.cpp:914
static int warning(QWidget *parent, QString caption, QString text, int button0, int button1=NoButton, int button2=NoButton)
void applyChanges()
#define IMAGE_SERVICE
bool isConnected()
Definition: TorControl.cpp:262
void saveChanges()
QAction * createPageAction(const QIcon &img, const QString &text, const QString &data, QActionGroup *group)
virtual bool changedSinceLastApply()
Definition: ConfigPage.h:43
#define IMAGE_APPEARANCE
static void createShortcut(const QKeySequence &key, QWidget *sender, QObject *receiver, const char *slot)
Definition: Vidalia.cpp:402
virtual void retranslateUi()
Definition: ConfigPage.h:58