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<QByteArray> data;
QVector<char *> 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<std::string, std::string>::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("<pre>") + msg + QLatin1String("</pre>");
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("<pre>") + msg + QLatin1String("</pre>");
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'nn"
"Python is searching for its files in the following directories:n%3nn"
"Python version information:n%4n")
.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.nn");
} else {
msg += QObject::tr("nPlease contact the application's support team for more information.nn");
}
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.nn"
"Please contact the application's support team for more information.nn").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: %sn", e.what());
exit(1);
}
catch (...) {
Base::Console().Error("Application unexpectedly terminatedn");
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 terminatedn",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<QByteArray> data;
QVector<char *> 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<std::string, std::string>::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("<pre>") + msg + QLatin1String("</pre>");
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("<pre>") + msg + QLatin1String("</pre>");
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'nn"
"Python is searching for its files in the following directories:n%3nn"
"Python version information:n%4n")
.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.nn");
} else {
// 如果环境变量PYTHONHOME没有被设置,则添加相应的错误消息
msg += QObject::tr("nPlease contact the application's support team for more information.nn");
}
// 显示错误消息的对话框,标题为应用名称,内容为错误消息,然后退出程序并返回错误码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.nn"
"Please contact the application's support team for more information.nn").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: %sn", e.what());
exit(1);
}
// 捕获其他所有异常,输出错误信息并退出程序,返回状态码1
catch (...) {
Base::Console().Error("Application unexpectedly terminatedn");
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 terminatedn",App::Application::Config() ["ExeName"].c_str());
// 返回0,表示程序正常结束
return 0;
}
3 编译运行截图
原文地址:https://blog.csdn.net/weixin_44270564/article/details/134754163
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_45036.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。