Merge branch 'qt-launcher' of github.com:danteruiz/hifi into qt-launcher

This commit is contained in:
Ryan Huffman 2019-10-01 15:48:13 -07:00
commit 4caf55bb0f
18 changed files with 283 additions and 77 deletions

View file

@ -16,6 +16,10 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
include("cmake/init.cmake")
include("cmake/macros/SetPackagingParameters.cmake")
if (WIN32)
set(CMAKE_MFC_FLAG 1)
endif()
function(set_from_env _RESULT_NAME _ENV_VAR_NAME _DEFAULT_VALUE)
if (NOT DEFINED ${_RESULT_NAME})
@ -31,6 +35,7 @@ include(ExternalProject)
if (APPLE)
set(CMAKE_EXE_LINKER_FLAGS "-framework Cocoa -framework CoreServices -framework Carbon -framework IOKit -framework Security -framework SystemConfiguration")
add_compile_options(-W -Wall -Wextra -Wpedantic)
endif()
if (WIN32)
@ -64,8 +69,8 @@ endif ()
if (APPLE)
ExternalProject_Add(
qtlite
URL "https://dantescalves.com/launcher/qt-lite-clang-8.1.0.zip"
URL_HASH MD5=f8462bfcd54e6b05ef888f8b197149c2
URL "https://dantescalves.com/launcher/qt-lite-5.9.9-mac.zip"
URL_HASH MD5=0cd78d40e5f539a7e314cf99b6cae0d0
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
@ -139,9 +144,10 @@ set(src_files
src/Unzipper.cpp
src/Helper.h
src/Helper.cpp
src/CommandlineOptions.h
src/CommandlineOptions.cpp
deps/miniz/miniz.h
deps/miniz/miniz.cpp
${RES_SOURCES}
)
@ -165,13 +171,13 @@ set(TARGET_NAME ${PROJECT_NAME})
set_packaging_parameters()
if (WIN32)
add_executable(${PROJECT_NAME} ${src_files} ${CMAKE_CURRENT_BINARY_DIR}/resources.qrc)
add_executable(${PROJECT_NAME} ${src_files} ${RES_SOURCES})
elseif (APPLE)
set_target_properties(${this_target} PROPERTIES
MACOSX_BUNDLE_INFO_PLIST MacOSXBundleInfo.plist.in)
set(MACOSX_BUNDLE_ICON_FILE "interface.icns")
add_executable(${PROJECT_NAME} MACOSX_BUNDLE ${src_files})
add_executable(${PROJECT_NAME} MACOSX_BUNDLE ${src_files} ${RES_SOURCES})
set_target_properties(${PROJECT_NAME} PROPERTIES XCODE_ATTRIBUTE_ENABLE_BITCODE "NO")
endif()
@ -220,21 +226,14 @@ if (APPLE)
${OPENSSL_INCLUDE_DIR})
endif()
set(INTERFACE_EXEC_DIR "$<TARGET_FILE_DIR:${PROJECT_NAME}>")
set(RESOURCES_DEV_DIR "${INTERFACE_EXEC_DIR}/resources")
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
"${RESOURCES_RCC}"
"${INTERFACE_EXEC_DIR}")
if (LAUNCHER_SOURCE_TREE_RESOURCES)
target_compile_definitions(${PROJECT_NAME} PRIVATE RESOURCE_PREFIX_URL="${CMAKE_CURRENT_SOURCE_DIR}/resources/")
message("Use source tree resources path: file://${CMAKE_CURRENT_SOURCE_DIR}/resources/")
else()
target_compile_definitions(${PROJECT_NAME} PRIVATE RESOURCE_PREFIX_URL="qrc:/")
message("Use resource.rcc path: qrc:/")
endif()
if (LAUNCHER_SOURCE_TREE_RESOURCES)
target_compile_definitions(${PROJECT_NAME} PRIVATE RESOURCE_PREFIX_URL="${CMAKE_CURRENT_SOURCE_DIR}/resources/")
message("Use source tree resources path: file://${CMAKE_CURRENT_SOURCE_DIR}/resources/")
else()
target_compile_definitions(${PROJECT_NAME} PRIVATE RESOURCE_PREFIX_URL="qrc:/")
message("Use resource.rcc path: qrc:/")
endif()
target_compile_definitions(${PROJECT_NAME} PRIVATE LAUNCHER_BUILD_VERSION="${BUILD_VERSION}")

