diff --git a/vkconfig_core/application.cpp b/vkconfig_core/application.cpp deleted file mode 100644 index 3122339e57..0000000000 --- a/vkconfig_core/application.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2020-2021 Valve Corporation - * Copyright (c) 2020-2021 LunarG, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Authors: - * - Christophe Riccio - */ - -#include "application.h" - -#include -#include -/* -Application::Application(const std::string& name, const std::string& executable_full_path, const std::string& arguments) - : app_name(name), - executable_path(executable_full_path), - working_folder(QFileInfo(executable_full_path.c_str()).path().toStdString()), - arguments(arguments), - log_file((QString(GetPath(BUILTIN_PATH_LOCAL).c_str()) + GetNativeSeparator() + - QFileInfo(executable_full_path.c_str()).baseName() + ".txt") - .toStdString() - .c_str()), - layers_mode(LAYERS_MODE_BY_CONFIGURATOR_RUNNING) {} -*/ diff --git a/vkconfig_core/application.h b/vkconfig_core/application.h deleted file mode 100644 index e230db59ff..0000000000 --- a/vkconfig_core/application.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2020-2024 Valve Corporation - * Copyright (c) 2020-2024 LunarG, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Authors: - * - Christophe Riccio - */ - -#pragma once - -#include "type_layers_mode.h" -#include "path.h" - -#include -#include - -struct ApplicationOptions { - std::string label; - Path working_folder; - std::vector arguments; - std::vector environment_variables; - Path log_file; -}; - -struct Application { - Path executable_path; - int active_option_index = 0; - std::vector options; - - ApplicationOptions& GetActiveOptions() { return this->options[active_option_index]; } - - const ApplicationOptions& GetActiveOptions() const { return this->options[active_option_index]; } -}; diff --git a/vkconfig_core/application_manager.cpp b/vkconfig_core/application_manager.cpp deleted file mode 100644 index 974198f104..0000000000 --- a/vkconfig_core/application_manager.cpp +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2020-2024 Valve Corporation - * Copyright (c) 2020-2024 LunarG, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Authors: - * - Christophe Riccio - */ - -#include "application_manager.h" diff --git a/vkconfig_core/application_manager.h b/vkconfig_core/application_manager.h deleted file mode 100644 index 8264ae2b2a..0000000000 --- a/vkconfig_core/application_manager.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2020-2024 Valve Corporation - * Copyright (c) 2020-2024 LunarG, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Authors: - * - Christophe Riccio - */ - -#pragma once - -class ApplicationManager { - public: - private: -}; diff --git a/vkconfig_core/configuration_manager.cpp b/vkconfig_core/configuration_manager.cpp index ac70a3f3e6..82f609f7b1 100644 --- a/vkconfig_core/configuration_manager.cpp +++ b/vkconfig_core/configuration_manager.cpp @@ -36,9 +36,9 @@ bool ConfigurationManager::Load(const QJsonObject &json_root_object) { // configurations json object if (json_root_object.value("configurations") != QJsonValue::Undefined) { const QJsonObject &json_configurations_object = json_root_object.value("configurations").toObject(); - this->use_per_application_configuration = json_configurations_object.value("use_per_application").toBool(); + this->use_per_executable_configuration = json_configurations_object.value("use_per_executable").toBool(); this->use_system_tray = json_configurations_object.value("use_system_tray").toBool(); - this->active_application = json_configurations_object.value("active_application").toString().toStdString(); + this->active_executable = json_configurations_object.value("active_application").toString().toStdString(); if (json_configurations_object.value("infos") != QJsonValue::Undefined) { this->configuration_infos.clear(); @@ -90,9 +90,9 @@ bool ConfigurationManager::Save(QJsonObject &json_root_object) const { } QJsonObject json_configurations_object; - json_configurations_object.insert("use_per_application", this->use_per_application_configuration); + json_configurations_object.insert("use_per_executable", this->use_per_executable_configuration); json_configurations_object.insert("use_system_tray", this->use_system_tray); - json_configurations_object.insert("active_application", this->active_application.c_str()); + json_configurations_object.insert("active_executable", this->active_executable.c_str()); json_configurations_object.insert("infos", json_infos_object); json_configurations_object.insert("removed_builtin", json_removed_builtin_configurations_object); @@ -103,9 +103,9 @@ bool ConfigurationManager::Save(QJsonObject &json_root_object) const { void ConfigurationManager::Reset() { this->removed_built_in_configuration.clear(); - this->use_per_application_configuration = false; + this->use_per_executable_configuration = false; this->use_system_tray = false; - this->active_application.clear(); + this->active_executable.clear(); this->configuration_infos.clear(); this->available_configurations.clear(); @@ -212,16 +212,16 @@ void ConfigurationManager::SaveAllConfigurations() const { } const ConfigurationInfo *ConfigurationManager::GetActiveConfigurationInfo() const { - if (this->use_per_application_configuration) { - return &this->configuration_infos.find(this->active_application.c_str())->second; + if (this->use_per_executable_configuration) { + return &this->configuration_infos.find(this->active_executable.c_str())->second; } else { return &this->configuration_infos.find(GLOBAL_CONFIGURATION_TOKEN)->second; } } ConfigurationInfo *ConfigurationManager::GetActiveConfigurationInfo() { - if (this->use_per_application_configuration) { - return &this->configuration_infos.find(this->active_application.c_str())->second; + if (this->use_per_executable_configuration) { + return &this->configuration_infos.find(this->active_executable.c_str())->second; } else { return &this->configuration_infos.find(GLOBAL_CONFIGURATION_TOKEN)->second; } @@ -376,6 +376,8 @@ const Configuration *ConfigurationManager::FindConfiguration(const std::string & void ConfigurationManager::ImportConfiguration(const LayerManager &layers, const Path &full_import_path) { assert(!full_import_path.Empty()); + this->last_path_import = full_import_path; + Configuration configuration; if (!configuration.Load(full_import_path, layers)) { QMessageBox msg; @@ -399,6 +401,8 @@ void ConfigurationManager::ExportConfiguration(const LayerManager &layers, const assert(!configuration_name.empty()); assert(!full_export_path.Empty()); + this->last_path_export = full_export_path; + Configuration *configuration = this->FindConfiguration(configuration_name); assert(configuration); @@ -460,9 +464,9 @@ bool ConfigurationManager::CompareLayersVersions(const std::vector &avail return result; } -bool ConfigurationManager::GetPerApplicationConfig() const { return this->use_per_application_configuration; } +bool ConfigurationManager::GetPerExecutableConfig() const { return this->use_per_executable_configuration; } -void ConfigurationManager::SetPerApplicationConfig(bool enabled) { this->use_per_application_configuration = enabled; } +void ConfigurationManager::SetPerExecutableConfig(bool enabled) { this->use_per_executable_configuration = enabled; } bool ConfigurationManager::GetUseSystemTray() const { return this->use_system_tray; } diff --git a/vkconfig_core/configuration_manager.h b/vkconfig_core/configuration_manager.h index fdf54bbc49..840ee1e6c6 100644 --- a/vkconfig_core/configuration_manager.h +++ b/vkconfig_core/configuration_manager.h @@ -70,13 +70,15 @@ class ConfigurationManager : public Serialize { bool HasFile(const Configuration& configuration) const; void RemoveConfigurationFile(const std::string& key); - bool GetPerApplicationConfig() const; - void SetPerApplicationConfig(bool enabled); + bool GetPerExecutableConfig() const; + void SetPerExecutableConfig(bool enabled); bool GetUseSystemTray() const; void SetUseSystemTray(bool enabled); std::vector available_configurations; + Path last_path_import; + Path last_path_export; private: bool CompareLayersVersions(const std::vector& available_layers, Configuration* selected_configuration, @@ -89,7 +91,7 @@ class ConfigurationManager : public Serialize { std::map removed_built_in_configuration; bool use_system_tray = false; - bool use_per_application_configuration = false; - std::string active_application; + bool use_per_executable_configuration = false; + std::string active_executable; std::map configuration_infos; }; diff --git a/vkconfig_core/configurator.cpp b/vkconfig_core/configurator.cpp index 844b9f255f..db7a6e67c1 100644 --- a/vkconfig_core/configurator.cpp +++ b/vkconfig_core/configurator.cpp @@ -215,7 +215,7 @@ bool Configurator::WriteLoaderSettings(OverrideArea override_area, const Path& l const std::map& infos = this->configurations.GetConfigurationInfos(); for (auto it = infos.begin(), end = infos.end(); it != end; ++it) { - if (this->configurations.GetPerApplicationConfig()) { + if (this->configurations.GetPerExecutableConfig()) { if (it->first == GLOBAL_CONFIGURATION_TOKEN) { continue; } @@ -264,15 +264,14 @@ bool Configurator::WriteLayersSettings(OverrideArea override_area, const Path& l if (override_area & OVERRIDE_AREA_LAYERS_SETTINGS_BIT) { std::vector layers_settings_array; - if (this->configurations.GetPerApplicationConfig()) { - const std::vector& applications = this->environment.GetApplications(); + if (this->configurations.GetPerExecutableConfig()) { + const std::vector& executables = this->executables.GetExecutables(); - for (std::size_t i = 0, n = applications.size(); i < n; ++i) { + for (std::size_t i = 0, n = executables.size(); i < n; ++i) { LayersSettings settings; - settings.configuration_name = - this->configurations.FindConfigurationInfo(applications[i].executable_path.AbsolutePath())->name; - settings.executable_path = applications[i].executable_path; - settings.settings_path = applications[i].GetActiveOptions().working_folder; + settings.configuration_name = this->configurations.FindConfigurationInfo(executables[i].path.AbsolutePath())->name; + settings.executable_path = executables[i].path; + settings.settings_path = executables[i].GetActiveOptions().working_folder; layers_settings_array.push_back(settings); } } else { diff --git a/vkconfig_core/configurator.h b/vkconfig_core/configurator.h index 65dfef3e73..8ce2369c67 100644 --- a/vkconfig_core/configurator.h +++ b/vkconfig_core/configurator.h @@ -22,10 +22,10 @@ #pragma once #include "../vkconfig_core/version.h" -#include "../vkconfig_core/layer.h" +#include "../vkconfig_core/configuration_manager.h" #include "../vkconfig_core/layer_manager.h" +#include "../vkconfig_core/executable_manager.h" #include "../vkconfig_core/environment.h" -#include "../vkconfig_core/configuration_manager.h" #include "../vkconfig_core/type_platform.h" #include "../vkconfig_core/type_override_area.h" #include "../vkconfig_core/vulkan_info.h" @@ -85,5 +85,6 @@ class Configurator { Environment environment; LayerManager layers; ConfigurationManager configurations; + ExecutableManager executables; VulkanSystemInfo vulkan_system_info; }; diff --git a/vkconfig_core/environment.cpp b/vkconfig_core/environment.cpp index f0c4b9d9dd..0cd1221a68 100644 --- a/vkconfig_core/environment.cpp +++ b/vkconfig_core/environment.cpp @@ -39,29 +39,11 @@ #include #include -static const char* GetApplicationSuffix() { - static const char* TABLE[] = { - ".exe", // PLATFORM_WINDOWS_X86 - ".exe", // PLATFORM_WINDOWS_ARM - "", // PLATFORM_LINUX - ".app", // PLATFORM_MACOS - "N/A", // PLATFORM_ANDROID - "N/A" // PLATFORM_IOS - }; - static_assert(std::size(TABLE) == PLATFORM_COUNT, "The tranlation table size doesn't match the enum number of elements"); - - return TABLE[VKC_PLATFORM]; -} - Environment::Environment() {} Environment::~Environment() {} -void Environment::Reset() { - this->loader_message_types_flags = ::GetLogFlags(qgetenv("VK_LOADER_DEBUG").toStdString()); - this->active_executable_index = 0; - this->applications = CreateDefaultApplications(); -} +void Environment::Reset() { this->loader_message_types_flags = ::GetLogFlags(qgetenv("VK_LOADER_DEBUG").toStdString()); } std::string GetPath() { static const char* TABLE[] = { @@ -94,50 +76,6 @@ bool Environment::Load(const QJsonObject& json_root_object) { this->loader_message_types_flags |= GetLogBit(token.c_str()); } - // applications json object - const QJsonObject& json_applications_object = json_root_object.value("applications").toObject(); - - this->active_executable_index = json_applications_object.value("active_executable_index").toInt(); - - const QJsonObject& json_list_object = json_applications_object.value("list").toObject(); - - const QStringList& json_list_keys = json_list_object.keys(); - - this->applications.clear(); - for (int i = 0, n = json_list_keys.length(); i < n; ++i) { - Application application; - - const QJsonObject& json_application_object = json_list_object.value(json_list_keys[i]).toObject(); - application.executable_path = json_list_keys[i].toStdString(); - application.active_option_index = json_application_object.value("active_option_index").toInt(); - - const QJsonArray& json_options_array = json_application_object.value("options").toArray(); - for (int j = 0, o = json_options_array.size(); j < o; ++j) { - const QJsonObject& json_options_object = json_options_array[j].toObject(); - - ApplicationOptions application_options; - - application_options.label = json_options_object.value("label").toString().toStdString(); - application_options.working_folder = json_options_object.value("working_folder").toString().toStdString(); - - const QJsonArray& json_command_lines_array = json_options_object.value("arguments").toArray(); - for (int k = 0, p = json_command_lines_array.size(); k < p; ++k) { - application_options.arguments.push_back(json_command_lines_array[k].toString().toStdString()); - } - - const QJsonArray& json_environment_variables_array = json_options_object.value("environment_variables").toArray(); - for (int k = 0, p = json_environment_variables_array.size(); k < p; ++k) { - application_options.environment_variables.push_back(json_environment_variables_array[k].toString().toStdString()); - } - - application_options.log_file = json_options_array[j].toObject().value("log_file").toString().toStdString(); - - application.options.push_back(application_options); - } - - this->applications.push_back(application); - } - // preferences json object const QJsonObject& json_preferences_object = json_root_object.value("preferences").toObject(); this->home_sdk_path = json_preferences_object.value("VK_HOME").toString().toStdString(); @@ -152,10 +90,6 @@ bool Environment::Load(const QJsonObject& json_root_object) { this->hide_message_boxes_flags |= GetLogBit(token.c_str()); } - if (this->applications.empty()) { - this->applications = CreateDefaultApplications(); - } - return true; } @@ -180,48 +114,6 @@ bool Environment::Save(QJsonObject& json_root_object) const { json_root_object.insert("diagnostic", json_diagnostic_object); - QJsonObject json_applications_object; - json_applications_object.insert("active_executable", this->active_executable_index); - QJsonObject json_applications_list_object; - - for (std::size_t i = 0, n = this->applications.size(); i < n; ++i) { - const Application& application = this->applications[i]; - - QJsonObject json_application_object; - json_application_object.insert("active_option", application.active_option_index); - - QJsonArray json_options_array; - for (std::size_t j = 0, o = application.options.size(); j < o; ++j) { - const ApplicationOptions& options = application.options[j]; - - QJsonArray json_arg_array; - for (std::size_t k = 0, p = options.arguments.size(); k < p; ++k) { - json_arg_array.append(options.arguments[k].c_str()); - } - - QJsonArray json_env_array; - for (std::size_t k = 0, p = options.environment_variables.size(); k < p; ++k) { - json_env_array.append(options.environment_variables[k].c_str()); - } - - QJsonObject json_option_object; - json_option_object.insert("label", options.label.c_str()); - json_option_object.insert("working_folder", options.working_folder.RelativePath().c_str()); - json_option_object.insert("arguments", json_arg_array); - json_option_object.insert("environment_variables", json_env_array); - json_option_object.insert("log_file", options.log_file.RelativePath().c_str()); - - json_options_array.append(json_option_object); - } - json_application_object.insert("options", json_options_array); - - json_applications_list_object.insert(application.executable_path.RelativePath().c_str(), json_application_object); - } - - json_applications_object.insert("list", json_applications_list_object); - - json_root_object.insert("applications", json_applications_object); - QJsonObject json_preferences_object; json_preferences_object.insert("VK_HOME", this->home_sdk_path.RelativePath().c_str()); @@ -238,261 +130,3 @@ bool Environment::Save(QJsonObject& json_root_object) const { return true; } - -void Environment::SelectActiveApplication(std::size_t application_index) { - assert(application_index < this->applications.size()); - this->active_executable_index = application_index; -} - -int Environment::GetActiveApplicationIndex() const { - return this->active_executable_index; // Not found, but the list is present, so return the first item. -} - -bool Environment::AppendApplication(const Application& application) { - this->applications.push_back(application); - return true; -} - -bool Environment::RemoveApplication(std::size_t application_index) { - assert(!this->applications.empty()); - assert(application_index < this->applications.size()); - - if (this->applications.size() == 1u) { - this->applications.clear(); - return true; - } - - std::vector new_applications; - new_applications.reserve(this->applications.size() - 1); - - for (std::size_t i = 0, n = this->applications.size(); i < n; ++i) { - if (i == application_index) { - continue; - } - new_applications.push_back(this->applications[i]); - } - - std::swap(this->applications, new_applications); - return true; -} - -const Application& Environment::GetActiveApplication() const { - assert(!this->applications.empty()); - - return this->applications[this->active_executable_index]; // Not found, but the list is present, so return the first item. -} - -Application& Environment::GetActiveApplication() { - assert(!this->applications.empty()); - - return this->applications[this->active_executable_index]; // Not found, but the list is present, so return the first item. -} - -const Application& Environment::GetApplication(std::size_t application_index) const { - assert(application_index < this->applications.size()); - - return this->applications[application_index]; -} - -Application& Environment::GetApplication(std::size_t application_index) { - assert(application_index < this->applications.size()); - - return this->applications[application_index]; -} - -/////////////////////////////////////////////////////////////////////////// -/// This is only used on macOS to extract the executable from the bundle. -/// You have to look at the plist.info file, you can't just assume whatever -/// you find in the /MacOS folder is the executable. -/// The initial path is the folder where info.plist resides, and the -/// path is completed to the executable upon completion. -/// Note, not ALL macOS executables are in a bundle, so if a non-bundled -/// executable is fed in here, it will silently just return without -/// modifying the path (which will be the correct behavior) -bool ExactExecutableFromAppBundle(Path& app_path) { - std::string path = app_path.AbsolutePath(); - path += "/Contents/"; - std::string list_file = path + "Info.plist"; - QFile file(list_file.c_str()); - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - return false; - } - - QTextStream stream(&file); - - // Read a line at a time looking for the executable tag - QString line_buffer; - while (!stream.atEnd()) { - line_buffer = stream.readLine(); - if (line_buffer.contains("CFBundleExecutable")) { // Exe follows this - line_buffer = stream.readLine(); // Qt Creator - char* cExeName = new char[line_buffer.length()]; // Prevent buffer overrun - - QByteArray line_array = line_buffer.toUtf8(); - const char* pStart = strstr(line_array.constData(), ""); - if (pStart == nullptr) return false; - - // We found it, now extract it out - pStart += 8; - int iIndex = 0; - while (*pStart != '<') { - cExeName[iIndex++] = *pStart++; - } - cExeName[iIndex] = '\0'; - - // Complete the partial path - path += "MacOS/"; - path += cExeName; - - // Return original if not found, but root if found - app_path = Path(path); - - delete[] cExeName; - break; - } - } - - file.close(); - - return true; -} - -DefaultPath Environment::GetDefaultExecutablePath(const std::string& executable_name) const { - static const char* DEFAULT_PATH = VKC_PLATFORM == PLATFORM_MACOS ? "/../.." : ""; - - DefaultPath default_path{"." + executable_name, "."}; - - // Using VULKAN_SDK environement variable - const Path env = ::Get(Path::SDK_BIN); - if (!env.Empty()) { - const Path search_path(env + DEFAULT_PATH + executable_name.c_str()); - if (search_path.Exists()) { - default_path.executable_path = Path(search_path.AbsolutePath(), true); - default_path.working_folder = Path(search_path.AbsoluteDir(), true); - return default_path; - } - } - - // Search the default applications from package installation (Linux) - if (VKC_PLATFORM == PLATFORM_LINUX) { - const Path search_path(std::string("/usr/bin") + DEFAULT_PATH + executable_name); - if (search_path.Exists()) { - default_path.executable_path = Path(search_path.AbsolutePath(), true); - default_path.working_folder = Path(search_path.AbsoluteDir(), true); - return default_path; - } - } else if (VKC_PLATFORM == PLATFORM_MACOS) { - Path search_path(std::string("/Applications") + executable_name); - if (search_path.Exists() && ExactExecutableFromAppBundle(search_path)) { - default_path.executable_path = Path(search_path.AbsolutePath(), true); - default_path.working_folder = Path(search_path.AbsoluteDir(), true); - return default_path; - } - } - - // Using relative path to vkconfig in case SDK is not "installed" - if (VKC_PLATFORM == PLATFORM_MACOS) { - Path search_path(std::string("..") + DEFAULT_PATH + executable_name); - if (search_path.Exists() && ExactExecutableFromAppBundle(search_path)) { - default_path.executable_path = Path(search_path.AbsolutePath(), true); - default_path.working_folder = Path(search_path.AbsoluteDir(), true); - return default_path; - } - } else { - Path search_path(std::string(".") + DEFAULT_PATH + executable_name); - if (search_path.Exists()) { - default_path.executable_path = Path(search_path.AbsolutePath(), true); - default_path.working_folder = Path(search_path.AbsoluteDir(), true); - return default_path; - } - } - - return default_path; -} - -static const DefaultApplication defaults_applications[] = {{"vkcube", "/vkcube", "--suppress_popups"}, - {"vkcubepp", "/vkcubepp", "--suppress_popups"}}; - -Application Environment::CreateDefaultApplication(const DefaultApplication& default_application) const { - const DefaultPath& default_paths = GetDefaultExecutablePath((default_application.key + GetApplicationSuffix()).c_str()); - if (default_paths.executable_path.Empty()) { - Application(); // application could not be found.. - } - - ApplicationOptions options; - options.label = "Default"; - options.working_folder = default_paths.working_folder; - // On all operating systems, but Windows we keep running into problems with this ending up - // somewhere the user isn't allowed to create and write files. For consistncy sake, the log - // initially will be set to the users home folder across all OS's. This is highly visible - // in the application launcher and should not present a usability issue. The developer can - // easily change this later to anywhere they like. - options.log_file = std::string("${VK_LOCAL}") + default_application.key + ".txt"; - - Application application; - application.executable_path = Path(default_paths.executable_path.AbsolutePath(), true); - application.options.push_back(options); - application.active_option_index = 0; - - return application; -} - -std::vector Environment::CreateDefaultApplications() const { - std::vector new_applications; - - for (std::size_t name_index = 0, name_count = std::size(defaults_applications); name_index < name_count; ++name_index) { - const Application& application = CreateDefaultApplication(defaults_applications[name_index]); - - if (application.executable_path.Empty()) { - continue; - } - - new_applications.push_back(application); - } - - return new_applications; -} - -std::vector Environment::RemoveMissingApplications(const std::vector& applications) const { - std::vector valid_applications; - - // Remove applications that can't be found - for (std::size_t i = 0, n = applications.size(); i < n; ++i) { - const Application& application = applications[i]; - - const QFileInfo file_info(application.executable_path.AbsolutePath().c_str()); - if (!file_info.exists()) { - continue; - } - - valid_applications.push_back(application); - } - - return valid_applications; -} - -std::vector Environment::UpdateDefaultApplications(const std::vector& applications) const { - std::vector search_applications; - std::vector updated_applications = applications; - - for (std::size_t default_index = 0, default_count = std::size(defaults_applications); default_index < default_count; - ++default_index) { - const std::string defaults_name = defaults_applications[default_index].key + GetApplicationSuffix(); - - std::swap(updated_applications, search_applications); - updated_applications.clear(); - - for (std::size_t application_index = 0, application_count = search_applications.size(); - application_index < application_count; ++application_index) { - const Application& application = search_applications[application_index]; - - if (QString(application.executable_path.AbsolutePath().c_str()).endsWith(defaults_name.c_str())) { - updated_applications.push_back(CreateDefaultApplication(defaults_applications[default_index])); - } else { - updated_applications.push_back(application); - } - } - } - - return updated_applications; -} diff --git a/vkconfig_core/environment.h b/vkconfig_core/environment.h index 730e49f0e1..2bdbb6d39c 100644 --- a/vkconfig_core/environment.h +++ b/vkconfig_core/environment.h @@ -21,9 +21,9 @@ #pragma once #include "version.h" -#include "application.h" #include "type_tab.h" #include "type_log.h" +#include "path.h" #include "serialization.h" #include @@ -32,17 +32,6 @@ #include #include -struct DefaultApplication { - std::string name; - std::string key; - std::string arguments; -}; - -struct DefaultPath { - Path executable_path; - Path working_folder; -}; - class Environment : public Serialize { public: Environment(); @@ -52,31 +41,12 @@ class Environment : public Serialize { bool Save(QJsonObject& json_root_object) const override; void Reset() override; - void SelectActiveApplication(std::size_t application_index); - int GetActiveApplicationIndex() const; - bool AppendApplication(const Application& application); - bool RemoveApplication(std::size_t application_index); - - const std::vector& GetApplications() const { return applications; } - const Application& GetActiveApplication() const; - Application& GetActiveApplication(); - const Application& GetApplication(std::size_t application_index) const; - Application& GetApplication(std::size_t application_index); - LogFlags GetLoaderMessageFlags() const { return this->loader_message_types_flags; } void SetLoaderMessageFlags(LogFlags flags) { this->loader_message_types_flags = flags; } - // Search for all the applications in the list, an remove the application which executable can't be found - std::vector RemoveMissingApplications(const std::vector& applications) const; - bool has_crashed = false; int hide_message_boxes_flags = 0; - Path path_export; - Path path_import; - - bool launcher_clear_on_launch = true; - private: Environment(const Environment&) = delete; Environment& operator=(const Environment&) = delete; @@ -84,17 +54,4 @@ class Environment : public Serialize { TabType active_tab = TAB_DIAGNOSTIC; LogFlags loader_message_types_flags; Path home_sdk_path; - - int active_executable_index; - std::vector applications; - - // Update default applications path to use relative path (really useful only on Windows) - std::vector UpdateDefaultApplications(const std::vector& applications) const; - - // Create a list of default applications, eg vkcube - std::vector CreateDefaultApplications() const; - Application CreateDefaultApplication(const DefaultApplication& default_application) const; - DefaultPath GetDefaultExecutablePath(const std::string& executable_name) const; }; - -bool ExactExecutableFromAppBundle(Path& path); diff --git a/vkconfig_core/executable_manager.cpp b/vkconfig_core/executable_manager.cpp new file mode 100644 index 0000000000..3bdcb95886 --- /dev/null +++ b/vkconfig_core/executable_manager.cpp @@ -0,0 +1,375 @@ +/* + * Copyright (c) 2020-2024 Valve Corporation + * Copyright (c) 2020-2024 LunarG, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Authors: + * - Christophe Riccio + */ + +#include "executable_manager.h" +#include "version.h" +#include "type_platform.h" + +#include + +static const char* GetExecutableSuffix() { + static const char* TABLE[] = { + ".exe", // PLATFORM_WINDOWS_X86 + ".exe", // PLATFORM_WINDOWS_ARM + "", // PLATFORM_LINUX + ".app", // PLATFORM_MACOS + "N/A", // PLATFORM_ANDROID + "N/A" // PLATFORM_IOS + }; + static_assert(std::size(TABLE) == PLATFORM_COUNT, "The tranlation table size doesn't match the enum number of elements"); + + return TABLE[VKC_PLATFORM]; +} + +static const DefaultExecutable defaults_executables[] = {{"vkcube", "/vkcube", "--suppress_popups"}, + {"vkcubepp", "/vkcubepp", "--suppress_popups"}}; + +void ExecutableManager::Reset() { + this->active_executable_index = 0; + this->executables = this->CreateDefaultExecutables(); +} + +bool ExecutableManager::Load(const QJsonObject& json_root_object) { + // applications json object + const QJsonObject& json_executables_object = json_root_object.value("executables").toObject(); + + this->active_executable_index = json_executables_object.value("active_executable_index").toInt(); + + const QJsonObject& json_list_object = json_executables_object.value("list").toObject(); + + const QStringList& json_list_keys = json_list_object.keys(); + + this->executables.clear(); + for (int i = 0, n = json_list_keys.length(); i < n; ++i) { + Executable executable; + + const QJsonObject& json_application_object = json_list_object.value(json_list_keys[i]).toObject(); + executable.path = json_list_keys[i].toStdString(); + executable.active_option_index = json_application_object.value("active_option_index").toInt(); + + const QJsonArray& json_options_array = json_application_object.value("options").toArray(); + for (int j = 0, o = json_options_array.size(); j < o; ++j) { + const QJsonObject& json_options_object = json_options_array[j].toObject(); + + ExecutableOptions executable_options; + + executable_options.label = json_options_object.value("label").toString().toStdString(); + executable_options.working_folder = json_options_object.value("working_folder").toString().toStdString(); + + const QJsonArray& json_command_lines_array = json_options_object.value("arguments").toArray(); + for (int k = 0, p = json_command_lines_array.size(); k < p; ++k) { + executable_options.arguments.push_back(json_command_lines_array[k].toString().toStdString()); + } + + const QJsonArray& json_environment_variables_array = json_options_object.value("environment_variables").toArray(); + for (int k = 0, p = json_environment_variables_array.size(); k < p; ++k) { + executable_options.environment_variables.push_back(json_environment_variables_array[k].toString().toStdString()); + } + + executable_options.log_file = json_options_array[j].toObject().value("log_file").toString().toStdString(); + + executable.options.push_back(executable_options); + } + + this->executables.push_back(executable); + } + + if (this->executables.empty()) { + this->executables = CreateDefaultExecutables(); + } + + return true; +} + +bool ExecutableManager::Save(QJsonObject& json_root_object) const { + QJsonObject json_executables_object; + json_executables_object.insert("active_executable", this->active_executable_index); + + QJsonObject json_executables_list_object; + for (std::size_t i = 0, n = this->executables.size(); i < n; ++i) { + const Executable& executable = this->executables[i]; + + QJsonObject json_executable_object; + json_executable_object.insert("active_option", executable.active_option_index); + + QJsonArray json_options_array; + for (std::size_t j = 0, o = executable.options.size(); j < o; ++j) { + const ExecutableOptions& options = executable.options[j]; + + QJsonArray json_arg_array; + for (std::size_t k = 0, p = options.arguments.size(); k < p; ++k) { + json_arg_array.append(options.arguments[k].c_str()); + } + + QJsonArray json_env_array; + for (std::size_t k = 0, p = options.environment_variables.size(); k < p; ++k) { + json_env_array.append(options.environment_variables[k].c_str()); + } + + QJsonObject json_option_object; + json_option_object.insert("label", options.label.c_str()); + json_option_object.insert("layers_mode", GetToken(options.layers_mode)); + json_option_object.insert("configuration", options.configuration.c_str()); + json_option_object.insert("working_folder", options.working_folder.RelativePath().c_str()); + json_option_object.insert("arguments", json_arg_array); + json_option_object.insert("environment_variables", json_env_array); + json_option_object.insert("log_file", options.log_file.RelativePath().c_str()); + + json_options_array.append(json_option_object); + } + json_executable_object.insert("options", json_options_array); + + json_executables_list_object.insert(executable.path.RelativePath().c_str(), json_executable_object); + } + + json_executables_object.insert("list", json_executables_list_object); + + json_root_object.insert("executables", json_executables_object); + + return true; +} + +void ExecutableManager::SelectActiveExecutable(std::size_t executable_index) { + assert(executable_index < this->executables.size()); + this->active_executable_index = executable_index; +} + +int ExecutableManager::GetActiveExecutableIndex() const { + return this->active_executable_index; // Not found, but the list is present, so return the first item. +} + +bool ExecutableManager::AppendExecutable(const Executable& executable) { + this->executables.push_back(executable); + return true; +} + +bool ExecutableManager::RemoveExecutable(std::size_t executable_index) { + assert(!this->executables.empty()); + assert(executable_index < this->executables.size()); + + if (this->executables.size() == 1u) { + this->executables.clear(); + return true; + } + + std::vector new_executables; + new_executables.reserve(this->executables.size() - 1); + + for (std::size_t i = 0, n = this->executables.size(); i < n; ++i) { + if (i == executable_index) { + continue; + } + new_executables.push_back(this->executables[i]); + } + + std::swap(this->executables, new_executables); + return true; +} + +const Executable& ExecutableManager::GetActiveExecutable() const { + assert(!this->executables.empty()); + + return this->executables[this->active_executable_index]; // Not found, but the list is present, so return the first item. +} + +Executable& ExecutableManager::GetActiveExecutable() { + assert(!this->executables.empty()); + + return this->executables[this->active_executable_index]; // Not found, but the list is present, so return the first item. +} + +const Executable& ExecutableManager::GetExecutable(std::size_t executable_index) const { + assert(executable_index < this->executables.size()); + + return this->executables[executable_index]; +} + +Executable& ExecutableManager::GetExecutable(std::size_t executable_index) { + assert(executable_index < this->executables.size()); + + return this->executables[executable_index]; +} + +/////////////////////////////////////////////////////////////////////////// +/// This is only used on macOS to extract the executable from the bundle. +/// You have to look at the plist.info file, you can't just assume whatever +/// you find in the /MacOS folder is the executable. +/// The initial path is the folder where info.plist resides, and the +/// path is completed to the executable upon completion. +/// Note, not ALL macOS executables are in a bundle, so if a non-bundled +/// executable is fed in here, it will silently just return without +/// modifying the path (which will be the correct behavior) +bool ExactExecutableFromAppBundle(Path& app_path) { + std::string path = app_path.AbsolutePath(); + path += "/Contents/"; + std::string list_file = path + "Info.plist"; + QFile file(list_file.c_str()); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + return false; + } + + QTextStream stream(&file); + + // Read a line at a time looking for the executable tag + QString line_buffer; + while (!stream.atEnd()) { + line_buffer = stream.readLine(); + if (line_buffer.contains("CFBundleExecutable")) { // Exe follows this + line_buffer = stream.readLine(); // Qt Creator + char* cExeName = new char[line_buffer.length()]; // Prevent buffer overrun + + QByteArray line_array = line_buffer.toUtf8(); + const char* pStart = strstr(line_array.constData(), ""); + if (pStart == nullptr) return false; + + // We found it, now extract it out + pStart += 8; + int iIndex = 0; + while (*pStart != '<') { + cExeName[iIndex++] = *pStart++; + } + cExeName[iIndex] = '\0'; + + // Complete the partial path + path += "MacOS/"; + path += cExeName; + + // Return original if not found, but root if found + app_path = Path(path); + + delete[] cExeName; + break; + } + } + + file.close(); + + return true; +} + +DefaultPath ExecutableManager::GetDefaultExecutablePath(const std::string& executable_name) const { + static const char* DEFAULT_PATH = VKC_PLATFORM == PLATFORM_MACOS ? "/../.." : ""; + + DefaultPath default_path{"." + executable_name, "."}; + + // Using VULKAN_SDK environement variable + const Path env = ::Get(Path::SDK_BIN); + if (!env.Empty()) { + const Path search_path(env + DEFAULT_PATH + executable_name.c_str()); + if (search_path.Exists()) { + default_path.executable_path = Path(search_path.AbsolutePath(), true); + default_path.working_folder = Path(search_path.AbsoluteDir(), true); + return default_path; + } + } + + // Search the default applications from package installation (Linux) + if (VKC_PLATFORM == PLATFORM_LINUX) { + const Path search_path(std::string("/usr/bin") + DEFAULT_PATH + executable_name); + if (search_path.Exists()) { + default_path.executable_path = Path(search_path.AbsolutePath(), true); + default_path.working_folder = Path(search_path.AbsoluteDir(), true); + return default_path; + } + } else if (VKC_PLATFORM == PLATFORM_MACOS) { + Path search_path(std::string("/Applications") + executable_name); + if (search_path.Exists() && ExactExecutableFromAppBundle(search_path)) { + default_path.executable_path = Path(search_path.AbsolutePath(), true); + default_path.working_folder = Path(search_path.AbsoluteDir(), true); + return default_path; + } + } + + // Using relative path to vkconfig in case SDK is not "installed" + if (VKC_PLATFORM == PLATFORM_MACOS) { + Path search_path(std::string("..") + DEFAULT_PATH + executable_name); + if (search_path.Exists() && ExactExecutableFromAppBundle(search_path)) { + default_path.executable_path = Path(search_path.AbsolutePath(), true); + default_path.working_folder = Path(search_path.AbsoluteDir(), true); + return default_path; + } + } else { + Path search_path(std::string(".") + DEFAULT_PATH + executable_name); + if (search_path.Exists()) { + default_path.executable_path = Path(search_path.AbsolutePath(), true); + default_path.working_folder = Path(search_path.AbsoluteDir(), true); + return default_path; + } + } + + return default_path; +} + +Executable ExecutableManager::CreateDefaultExecutable(const DefaultExecutable& default_executable) const { + const DefaultPath& default_paths = GetDefaultExecutablePath((default_executable.key + GetExecutableSuffix()).c_str()); + if (default_paths.executable_path.Empty()) { + Executable(); // application could not be found.. + } + + ExecutableOptions options; + options.label = "Default"; + options.working_folder = default_paths.working_folder; + // On all operating systems, but Windows we keep running into problems with this ending up + // somewhere the user isn't allowed to create and write files. For consistncy sake, the log + // initially will be set to the users home folder across all OS's. This is highly visible + // in the application launcher and should not present a usability issue. The developer can + // easily change this later to anywhere they like. + options.log_file = std::string("${VK_LOCAL}") + default_executable.key + ".txt"; + + Executable executable; + executable.path = Path(default_paths.executable_path.AbsolutePath(), true); + executable.options.push_back(options); + executable.active_option_index = 0; + return executable; +} + +std::vector ExecutableManager::CreateDefaultExecutables() const { + std::vector new_executables; + + for (std::size_t name_index = 0, name_count = std::size(defaults_executables); name_index < name_count; ++name_index) { + const Executable& executable = CreateDefaultExecutable(defaults_executables[name_index]); + + if (executable.path.Empty()) { + continue; + } + + new_executables.push_back(executable); + } + + return new_executables; +} + +std::vector ExecutableManager::RemoveMissingExecutables(const std::vector& executables) const { + std::vector valid_applications; + + // Remove applications that can't be found + for (std::size_t i = 0, n = executables.size(); i < n; ++i) { + const Executable& application = executables[i]; + + const QFileInfo file_info(application.path.AbsolutePath().c_str()); + if (!file_info.exists()) { + continue; + } + + valid_applications.push_back(application); + } + + return valid_applications; +} diff --git a/vkconfig_core/executable_manager.h b/vkconfig_core/executable_manager.h new file mode 100644 index 0000000000..0350b77cc2 --- /dev/null +++ b/vkconfig_core/executable_manager.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2020-2024 Valve Corporation + * Copyright (c) 2020-2024 LunarG, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Authors: + * - Christophe Riccio + */ + +#pragma once + +#include "serialization.h" +#include "path.h" +#include "type_layers_mode.h" + +#include +#include + +struct DefaultExecutable { + std::string name; + std::string key; + std::string arguments; +}; + +struct DefaultPath { + Path executable_path; + Path working_folder; +}; + +struct ExecutableOptions { + std::string label; + LayersMode layers_mode; + std::string configuration; + Path working_folder; + std::vector arguments; + std::vector environment_variables; + Path log_file; +}; + +struct Executable { + Path path; + int active_option_index = 0; + std::vector options; + + ExecutableOptions& GetActiveOptions() { return this->options[active_option_index]; } + + const ExecutableOptions& GetActiveOptions() const { return this->options[active_option_index]; } +}; + +class ExecutableManager : public Serialize { + public: + bool Load(const QJsonObject& json_root_object) override; + bool Save(QJsonObject& json_root_object) const override; + void Reset() override; + + void SelectActiveExecutable(std::size_t executable_index); + int GetActiveExecutableIndex() const; + bool AppendExecutable(const Executable& executable); + bool RemoveExecutable(std::size_t executable_index); + + const std::vector& GetExecutables() const { return this->executables; } + const Executable& GetActiveExecutable() const; + Executable& GetActiveExecutable(); + const Executable& GetExecutable(std::size_t executable_index) const; + Executable& GetExecutable(std::size_t executable_index); + + // Search for all the applications in the list, an remove the application which executable can't be found + std::vector RemoveMissingExecutables(const std::vector& executables) const; + + bool launcher_clear_on_launch = true; + + private: + int active_executable_index; + std::vector executables; + + // Create a list of default executables, eg vkcube + std::vector CreateDefaultExecutables() const; + Executable CreateDefaultExecutable(const DefaultExecutable& default_executable) const; + DefaultPath GetDefaultExecutablePath(const std::string& executable_name) const; +}; diff --git a/vkconfig_core/layer_manager.cpp b/vkconfig_core/layer_manager.cpp index a09e2e4a98..6b7ca517a9 100644 --- a/vkconfig_core/layer_manager.cpp +++ b/vkconfig_core/layer_manager.cpp @@ -121,10 +121,6 @@ static LayersPathInfo *FindPathInfo(std::array, LAYE return nullptr; } -LayerManager::LayerManager() {} - -LayerManager::~LayerManager() {} - bool LayerManager::Load(const QJsonObject &json_root_object) { this->paths[LAYERS_PATHS_IMPLICIT] = GetImplicitLayerPaths(); diff --git a/vkconfig_core/layer_manager.h b/vkconfig_core/layer_manager.h index 864b9126cc..c35e3c6918 100644 --- a/vkconfig_core/layer_manager.h +++ b/vkconfig_core/layer_manager.h @@ -46,9 +46,6 @@ LayerType GetLayerType(LayersPaths Layers_paths_type); class LayerManager : public Serialize { public: - LayerManager(); - ~LayerManager(); - bool Load(const QJsonObject& json_root_object) override; bool Save(QJsonObject& json_root_object) const override; void Reset() override; diff --git a/vkconfig_core/test/CMakeLists.txt b/vkconfig_core/test/CMakeLists.txt index 07133ae207..aaf664c819 100644 --- a/vkconfig_core/test/CMakeLists.txt +++ b/vkconfig_core/test/CMakeLists.txt @@ -64,6 +64,7 @@ vkConfigTest(test_path) vkConfigTest(test_configuration) vkConfigTest(test_configuration_built_in) vkConfigTest(test_configuration_manager) +vkConfigTest(test_executable_manager) vkConfigTest(test_override) vkConfigTest(test_application_singleton) vkConfigTest(test_type_hide_message) diff --git a/vkconfig_core/test/test_executable_manager.cpp b/vkconfig_core/test/test_executable_manager.cpp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/vkconfig_gui/mainwindow.cpp b/vkconfig_gui/mainwindow.cpp index c7402c4405..bfceab9b0b 100644 --- a/vkconfig_gui/mainwindow.cpp +++ b/vkconfig_gui/mainwindow.cpp @@ -61,7 +61,6 @@ MainWindow::MainWindow(QWidget *parent) _tray_quit_action(nullptr), ui(new Ui::MainWindow) { ui->setupUi(this); - ui->application_list->installEventFilter(this); this->InitTray(); @@ -273,14 +272,13 @@ void MainWindow::UpdateUI() { assert(check_recurse <= 1); Configurator &configurator = Configurator::Get(); - const Environment &environment = Configurator::Get().environment; this->blockSignals(true); ui->configurations_list->blockSignals(true); - const bool has_application_list = !environment.GetApplications().empty(); + const bool has_application_list = !configurator.executables.GetExecutables().empty(); ui->push_button_launcher->setText(_launch_application ? "Terminate" : "Launch"); - ui->check_box_clear_on_launch->setChecked(environment.launcher_clear_on_launch); + ui->check_box_clear_on_launch->setChecked(configurator.executables.launcher_clear_on_launch); // Mode states // this->UpdateUI_Status(); @@ -292,7 +290,7 @@ void MainWindow::UpdateUI() { } void MainWindow::on_check_box_clear_on_launch_clicked() { - Configurator::Get().environment.launcher_clear_on_launch = ui->check_box_clear_on_launch->isChecked(); + Configurator::Get().executables.launcher_clear_on_launch = ui->check_box_clear_on_launch->isChecked(); } void MainWindow::toolsResetToDefault(bool checked) { @@ -312,7 +310,7 @@ void MainWindow::toolsResetToDefault(bool checked) { void MainWindow::StartTool(Tool tool) { Configurator &configurator = Configurator::Get(); - if (!configurator.configurations.GetPerApplicationConfig()) { + if (!configurator.configurations.GetPerExecutableConfig()) { configurator.Surrender(OVERRIDE_AREA_LOADER_SETTINGS_BIT); } @@ -325,7 +323,7 @@ void MainWindow::StartTool(Tool tool) { break; } - if (!configurator.configurations.GetPerApplicationConfig()) { + if (!configurator.configurations.GetPerExecutableConfig()) { configurator.Override(OVERRIDE_AREA_LOADER_SETTINGS_BIT); } } @@ -497,23 +495,23 @@ void MainWindow::on_push_button_launcher_clicked() { std::string launch_log = "Launching Vulkan Application:\n"; Configurator &configurator = Configurator::Get(); - const Application &active_application = configurator.environment.GetActiveApplication(); + const Executable &active_executable = configurator.executables.GetActiveExecutable(); - assert(!active_application.executable_path.Empty()); - launch_log += format("- Executable: %s\n", active_application.executable_path.AbsolutePath().c_str()); - if (!active_application.executable_path.Exists()) { + assert(!active_executable.path.Empty()); + launch_log += format("- Executable: %s\n", active_executable.path.AbsolutePath().c_str()); + if (!active_executable.path.Exists()) { Alert::PathInvalid( - active_application.executable_path, - format("The '%s' application will fail to launch.", active_application.executable_path.AbsolutePath().c_str()).c_str()); + active_executable.path, + format("The '%s' application will fail to launch.", active_executable.path.AbsolutePath().c_str()).c_str()); } - const ApplicationOptions &options = active_application.GetActiveOptions(); + const ExecutableOptions &options = active_executable.GetActiveOptions(); launch_log += format("- Working Directory: %s\n", options.working_folder.AbsolutePath().c_str()); if (!options.working_folder.Exists()) { Alert::PathInvalid( options.working_folder, - format("The '%s' application will fail to launch.", active_application.executable_path.AbsolutePath().c_str()).c_str()); + format("The '%s' application will fail to launch.", active_executable.path.AbsolutePath().c_str()).c_str()); } /* if (!_launcher_arguments->text().isEmpty()) { @@ -569,8 +567,7 @@ void MainWindow::on_push_button_launcher_clicked() { _launch_application->deleteLater(); _launch_application = nullptr; - const std::string failed_log = - std::string("Failed to launch ") + active_application.executable_path.AbsolutePath().c_str() + "!\n"; + const std::string failed_log = std::string("Failed to launch ") + active_executable.path.AbsolutePath().c_str() + "!\n"; Log(failed_log); } diff --git a/vkconfig_gui/mainwindow.ui b/vkconfig_gui/mainwindow.ui index c0f9aa71a6..478e597426 100644 --- a/vkconfig_gui/mainwindow.ui +++ b/vkconfig_gui/mainwindow.ui @@ -72,7 +72,7 @@ QTabWidget::Rounded - 3 + 1 @@ -121,7 +121,7 @@ 0 - + 0 @@ -222,7 +222,7 @@ - Per-Application: + Per-executable: @@ -679,6 +679,9 @@ Layers + + 0 + 5 @@ -775,16 +778,19 @@ - 6 + 0 + + + 5 - 6 + 5 - 6 + 5 - 6 + 0 @@ -802,11 +808,17 @@ 0 + + 0 + 0 + + 0 + - + 0 @@ -820,94 +832,43 @@ 0 - 0 + 3 - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 + + + + 16777215 + 32 + - - - - - - - - 32 - 16777215 - - - - + - - - - - - - - 32 - 16777215 - - - - - - - - - + - - - 0 + + + + 32 + 32 + - - 0 + + - - - 0 + + + + + + + 32 + 32 + - - 0 + + ... - - - - Executable Path: - - - - - - - - - - - 32 - 16777215 - - - - ... - - - - + @@ -916,24 +877,36 @@ 0 + + 0 + 0 - + 0 + + 3 + - + 0 0 + + + 16777215 + 32 + + - + 0 @@ -942,23 +915,30 @@ - 0 + 32 0 32 - 16777215 + 32 - + + - + + + + .. + + + false - + 0 @@ -967,25 +947,18 @@ - 32 + 0 0 32 - 16777215 + 32 - - - - - - .. - - - false + + @@ -1011,14 +984,17 @@ 0 - + Label: - + + + + Env Variables: @@ -1028,50 +1004,19 @@ - - - - Layers Mode: - - - - - - - Arguments: - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - - - - - - - - Output Log: - - - - - - - - - - Working Dir: - - - - + 0 - + + + + 16777215 + 32 + + Layers Controlled by Vulkan Applications @@ -1090,24 +1035,82 @@ - + + + + 16777215 + 32 + + + - - + + + + + + + Layers Mode: + + + + + + + + 16777215 + 32 + + + + + + + + Output Log: + + + + + + + Working Dir: + + + + + + + Arguments: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + 0 - + + + + 16777215 + 32 + + + - + 32 - 16777215 + 32 @@ -1117,20 +1120,27 @@ - - + + 0 - + + + + 16777215 + 32 + + + - + 32 - 16777215 + 32 @@ -1140,9 +1150,6 @@ - - - diff --git a/vkconfig_gui/tab_applications.cpp b/vkconfig_gui/tab_applications.cpp index cb9225de60..2bb4735b48 100644 --- a/vkconfig_gui/tab_applications.cpp +++ b/vkconfig_gui/tab_applications.cpp @@ -56,27 +56,35 @@ } */ -TabApplications::TabApplications(MainWindow &window, std::shared_ptr ui) : Tab(TAB_APPLICATIONS, window, ui) {} +TabApplications::TabApplications(MainWindow &window, std::shared_ptr ui) : Tab(TAB_APPLICATIONS, window, ui) { + this->connect(this->ui->applications_remove_application_pushButton, SIGNAL(pressed()), this, + SLOT(on_applications_remove_application_pushButton_pressed())); + this->connect(this->ui->applications_add_application_pushButton, SIGNAL(pressed()), this, + SLOT(on_applications_add_application_pushButton_pressed())); + + this->connect(this->ui->applications_option_remove_pushButton, SIGNAL(pressed()), this, + SLOT(on_applications_option_remove_pushButton_pressed())); + this->connect(this->ui->applications_option_duplicate_pushButton, SIGNAL(pressed()), this, + SLOT(on_applications_option_duplicate_pushButton_pressed())); +} TabApplications::~TabApplications() {} void TabApplications::UpdateUI(UpdateUIMode mode) { const Configurator &configurator = Configurator::Get(); - const Environment &environment = Configurator::Get().environment; - - const std::vector &applications = configurator.environment.GetApplications(); - ui->application_list->clear(); - for (std::size_t i = 0, n = applications.size(); i < n; ++i) { - QListWidgetItem *application_item = new QListWidgetItem(); - application_item->setText(applications[i].executable_path.RelativePath().c_str()); - application_item->setToolTip(applications[i].executable_path.AbsolutePath().c_str()); - ui->application_list->addItem(application_item); + + const std::vector &executables = configurator.executables.GetExecutables(); + ui->applications_list_comboBox->clear(); + for (std::size_t i = 0, n = executables.size(); i < n; ++i) { + ui->applications_list_comboBox->addItem(executables[i].path.RelativePath().c_str()); } + // application_item->setText(applications[i].executable_path.RelativePath().c_str()); + // application_item->setToolTip(applications[i].executable_path.AbsolutePath().c_str()); const std::vector &configurations = configurator.configurations.available_configurations; - ui->application_configuration_comboBox->clear(); + ui->applications_configuration_comboBox->clear(); for (std::size_t i = 0, n = configurations.size(); i < n; ++i) { - ui->application_configuration_comboBox->addItem(configurations[i].key.c_str()); + ui->applications_configuration_comboBox->addItem(configurations[i].key.c_str()); } /* @@ -190,6 +198,14 @@ void TabApplications::CleanUI() {} bool TabApplications::EventFilter(QObject *target, QEvent *event) { return false; } +void TabApplications::on_applications_remove_application_pushButton_pressed() {} + +void TabApplications::on_applications_add_application_pushButton_pressed() {} + +void TabApplications::on_applications_option_remove_pushButton_pressed() {} + +void TabApplications::on_applications_option_duplicate_pushButton_pressed() {} + /* // Expanding the tree also grows the tree to match void MainWindow::launchItemExpanded(QTreeWidgetItem *item) { diff --git a/vkconfig_gui/tab_applications.h b/vkconfig_gui/tab_applications.h index e5cb295be4..75aee49b8c 100644 --- a/vkconfig_gui/tab_applications.h +++ b/vkconfig_gui/tab_applications.h @@ -34,6 +34,10 @@ struct TabApplications : public Tab { virtual bool EventFilter(QObject* target, QEvent* event) override; public Q_SLOTS: + void on_applications_remove_application_pushButton_pressed(); + void on_applications_add_application_pushButton_pressed(); + void on_applications_option_remove_pushButton_pressed(); + void on_applications_option_duplicate_pushButton_pressed(); private: }; diff --git a/vkconfig_gui/tab_configurations.cpp b/vkconfig_gui/tab_configurations.cpp index 5ef56d0b73..d95474af2b 100644 --- a/vkconfig_gui/tab_configurations.cpp +++ b/vkconfig_gui/tab_configurations.cpp @@ -142,32 +142,33 @@ void TabConfigurations::UpdateUI_Configurations(UpdateUIMode ui_update_mode) { void TabConfigurations::UpdateUI_Applications(UpdateUIMode ui_update_mode) { Configurator &configurator = Configurator::Get(); - Environment &environment = configurator.environment; - if (environment.GetApplications().empty()) { + const std::vector &executables = configurator.executables.GetExecutables(); + + if (executables.empty()) { ui->check_box_per_application->setEnabled(false); ui->check_box_per_application->setVisible(false); ui->combo_box_applications->setVisible(false); } else { ui->check_box_per_application->setEnabled(true); - ui->check_box_per_application->setChecked(configurator.configurations.GetPerApplicationConfig()); + ui->check_box_per_application->setChecked(configurator.configurations.GetPerExecutableConfig()); - ui->combo_box_applications->setEnabled(configurator.configurations.GetPerApplicationConfig()); + ui->combo_box_applications->setEnabled(configurator.configurations.GetPerExecutableConfig()); ui->combo_box_applications->blockSignals(true); if (ui_update_mode == UPDATE_REBUILD_UI) { ui->combo_box_applications->clear(); - for (std::size_t i = 0, n = environment.GetApplications().size(); i < n; ++i) { - const Application &application = environment.GetApplications()[i]; + for (std::size_t i = 0, n = executables.size(); i < n; ++i) { + const Executable &executable = executables[i]; - ui->combo_box_applications->addItem(application.executable_path.RelativePath().c_str()); + ui->combo_box_applications->addItem(executable.path.RelativePath().c_str()); } } - Application &application = configurator.environment.GetActiveApplication(); - ui->combo_box_applications->setCurrentIndex(environment.GetActiveApplicationIndex()); - ui->combo_box_applications->setToolTip(application.executable_path.AbsolutePath().c_str()); + const Executable &executable = configurator.executables.GetActiveExecutable(); + ui->combo_box_applications->setCurrentIndex(configurator.executables.GetActiveExecutableIndex()); + ui->combo_box_applications->setToolTip(executable.path.AbsolutePath().c_str()); ui->combo_box_applications->blockSignals(false); } } @@ -594,7 +595,7 @@ void TabConfigurations::OnContextMenuImportClicked(ConfigurationListItem *item) Configurator &configurator = Configurator::Get(); - const Path &path_import = configurator.environment.path_import; + const Path &path_import = configurator.configurations.last_path_import; const std::string selected_path = QFileDialog::getOpenFileName(&this->window, "Import Layers Configuration File", path_import.AbsolutePath().c_str(), "JSON configuration(*.json)") .toStdString(); @@ -603,7 +604,6 @@ void TabConfigurations::OnContextMenuImportClicked(ConfigurationListItem *item) return; } - configurator.environment.path_import = selected_path; configurator.configurations.ImportConfiguration(configurator.layers, selected_path); configurator.Override(OVERRIDE_AREA_ALL); @@ -711,7 +711,7 @@ void TabConfigurations::OnContextMenuExportConfigsClicked(ConfigurationListItem Configurator &configurator = Configurator::Get(); - const Path &path_export = configurator.environment.path_export; + const Path &path_export = configurator.configurations.last_path_export; const std::string &selected_path = QFileDialog::getSaveFileName(&this->window, "Export Layers Configuration File", path_export.AbsolutePath().c_str(), "JSON configuration(*.json)") @@ -743,7 +743,7 @@ void TabConfigurations::on_combo_box_mode_currentIndexChanged(int index) { void TabConfigurations::on_combo_box_applications_currentIndexChanged(int index) { Configurator &configurator = Configurator::Get(); - configurator.environment.SelectActiveApplication(index); + configurator.executables.SelectActiveExecutable(index); this->UpdateUI(UPDATE_REFRESH_UI); this->window.UpdateUI_Status(); @@ -752,7 +752,7 @@ void TabConfigurations::on_combo_box_applications_currentIndexChanged(int index) void TabConfigurations::on_check_box_per_application_toggled(bool checked) { Configurator &configurator = Configurator::Get(); - configurator.configurations.SetPerApplicationConfig(checked); + configurator.configurations.SetPerExecutableConfig(checked); configurator.Override(OVERRIDE_AREA_ALL); this->UpdateUI(UPDATE_REFRESH_UI);