0.程序 main() 函数执行流程图

QtCreator-程序入口流程图.png

1.Restarter restarter(argc, argv)

1
2
3
4
5
6
int main(int argc, char **argv)
{
Restarter restarter(argc, argv);
......
return restarter.restartOrExit(app.exec());
}

程序重启器,用于某些配置修改后,需要重启程序才能够使配置生效。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class Restarter
{
public:
Restarter(int argc, char *argv[])
{
Q_UNUSED(argc)
m_executable = QString::fromLocal8Bit(argv[0]);
m_workingPath = QDir::currentPath();
}

void setArguments(const QStringList &args) { m_args = args; }

QString executable() const { return m_executable; }
QStringList arguments() const { return m_args; }
QString workingPath() const { return m_workingPath; }

int restartOrExit(int exitCode)
{
// 根据 "restart" 属性判断是需要重启程序
return qApp->property("restart").toBool() ? restart(exitCode) : exitCode;
}

int restart(int exitCode)
{
// 启动进程
QProcess::startDetached(m_executable, m_args, m_workingPath);
return exitCode;
}

private:
QString m_executable; // 可执行程序名称
QStringList m_args; // 可执行程序的命令参数
QString m_workingPath; // 可执行程序所在的工作目录
};

2.SharedTools::QtSingleApplication app()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
    SharedTools::QtSingleApplication app((QLatin1String(Core::Constants::IDE_DISPLAY_NAME)),
numberofArguments,
options.appArguments.data());
......
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
app.setAttribute(Qt::AA_UseHighDpiPixmaps);
app.setAttribute(Qt::AA_DisableWindowContextHelpButton);
#endif
......
QTranslator translator;
QTranslator qtTranslator;
......
app.installTranslator(&translator);
app.installTranslator(&qtTranslator);
app.setProperty("qtc_locale", locale);
......
app.setDesktopFileName("org.qt-project.qtcreator.desktop");

bool isBlock = foundAppOptions.contains(QLatin1String(BLOCK_OPTION));
if (app.isRunning() && (pid != -1 || isBlock
|| foundAppOptions.contains(QLatin1String(CLIENT_OPTION)))) {
app.setBlock(isBlock);
if (app.sendMessage(PluginManager::serializedArguments(), 5000 /*timeout*/, pid))
return 0;

// Message could not be send, maybe it was in the process of quitting
if (app.isRunning(pid)) {
// Nah app is still running, ask the user
int button = askMsgSendFailed();
while (button == QMessageBox::Retry) {
if (app.sendMessage(PluginManager::serializedArguments(), 5000 /*timeout*/, pid))
return 0;
if (!app.isRunning(pid)) // App quit while we were trying so start a new creator
button = QMessageBox::Yes;
else
button = askMsgSendFailed();
}
if (button == QMessageBox::No)
return -1;
}
}

// Set up remote arguments.
QObject::connect(&app, &SharedTools::QtSingleApplication::messageReceived,
&pluginManager, &PluginManager::remoteArguments);

QObject::connect(&app, SIGNAL(fileOpenRequest(QString)), coreplugin->plugin(),
SLOT(fileOpenRequest(QString)));

// shutdown plugin manager on the exit
QObject::connect(&app, &QCoreApplication::aboutToQuit, &pluginManager, &PluginManager::shutdown);

return restarter.restartOrExit(app.exec());

QtSingleApplication 提供了每个用户只能启动一次的应用程序的功能。
Qt 提供了解决方案组件项目 qtproject/qt-solutions https://github.com/qtproject/qt-solutions
Qt Creator 里的 QtSingleApplication 和 qt-solutions 有些不一样

qtproject/qt-solutions 提供的解决方案项目在另外的篇章展开分析:QtSingleApplication(TODO)

3.程序工作环境配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
QCoreApplication::setApplicationName(Core::Constants::IDE_CASED_ID);
QCoreApplication::setApplicationVersion(QLatin1String(Core::Constants::IDE_VERSION_LONG));
QCoreApplication::setOrganizationName(QLatin1String(Core::Constants::IDE_SETTINGSVARIANT_STR));
QGuiApplication::setApplicationDisplayName(Core::Constants::IDE_DISPLAY_NAME);

auto cleanup = qScopeGuard([] { Utils::Singleton::deleteAll(); });

const QStringList pluginArguments = app.arguments();

/*Initialize global settings and resetup install settings with QApplication::applicationDirPath */
setupInstallSettings(options.installSettingsPath);
Utils::QtcSettings *settings = createUserSettings();
// static Utils::QtcSettings *createUserSettings()
// {
// return new Utils::QtcSettings(QSettings::IniFormat,
// QSettings::UserScope,
// QLatin1String(Core::Constants::IDE_SETTINGSVARIANT_STR),
// QLatin1String(Core::Constants::IDE_CASED_ID));
// }
Utils::QtcSettings *globalSettings
= new Utils::QtcSettings(QSettings::IniFormat,
QSettings::SystemScope,
QLatin1String(Core::Constants::IDE_SETTINGSVARIANT_STR),
QLatin1String(Core::Constants::IDE_CASED_ID));
Utils::TerminalCommand::setSettings(settings);
loadFonts();
// void loadFonts()
// {
// const QDir dir(resourcePath() + "/fonts/");

// const QFileInfoList fonts = dir.entryInfoList(QStringList("*.ttf"), QDir::Files);
// for (const QFileInfo &fileInfo : fonts)
// QFontDatabase::addApplicationFont(fileInfo.absoluteFilePath());
// }

主要理解这两个代表什么就行了
QSettings::UserScope
QSettings::SystemScope

TODO:QSettings 需要另外的篇章介绍。

4.PluginManager pluginManager

1
2
3
4
5
6
7
8
9
10
11
PluginManager pluginManager;
PluginManager::setPluginIID(QLatin1String("org.qt-project.Qt.QtCreatorPlugin"));
PluginManager::setGlobalSettings(globalSettings);
PluginManager::setSettings(settings);
...
// 读取所有路径下的插件属性信息
PluginManager::setPluginPaths(pluginPaths);
...
PluginManager::checkForProblematicPlugins();
// 加载插件
PluginManager::loadPlugins();