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 vidalia.cpp 00024 * \version $Id: vidalia.cpp 1238 2006-09-25 17:50:57Z edmanm $ 00025 * \brief Main Vidalia QApplication object 00026 */ 00027 00028 #include <QDir> 00029 #include <QTextStream> 00030 #include <QStyleFactory> 00031 #include <util/string.h> 00032 #include <lang/languagesupport.h> 00033 00034 #include "vidalia.h" 00035 00036 /* Available command-line arguments. */ 00037 #define ARG_LANGUAGE "lang" /**< Argument specifying language. */ 00038 #define ARG_GUISTYLE "style" /**< Argument specfying GUI style. */ 00039 #define ARG_RESET "reset" /**< Reset Vidalia's saved settings. */ 00040 #define ARG_HELP "help" /**< Display usage informatino. */ 00041 #define ARG_DATADIR "datadir" /**< Directory to use for data files. */ 00042 #define ARG_PIDFILE "/var/run/tor/tor.pid" /**< Location and name of our pidfile.*/ 00043 00044 /* Static member variables */ 00045 QMap<QString, QString> Vidalia::_args; /**< List of command-line arguments. */ 00046 QString Vidalia::_style; /**< The current GUI style. */ 00047 QString Vidalia::_language; /**< The current language. */ 00048 VidaliaSettings Vidalia::_settings; /**< Vidalia's configurable settings. */ 00049 HelpBrowser* Vidalia::_help = 0; /**< Vidalia's help system. */ 00050 TorControl* Vidalia::_torControl = 0; /**< Main TorControl object. */ 00051 00052 00053 /** Constructor. Parses the command-line arguments, resets Vidalia's 00054 * configuration (if requested), and sets up the GUI style and language 00055 * translation. */ 00056 Vidalia::Vidalia(QStringList args, int &argc, char **argv) 00057 : QApplication(argc, argv) 00058 { 00059 /* Read in all our command-line arguments. */ 00060 parseArguments(args); 00061 00062 /* Check if we're supposed to reset our config before proceeding. */ 00063 if (_args.contains(ARG_RESET)) { 00064 _settings.reset(); 00065 } 00066 00067 /** Translate the GUI to the appropriate language. */ 00068 setLanguage(_args.value(ARG_LANGUAGE)); 00069 00070 /** Set the GUI style appropriately. */ 00071 setStyle(_args.value(ARG_GUISTYLE)); 00072 00073 /** Creates a TorControl object, used to talk to Tor. */ 00074 _torControl = new TorControl(); 00075 /** Create a help browser object, used to dispaly various help topics. */ 00076 _help = new HelpBrowser(); 00077 } 00078 00079 /** Destructor */ 00080 Vidalia::~Vidalia() 00081 { 00082 delete _help; 00083 delete _torControl; 00084 } 00085 00086 #if defined(Q_OS_WIN) 00087 /** On Windows, we need to catch the WM_QUERYENDSESSION message 00088 * so we know that it is time to shutdown. */ 00089 bool 00090 Vidalia::winEventFilter(MSG *msg, long *result) 00091 { 00092 if (msg->message == WM_QUERYENDSESSION) { 00093 emit shutdown(); 00094 } 00095 return QApplication::winEventFilter(msg, result); 00096 } 00097 #endif 00098 00099 /** Display usage information regarding command-line arguments. */ 00100 void 00101 Vidalia::printUsage(QString errmsg) 00102 { 00103 QTextStream out(stdout); 00104 00105 /* If there was an error message, print it out. */ 00106 if (!errmsg.isEmpty()) { 00107 out << "** " << errmsg << " **" << endl << endl; 00108 } 00109 00110 /* Now print the application usage */ 00111 out << "Usage: " << endl; 00112 out << "\t" << qApp->arguments().at(0) << " [options]" << endl; 00113 00114 /* And available options */ 00115 out << endl << "Available Options:" << endl; 00116 out << "\t-"ARG_HELP"\t\tDisplays this usage message and exits." << endl; 00117 out << "\t-"ARG_RESET"\t\tResets ALL stored Vidalia settings." << endl; 00118 out << "\t-"ARG_DATADIR"\tSets the directory Vidalia uses for data files"<< endl; 00119 out << "\t-"ARG_PIDFILE"\tSets the name and location of Vidalia's pidfile"<< endl; 00120 out << "\t-"ARG_GUISTYLE"\t\tSets Vidalia's interface style." << endl; 00121 out << "\t\t\t[" << QStyleFactory::keys().join("|") << "]" << endl; 00122 out << "\t-"ARG_LANGUAGE"\t\tSets Vidalia's language." << endl; 00123 out << "\t\t\t[" << LanguageSupport::languageCodes().join("|") << "]" << endl; 00124 } 00125 00126 /** Returns true if the specified argument expects a value. */ 00127 bool 00128 Vidalia::argNeedsValue(QString argName) 00129 { 00130 return (argName == ARG_GUISTYLE || 00131 argName == ARG_LANGUAGE || 00132 argName == ARG_DATADIR || 00133 argName == ARG_PIDFILE); 00134 } 00135 00136 /** Parses the list of command-line arguments for their argument names and 00137 * values. */ 00138 void 00139 Vidalia::parseArguments(QStringList args) 00140 { 00141 QString arg, value; 00142 00143 /* Loop through all command-line args/values and put them in a map */ 00144 for (int i = 0; i < args.size(); i++) { 00145 /* Get the argument name and set a blank value */ 00146 arg = args.at(i).toLower(); 00147 value = ""; 00148 00149 /* Check if it starts with a - or -- */ 00150 if (arg.startsWith("-")) { 00151 arg = arg.mid((arg.startsWith("--") ? 2 : 1)); 00152 } 00153 /* Check if it takes a value and there is one on the command-line */ 00154 if (i < args.size()-1 && argNeedsValue(arg)) { 00155 value = args.at(++i); 00156 } 00157 /* Place this arg/value in the map */ 00158 _args.insert(arg, value); 00159 } 00160 } 00161 00162 /** Verifies that all specified arguments were valid. */ 00163 bool 00164 Vidalia::validateArguments(QString &errmsg) 00165 { 00166 /* If they want help, just return false now */ 00167 if (_args.contains(ARG_HELP)) { 00168 return false; 00169 } 00170 /* Check for a language that Vidalia recognizes. */ 00171 if (_args.contains(ARG_LANGUAGE) && 00172 !LanguageSupport::isValidLanguageCode(_args.value(ARG_LANGUAGE))) { 00173 errmsg = tr("Invalid language code specified: ") + _args.value(ARG_LANGUAGE); 00174 return false; 00175 } 00176 /* Check for a valid GUI style */ 00177 if (_args.contains(ARG_GUISTYLE) && 00178 !QStyleFactory::keys().contains(_args.value(ARG_GUISTYLE), 00179 Qt::CaseInsensitive)) { 00180 errmsg = tr("Invalid GUI style specified: ") + _args.value(ARG_GUISTYLE); 00181 return false; 00182 } 00183 return true; 00184 } 00185 00186 /** Sets the translation Vidalia will use. If one was specified on the 00187 * command-line, we will use that. Otherwise, we'll check to see if one was 00188 * saved previously. If not, we'll default to one appropriate for the system 00189 * locale. */ 00190 bool 00191 Vidalia::setLanguage(QString languageCode) 00192 { 00193 /* If the language code is empty, use the previously-saved setting */ 00194 if (languageCode.isEmpty()) { 00195 languageCode = _settings.getLanguageCode(); 00196 } 00197 /* Translate into the desired langauge */ 00198 if (LanguageSupport::translate(languageCode)) { 00199 _language = languageCode; 00200 return true; 00201 } 00202 return false; 00203 } 00204 00205 /** Sets the GUI style Vidalia will use. If one was specified on the 00206 * command-line, we will use that. Otherwise, we'll check to see if one was 00207 * saved previously. If not, we'll default to one appropriate for the 00208 * operating system. */ 00209 bool 00210 Vidalia::setStyle(QString styleKey) 00211 { 00212 /* If no style was specified, use the previously-saved setting */ 00213 if (styleKey.isEmpty()) { 00214 styleKey = _settings.getInterfaceStyle(); 00215 } 00216 /* Apply the specified GUI style */ 00217 if (QApplication::setStyle(styleKey)) { 00218 _style = styleKey; 00219 return true; 00220 } 00221 return false; 00222 } 00223 00224 /** Displays the help page associated with the specified topic. If no topic is 00225 * specified, then the default help page will be displayed. */ 00226 void 00227 Vidalia::help(QString topic) 00228 { 00229 _help->show(topic); 00230 } 00231 00232 /** Returns the directory Vidalia uses for its data files. */ 00233 QString 00234 Vidalia::dataDirectory() 00235 { 00236 if (_args.contains(ARG_DATADIR)) { 00237 return _args.value(ARG_DATADIR); 00238 } 00239 return defaultDataDirectory(); 00240 } 00241 00242 /** Returns the default location of Vidalia's data directory. */ 00243 QString 00244 Vidalia::defaultDataDirectory() 00245 { 00246 #if defined(Q_OS_WIN32) 00247 return (win32_app_data_folder() + "\\Vidalia"); 00248 #else 00249 return (QDir::homePath() + "/.vidalia"); 00250 #endif 00251 } 00252 00253 /** Returns the location of Vidalia's pid file. */ 00254 QString 00255 Vidalia::pidFile() 00256 { 00257 if (_args.contains(ARG_PIDFILE)) { 00258 return _args.value(ARG_PIDFILE); 00259 } 00260 return QDir::convertSeparators(dataDirectory() + "/vidalia.pid"); 00261 } 00262