MainGui.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <FCConfig.h>
00025
00026 #ifdef _PreComp_
00027 # undef _PreComp_
00028 #endif
00029
00030 #ifdef FC_OS_LINUX
00031 # include <unistd.h>
00032 #endif
00033
00034 #if HAVE_CONFIG_H
00035 # include <config.h>
00036 #endif // HAVE_CONFIG_H
00037
00038 #include <cstdio>
00039 #include <QApplication>
00040 #include <QFile>
00041 #include <QMessageBox>
00042 #include <QLocale>
00043 #include <QTextCodec>
00044
00045 #include <QDomDocument>
00046 #include <QXmlSimpleReader>
00047 #include <QXmlInputSource>
00048 #include <QDir>
00049 #include <QFile>
00050 #include <QFileInfo>
00051
00052
00053 #include <Base/Console.h>
00054 #include <Base/Interpreter.h>
00055 #include <Base/Parameter.h>
00056 #include <Base/Exception.h>
00057 #include <Base/Factory.h>
00058 #include <App/Application.h>
00059 #include <Gui/BitmapFactory.h>
00060 #include <Gui/Icons/background.xpm>
00061 #include <Gui/Application.h>
00062
00063 void PrintInitHelp(void);
00064
00065 const char sBanner[] = "\xc2\xa9 Juergen Riegel, Werner Mayer, Yorik van Havre 2001-2011\n"\
00066 " ##### #### ### #### \n" \
00067 " # # # # # # \n" \
00068 " # ## #### #### # # # # # \n" \
00069 " #### # # # # # # # ##### # # \n" \
00070 " # # #### #### # # # # # \n" \
00071 " # # # # # # # # # ## ## ##\n" \
00072 " # # #### #### ### # # #### ## ## ##\n\n" ;
00073
00074 class Branding
00075 {
00076 public:
00077 struct UserDefines
00078 {
00079 std::string windowTitle;
00080 std::string windowIcon;
00081 std::string programLogo;
00082 std::string splashScreen;
00083 };
00084
00085 Branding()
00086 {
00087 }
00088
00089 bool readFile(const QString& fn)
00090 {
00091 QFile file(fn);
00092 if (!file.open(QFile::ReadOnly))
00093 return false;
00094 if (!evaluateXML(&file, domDocument))
00095 return false;
00096 file.close();
00097 return true;
00098 }
00099 UserDefines getUserDefines() const
00100 {
00101 UserDefines ud;
00102 QDomElement root = domDocument.documentElement();
00103 QDomElement child;
00104 if (!root.isNull()) {
00105 child = root.firstChildElement(QLatin1String("WindowTitle"));
00106 if (!child.isNull())
00107 ud.windowTitle = (const char*)child.text().toUtf8();
00108 child = root.firstChildElement(QLatin1String("WindowIcon"));
00109 if (!child.isNull())
00110 ud.windowIcon = (const char*)child.text().toUtf8();
00111 child = root.firstChildElement(QLatin1String("ProgramLogo"));
00112 if (!child.isNull())
00113 ud.programLogo = (const char*)child.text().toUtf8();
00114 child = root.firstChildElement(QLatin1String("SplashScreen"));
00115 if (!child.isNull())
00116 ud.splashScreen = (const char*)child.text().toUtf8();
00117 }
00118 return ud;
00119 }
00120
00121 private:
00122 bool evaluateXML(QIODevice *device, QDomDocument& xmlDocument)
00123 {
00124 QString errorStr;
00125 int errorLine;
00126 int errorColumn;
00127
00128 if (!xmlDocument.setContent(device, true, &errorStr, &errorLine,
00129 &errorColumn)) {
00130 return false;
00131 }
00132
00133 QDomElement root = xmlDocument.documentElement();
00134 if (root.tagName() != QLatin1String("Branding")) {
00135 return false;
00136 }
00137 else if (root.hasAttribute(QLatin1String("version"))) {
00138 QString attr = root.attribute(QLatin1String("version"));
00139 if (attr != QLatin1String("1.0"))
00140 return false;
00141 }
00142
00143 return true;
00144 }
00145 QDomDocument domDocument;
00146 };
00147
00148 class ProgramOptions
00149 {
00150 public:
00151 ProgramOptions()
00152 {
00153 newcout = new ProgramOptionsStream(out);
00154 oldcout = std::cout.rdbuf(newcout);
00155 out.reserve(80);
00156 newcerr = new ProgramOptionsStream(err);
00157 oldcerr = std::cerr.rdbuf(newcerr);
00158 err.reserve(80);
00159
00160 error = true;
00161 ::atexit(ProgramOptions::failure);
00162 }
00163 ~ProgramOptions()
00164 {
00165 std::cout.rdbuf(oldcout);
00166 delete newcout;
00167 std::cerr.rdbuf(oldcerr);
00168 delete newcerr;
00169 error = false;
00170 }
00171 static void failure()
00172 {
00173 if (error) {
00174 int argc=0;
00175 QApplication app(argc,0);
00176 QString appName = QString::fromAscii(App::Application::Config()["ExeName"].c_str());
00177 if (!err.empty()) {
00178 QString msg = QString::fromAscii(err.c_str());
00179 QString s = QLatin1String("<pre>") + msg + QLatin1String("</pre>");
00180 QMessageBox::critical(0, appName, s);
00181 }
00182 else if (!out.empty()) {
00183 QString msg = QString::fromAscii(out.c_str());
00184 QString s = QLatin1String("<pre>") + msg + QLatin1String("</pre>");
00185 QMessageBox::information(0, appName, s);
00186 }
00187 }
00188 }
00189
00190 private:
00191 class ProgramOptionsStream : public std::streambuf
00192 {
00193 public:
00194 ProgramOptionsStream(std::string& s) : buf(s)
00195 {
00196 }
00197 int overflow(int c = EOF)
00198 {
00199 if (c != EOF)
00200 buf.push_back((char)c);
00201 return c;
00202 }
00203 int sync()
00204 {
00205 return 0;
00206 }
00207 private:
00208 std::string& buf;
00209 };
00210
00211 private:
00212 friend class ProgramOptionsStream;
00213 std::streambuf* oldcout;
00214 std::streambuf* newcout;
00215 std::streambuf* oldcerr;
00216 std::streambuf* newcerr;
00217 static std::string out, err;
00218 static bool error;
00219 };
00220
00221 bool ProgramOptions::error = false;
00222 std::string ProgramOptions::out;
00223 std::string ProgramOptions::err;
00224
00225 #if defined (FC_OS_LINUX) || defined(FC_OS_BSD)
00226 QString myDecoderFunc(const QByteArray &localFileName)
00227 {
00228 QTextCodec* codec = QTextCodec::codecForName("UTF-8");
00229 return codec->toUnicode(localFileName);
00230 }
00231
00232 QByteArray myEncoderFunc(const QString &fileName)
00233 {
00234 QTextCodec* codec = QTextCodec::codecForName("UTF-8");
00235 return codec->fromUnicode(fileName);
00236 }
00237 #endif
00238
00239 int main( int argc, char ** argv )
00240 {
00241 #if defined (FC_OS_LINUX) || defined(FC_OS_BSD)
00242
00243
00244 (void)QLocale::system();
00245
00246
00247
00248 QFile::setEncodingFunction(myEncoderFunc);
00249 QFile::setDecodingFunction(myDecoderFunc);
00250
00251
00252 putenv("LANG=C");
00253 putenv("LC_ALL=C");
00254 putenv("PYTHONPATH=");
00255 #elif defined(FC_OS_MACOSX)
00256 (void)QLocale::system();
00257 putenv("LANG=C");
00258 putenv("LC_ALL=C");
00259 putenv("PYTHONPATH=");
00260 #else
00261 setlocale(LC_NUMERIC, "C");
00262 _putenv("PYTHONPATH=");
00263 #endif
00264
00265
00266 App::Application::Config()["ExeName"] = "FreeCAD";
00267 App::Application::Config()["ExeVendor"] = "FreeCAD";
00268 App::Application::Config()["AppDataSkipVendor"] = "true";
00269 App::Application::Config()["MaintainerUrl"] = "http://apps.sourceforge.net/mediawiki/free-cad/index.php?title=Main_Page";
00270
00271
00272 App::Application::Config()["ConsoleBanner"] = sBanner;
00273 App::Application::Config()["AppIcon"] = "freecad";
00274 App::Application::Config()["SplashPicture"] = "freecadsplash";
00275 App::Application::Config()["StartWorkbench"] = "StartWorkbench";
00276
00277 App::Application::Config()["SplashAlignment" ] = "Bottom|Left";
00278 App::Application::Config()["SplashTextColor" ] = "#ffffff";
00279
00280 try {
00281
00282
00283 App::Application::Config()["RunMode"] = "Gui";
00284
00285
00286 ProgramOptions po;
00287 App::Application::init(argc,argv);
00288 Gui::Application::initApplication();
00289 }
00290 catch (const Base::Exception& e) {
00291
00292 QApplication app(argc,argv);
00293 QString appName = QString::fromAscii(App::Application::Config()["ExeName"].c_str());
00294 QString msg;
00295 msg = QObject::tr("While initializing %1 the following exception occurred: '%2'\n\n"
00296 "Python is searching for its files in the following directories:\n%3\n\n"
00297 "Python version information:\n%4\n")
00298 .arg(appName).arg(QString::fromUtf8(e.what()))
00299 .arg(QString::fromUtf8(Py_GetPath())).arg(QString::fromAscii(Py_GetVersion()));
00300 const char* pythonhome = getenv("PYTHONHOME");
00301 if (pythonhome) {
00302 msg += QObject::tr("\nThe environment variable PYTHONHOME is set to '%1'.")
00303 .arg(QString::fromUtf8(pythonhome));
00304 msg += QObject::tr("\nSetting this environment variable might cause Python to fail. "
00305 "Please contact your administrator to unset it on your system.\n\n");
00306 } else {
00307 msg += QObject::tr("\nPlease contact the application's support team for more information.\n\n");
00308 }
00309
00310 QMessageBox::critical(0, QObject::tr("Initialization of %1 failed").arg(appName), msg);
00311 exit(100);
00312 }
00313 catch (...) {
00314
00315 QApplication app(argc,argv);
00316 QString appName = QString::fromAscii(App::Application::Config()["ExeName"].c_str());
00317 QString msg = QObject::tr("Unknown runtime error occurred while initializing %1.\n\n"
00318 "Please contact the application's support team for more information.\n\n").arg(appName);
00319 QMessageBox::critical(0, QObject::tr("Initialization of %1 failed").arg(appName), msg);
00320 exit(101);
00321 }
00322
00323
00324 Branding brand;
00325 QString path = QString::fromUtf8(App::GetApplication().GetHomePath());
00326 QFileInfo fi(path, QString::fromAscii("branding.xml"));
00327 if (brand.readFile(fi.absoluteFilePath())) {
00328 Branding::UserDefines ud = brand.getUserDefines();
00329 if (!ud.windowTitle.empty())
00330 App::Application::Config()["WindowTitle"] = ud.windowTitle;
00331 if (!ud.windowIcon.empty())
00332 App::Application::Config()["WindowIcon"] = ud.windowIcon;
00333 if (!ud.programLogo.empty())
00334 App::Application::Config()["ProgramLogo"] = ud.programLogo;
00335 if (!ud.splashScreen.empty())
00336 App::Application::Config()["SplashPicture"] = ud.splashScreen;
00337 }
00338
00339
00340 Base::RedirectStdOutput stdcout;
00341 Base::RedirectStdLog stdclog;
00342 Base::RedirectStdError stdcerr;
00343 std::streambuf* oldcout = std::cout.rdbuf(&stdcout);
00344 std::streambuf* oldclog = std::clog.rdbuf(&stdclog);
00345 std::streambuf* oldcerr = std::cerr.rdbuf(&stdcerr);
00346
00347 try {
00348 if (App::Application::Config()["RunMode"] == "Gui")
00349 Gui::Application::runApplication();
00350 else
00351 App::Application::runApplication();
00352 }
00353 catch (const Base::Exception& e) {
00354 Base::Console().Error("%s\n", e.what());
00355 }
00356 catch (...) {
00357 Base::Console().Error("Application unexpectedly terminated\n");
00358 }
00359
00360 std::cout.rdbuf(oldcout);
00361 std::clog.rdbuf(oldclog);
00362 std::cerr.rdbuf(oldcerr);
00363
00364
00365 Base::Console().Log("%s terminating...\n",App::Application::Config()["ExeName"].c_str());
00366
00367
00368 App::Application::destruct();
00369
00370 Base::Console().Log("%s completely terminated\n",App::Application::Config()["ExeName"].c_str());
00371
00372 return 0;
00373 }