Vidalia
0.2.15
|
00001 /* 00002 ** This file is part of Vidalia, and is subject to the license terms in the 00003 ** LICENSE file, found in the top level directory of this distribution. If you 00004 ** did not receive the LICENSE file with this file, you may obtain it from the 00005 ** Vidalia source package distributed by the Vidalia Project at 00006 ** http://www.torproject.org/projects/vidalia.html. No part of Vidalia, 00007 ** including this file, may be copied, modified, propagated, or distributed 00008 ** except according to the terms described in the LICENSE file. 00009 */ 00010 00011 /* 00012 ** \file ConfigDialog.cpp 00013 ** \brief Contains a series of Vidalia and Tor configuration pages 00014 */ 00015 00016 #include "ConfigDialog.h" 00017 #include "GeneralPage.h" 00018 #include "NetworkPage.h" 00019 #include "ServerPage.h" 00020 #include "AdvancedPage.h" 00021 #include "AppearancePage.h" 00022 #include "ServicePage.h" 00023 #include "VMessageBox.h" 00024 #include "ServerSettings.h" 00025 #include "NetworkSettings.h" 00026 #include "Vidalia.h" 00027 00028 #include "html.h" 00029 00030 00031 /* Images for toolbar icons */ 00032 #define IMAGE_GENERAL ":/images/32x32/preferences-system.png" 00033 #define IMAGE_NETWORK ":/images/32x32/preferences-system-network.png" 00034 #define IMAGE_SERVER ":/images/32x32/preferences-system-network-sharing.png" 00035 #define IMAGE_APPEARANCE ":/images/32x32/preferences-desktop-locale.png" 00036 #define IMAGE_ADVANCED ":/images/32x32/applications-system.png" 00037 #define IMAGE_HELP ":/images/32x32/system-help.png" 00038 #define IMAGE_SERVICE ":/images/32x32/services.png" 00039 00040 00041 /** Constructor */ 00042 ConfigDialog::ConfigDialog(QWidget* parent) 00043 : VidaliaWindow("ConfigDialog", parent) 00044 { 00045 /* Invoke the Qt Designer generated QObject setup routine */ 00046 ui.setupUi(this); 00047 00048 /* Override the QDialogButtonBox button text so we can use our own 00049 * translations. */ 00050 QPushButton *button = ui.buttonBox->button(QDialogButtonBox::Ok); 00051 if (button) { 00052 Vidalia::createShortcut(QKeySequence(Qt::Key_Return), 00053 this, button, SLOT(click())); 00054 } 00055 button = ui.buttonBox->button(QDialogButtonBox::Cancel); 00056 if (button) { 00057 Vidalia::createShortcut("Esc", this, button, SLOT(click())); 00058 Vidalia::createShortcut("Ctrl+W", this, button, SLOT(click())); 00059 } 00060 00061 /* Connect the button box signals to the appropriate slots */ 00062 connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(saveChanges())); 00063 connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(close())); 00064 connect(ui.buttonBox, SIGNAL(helpRequested()), this, SLOT(help())); 00065 connect(Vidalia::torControl(), SIGNAL(authenticated()), 00066 this, SLOT(applyChanges())); 00067 00068 /* Used to connect restartTor signals */ 00069 AdvancedPage *advancedPage; 00070 /* Create the config pages and actions */ 00071 QActionGroup *grp = new QActionGroup(this); 00072 GeneralPage *generalPage = new GeneralPage(ui.stackPages); 00073 ui.stackPages->add(generalPage, 00074 createPageAction(QIcon(IMAGE_GENERAL), 00075 tr("General"), "General", grp)); 00076 connect(generalPage, SIGNAL(checkForUpdates()), 00077 this, SLOT(onCheckForUpdates())); 00078 00079 ui.stackPages->add(new NetworkPage(ui.stackPages), 00080 createPageAction(QIcon(IMAGE_NETWORK), 00081 tr("Network"), "Network", grp)); 00082 00083 ui.stackPages->add(new ServerPage(ui.stackPages), 00084 createPageAction(QIcon(IMAGE_SERVER), 00085 tr("Sharing"), "Sharing", grp)); 00086 00087 ui.stackPages->add(new ServicePage(ui.stackPages), 00088 createPageAction(QIcon(IMAGE_SERVICE), 00089 tr("Services"), "Services", grp)); 00090 00091 ui.stackPages->add(new AppearancePage(ui.stackPages), 00092 createPageAction(QIcon(IMAGE_APPEARANCE), 00093 tr("Appearance"), "Appearance", grp)); 00094 00095 ui.stackPages->add(advancedPage = new AdvancedPage(ui.stackPages), 00096 createPageAction(QIcon(IMAGE_ADVANCED), 00097 tr("Advanced"), "Advanced", grp)); 00098 00099 connect(advancedPage, SIGNAL(restartTor()), this, SIGNAL(restartTor())); 00100 00101 foreach (ConfigPage *page, ui.stackPages->pages()) { 00102 connect(page, SIGNAL(helpRequested(QString)), 00103 this, SLOT(help(QString))); 00104 } 00105 00106 /* Create the toolbar */ 00107 ui.toolBar->addActions(grp->actions()); 00108 ui.toolBar->addSeparator(); 00109 connect(grp, SIGNAL(triggered(QAction *)), 00110 ui.stackPages, SLOT(showPage(QAction *))); 00111 00112 /* Create and bind the Help button */ 00113 QAction *helpAct = new QAction(QIcon(IMAGE_HELP), tr("Help"), ui.toolBar); 00114 helpAct->setData("Help"); 00115 addAction(helpAct, SLOT(help())); 00116 00117 /* Select the first action */ 00118 grp->actions()[0]->setChecked(true); 00119 00120 #if defined(Q_WS_WIN) 00121 helpAct->setShortcut(QString("F1")); 00122 #else 00123 helpAct->setShortcut(QString("Ctrl+?")); 00124 #endif 00125 } 00126 00127 /** Creates a new action associated with a config page. */ 00128 QAction* 00129 ConfigDialog::createPageAction(const QIcon &img, const QString &text, 00130 const QString &data, QActionGroup *group) 00131 { 00132 QAction *action = new QAction(img, text, group); 00133 action->setData(data); 00134 action->setCheckable(true); 00135 return action; 00136 } 00137 00138 /** Adds the given action to the toolbar and hooks its triggered() signal to 00139 * the specified slot (if given). */ 00140 void 00141 ConfigDialog::addAction(QAction *action, const char *slot) 00142 { 00143 ui.toolBar->addAction(action); 00144 connect(action, SIGNAL(triggered()), this, slot); 00145 } 00146 00147 /** Shows the config dialog with focus set to the given page. */ 00148 void 00149 ConfigDialog::showWindow(Page page) 00150 { 00151 /* Load saved settings */ 00152 loadSettings(); 00153 /* Show the dialog. */ 00154 VidaliaWindow::showWindow(); 00155 /* Set the focus to the specified page. */ 00156 ui.stackPages->setCurrentIndex((int)page); 00157 } 00158 00159 /** Called when the user changes the UI translation. */ 00160 void 00161 ConfigDialog::retranslateUi() 00162 { 00163 ui.retranslateUi(this); 00164 foreach (ConfigPage *page, ui.stackPages->pages()) { 00165 page->retranslateUi(); 00166 } 00167 foreach (QAction *action, ui.toolBar->actions()) { 00168 action->setText(tr(qPrintable(action->data().toString()), "ConfigDialog")); 00169 } 00170 ui.buttonBox->setStandardButtons(ui.buttonBox->standardButtons()); 00171 } 00172 00173 /** Loads the saved ConfigDialog settings. */ 00174 void 00175 ConfigDialog::loadSettings() 00176 { 00177 /* Call each config page's load() method to load its data */ 00178 foreach (ConfigPage *page, ui.stackPages->pages()) { 00179 page->load(); 00180 } 00181 } 00182 00183 /** Saves changes made to settings. If Tor is running and Vidalia is 00184 * connected, we will also attempt to apply the changes to Tor. */ 00185 void 00186 ConfigDialog::saveChanges() 00187 { 00188 QString errmsg; 00189 00190 /* Call each config page's save() method to save its data */ 00191 foreach (ConfigPage *page, ui.stackPages->pages()) { 00192 if (!page->save(errmsg)) { 00193 /* Display the offending page */ 00194 ui.stackPages->setCurrentPage(page); 00195 00196 /* Show the user what went wrong */ 00197 VMessageBox::warning(this, 00198 tr("Error Saving Settings"), 00199 p(tr("Vidalia was unable to save your %1 settings.") 00200 .arg(tr(qPrintable(page->title()), "ConfigDialog"))) + p(errmsg), 00201 VMessageBox::Ok); 00202 00203 /* Don't process the rest of the pages */ 00204 return; 00205 } 00206 } 00207 if (Vidalia::torControl()->isConnected()) 00208 applyChanges(); 00209 else 00210 close(); 00211 } 00212 00213 /** Called after Vidalia has authenticated to Tor and applies any changes 00214 * made since the last time they were applied. */ 00215 void 00216 ConfigDialog::applyChanges() 00217 { 00218 QString errmsg; 00219 bool appliedChanges = false; 00220 00221 foreach (ConfigPage *page, ui.stackPages->pages()) { 00222 if (!page->changedSinceLastApply()) 00223 continue; 00224 if (!page->apply(errmsg)) { 00225 /* Failed to apply the changes to Tor */ 00226 int ret = VMessageBox::warning(this, 00227 tr("Error Applying Settings"), 00228 p(tr("Vidalia was unable to apply your %1 settings " 00229 "to Tor.").arg(page->title())) 00230 + p(errmsg), 00231 VMessageBox::ShowSettings|VMessageBox::Default, 00232 VMessageBox::Cancel|VMessageBox::Escape); 00233 if (ret == VMessageBox::ShowSettings) { 00234 /* Show the user the page with the bad settings */ 00235 showWindow(); 00236 ui.stackPages->setCurrentPage(page); 00237 } else { 00238 /* The user clicked 'Cancel', so revert the failed settings */ 00239 page->revert(); 00240 close(); 00241 } 00242 return; 00243 } 00244 appliedChanges = true; 00245 } 00246 if (appliedChanges) 00247 saveConf(); 00248 close(); 00249 } 00250 00251 /** Sends Tor a SAVECONF to write its configuration to disk. If the SAVECONF 00252 * is successful, then all settings are considered to be applied. */ 00253 void 00254 ConfigDialog::saveConf() 00255 { 00256 TorControl *tc = Vidalia::torControl(); 00257 if (tc->saveConf()) { 00258 ServerSettings(tc).setChanged(false); 00259 NetworkSettings(tc).setChanged(false); 00260 TorSettings(tc).setChanged(false); 00261 } 00262 } 00263 00264 /** Shows help information for whichever settings page the user is currently 00265 * viewing. */ 00266 void 00267 ConfigDialog::help() 00268 { 00269 Page currentPage = static_cast<Page>(ui.stackPages->currentIndex()); 00270 00271 switch (currentPage) { 00272 case Network: 00273 help("config.network"); break; 00274 case Server: 00275 help("server"); break; 00276 case Appearance: 00277 help("config.appearance"); break; 00278 case Advanced: 00279 help("config.advanced"); break; 00280 case Service: 00281 help("config.services"); break; 00282 default: 00283 help("config.general"); break; 00284 } 00285 } 00286 00287 /** Stub method that relays the checkForUpdates() signal from the General 00288 * settings page to the owner of the config dialog (MainWindow). */ 00289 void 00290 ConfigDialog::onCheckForUpdates() 00291 { 00292 emit checkForUpdates(); 00293 } 00294 00295 00296 /** Called when a ConfigPage in the dialog requests help on a specific 00297 * <b>topic</b>. */ 00298 void 00299 ConfigDialog::help(const QString &topic) 00300 { 00301 emit helpRequested(topic); 00302 } 00303