主程序:
{
// Open the log file and install our handler.
QString logPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
logPath.append("/Revive1");
if (QDir().mkpath(logPath)) {
g_LogFile = new QFile(logPath + "/ReviveOverlay.txt");
g_LogFile->open(QIODevice::WriteOnly | QIODevice::Truncate);
// Remove obsolete log files
QDir logDir(logPath);
logDir.remove("ReviveOverlay.log");
logDir.remove("ReviveInjector.log");
}
qInstallMessageHandler(myMessageOutput);
QApplication a(argc, argv);
a.setQuitOnLastWindowClosed(false);
// Handle command-line arguments
if (a.arguments().contains("-manifest")) {
// Only initialize the manifest
vr::EVRInitError err = vr::VRInitError_None;
vr::IVRSystem *pVRSystem = vr::VR_Init( &err, vr::VRApplication_Utility );
if ( err != vr::VRInitError_None )
return -1;
QString filePath = QDir::toNativeSeparators(QCoreApplication::applicationDirPath() + "/app.vrmanifest");
vr::VRApplications()->AddApplicationManifest(qPrintable(filePath));
vr::VRApplications()->SetApplicationAutoLaunch(CReviveManifestController::SharedInstance()->AppKey, true);
vr::VR_Shutdown();
return 0;
}
// Initialize singletons
if (!COpenVROverlayController::SharedInstance()->Init())
return -1;
if (!CTrayIconController::SharedInstance()->Init())
return -1;
if (!CReviveManifestController::SharedInstance()->Init())
return -1;
// Create a QML engine.
QQmlEngine qmlEngine;
qmlEngine.rootContext()->setContextProperty("Revive", CReviveManifestController::SharedInstance());
qmlEngine.rootContext()->setContextProperty("OpenVR", COpenVROverlayController::SharedInstance());
QQmlComponent qmlComponent( &qmlEngine, QUrl("qrc:/Overlay.qml"));
if (qmlComponent.isError())
{
qDebug(qUtf8Printable(qmlComponent.errorString()));
return -1;
}
QObject *rootObject = qmlComponent.create();
QQuickItem *rootItem = qobject_cast<QQuickItem*>( rootObject );
COpenVROverlayController::SharedInstance()->SetQuickItem( rootItem );
win_sparkle_set_appcast_url("https://raw.githubusercontent.com/LibreVR/Revive/master/appcast.xml");
win_sparkle_set_can_shutdown_callback([]() { return (BOOL)!QApplication::startingUp(); });
win_sparkle_set_shutdown_request_callback([]() { CTrayIconController::SharedInstance()->quit(); });
win_sparkle_init();
QObject::connect(&a, &QApplication::aboutToQuit, win_sparkle_cleanup);
return a.exec();
}
1.QStandardPaths::writableLocation:获取程序数据存放路径,通常会将程序所需的一些数据存入注册表中。但是有时需要存储的数据太多,放在注册表中不合适,因此需要找个专门的地方来存放数据,由于将数据直接放在程序所在目录,可能程序运行时没有权限对该目录下的文件进行写操作。Qt为这点考虑引入该方法。
QString logPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
2.QDir().mkpath:无条件创建目录,它与mkdir区别为,mkdir上层目录必须存在,否则会创建失败。而mkpath如果上层目录不存在,会连上层目录一起创建。
3.g_LogFile = new QFile(logPath + "/ReviveOverlay.txt");生成文件名为ReviveOverlay.txt的一个QFile文件。到此为止会生成类似如下目录:
4.QDir用来操作路径名称,关于路径和文件的访问信息和操作底层文件系统;下面是若存在这两个文件,删除。
// Remove obsolete log files
QDir logDir(logPath);
logDir.remove("ReviveOverlay.log");
logDir.remove("ReviveInjector.log");
5.qInstallMessageHandler注册安装消息处理程序:QString的toLocal8Bit方法,返回一个系统本地编码的8位字符串,并将它存储在QByteArray字符数组中,在通过constData返回,输入到QTextStream文本流中,也就是文件ReviveOverlay.txt中,OutputDebugStringA对非控制台信息进行log信息输出。
qInstallMessageHandler(myMessageOutput);
//---------------------------
void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
QByteArray localMsg = msg.toLocal8Bit();
QTextStream log(g_LogFile);
log << localMsg.constData() << "\n";
OutputDebugStringA(localMsg.constData());
OutputDebugStringA("\n");
if (type == QtFatalMsg)
abort();
}
6.QApplication该类操作GUI应用程序的控制流程以及主设置界面。它包括主事件循环(处理以及分发Windows系统以及其他来源的所有事件),处理应用程序的初始化,结束,以及提供会话管理,还有处理大多数系统级以及应用程序级别的设置。对任何一个使用QT的应用程序,都有一个QApplication对象,无论在何时不论该应用程序是否有0个,1个还是2个甚至更多个窗口都是如此。
QApplication a(argc, argv);
7.设置在最后一个窗口关闭时,QT应用程序不退出。 a.setQuitOnLastWindowClosed,这里很重要,这是为了保持任务栏托盘图标程序处于继续运行状态。
8.a.arguments().contains("-manifest")判断参数中是否包含字符串-manifest。
9.QString filePath = QDir::toNativeSeparators(QCoreApplication::applicationDirPath() + "/app.vrmanifest") 获取app.vrmanifest的路径。
其中假设:QDir::toNativeSeparators("c:/test/app/app.vrmanifest"),它返回后会得到值c:\test\app\app.vrmanifest。QCoreApplication::applicationDirPath()获取应用程序所在目录,即执行该ReviveOverlay.exe所在目录
10.vr::VRApplications()->AddApplicationManifest(qPrintable(filePath)); //通过参数filePath添加配置文件到openVR的配置列表中。
11.vr::VRApplications()->SetApplicationAutoLaunch(CReviveManifestController::SharedInstance()->AppKey, true);//设置自动启动标志,该标志在配置文件中可找到
之后是创建QML以及使用WinSparkle检查版本更新并安装更新等。最后a.exec()执行该QT应用程序。