configdialog.cpp

Go to the documentation of this file.
00001 /****************************************************************
00002  *  Vidalia is distributed under the following license:
00003  *
00004  *  Copyright (C) 2006,  Matt Edman, Justin Hipple
00005  *
00006  *  This program is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU General Public License
00008  *  as published by the Free Software Foundation; either version 2
00009  *  of the License, or (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, 
00019  *  Boston, MA  02110-1301, USA.
00020  ****************************************************************/
00021 
00022 /** 
00023  * \file configdialog.cpp
00024  * \version $Id: configdialog.cpp 3005 2008-08-20 23:51:02Z edmanm $
00025  * \brief Contains a series of Vidalia and Tor configuration pages
00026  */
00027 
00028 #include <vmessagebox.h>
00029 #include <html.h>
00030 #include <serversettings.h>
00031 #include <networksettings.h>
00032 #include <vidalia.h>
00033 
00034 #include "configdialog.h"
00035 
00036 /* Images for toolbar icons */
00037 #define IMAGE_GENERAL       ":/images/32x32/preferences-system.png"
00038 #define IMAGE_NETWORK       ":/images/32x32/preferences-system-network.png"
00039 #define IMAGE_SERVER        ":/images/32x32/preferences-system-network-sharing.png"
00040 #define IMAGE_APPEARANCE    ":/images/32x32/preferences-desktop-locale.png"
00041 #define IMAGE_ADVANCED      ":/images/32x32/applications-system.png"
00042 #define IMAGE_HELP          ":/images/32x32/system-help.png"
00043 #define IMAGE_SERVICE       ":/images/32x32/services.png"
00044 
00045 /** Constructor */
00046 ConfigDialog::ConfigDialog(QWidget* parent)
00047 : VidaliaWindow("ConfigDialog", parent)
00048 {
00049   /* Invoke the Qt Designer generated QObject setup routine */
00050   ui.setupUi(this);
00051  
00052   /* Override the QDialogButtonBox button text so we can use our own
00053    * translations. */
00054   QPushButton *button = ui.buttonBox->button(QDialogButtonBox::Ok);
00055   if (button) {
00056     Vidalia::createShortcut(QKeySequence(Qt::Key_Return), 
00057                             this, button, SLOT(click()));
00058   }
00059   button = ui.buttonBox->button(QDialogButtonBox::Cancel);
00060   if (button) {
00061     Vidalia::createShortcut("Esc", this, button, SLOT(click()));
00062     Vidalia::createShortcut("Ctrl+W", this, button, SLOT(click()));
00063   }
00064   
00065   /* Connect the button box signals to the appropriate slots */
00066   connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(saveChanges()));
00067   connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(close()));
00068   connect(ui.buttonBox, SIGNAL(helpRequested()), this, SLOT(help()));
00069   connect(Vidalia::torControl(), SIGNAL(authenticated()),
00070                            this, SLOT(applyChanges()));
00071 
00072   /* Create the config pages and actions */
00073   QActionGroup *grp = new QActionGroup(this);
00074   ui.stackPages->add(new GeneralPage(ui.stackPages),
00075                      createPageAction(QIcon(IMAGE_GENERAL),
00076                                       tr("General"), grp));
00077   
00078   ui.stackPages->add(new NetworkPage(ui.stackPages),
00079                      createPageAction(QIcon(IMAGE_NETWORK),
00080                                       tr("Network"), grp));
00081   
00082   ui.stackPages->add(new ServerPage(ui.stackPages),
00083                      createPageAction(QIcon(IMAGE_SERVER),
00084                                       tr("Sharing"), grp));
00085   
00086   ui.stackPages->add(new ServicePage(ui.stackPages),
00087                      createPageAction(QIcon(IMAGE_SERVICE),
00088                                       tr("Services"), grp));
00089 
00090   ui.stackPages->add(new AppearancePage(ui.stackPages),
00091                      createPageAction(QIcon(IMAGE_APPEARANCE),
00092                                       tr("Appearance"), grp));
00093   
00094   ui.stackPages->add(new AdvancedPage(ui.stackPages),
00095                      createPageAction(QIcon(IMAGE_ADVANCED),
00096                                       tr("Advanced"), grp));
00097 
00098   foreach (ConfigPage *page, ui.stackPages->pages()) {
00099     connect(page, SIGNAL(helpRequested(QString)),
00100             this, SLOT(help(QString)));
00101   }
00102 
00103   /* Create the toolbar */
00104   ui.toolBar->addActions(grp->actions());
00105   ui.toolBar->addSeparator();
00106   connect(grp, SIGNAL(triggered(QAction *)), 
00107           ui.stackPages, SLOT(showPage(QAction *)));
00108   
00109   /* Create and bind the Help button */
00110   QAction *helpAct = new QAction(QIcon(IMAGE_HELP), tr("Help"), ui.toolBar);
00111   addAction(helpAct, SLOT(help()));
00112 
00113   /* Select the first action */
00114   grp->actions()[0]->setChecked(true);
00115 
00116 #if defined(Q_WS_WIN)
00117   helpAct->setShortcut(QString("F1"));
00118 #else
00119   helpAct->setShortcut(QString("Ctrl+?"));
00120 #endif
00121 }
00122 
00123 /** Creates a new action associated with a config page. */
00124 QAction*
00125 ConfigDialog::createPageAction(QIcon img, QString text, QActionGroup *group)
00126 {
00127   QAction *action = new QAction(img, text, group);
00128   action->setCheckable(true);
00129   return action;
00130 }
00131 
00132 /** Adds the given action to the toolbar and hooks its triggered() signal to
00133  * the specified slot (if given). */
00134 void
00135 ConfigDialog::addAction(QAction *action, const char *slot)
00136 {
00137   ui.toolBar->addAction(action);
00138   connect(action, SIGNAL(triggered()), this, slot);
00139 }
00140 
00141 /** Shows the config dialog with focus set to the given page. */
00142 void
00143 ConfigDialog::showWindow(Page page)
00144 {
00145   /* Load saved settings */
00146   loadSettings();
00147   /* Show the dialog. */
00148   VidaliaWindow::showWindow();
00149   /* Set the focus to the specified page. */
00150   ui.stackPages->setCurrentIndex((int)page);
00151 }
00152 
00153 /** Loads the saved ConfigDialog settings. */
00154 void
00155 ConfigDialog::loadSettings()
00156 {
00157   /* Call each config page's load() method to load its data */
00158   foreach (ConfigPage *page, ui.stackPages->pages()) {
00159     page->load();
00160   }
00161 }
00162 
00163 /** Saves changes made to settings. If Tor is running and Vidalia is
00164  * connected, we will also attempt to apply the changes to Tor. */
00165 void
00166 ConfigDialog::saveChanges()
00167 {
00168   QString errmsg;
00169   
00170   /* Call each config page's save() method to save its data */
00171   foreach (ConfigPage *page, ui.stackPages->pages()) {
00172     if (!page->save(errmsg)) {
00173       /* Display the offending page */
00174       ui.stackPages->setCurrentPage(page);
00175       
00176       /* Show the user what went wrong */
00177       VMessageBox::warning(this, 
00178         tr("Error Saving Settings"), 
00179         p(tr("Vidalia was unable to save your %1 settings.")
00180              .arg(page->title())) + p(errmsg),
00181         VMessageBox::Ok);
00182 
00183       /* Don't process the rest of the pages */
00184       return;
00185     }
00186   }
00187   if (Vidalia::torControl()->isConnected())
00188     applyChanges();
00189   else
00190     close();
00191 }
00192 
00193 /** Called after Vidalia has authenticated to Tor and applies any changes
00194  * made since the last time they were applied. */
00195 void
00196 ConfigDialog::applyChanges()
00197 {
00198   QString errmsg;
00199   bool appliedChanges = false;
00200 
00201   foreach (ConfigPage *page, ui.stackPages->pages()) {
00202     if (!page->changedSinceLastApply())
00203       continue;
00204     if (!page->apply(errmsg)) {
00205       /* Failed to apply the changes to Tor */
00206       int ret = VMessageBox::warning(this,
00207                   tr("Error Applying Settings"),
00208                   p(tr("Vidalia was unable to apply your %1 settings "
00209                        "to Tor.").arg(page->title()))
00210                     + p(errmsg),
00211                   VMessageBox::ShowSettings|VMessageBox::Default,
00212                   VMessageBox::Cancel|VMessageBox::Escape);
00213       if (ret == VMessageBox::ShowSettings) {
00214         /* Show the user the page with the bad settings */
00215         showWindow();
00216         ui.stackPages->setCurrentPage(page);
00217       } else {
00218         /* The user clicked 'Cancel', so revert the failed settings */
00219         page->revert();
00220         close();
00221       }
00222       return;
00223     }
00224     appliedChanges = true;
00225   }
00226   if (appliedChanges)
00227     saveConf();      
00228   close();
00229 }
00230 
00231 /** Sends Tor a SAVECONF to write its configuration to disk. If the SAVECONF
00232  * is successful, then all settings are considered to be applied. */
00233 void
00234 ConfigDialog::saveConf()
00235 {
00236   TorControl *tc = Vidalia::torControl();
00237   if (tc->saveConf()) {
00238     ServerSettings(tc).setChanged(false);
00239     NetworkSettings(tc).setChanged(false);
00240     TorSettings(tc).setChanged(false);
00241   }
00242 }
00243 
00244 /** Shows help information for whichever settings page the user is currently
00245  * viewing. */
00246 void
00247 ConfigDialog::help()
00248 {
00249   Page currentPage = static_cast<Page>(ui.stackPages->currentIndex());
00250   
00251   switch (currentPage) {
00252     case Network:
00253       help("config.network"); break;
00254     case Server:
00255       help("server"); break;
00256     case Appearance:
00257       help("config.appearance"); break;
00258     case Advanced:
00259       help("config.advanced"); break;
00260     case Service:
00261       help("config.services"); break;
00262     default:
00263       help("config.general"); break;
00264   }
00265 }
00266 
00267 /** Called when a ConfigPage in the dialog requests help on a specific
00268  * <b>topic</b>. */
00269 void
00270 ConfigDialog::help(const QString &topic)
00271 {
00272   emit helpRequested(topic);
00273 }
00274 

Generated on Wed Nov 26 21:03:58 2008 for Vidalia by  doxygen 1.5.6