View file

@ -78,6 +78,10 @@ Item {
topMargin: 15
horizontalCenter: description.horizontalCenter
}
onClicked: {
LauncherState.restart();
}
}

View file

@ -15,7 +15,7 @@ Item {
}
Component.onCompleted: {
loader.source = LauncherState.getCurrentUISource();
loader.source = "./SplashScreen.qml";
LauncherState.updateSourceUrl.connect(function(url) {
loader.source = url;
});

View file

@ -0,0 +1,30 @@
#include "CommandlineOptions.h"
#include <algorithm>
#include <iostream>
bool isCommandlineOption(const std::string& option) {
if (option.rfind("--", 0) == 0 && option.at(2) != '-') {
return true;
}
return false;
}
bool CommandlineOptions::contains(const std::string& option) {
auto iter = std::find(_commandlineOptions.begin(), _commandlineOptions.end(), option);
return (iter != _commandlineOptions.end());
}
void CommandlineOptions::parse(const int argc, char** argv) {
for (int index = 1; index < argc; index++) {
std::string option = argv[index];
if (isCommandlineOption(option)) {
std::cout << "adding commandline option: " << option << "\n";
_commandlineOptions.push_back(option);
}
}
}
CommandlineOptions* CommandlineOptions::getInstance() {
static CommandlineOptions commandlineOptions;
return &commandlineOptions;
}

View file

@ -0,0 +1,16 @@
#pragma once
#include <string>
#include <vector>
class CommandlineOptions {
public:
CommandlineOptions() = default;
~CommandlineOptions() = default;
void parse(const int argc, char** argv);
bool contains(const std::string& option);
static CommandlineOptions* getInstance();
private:
std::vector<std::string> _commandlineOptions;
};

View file

@ -1,6 +1,10 @@
#include <QString>
#include <string>
#ifdef Q_OS_WIN
#include "Windows.h"
#endif
//#define USE_STAGING
#ifdef USE_STAGING
@ -18,6 +22,13 @@ void swapLaunchers(const QString& oldLauncherPath = QString(), const QString& ne
#ifdef Q_OS_MAC
bool replaceDirectory(const QString& orginalDirectory, const QString& newDirectory);
void closeInterfaceIfRunning();
void waitForInterfaceToClose();
bool isLauncherAlreadyRunning();
#endif
#ifdef Q_OS_WIN
HRESULT createSymbolicLink(LPCSTR lpszPathObj, LPCSTR lpszPathLink, LPCSTR lpszDesc, LPCSTR lpszArgs = (LPCSTR)"");
#endif
QString getHTTPUserAgent();

View file

@ -1,4 +1,4 @@
#include "../Helper.h"
#include "Helper.h"
#import "NSTask+NSTaskExecveAdditions.h"
@ -7,7 +7,7 @@
#include <QDebug>
void launchClient(const QString& clientPath, const QString& homePath, const QString& defaultScriptOverride,
const QString& displayName, const QString& contentCachePath, QString& loginTokenResponse) {
const QString& displayName, const QString& contentCachePath, QString loginTokenResponse) {
NSString* homeBookmark = [[NSString stringWithFormat:@"hqhome="] stringByAppendingString:homePath.toNSString()];
NSArray* arguments;
@ -70,3 +70,43 @@ bool replaceDirectory(const QString& orginalDirectory, const QString& newDirecto
return (bool) [fileManager replaceItemAtURL:[UpdaterHelper NSStringToNSURL:orginalDirectory.toNSString()] withItemAtURL:[UpdaterHelper NSStringToNSURL:newDirectory.toNSString()]
backupItemName:nil options:NSFileManagerItemReplacementUsingNewMetadataOnly resultingItemURL:&destinationUrl error:nil];
}
void waitForInterfaceToClose() {
bool interfaceRunning = true;
while (interfaceRunning) {
interfaceRunning = false;
NSWorkspace* workspace = [NSWorkspace sharedWorkspace];
NSArray* apps = [workspace runningApplications];
for (NSRunningApplication* app in apps) {
if ([[app bundleIdentifier] isEqualToString:@"com.highfidelity.interface"] ||
[[app bundleIdentifier] isEqualToString:@"com.highfidelity.interface-pr"]) {
interfaceRunning = true;
break;
}
}
}
}
bool isLauncherAlreadyRunning() {
NSArray* apps = [NSRunningApplication runningApplicationsWithBundleIdentifier:@"com.highfidelity.launcher"];
NSLog(@"Count: %lu", [apps count]);
if ([apps count] > 1) {
NSLog(@"launcher is already running");
return true;
}
return false;
}
void closeInterfaceIfRunning() {
NSWorkspace* workspace = [NSWorkspace sharedWorkspace];
NSArray* apps = [workspace runningApplications];
for (NSRunningApplication* app in apps) {
if ([[app bundleIdentifier] isEqualToString:@"com.highfidelity.interface"] ||
[[app bundleIdentifier] isEqualToString:@"com.highfidelity.interface-pr"]) {
[app terminate];
}
}
}

View file

@ -1,7 +1,12 @@
#include "Helper.h"
#include "windows.h"
#include "winnls.h"
#include "shobjidl.h"
#include "objbase.h"
#include "objidl.h"
#include "shlguid.h"
#include <QCoreApplication>
#include <Windows.h>
void launchClient(const QString& clientPath, const QString& homePath, const QString& defaultScriptsPath,
const QString& displayName, const QString& contentCachePath, QString loginResponseToken) {
@ -34,12 +39,12 @@ void launchClient(const QString& clientPath, const QString& homePath, const QStr
FALSE, // Set handle inheritance to FALSE
CREATE_NEW_CONSOLE, // Opens file in a separate console
nullptr, // Use parent's environment block
nullptr, // Use parent's starting directory
nullptr, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi // Pointer to PROCESS_INFORMATION structure
);
// Close process and thread handles.
// Close process and thread handles.
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
@ -68,3 +73,43 @@ void launchAutoUpdater(const QString& autoUpdaterPath) {
&pi // Pointer to PROCESS_INFORMATION structure
);
}
HRESULT createSymbolicLink(LPCSTR lpszPathObj, LPCSTR lpszPathLink, LPCSTR lpszDesc, LPCSTR lpszArgs) {
IShellLink* psl;
// Get a pointer to the IShellLink interface. It is assumed that CoInitialize
// has already been called.
CoInitialize(NULL);
HRESULT hres = E_INVALIDARG;
hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl);
if (SUCCEEDED(hres)) {
IPersistFile* ppf;
// Set the path to the shortcut target and add the description.
psl->SetPath(lpszPathObj);
psl->SetDescription(lpszDesc);
psl->SetArguments(lpszArgs);
// Query IShellLink for the IPersistFile interface, used for saving the
// shortcut in persistent storage.
hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf);
if (SUCCEEDED(hres)) {
WCHAR wsz[MAX_PATH];
// Ensure that the string is Unicode.
MultiByteToWideChar(CP_ACP, 0, lpszPathLink, -1, wsz, MAX_PATH);
// Add code here to check return value from MultiByteWideChar
// for success.
// Save the link by calling IPersistFile::Save.
hres = ppf->Save(wsz, TRUE);
ppf->Release();
}
psl->Release();
}
CoUninitialize();
return SUCCEEDED(hres);
}

View file

@ -9,12 +9,7 @@
#include "PathUtils.h"
Launcher::Launcher(int& argc, char**argv) : QGuiApplication(argc, argv) {
Q_INIT_RESOURCE(resources);
QString resourceBinaryLocation = QGuiApplication::applicationDirPath() + "/resources.rcc";
qDebug() << "resources.rcc path: " << resourceBinaryLocation;
QResource::registerResource(resourceBinaryLocation);
_launcherState = std::make_shared<LauncherState>();
//_launcherState->setUIState(LauncherState::SPLASH_SCREEN);
_launcherWindow = std::make_unique<LauncherWindow>();
_launcherWindow->rootContext()->setContextProperty("LauncherState", _launcherState.get());
_launcherWindow->rootContext()->setContextProperty("PathUtils", new PathUtils());

View file

@ -1,6 +1,7 @@
#include "LauncherInstaller_windows.h"
#include "Helper.h"
#include <Windows.h>
#include <string>
#include <QStandardPaths>
#include <QFileInfo>
@ -9,8 +10,11 @@
LauncherInstaller::LauncherInstaller(const QString& applicationFilePath) {
_launcherInstallDir = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + "/HQ";
_launcherApplicationsDir = QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation) + "/HQ";
qDebug() << "Launcher install dir: " << _launcherInstallDir.absolutePath();
qDebug() << "Launcher Application dir: " << _launcherApplicationsDir.absolutePath();
_launcherInstallDir.mkpath(_launcherInstallDir.absolutePath());
_launcherApplicationsDir.mkpath(_launcherApplicationsDir.absolutePath());
QFileInfo fileInfo(applicationFilePath);
_launcherRunningFilePath = fileInfo.absoluteFilePath();
_launcherRunningDirPath = fileInfo.absoluteDir().absolutePath();
@ -23,6 +27,7 @@ bool LauncherInstaller::runningOutsideOfInstallDir() {
}
void LauncherInstaller::install() {
//qDebug() << "Is install dir empty: " << _launcherInstallDir.isEmpty();
if (runningOutsideOfInstallDir()) {
qDebug() << "Installing HQ Launcher....";
QString oldLauncherPath = _launcherInstallDir.absolutePath() + "/HQ Launcher.exe";
@ -37,7 +42,61 @@ void LauncherInstaller::install() {
} else {
qDebug() << "not successful";
}
qDebug() << "LauncherInstaller: create uninstall link";
QString uninstallLinkPath = _launcherInstallDir.absolutePath() + "/Uninstall HQ.lnk";
if (QFile::exists(uninstallLinkPath)) {
QFile::remove(uninstallLinkPath);
}
QString desktopPath = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
QString applicationPath = _launcherApplicationsDir.absolutePath();
QString appStartLinkPath = applicationPath + "/HQ.lnk";
QString uninstallAppStartLinkPath = applicationPath + "/Uninstall HQ.lnk";
QString desktopAppLinkPath = desktopPath + "/HQ.lnk";
createSymbolicLink((LPCSTR)oldLauncherPath.toStdString().c_str(), (LPCSTR)uninstallLinkPath.toStdString().c_str(),
(LPCSTR)("Click to Uninstall HQ"), (LPCSTR)("--uninstall"));
createSymbolicLink((LPCSTR)oldLauncherPath.toStdString().c_str(), (LPCSTR)uninstallAppStartLinkPath.toStdString().c_str(),
(LPCSTR)("Click to Uninstall HQ"), (LPCSTR)("--uninstall"));
createSymbolicLink((LPCSTR)oldLauncherPath.toStdString().c_str(), (LPCSTR)desktopAppLinkPath.toStdString().c_str(),
(LPCSTR)("Click to Setup and Launch HQ"));
createSymbolicLink((LPCSTR)oldLauncherPath.toStdString().c_str(), (LPCSTR)appStartLinkPath.toStdString().c_str(),
(LPCSTR)("Click to Setup and Launch HQ"));
} else {
qDebug() << "FAILED!!!!!!!";
}
}
void LauncherInstaller::uninstall() {}
void LauncherInstaller::uninstall() {
qDebug() << "Uninstall Launcher";
QString desktopPath = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
QString applicationPath = _launcherApplicationsDir.absolutePath();
QString uninstallLinkPath = _launcherInstallDir.absolutePath() + "/Uninstall HQ.lnk";
if (QFile::exists(uninstallLinkPath)) {
QFile::remove(uninstallLinkPath);
}
QString appStartLinkPath = applicationPath + "/HQ.lnk";
if (QFile::exists(appStartLinkPath)) {
QFile::remove(appStartLinkPath);
}
QString uninstallAppStartLinkPath = applicationPath + "/Uninstall HQ.lnk";
if (QFile::exists(uninstallAppStartLinkPath)) {
QFile::remove(uninstallAppStartLinkPath);
}
QString desktopAppLinkPath = desktopPath + "/HQ.lnk";
if (QFile::exists(desktopAppLinkPath)) {
QFile::remove(desktopAppLinkPath);
}
}

View file

@ -8,9 +8,13 @@ public:
void install();
void uninstall();
private:
bool runningOutsideOfInstallDir();
private:
void createShortcuts();
void deleteShortcuts();
QDir _launcherInstallDir;
QDir _launcherApplicationsDir;
QString _launcherRunningFilePath;
QString _launcherRunningDirPath;
};

View file

@ -4,9 +4,6 @@
#include "Unzipper.h"
#include "Helper.h"
#ifdef Q_OS_WIN
#include <Windows.h>
#endif
#include <array>
#include <cstdlib>
@ -68,7 +65,7 @@ bool LatestBuilds::getBuild(QString tag, Build* outBuild) {
}
static const std::array<QString, LauncherState::UIState::UI_STATE_NUM> QML_FILE_FOR_UI_STATE =
{ { "SplashScreen.qml", "qml/HFBase/CreateAccountBase.qml", "qml/HFBase/LoginBase.qml", "DisplayName.qml",
{ { "qml/SplashScreen.qml", "qml/HFBase/CreateAccountBase.qml", "qml/HFBase/LoginBase.qml", "DisplayName.qml",
"qml/Download.qml", "qml/DownloadFinished.qml", "qml/HFBase/Error.qml" } };
void LauncherState::ASSERT_STATE(LauncherState::ApplicationState state) {
@ -155,12 +152,25 @@ void LauncherState::requestBuilds() {
setApplicationState(ApplicationState::RequestingBuilds);
// TODO Show splash screen until this request is complete
auto request = new QNetworkRequest(QUrl("https://thunder.highfidelity.com/builds/api/tags/latest/?format=json"));
QString latestBuildRequestUrl { "https://thunder.highfidelity.com/builds/api/tags/latest/?format=json" };
QProcessEnvironment processEnvironment =QProcessEnvironment::systemEnvironment();
if (processEnvironment.contains("HQ_LAUNCHER_BUILDS_URL")) {
latestBuildRequestUrl = processEnvironment.value("HQ_LAUNCHER_BUILDS_URL");
}
auto request = new QNetworkRequest(QUrl(latestBuildRequestUrl));
auto reply = _networkAccessManager.get(*request);
QObject::connect(reply, &QNetworkReply::finished, this, &LauncherState::receivedBuildsReply);
}
void LauncherState::restart() {
setApplicationState(ApplicationState::Init);
requestBuilds();
}
void LauncherState::receivedBuildsReply() {
auto reply = static_cast<QNetworkReply*>(sender());
@ -223,7 +233,7 @@ void LauncherState::receivedBuildsReply() {
}
if (shouldDownloadLauncher()) {
downloadLauncher();
//downloadLauncher();
}
getCurrentClientVersion();
}

View file

@ -29,9 +29,9 @@ struct LatestBuilds {
class LauncherState : public QObject {
Q_OBJECT
Q_PROPERTY(UIState uiState READ getUIState NOTIFY uiStateChanged);
Q_PROPERTY(ApplicationState applicationState READ getApplicationState NOTIFY applicationStateChanged);
Q_PROPERTY(float downloadProgress READ getDownloadProgress NOTIFY downloadProgressChanged);
Q_PROPERTY(UIState uiState READ getUIState NOTIFY uiStateChanged)
Q_PROPERTY(ApplicationState applicationState READ getApplicationState NOTIFY applicationStateChanged)
Q_PROPERTY(float downloadProgress READ getDownloadProgress NOTIFY downloadProgressChanged)
Q_PROPERTY(SignupRequest::Error lastSignupError MEMBER _lastSignupError NOTIFY lastSignupErrorChanged);
public:
@ -118,6 +118,8 @@ public:
// Request Settings
void requestSettings();
Q_INVOKABLE void restart();
// Launcher
void downloadLauncher();
void installLauncher();
@ -136,7 +138,7 @@ public:
Q_INVOKABLE float getDownloadProgress() const { return _downloadProgress; }
signals:
void updateSourceUrl(QString sourceUrl);
void updateSourceUrl(QUrl sourceUrl);
void uiStateChanged();
void applicationStateChanged();
void downloadProgressChanged();

View file

@ -15,7 +15,7 @@ toCArray(NSArray<NSString *> *array)
@throw exception;
}
char *str;
for (int i = 0; i < [array count]; i++) {
for (NSUInteger i = 0; i < [array count]; i++) {
str = (char *) [array[i] UTF8String];
if (str == NULL) {
NSException *exception = [NSException
@ -25,7 +25,7 @@ toCArray(NSArray<NSString *> *array)
@throw exception;
}
if (asprintf(&cArray[i], "%s", str) == -1) {
for (int j = 0; j < i; j++) {
for (NSUInteger j = 0; j < i; j++) {
free(cArray[j]);
}
free(cArray);
@ -54,13 +54,11 @@ toCArray(NSArray<NSString *> *array)
char** envp = toCArray(env);
// `execve` replaces the current process with `path`.
// It will only return if it fails to replace the current process.
NSLog(@"------------>");
chdir(dirname(args[0]));
execve(args[0], (char * const *)args, envp);
NSLog(@"----------- FAILED ");
// If we're here `execve` failed. :(
for (int i = 0; i < [[self arguments] count]; i++) {
for (NSUInteger i = 0; i < [[self arguments] count]; i++) {
free((void *) args[i]);
}
free((void *) args);

View file

@ -2,6 +2,6 @@
#include <QDebug>
QString PathUtils::resourcePath(const QString& source) {
return QString(RESOURCE_PREFIX_URL + source);
QUrl PathUtils::resourcePath(const QString& source) {
return QUrl(RESOURCE_PREFIX_URL + source);
}

View file

@ -2,10 +2,12 @@
#include <QObject>
#include <QString>
#include <QFile>
#include <QUrl>
class PathUtils : public QObject {
Q_OBJECT
public:
PathUtils() = default;
~PathUtils() = default;
Q_INVOKABLE static QString resourcePath(const QString& source);
Q_INVOKABLE static QUrl resourcePath(const QString& source);
};

View file

@ -49,7 +49,7 @@ void Unzipper::run() {
uint64_t totalSize = 0;
uint64_t totalCompressedSize = 0;
bool _shouldFail = false;
//bool _shouldFail = false;
for (int i = 0; i < fileCount; i++) {
if (!mz_zip_reader_file_stat(&zip_archive, i, &file_stat)) continue;

View file

@ -4,6 +4,7 @@
#include "LauncherWindow.h"
#include "Launcher.h"
#include "CommandlineOptions.h"
#include <iostream>
#include <string>
#include "Helper.h"
@ -29,46 +30,36 @@ bool hasSuffix(const std::string& path, const std::string& suffix) {
return false;
}
bool containsOption(int argc, char* argv[], const std::string& option) {
for (int index = 0; index < argc; index++) {
if (option.compare(argv[index]) == 0) {
return true;
}
}
return false;
}
int main(int argc, char *argv[]) {
//std::cout << "Launcher version: " << LAUNCHER_BUILD_VERSION;
Q_INIT_RESOURCE(resources);
#ifdef Q_OS_MAC
if (isLauncherAlreadyRunning()) {
return 0;
}
closeInterfaceIfRunning();
// waitForInterfaceToClose();
// auto updater
if (argc == 3) {
if (hasSuffix(argv[1], "app") && hasSuffix(argv[2], "app")) {
std::cout << "swapping launcher \n";
swapLaunchers(argv[1], argv[2]);
} else {
std::cout << "not swapping launcher \n";
}
}
#elif defined(Q_OS_WIN)
// try-install
if (containsOption(argc, argv, "--restart")) {
LauncherInstaller launcherInstaller(argv[0]);
#endif
CommandlineOptions* options = CommandlineOptions::getInstance();
options->parse(argc, argv);
#ifdef Q_OS_WIN
LauncherInstaller launcherInstaller(argv[0]);
if (options->contains("--restart") || launcherInstaller.runningOutsideOfInstallDir()) {
launcherInstaller.install();
} else if (options->contains("--uninstall")) {
launcherInstaller.uninstall();
return 0;
}
#endif
QString name { "High Fidelity" };
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QCoreApplication::setOrganizationName(name);
#ifdef Q_OS_WIN
//QSharedMemory sharedMemory{ applicationName };
//instanceMightBeRunning = !sharedMemory.create(1, QSharedMemory::ReadOnly);
#endif
Launcher launcher(argc, argv);
return launcher.exec();