000FreeCAD源码学习--MainGui.cpp

目录

1 MainGui.cpp源代码

2 int main()函数分析

3 编译运行截图


 

FreeCADMain项目下的MainGui.cpp

1 MainGui.cpp源代码
int main( int argc, char ** argv )
{
#if defined (FC_OS_LINUX) || defined(FC_OS_BSD)
    setlocale(LC_ALL, ""); // use native environment settings

    // Make sure to setup the Qt locale system before setting LANG and LC_ALL to C.
    // which is needed to use the system locale settings.
    (void)QLocale::system();
    // See https://forum.freecad.org/viewtopic.php?f=18&t=20600
    // See Gui::Application::runApplication()
    putenv("LC_NUMERIC=C");
    putenv("PYTHONPATH=");
#elif defined(FC_OS_MACOSX)
    (void)QLocale::system();
    putenv("PYTHONPATH=");
#elif defined(__MINGW32__)
    const char* mingw_prefix = getenv("MINGW_PREFIX");
    const char* py_home = getenv("PYTHONHOME");
    if (!py_home && mingw_prefix)
        _putenv_s("PYTHONHOME", mingw_prefix);
#else
    _putenv("PYTHONPATH=");
    // https://forum.freecad.org/viewtopic.php?f=4&t=18288
    // https://forum.freecad.org/viewtopic.php?f=3&t=20515
    const char* fc_py_home = getenv("FC_PYTHONHOME");
    if (fc_py_home)
        _putenv_s("PYTHONHOME", fc_py_home);
    else
        _putenv("PYTHONHOME=");
#endif

#if defined (FC_OS_WIN32)
    // we need to force Coin not to use Freetype in order to find installed fonts on Windows
    // see https://forum.freecad.org/viewtopic.php?p=485142#p485016
    _putenv("COIN_FORCE_FREETYPE_OFF=1");

    int argc_ = argc;
    QVector data;
    QVector argv_;

    // get the command line arguments as unicode string
    {
        QCoreApplication app(argc, argv);
        QStringList args = app.arguments();
        for (QStringList::iterator it = args.begin(); it != args.end(); ++it) {
            data.push_back(it->toUtf8());
            argv_.push_back(data.back().data());
        }
        argv_.push_back(0); // 0-terminated string
    }
#endif

    // Name and Version of the Application
    App::Application::Config()["ExeName"] = "FreeCAD";
    App::Application::Config()["ExeVendor"] = "FreeCAD";
    App::Application::Config()["AppDataSkipVendor"] = "true";
    App::Application::Config()["MaintainerUrl"] = "http://www.freecad.org/wiki/Main_Page";

    // set the banner (for logging and console)
    App::Application::Config()["CopyrightInfo"] = sBanner;
    App::Application::Config()["AppIcon"] = "freecad";
    App::Application::Config()["SplashScreen"] = "freecadsplash";
    App::Application::Config()["AboutImage"] = "freecadabout";
    App::Application::Config()["StartWorkbench"] = "StartWorkbench";
    //App::Application::Config()["HiddenDockWindow"] = "Property editor";
    App::Application::Config()["SplashAlignment" ] = "Bottom|Left";
    App::Application::Config()["SplashTextColor" ] = "#8aadf4"; // light blue
    App::Application::Config()["SplashInfoColor" ] = "#8aadf4"; // light blue 
    App::Application::Config()["SplashInfoPosition" ] = "6,75";

    QGuiApplication::setDesktopFileName(QStringLiteral("org.freecad.FreeCAD.desktop"));

    try {
        // Init phase ===========================================================
        // sets the default run mode for FC, starts with gui if not overridden in InitConfig...
        App::Application::Config()["RunMode"] = "Gui";
        App::Application::Config()["Console"] = "0";
        App::Application::Config()["LoggingConsole"] = "1";

        // Inits the Application
#if defined (FC_OS_WIN32)
        App::Application::init(argc_, argv_.data());
#else
        App::Application::init(argc, argv);
#endif
#if defined(_MSC_VER)
        // create a dump file when the application crashes
        std::string dmpfile = App::Application::getUserAppDataDir();
        dmpfile += "crash.dmp";
        InitMiniDumpWriter(dmpfile);
#endif
        std::map::iterator it = App::Application::Config().find("NavigationStyle");
        if (it != App::Application::Config().end()) {
            ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/View");
            // if not already defined do it now (for the very first start)
            std::string style = hGrp->GetASCII("NavigationStyle", it->second.c_str());
            hGrp->SetASCII("NavigationStyle", style.c_str());
        }

        Gui::Application::initApplication();

        // Only if 'RunMode' is set to 'Gui' do the replacement
        if (App::Application::Config()["RunMode"] == "Gui")
            Base::Interpreter().replaceStdOutput();
    }
    catch (const Base::UnknownProgramOption& e) {
        QApplication app(argc,argv);
        QString appName = QString::fromLatin1(App::Application::Config()["ExeName"].c_str());
        QString msg = QString::fromLatin1(e.what());
        QString s = QLatin1String("
") + msg + QLatin1String("
"); QMessageBox::critical(nullptr, appName, s); exit(1); } catch (const Base::ProgramInformation& e) { QApplication app(argc,argv); QString appName = QString::fromLatin1(App::Application::Config()["ExeName"].c_str()); QString msg = QString::fromUtf8(e.what()); QString s = QLatin1String("
") + msg + QLatin1String("
"); QMessageBox msgBox; msgBox.setIcon(QMessageBox::Information); msgBox.setWindowTitle(appName); msgBox.setDetailedText(msg); msgBox.setText(s); msgBox.exec(); exit(0); } catch (const Base::Exception& e) { // Popup an own dialog box instead of that one of Windows QApplication app(argc,argv); QString appName = QString::fromLatin1(App::Application::Config()["ExeName"].c_str()); QString msg; msg = QObject::tr("While initializing %1 the following exception occurred: '%2'\n\n" "Python is searching for its files in the following directories:\n%3\n\n" "Python version information:\n%4\n") .arg(appName, QString::fromUtf8(e.what()), QString::fromUtf8(Py_EncodeLocale(Py_GetPath(),nullptr)), QString::fromLatin1(Py_GetVersion())); const char* pythonhome = getenv("PYTHONHOME"); if (pythonhome) { msg += QObject::tr("\nThe environment variable PYTHONHOME is set to '%1'.") .arg(QString::fromUtf8(pythonhome)); msg += QObject::tr("\nSetting this environment variable might cause Python to fail. " "Please contact your administrator to unset it on your system.\n\n"); } else { msg += QObject::tr("\nPlease contact the application's support team for more information.\n\n"); } QMessageBox::critical(nullptr, QObject::tr("Initialization of %1 failed").arg(appName), msg); exit(100); } catch (...) { // Popup an own dialog box instead of that one of Windows QApplication app(argc,argv); QString appName = QString::fromLatin1(App::Application::Config()["ExeName"].c_str()); QString msg = QObject::tr("Unknown runtime error occurred while initializing %1.\n\n" "Please contact the application's support team for more information.\n\n").arg(appName); QMessageBox::critical(nullptr, QObject::tr("Initialization of %1 failed").arg(appName), msg); exit(101); } // Run phase =========================================================== Base::RedirectStdOutput stdcout; Base::RedirectStdLog stdclog; Base::RedirectStdError stdcerr; std::streambuf* oldcout = std::cout.rdbuf(&stdcout); std::streambuf* oldclog = std::clog.rdbuf(&stdclog); std::streambuf* oldcerr = std::cerr.rdbuf(&stdcerr); try { // if console option is set then run in cmd mode if (App::Application::Config()["Console"] == "1") App::Application::runApplication(); if (App::Application::Config()["RunMode"] == "Gui" || App::Application::Config()["RunMode"] == "Internal") Gui::Application::runApplication(); else App::Application::runApplication(); } catch (const Base::SystemExitException& e) { exit(e.getExitCode()); } catch (const Base::Exception& e) { e.ReportException(); exit(1); } catch (const std::exception& e) { Base::Console().Error("Application unexpectedly terminated: %s\n", e.what()); exit(1); } catch (...) { Base::Console().Error("Application unexpectedly terminated\n"); exit(1); } std::cout.rdbuf(oldcout); std::clog.rdbuf(oldclog); std::cerr.rdbuf(oldcerr); // Destruction phase =========================================================== Base::Console().Log("%s terminating...\n",App::Application::Config()["ExeName"].c_str()); // cleans up App::Application::destruct(); Base::Console().Log("%s completely terminated\n",App::Application::Config()["ExeName"].c_str()); return 0; }
2 int main()函数分析
int main( int argc, char ** argv )  
{  
    // 如果操作系统是Linux或BSD,则设置本地化环境为当前环境设置  
#if defined (FC_OS_LINUX) || defined(FC_OS_BSD)  
    setlocale(LC_ALL, ""); // use native environment settings  
  
    // 在将LANG和LC_ALL设置为C之前,确保设置了Qt的本地化系统,  
    // 这样才能使用系统本地化设置。  
    // See https://forum.freecad.org/viewtopic.php?f=18&t=20600  
    // See Gui::Application::runApplication()  
    putenv("LC_NUMERIC=C");  
    putenv("PYTHONPATH=");  
#elif defined(FC_OS_MACOSX)  
    // 对于Mac OS X,同样设置本地化系统,并且设置PYTHONPATH环境变量为空  
    (void)QLocale::system();  
    putenv("PYTHONPATH=");  
#elif defined(__MINGW32__)  
    // 对于MinGW,获取MINGW_PREFIX环境变量,并获取PYTHONHOME环境变量,  
    // 如果PYTHONHOME未设置且MINGW_PREFIX存在,则将PYTHONHOME设置为MINGW_PREFIX  
    const char* mingw_prefix = getenv("MINGW_PREFIX");  
    const char* py_home = getenv("PYTHONHOME");  
    if (!py_home && mingw_prefix)  
        _putenv_s("PYTHONHOME", mingw_prefix);  
#else  
    // 对于其他操作系统,将PYTHONPATH环境变量设置为空,并获取FC_PYTHONHOME环境变量,  
    // 如果存在,则将PYTHONHOME设置为FC_PYTHONHOME;否则,将PYTHONHOME环境变量设置为空  
    _putenv("PYTHONPATH=");  
    // https://forum.freecad.org/viewtopic.php?f=4&t=18288  
    // https://forum.freecad.org/viewtopic.php?f=3&t=20515  
    const char*fc_py_home = getenv("FC_PYTHONHOME");  
    if (fc_py_home)  
        _putenv_s("PYTHONHOME",fc_py_home);  
    else  
        _putenv("PYTHONHOME=");  
#endif  
  
#if defined (FC_OS_WIN32)  
    // 我们需要强制Coin不使用Freetype来找到Windows上已安装的字体,  
    // 见 https://forum.freecad.org/viewtopic.php?p=485142#p485016  
    // 设置COIN_FORCE_FREETYPE_OFF环境变量为1,强制Coin不使用Freetype  
    _putenv("COIN_FORCE_FREETYPE_OFF=1");  
  
    // 对于Windows,我们创建一个新的命令行参数数组,并将其转换为unicode字符串格式  
    int argc_ = argc;  
    QVector data;  
    QVector argv_;  
  
    // 获取命令行参数并将其转换为unicode字符串格式  
    {  
        QCoreApplication app(argc, argv);  // 使用QCoreApplication来获取命令行参数列表  
        QStringList args = app.arguments();  // 获取命令行参数列表(包括程序名称)  
        for (QStringList::iterator it = args.begin(); it != args.end(); ++it) {  // 遍历参数列表并转换为utf-8格式的字节数组并存入data中  
            data.push_back(it->toUtf8());  // 转换参数为utf-8格式的字节数组并存入data中  
            argv_.push_back(data.back().data()); 

            argv_.push_back(0); // 0-terminated string
    }
#endif

        // 应用程序的名称和版本  
    App::Application::Config()["ExeName"] = "FreeCAD"; // 应用程序名称  
    App::Application::Config()["ExeVendor"] = "FreeCAD"; // 应用程序供应商  
    App::Application::Config()["AppDataSkipVendor"] = "true"; // 跳过应用程序数据供应商  
    App::Application::Config()["MaintainerUrl"] = "http://www.freecad.org/wiki/Main_Page"; // 维护者URL  
  
// 设置横幅(用于日志记录和控制台)  
    App::Application::Config()["CopyrightInfo"] = sBanner; // 版权信息  
    App::Application::Config()["AppIcon"] = "freecad"; // 应用程序图标  
    App::Application::Config()["SplashScreen"] = "freecadsplash"; // 启动画面  
    App::Application::Config()["AboutImage"] = "freecadabout"; // 关于图像  
    App::Application::Config()["StartWorkbench"] = "StartWorkbench"; // 启动工作台  
//App::Application::Config()["HiddenDockWindow"] = "Property editor"; // 隐藏停靠窗口  
    App::Application::Config()["SplashAlignment" ] = "Bottom|Left"; // 启动画面对齐方式  
    App::Application::Config()["SplashTextColor" ] = "#8aadf4"; // 启动画面文本颜色(浅蓝色)  
    App::Application::Config()["SplashInfoColor" ] = "#8aadf4"; // 启动画面信息颜色(浅蓝色)  
    App::Application::Config()["SplashInfoPosition" ] = "6,75"; // 启动画面信息位置  
  
QGuiApplication::setDesktopFileName(QStringLiteral("org.freecad.FreeCAD.desktop")); // 设置桌面文件名  
  
try {  
    // 初始化阶段 ===========================================================  
    // 设置FC的默认运行模式,如果没有在InitConfig中覆盖,则从GUI开始  
    App::Application::Config()["RunMode"] = "Gui"; // 运行模式(GUI)  
    App::Application::Config()["Console"] = "0"; // 控制台模式(0-无,1-有)  
    App::Application::Config()["LoggingConsole"] = "1"; // 日志记录到控制台(1-是,0-否)  
  
    // 初始化应用程序  
#if defined (FC_OS_WIN32)  
    App::Application::init(argc_, argv_.data()); // 在Windows平台上初始化应用程序  
#else  
    App::Application::init(argc, argv); // 在其他平台上初始化应用程序  
#endif  
#if defined(_MSC_VER)  
    // 当应用程序崩溃时创建一个转储文件  
    std::string dmpfile = App::Application::getUserAppDataDir(); // 获取用户应用程序数据目录  
    dmpfile += "crash.dmp"; // 添加文件后缀名  
    InitMiniDumpWriter(dmpfile); // 初始化MiniDumpWriter,用于生成.dmp文件,有助于程序崩溃后的调试  
#endif
#if defined(_MSC_VER)  
        // 当应用程序崩溃时创建一个转储文件  
        // create a dump file when the application crashes  
        std::string dmpfile = App::Application::getUserAppDataDir();  
        dmpfile += "crash.dmp";  
        InitMiniDumpWriter(dmpfile);  
#endif  
  
        // 查找配置文件中的 "NavigationStyle" 键值对  
        std::map::iterator it = App::Application::Config().find("NavigationStyle");  
        if (it != App::Application::Config().end()) {  
            // 通过路径获取用户参数组,并设置 "NavigationStyle" 的值  
            ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/View");  
            // 如果未定义,则立即定义(对于第一次启动)  
            std::string style = hGrp->GetASCII("NavigationStyle", it->second.c_str());  
            hGrp->SetASCII("NavigationStyle", style.c_str());  
        }  
  
        // 初始化应用程序  
        Gui::Application::initApplication();  
  
        // 如果 'RunMode' 被设置为 'Gui',则替换标准输出  
        // Only if 'RunMode' is set to 'Gui' do the replacement  
        if (App::Application::Config()["RunMode"] == "Gui")  
            Base::Interpreter().replaceStdOutput();  
    }  
    catch (const Base::UnknownProgramOption& e) {  
        // 捕获异常,用于处理未知的程序选项问题  
        QApplication app(argc,argv);  
        QString appName = QString::fromLatin1(App::Application::Config()["ExeName"].c_str());  
        QString msg = QString::fromLatin1(e.what());  
        QString s = QLatin1String("
") + msg + QLatin1String("
"); QMessageBox::critical(nullptr, appName, s); exit(1); } catch (const Base::ProgramInformation& e) { // 捕获异常,用于处理程序信息问题 QApplication app(argc,argv); QString appName = QString::fromLatin1(App::Application::Config()["ExeName"].c_str()); QString msg = QString::fromUtf8(e.what()); QString s = QLatin1String("
") + msg + QLatin1String("
"); QMessageBox msgBox; msgBox.setIcon(QMessageBox::Information); msgBox.setWindowTitle(appName); msgBox.setDetailedText(msg); msgBox.setText(s); msgBox.exec(); exit(0); } catch (const Base::Exception& e) { // 捕获Base::Exception类型的异常 // 弹出自定义的对话框,而不是Windows的对话框 // Popup an own dialog box instead of that one of Windows QApplication app(argc,argv); QString appName = QString::fromLatin1(App::Application::Config() ["ExeName"].c_str()); QString msg; // 使用占位符构建错误消息,其中%1表示应用名称,%2表示异常信息,%3表示Python正在搜索的目录,%4表示Python版本信息 msg = QObject::tr("While initializing %1 the following exception occurred: '%2'\n\n" "Python is searching for its files in the following directories:\n%3\n\n" "Python version information:\n%4\n") .arg(appName, QString::fromUtf8(e.what()), QString::fromUtf8(Py_EncodeLocale(Py_GetPath(),nullptr)), QString::fromLatin1(Py_GetVersion())); const char* pythonhome = getenv("PYTHONHOME"); if (pythonhome) { // 如果环境变量PYTHONHOME被设置,则添加相应的错误消息 msg += QObject::tr("\nThe environment variable PYTHONHOME is set to '%1'.") .arg(QString::fromUtf8(pythonhome)); msg += QObject::tr("\nSetting this environment variable might cause Python to fail. " "Please contact your administrator to unset it on your system.\n\n"); } else { // 如果环境变量PYTHONHOME没有被设置,则添加相应的错误消息 msg += QObject::tr("\nPlease contact the application's support team for more information.\n\n"); } // 显示错误消息的对话框,标题为应用名称,内容为错误消息,然后退出程序并返回错误码100 QMessageBox::critical(nullptr, QObject::tr("Initialization of %1 failed").arg(appName), msg); exit(100); } // 捕获任何异常,用于处理未知的运行时错误 catch (...) { // 弹出自定义的对话框,而不是Windows的系统对话框 // Popup an own dialog box instead of that one of Windows QApplication app(argc,argv); QString appName = QString::fromLatin1(App::Application::Config()["ExeName"].c_str()); QString msg = QObject::tr("Unknown runtime error occurred while initializing %1.\n\n" "Please contact the application's support team for more information.\n\n").arg(appName); // 显示错误消息的对话框,标题为应用名称,内容为错误消息,然后退出程序并返回错误码101 QMessageBox::critical(nullptr, QObject::tr("Initialization of %1 failed").arg(appName), msg); exit(101); } // 运行阶段 =========================================================== // 重定向标准输出流、标准日志流和标准错误流 Base::RedirectStdOutput stdcout; Base::RedirectStdLog stdclog; Base::RedirectStdError stdcerr; // 保存旧的cout、clog和cerr缓冲区指针,用于后续恢复 std::streambuf* oldcout = std::cout.rdbuf(&stdcout); std::streambuf* oldclog = std::clog.rdbuf(&stdclog); std::streambuf* oldcerr = std::cerr.rdbuf(&stdcerr); try { // 如果设置了控制台选项,则在命令行模式下运行应用程序 // if console option is set then run in cmd mode if (App::Application::Config()["Console"] == "1") App::Application::runApplication(); // 如果运行模式为Gui或Internal,则在GUI模式下运行应用程序 if (App::Application::Config()["RunMode"] == "Gui" || App::Application::Config()["RunMode"] == "Internal") Gui::Application::runApplication(); // 否则,在默认模式下运行应用程序 else App::Application::runApplication(); } // 捕获Base::SystemExitException异常,根据其退出码退出程序 catch (const Base::SystemExitException& e) { exit(e.getExitCode()); } // 捕获Base::Exception异常,报告异常并退出程序,返回状态码1 catch (const Base::Exception& e) { e.ReportException(); exit(1); } // 捕获std::exception异常,输出错误信息并退出程序,返回状态码1 catch (const std::exception& e) { Base::Console().Error("Application unexpectedly terminated: %s\n", e.what()); exit(1); } // 捕获其他所有异常,输出错误信息并退出程序,返回状态码1 catch (...) { Base::Console().Error("Application unexpectedly terminated\n"); exit(1); } // 恢复旧的cout、clog和cerr缓冲区指针,以便后续正常输出流控制恢复正常状态 std::cout.rdbuf(oldcout); std::clog.rdbuf(oldclog); std::cerr.rdbuf(oldcerr); // 销毁阶段 =========================================================== // 记录应用程序终止信息 Base::Console().Log("%s terminating...\n",App::Application::Config() ["ExeName"].c_str()); // 清理资源 // cleans up App::Application::destruct(); // 记录应用程序完全终止信息 Base::Console().Log("%s completely terminated\n",App::Application::Config() ["ExeName"].c_str()); // 返回0,表示程序正常结束 return 0; }
3 编译运行截图

000FreeCAD源码学习--MainGui.cpp_第1张图片

你可能感兴趣的:(FreeCAD源码学习,学习,freecad,qt)