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 2653 2008-06-03 13:44:14Z 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     button->setText(tr("OK"));
00057   button = ui.buttonBox->button(QDialogButtonBox::Cancel);
00058   if (button)
00059     button->setText(tr("Cancel"));
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   /* Create the config pages and actions */
00069   QActionGroup *grp = new QActionGroup(this);
00070   ui.stackPages->add(new GeneralPage(ui.stackPages),
00071                      createPageAction(QIcon(IMAGE_GENERAL),
00072                                       tr("General"), grp));
00073   
00074   ui.stackPages->add(new NetworkPage(ui.stackPages),
00075                      createPageAction(QIcon(IMAGE_NETWORK),
00076                                       tr("Network"), grp));
00077   
00078   ui.stackPages->add(new ServerPage(ui.stackPages),
00079                      createPageAction(QIcon(IMAGE_SERVER),
00080                                       tr("Sharing"), grp));
00081   
00082   ui.stackPages->add(new ServicePage(ui.stackPages),
00083                      createPageAction(QIcon(IMAGE_SERVICE),
00084                                       tr("Services"), grp));
00085 
00086   ui.stackPages->add(new AppearancePage(ui.stackPages),
00087                      createPageAction(QIcon(IMAGE_APPEARANCE),
00088                                       tr("Appearance"), grp));
00089   
00090   ui.stackPages->add(new AdvancedPage(ui.stackPages),
00091                      createPageAction(QIcon(IMAGE_ADVANCED),
00092                                       tr("Advanced"), grp));
00093 
00094   foreach (ConfigPage *page, ui.stackPages->pages()) {
00095     connect(page, SIGNAL(helpRequested(QString)),
00096             this, SLOT(help(QString)));
00097   }
00098 
00099   /* Create the toolbar */
00100   ui.toolBar->addActions(grp->actions());
00101   ui.toolBar->addSeparator();
00102   connect(grp, SIGNAL(triggered(QAction *)), 
00103           ui.stackPages, SLOT(showPage(QAction *)));
00104   
00105   /* Create and bind the Help button */
00106   QAction *helpAct = new QAction(QIcon(IMAGE_HELP), tr("Help"), ui.toolBar);
00107   addAction(helpAct, SLOT(help()));
00108 
00109   /* Select the first action */
00110   grp->actions()[0]->setChecked(true);
00111 
00112 #if defined(Q_WS_WIN)
00113   helpAct->setShortcut(QString("F1"));
00114 #else
00115   helpAct->setShortcut(QString("Ctrl+?"));
00116 #endif
00117 }
00118 
00119 /** Creates a new action associated with a config page. */
00120 QAction*
00121 ConfigDialog::createPageAction(QIcon img, QString text, QActionGroup *group)
00122 {
00123   QAction *action = new QAction(img, text, group);
00124   action->setCheckable(true);
00125   return action;
00126 }
00127 
00128 /** Adds the given action to the toolbar and hooks its triggered() signal to
00129  * the specified slot (if given). */
00130 void
00131 ConfigDialog::addAction(QAction *action, const char *slot)
00132 {
00133   ui.toolBar->addAction(action);
00134   connect(action, SIGNAL(triggered()), this, slot);
00135 }
00136 
00137 /** Shows the config dialog with focus set to the given page. */
00138 void
00139 ConfigDialog::showWindow(Page page)
00140 {
00141   /* Load saved settings */
00142   loadSettings();
00143   /* Show the dialog. */
00144   VidaliaWindow::showWindow();
00145   /* Set the focus to the specified page. */
00146   ui.stackPages->setCurrentIndex((int)page);
00147 }
00148 
00149 /** Loads the saved ConfigDialog settings. */
00150 void
00151 ConfigDialog::loadSettings()
00152 {
00153   /* Call each config page's load() method to load its data */
00154   foreach (ConfigPage *page, ui.stackPages->pages()) {
00155     page->load();
00156   }
00157 }
00158 
00159 /** Saves changes made to settings. If Tor is running and Vidalia is
00160  * connected, we will also attempt to apply the changes to Tor. */
00161 void
00162 ConfigDialog::saveChanges()
00163 {
00164   QString errmsg;
00165   
00166   /* Call each config page's save() method to save its data */
00167   foreach (ConfigPage *page, ui.stackPages->pages()) {
00168     if (!page->save(errmsg)) {
00169       /* Display the offending page */
00170       ui.stackPages->setCurrentPage(page);
00171       
00172       /* Show the user what went wrong */
00173       VMessageBox::warning(this, 
00174         tr("Error Saving Settings"), 
00175         p(tr("Vidalia was unable to save your %1 settings.")
00176              .arg(page->title())) + p(errmsg),
00177         VMessageBox::Ok);
00178 
00179       /* Don't process the rest of the pages */
00180       return;
00181     }
00182   }
00183   if (Vidalia::torControl()->isConnected())
00184     applyChanges();
00185   else
00186     close();
00187 }
00188 
00189 /** Called after Vidalia has authenticated to Tor and applies any changes
00190  * made since the last time they were applied. */
00191 void
00192 ConfigDialog::applyChanges()
00193 {
00194   QString errmsg;
00195   bool appliedChanges = false;
00196 
00197   foreach (ConfigPage *page, ui.stackPages->pages()) {
00198     if (!page->changedSinceLastApply())
00199       continue;
00200     if (!page->apply(errmsg)) {
00201       /* Failed to apply the changes to Tor */
00202       int ret = VMessageBox::warning(this,
00203                   tr("Error Applying Settings"),
00204                   p(tr("Vidalia was unable to apply your %1 settings "
00205                        "to Tor.").arg(page->title()))
00206                     + p(errmsg),
00207                   VMessageBox::ShowSettings|VMessageBox::Default,
00208                   VMessageBox::Cancel|VMessageBox::Escape);
00209       if (ret == VMessageBox::ShowSettings) {
00210         /* Show the user the page with the bad settings */
00211         showWindow();
00212         ui.stackPages->setCurrentPage(page);
00213       } else {
00214         /* The user clicked 'Cancel', so revert the failed settings */
00215         page->revert();
00216         close();
00217       }
00218       return;
00219     }
00220     appliedChanges = true;
00221   }
00222   if (appliedChanges)
00223     saveConf();      
00224   close();
00225 }
00226 
00227 /** Sends Tor a SAVECONF to write its configuration to disk. If the SAVECONF
00228  * is successful, then all settings are considered to be applied. */
00229 void
00230 ConfigDialog::saveConf()
00231 {
00232   TorControl *tc = Vidalia::torControl();
00233   if (tc->saveConf()) {
00234     ServerSettings(tc).setChanged(false);
00235     NetworkSettings(tc).setChanged(false);
00236     TorSettings(tc).setChanged(false);
00237   }
00238 }
00239 
00240 /** Shows help information for whichever settings page the user is currently
00241  * viewing. */
00242 void
00243 ConfigDialog::help()
00244 {
00245   Page currentPage = static_cast<Page>(ui.stackPages->currentIndex());
00246   
00247   switch (currentPage) {
00248     case Network:
00249       help("config.network"); break;
00250     case Server:
00251       help("server"); break;
00252     case Appearance:
00253       help("config.appearance"); break;
00254     case Advanced:
00255       help("config.advanced"); break;
00256     case Service:
00257       help("config.services"); break;
00258     default:
00259       help("config.general"); break;
00260   }
00261 }
00262 
00263 /** Called when a ConfigPage in the dialog requests help on a specific
00264  * <b>topic</b>. */
00265 void
00266 ConfigDialog::help(const QString &topic)
00267 {
00268   emit helpRequested(topic);
00269 }
00270 

Generated on Sat Aug 16 17:38:35 2008 for Vidalia by  doxygen 1.5.6