| /* |
| * Copyright (c) 2020-2025 Valve Corporation |
| * Copyright (c) 2020-2025 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 <christophe@lunarg.com> |
| */ |
| |
| #include "widget_tab_configurations_layer.h" |
| #include "tab_configurations.h" |
| #include "mainwindow.h" |
| #include "widget_resize_button.h" |
| #include "style.h" |
| #include "item_tree.h" |
| |
| #include "../vkconfig_core/configurator.h" |
| #include "../vkconfig_core/doc.h" |
| #include "../vkconfig_core/type_hide_message.h" |
| |
| #include <QSettings> |
| #include <QMenu> |
| #include <QFileDialog> |
| #include <QDesktopServices> |
| #include <QMessageBox> |
| |
| static std::string BuildPlatformsLog(int platforms) { |
| std::string log; |
| |
| if (platforms != 0) { |
| log += "Platforms: "; |
| |
| const std::vector<std::string> &list = GetPlatformTokens(platforms); |
| for (std::size_t i = 0, n = list.size(); i < n; ++i) { |
| log += list[i]; |
| if (i < n - 1) { |
| log += ", "; |
| } |
| } |
| |
| log += "\n"; |
| } |
| |
| return log; |
| } |
| |
| static std::string BuildPropertiesLog(const Layer &layer) { |
| std::string description; |
| if (!layer.description.empty()) { |
| description += layer.description + "\n"; |
| } |
| description += "API Version: " + layer.api_version.str() + " - Implementation Version: " + layer.implementation_version + "\n"; |
| description += ::BuildPlatformsLog(layer.platforms); |
| |
| description += "\n"; |
| description += layer.manifest_path.AbsolutePath() + "\n"; |
| description += format("- %s Layers Path \n", GetToken(layer.type)); |
| description += "- File Format: " + layer.file_format_version.str() + "\n"; |
| description += "- Layer Binary Path:\n " + layer.binary_path.AbsolutePath() + "\n"; |
| description += "\n"; |
| description += |
| format("Total Settings Count: %d - Total Presets Count: %d", CountSettings(layer.settings), layer.presets.size()); |
| return description; |
| } |
| |
| TabConfigurations::TabConfigurations(MainWindow &window, std::shared_ptr<Ui::MainWindow> ui) |
| : Tab(TAB_CONFIGURATIONS, window, ui), _settings_tree_manager(ui) { |
| this->ui->configurations_list->installEventFilter(&window); |
| this->ui->configurations_layers_list->installEventFilter(&window); |
| this->ui->configurations_settings->installEventFilter(&window); |
| |
| this->connect(this->ui->configurations_executable_scope, SIGNAL(currentIndexChanged(int)), this, |
| SLOT(on_configurations_executable_scope_currentIndexChanged(int))); |
| this->connect(this->ui->configurations_executable_list, SIGNAL(currentIndexChanged(int)), this, |
| SLOT(on_configurations_executable_list_currentIndexChanged(int))); |
| this->connect(this->ui->configurations_executable_append, SIGNAL(clicked()), this, |
| SLOT(on_configurations_executable_append_pressed())); |
| this->connect(this->ui->configurations_executable_remove, SIGNAL(clicked()), this, |
| SLOT(on_configurations_executable_remove_pressed())); |
| |
| this->connect(this->ui->configurations_group_box_list, SIGNAL(toggled(bool)), this, SLOT(on_configurations_list_toggled(bool))); |
| this->connect(this->ui->configurations_group_box_settings, SIGNAL(toggled(bool)), this, |
| SLOT(on_configurations_layers_settings_toggled(bool))); |
| |
| this->connect(this->ui->configurations_list, SIGNAL(itemChanged(QListWidgetItem *)), this, |
| SLOT(on_configurations_list_itemChanged(QListWidgetItem *))); |
| this->connect(this->ui->configurations_list, SIGNAL(itemDoubleClicked(QListWidgetItem *)), this, |
| SLOT(on_configurations_list_itemDoubleClicked(QListWidgetItem *))); |
| this->connect(this->ui->configurations_list, SIGNAL(currentRowChanged(int)), this, |
| SLOT(on_configurations_list_currentRowChanged(int))); |
| |
| this->connect(this->ui->configurations_layers_list, SIGNAL(currentRowChanged(int)), this, |
| SLOT(on_configurations_layers_list_currentRowChanged(int))); |
| |
| this->connect(&this->_settings_tree_manager, SIGNAL(signalLayerVersionChanged()), this, |
| SLOT(on_configurations_layerVersionChanged())); |
| |
| QSettings settings("LunarG", VKCONFIG_SHORT_NAME); |
| this->ui->splitter_main->restoreState(settings.value("vkconfig3/mainwindow/splitter_main_state").toByteArray()); |
| this->ui->splitter_configurations->restoreState( |
| settings.value("vkconfig3/mainwindow/splitter_configurations_state").toByteArray()); |
| this->ui->splitter_settings->restoreState(settings.value("vkconfig3/mainwindow/splitter_settings_state").toByteArray()); |
| |
| Configurator &configurator = Configurator::Get(); |
| |
| this->ui->configurations_executable_scope->blockSignals(true); |
| this->ui->configurations_executable_scope->clear(); |
| for (int i = 0, n = EXECUTABLE_SCOPE_COUNT; i < n; ++i) { |
| ExecutableScope scope = static_cast<ExecutableScope>(i); |
| this->ui->configurations_executable_scope->addItem(GetLabel(scope)); |
| this->ui->configurations_executable_scope->setItemData(i, GetTooltip(scope), Qt::ToolTipRole); |
| } |
| |
| ExecutableScope current_scope = configurator.GetExecutableScope(); |
| this->ui->configurations_executable_scope->setCurrentIndex(current_scope); |
| this->ui->configurations_executable_scope->blockSignals(false); |
| |
| this->advanced_mode = new ResizeButton(this->ui->configurations_group_box_layers, 0); |
| this->advanced_mode->setMinimumSize(24, 24); |
| this->advanced_mode->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); |
| this->advanced_mode->adjustSize(); |
| this->ui->configurations_group_box_layers->installEventFilter(this->advanced_mode); |
| |
| this->connect(this->advanced_mode, SIGNAL(pressed()), this, SLOT(on_configurations_advanced_toggle_pressed())); |
| |
| this->UpdateUI(UPDATE_REBUILD_UI); |
| } |
| |
| TabConfigurations::~TabConfigurations() { |
| QSettings settings("LunarG", VKCONFIG_SHORT_NAME); |
| settings.setValue("vkconfig3/mainwindow/splitter_main_state", ui->splitter_main->saveState()); |
| settings.setValue("vkconfig3/mainwindow/splitter_configurations_state", ui->splitter_configurations->saveState()); |
| settings.setValue("vkconfig3/mainwindow/splitter_settings_state", ui->splitter_settings->saveState()); |
| } |
| |
| void TabConfigurations::UpdateUI_Configurations(UpdateUIMode mode) { |
| (void)mode; |
| |
| Configurator &configurator = Configurator::Get(); |
| const Executable *executable = configurator.GetActiveExecutable(); |
| |
| this->ui->configurations_executable_scope->blockSignals(true); |
| this->ui->configurations_executable_scope->setCurrentIndex(configurator.GetExecutableScope()); |
| this->ui->configurations_executable_scope->blockSignals(false); |
| |
| this->ui->configurations_executable_list->blockSignals(true); |
| this->ui->configurations_executable_list->setToolTip(executable->path.AbsolutePath().c_str()); |
| this->ui->configurations_executable_list->blockSignals(false); |
| |
| this->ui->configurations_list->blockSignals(true); |
| this->ui->configurations_list->clear(); |
| |
| int current_row = -1; |
| |
| for (std::size_t i = 0, n = configurator.configurations.available_configurations.size(); i < n; ++i) { |
| const Configuration &configuration = configurator.configurations.available_configurations[i]; |
| |
| std::vector<std::string> missing_layers; |
| const bool has_missing_layer = configuration.HasMissingLayer(configurator.layers, missing_layers); |
| |
| std::string configuration_tooltip = configuration.key; |
| if (configuration.override_settings) { |
| configuration_tooltip += " ("; |
| configuration_tooltip += configuration.override_settings_path.AbsolutePath(); |
| configuration_tooltip += ")"; |
| } |
| |
| ListItem *item = new ListItem(configuration.key.c_str()); |
| item->setFlags(item->flags() | Qt::ItemIsEditable); |
| item->setText(configuration.key.c_str()); |
| if (configurator.GetActiveConfiguration() == &configuration) { |
| item->setIcon(::Get(configurator.current_theme_mode, ::ICON_SYSTEM_ON)); |
| item->setToolTip(configuration_tooltip.c_str()); |
| current_row = static_cast<int>(i); |
| } else if (has_missing_layer) { |
| item->setIcon(::Get(configurator.current_theme_mode, ::ICON_SYSTEM_INVALID)); |
| item->setToolTip( |
| format("The '%s' configuration has missing layers. These layers are ignored.", configuration.key.c_str()).c_str()); |
| } else { |
| item->setIcon(::Get(configurator.current_theme_mode, ::ICON_SYSTEM_OFF)); |
| item->setToolTip( |
| format("Select the '%s' configuration to use it with Vulkan executables", configuration.key.c_str()).c_str()); |
| } |
| ui->configurations_list->addItem(item); |
| } |
| |
| if (current_row != -1) { |
| this->ui->configurations_list->setCurrentRow(current_row); |
| } |
| |
| this->ui->configurations_list->blockSignals(false); |
| } |
| |
| void TabConfigurations::UpdateUI_Applications(UpdateUIMode ui_update_mode) { |
| Configurator &configurator = Configurator::Get(); |
| |
| const std::vector<Executable> &executables = configurator.executables.GetExecutables(); |
| |
| this->ui->configurations_executable_list->blockSignals(true); |
| |
| if (ui_update_mode == UPDATE_REBUILD_UI) { |
| this->ui->configurations_executable_list->clear(); |
| for (std::size_t i = 0, n = executables.size(); i < n; ++i) { |
| const Executable &executable = executables[i]; |
| |
| this->ui->configurations_executable_list->addItem(executable.path.RelativePath().c_str()); |
| } |
| } |
| |
| if (!executables.empty()) { |
| this->ui->configurations_executable_list->setCurrentIndex(configurator.executables.GetActiveExecutableIndex()); |
| } |
| |
| this->ui->configurations_executable_list->blockSignals(false); |
| } |
| |
| void TabConfigurations::UpdateUI_Layers(UpdateUIMode mode) { |
| (void)mode; |
| |
| ui->configurations_layers_list->blockSignals(true); |
| ui->configurations_layers_list->clear(); |
| |
| Configurator &configurator = Configurator::Get(); |
| this->ui->configurations_group_box_layers->setEnabled(configurator.HasEnabledUI(ENABLE_UI_LAYERS)); |
| |
| Configuration *configuration = configurator.GetActiveConfiguration(); |
| if (configuration != nullptr) { |
| const bool has_multiple_parameter = configuration->HasMultipleActiveParameter() || configurator.advanced; |
| |
| ui->execute_closer_application_label->setVisible(has_multiple_parameter); |
| ui->execute_closer_driver_label->setVisible(has_multiple_parameter); |
| ui->configurations_layers_list->setDragEnabled(has_multiple_parameter); |
| |
| bool selected_layer = configuration->selected_layer_name.empty(); |
| for (std::size_t i = 0, n = configuration->parameters.size(); i < n; ++i) { |
| Parameter ¶meter = configuration->parameters[i]; |
| |
| if (!configurator.advanced) { |
| if (parameter.control != LAYER_CONTROL_ON && parameter.control != LAYER_CONTROL_OFF) { |
| continue; |
| } |
| } |
| |
| QListWidgetItem *item = new ListItem(parameter.key.c_str()); |
| item->setFlags(item->flags() | Qt::ItemIsSelectable); |
| item->setSizeHint(QSize(0, ITEM_HEIGHT)); |
| if (has_multiple_parameter) { |
| item->setIcon(::Get(configurator.current_theme_mode, ICON_DRAG)); |
| } |
| ui->configurations_layers_list->addItem(item); |
| |
| ConfigurationLayerWidget *layer_widget = new ConfigurationLayerWidget(this, parameter); |
| |
| ui->configurations_layers_list->setItemWidget(item, layer_widget); |
| if (configuration->selected_layer_name == parameter.key) { |
| ui->configurations_layers_list->setCurrentItem(item); |
| selected_layer = true; |
| } |
| } |
| |
| if (!selected_layer) { |
| configuration->selected_layer_name.clear(); |
| } |
| // resizeEvent(nullptr); |
| |
| ui->configurations_layers_list->update(); |
| } |
| |
| ui->configurations_layers_list->blockSignals(false); |
| } |
| |
| void TabConfigurations::UpdateUI_Settings(UpdateUIMode mode) { |
| (void)mode; |
| |
| Configurator &configurator = Configurator::Get(); |
| |
| if (configurator.GetActiveConfiguration() == nullptr) { |
| this->_settings_tree_manager.CleanupGUI(); |
| this->ui->configurations_presets->setVisible(false); |
| } else { |
| this->_settings_tree_manager.CreateGUI(); |
| } |
| |
| const Parameter *parameter = configurator.GetActiveParameter(); |
| if (parameter != nullptr) { |
| if (configurator.GetActiveConfiguration()->override_settings) { |
| this->ui->configurations_group_box_settings->setToolTip("Disabled: Use External Layerd Settings file is enabled"); |
| } else { |
| const std::string state = parameter->override_settings ? "Uncheck to disable" : "Check to enable"; |
| const std::string tooltip = format("%s '%s' layer settings", state.c_str(), parameter->key.c_str()); |
| |
| this->ui->configurations_group_box_settings->setToolTip(tooltip.c_str()); |
| } |
| } |
| } |
| |
| void TabConfigurations::UpdateUI(UpdateUIMode ui_update_mode) { |
| this->UpdateUI_Configurations(ui_update_mode); |
| this->UpdateUI_Applications(ui_update_mode); |
| this->UpdateUI_Layers(ui_update_mode); |
| this->UpdateUI_Settings(ui_update_mode); |
| |
| const Configurator &configurator = Configurator::Get(); |
| const ExecutableScope scope = configurator.GetExecutableScope(); |
| |
| const bool enabled_executable = ::EnabledExecutables(scope); |
| |
| if (enabled_executable) { |
| const Executable *executable = configurator.GetActiveExecutable(); |
| |
| if (executable != nullptr) { |
| const std::string path = executable->path.RelativePath(); |
| |
| const std::string state = executable->enabled ? "Uncheck to disable" : "Check to enable"; |
| |
| if (scope == EXECUTABLE_PER) { |
| this->ui->configurations_group_box_list->setToolTip( |
| format("%s to select a loader configuration for '%s' executable", state.c_str(), path.c_str()).c_str()); |
| } else { |
| this->ui->configurations_group_box_list->setToolTip( |
| format("%s to enable the loader configuration for '%s' executable", state.c_str(), path.c_str()).c_str()); |
| } |
| } |
| } else if (scope == EXECUTABLE_ANY) { |
| this->ui->configurations_group_box_list->setToolTip("Select the active loader configuration for any executable"); |
| } else { |
| this->ui->configurations_group_box_list->setToolTip( |
| "Change the 'Vulkan Loader Configuration scope' to apply a configuration."); |
| } |
| |
| assert(this->advanced_mode != nullptr); |
| if (configurator.advanced) { |
| this->advanced_mode->setIcon(::Get(configurator.current_theme_mode, ::ICON_SHOW)); |
| this->advanced_mode->setToolTip("View only Enabled Vulkan layers"); |
| } else { |
| this->advanced_mode->setIcon(::Get(configurator.current_theme_mode, ::ICON_ADVANCED)); |
| this->advanced_mode->setToolTip("Configure all Available Vulkan Layers"); |
| } |
| |
| this->ui->configurations_executable_scope->setToolTip(::GetTooltip(scope)); |
| this->ui->configurations_executable_list->setEnabled(enabled_executable); |
| this->ui->configurations_executable_append->setEnabled(enabled_executable); |
| this->ui->configurations_executable_remove->setEnabled(enabled_executable); |
| |
| this->ui->configurations_group_box_list->blockSignals(true); |
| this->ui->configurations_group_box_list->setEnabled(configurator.HasEnabledUI(ENABLE_UI_CONFIG)); |
| this->ui->configurations_group_box_list->setCheckable(enabled_executable); |
| const Executable *executable = configurator.executables.GetActiveExecutable(); |
| if (executable != nullptr) { |
| this->ui->configurations_group_box_list->setChecked(executable->enabled); |
| } |
| this->ui->configurations_group_box_list->blockSignals(false); |
| } |
| |
| void TabConfigurations::CleanUI() { this->_settings_tree_manager.CleanupGUI(); } |
| |
| bool TabConfigurations::EventFilter(QObject *target, QEvent *event) { |
| if (target == nullptr || event == nullptr) { |
| return true; |
| } |
| |
| QEvent::Type event_type = event->type(); |
| |
| if (event_type == QEvent::Wheel) { |
| return true; |
| } |
| |
| Configurator &configurator = Configurator::Get(); |
| |
| if (target == this->ui->configurations_layers_list && event_type == QEvent::ChildRemoved) { |
| // Layers were reordered, we need to update the configuration |
| |
| std::vector<std::string> layer_names; |
| for (int i = 0, n = ui->configurations_layers_list->count(); i < n; ++i) { |
| QWidget *widget = ui->configurations_layers_list->itemWidget(ui->configurations_layers_list->item(i)); |
| if (widget != nullptr) { |
| ConfigurationLayerWidget *layer_widget = dynamic_cast<ConfigurationLayerWidget *>(widget); |
| if (layer_widget != nullptr) { |
| layer_names.push_back(layer_widget->layer_name); |
| } |
| } |
| } |
| |
| Configuration *configuration = configurator.GetActiveConfiguration(); |
| if (configuration != nullptr) { |
| configuration->Reorder(layer_names); |
| configurator.Override(OVERRIDE_AREA_LOADER_SETTINGS_BIT); |
| |
| this->UpdateUI_Settings(UPDATE_REBUILD_UI); |
| } |
| |
| return true; |
| } |
| |
| if (configurator.GetExecutableScope() == EXECUTABLE_NONE || !ui->configurations_list->isEnabled()) { |
| return true; |
| } else if (target == this->ui->configurations_list) { |
| QContextMenuEvent *right_click = dynamic_cast<QContextMenuEvent *>(event); |
| if (right_click) { |
| ListItem *item = static_cast<ListItem *>(this->ui->configurations_list->itemAt(right_click->pos())); |
| |
| std::string name; |
| |
| if (item != nullptr) { |
| name = item->key; |
| } |
| |
| QMenu menu(ui->configurations_list); |
| QFont subtitle_font = menu.font(); |
| subtitle_font.setBold(true); |
| |
| QAction *action_new = new QAction("Create a new Configuration", nullptr); |
| action_new->setEnabled(true); |
| menu.addAction(action_new); |
| |
| QAction *action_import = new QAction("Import a Configuration file...", nullptr); |
| action_import->setEnabled(true); |
| menu.addAction(action_import); |
| |
| QAction *action_export_config = new QAction("Export the Configuration file...", nullptr); |
| action_export_config->setEnabled(item != nullptr); |
| menu.addAction(action_export_config); |
| |
| menu.addSeparator(); |
| |
| QAction *action_rename = new QAction("Rename the Configuration", nullptr); |
| action_rename->setEnabled(item != nullptr); |
| menu.addAction(action_rename); |
| |
| QAction *action_duplicate = new QAction("Duplicate the Configuration", nullptr); |
| action_duplicate->setEnabled(item != nullptr); |
| menu.addAction(action_duplicate); |
| |
| QAction *action_delete = new QAction("Delete the Configuration", nullptr); |
| action_delete->setEnabled(item != nullptr); |
| menu.addAction(action_delete); |
| |
| menu.addSeparator(); |
| |
| QAction *action_use_external_settings = new QAction("Use External vk_layer_settings.txt file...", nullptr); |
| action_use_external_settings->setCheckable(true); |
| Configuration *configuration = configurator.GetActiveConfiguration(); |
| if (configuration != nullptr) { |
| action_use_external_settings->setChecked(configuration->override_settings); |
| if (configuration->override_settings) { |
| action_use_external_settings->setToolTip( |
| "Select another external layer settings file to control layer settings instead of Vulkan Configurator UI."); |
| } else { |
| action_use_external_settings->setToolTip( |
| "Disable the layer settings control from Vulkan Configurator UI to use an external file."); |
| } |
| } |
| action_use_external_settings->setEnabled(item != nullptr); |
| menu.addAction(action_use_external_settings); |
| |
| QAction *action_disable_external_settings = new QAction("Disable External vk_layer_settings.txt file", nullptr); |
| if (configuration != nullptr) { |
| action_disable_external_settings->setEnabled(configuration->override_settings); |
| if (configuration->override_settings) { |
| action_disable_external_settings->setToolTip("Restore the layer settings control from Vulkan Configurator UI."); |
| } |
| } else { |
| action_disable_external_settings->setEnabled(false); |
| } |
| menu.addAction(action_disable_external_settings); |
| |
| menu.addSeparator(); |
| |
| QAction *action_reset_one = new QAction("Reset the Default Configuration", nullptr); |
| action_reset_one->setEnabled(configurator.configurations.IsDefaultConfiguration(name)); |
| action_reset_one->setToolTip("Reset the configuration, discarding all changes of this configuration."); |
| menu.addAction(action_reset_one); |
| |
| QAction *action_reset_all = new QAction("Reset All Default Configurations", nullptr); |
| action_reset_all->setEnabled(true); |
| action_reset_all->setToolTip("Reset all the default configurations, discarding all changes of these configurations."); |
| menu.addAction(action_reset_all); |
| |
| menu.addSeparator(); |
| |
| if (!name.empty()) { |
| name = format(" '%s'", name.c_str()); |
| } |
| |
| QAction *action_export_html = new QAction( |
| format("Generate%s configuration %s...", name.c_str(), GetLabel(GENERATE_SETTINGS_HTML)).c_str(), nullptr); |
| action_export_html->setEnabled(item != nullptr); |
| menu.addAction(action_export_html); |
| |
| QAction *action_export_markdown = new QAction( |
| format("Generate%s configuration %s...", name.c_str(), GetLabel(GENERATE_SETTINGS_MARKDOWN)).c_str(), nullptr); |
| action_export_markdown->setEnabled(item != nullptr); |
| menu.addAction(action_export_markdown); |
| |
| QAction *action_export_settings = new QAction( |
| format("Generate%s configuration %s...", name.c_str(), GetLabel(GENERATE_SETTINGS_TXT)).c_str(), nullptr); |
| action_export_settings->setEnabled(item != nullptr); |
| menu.addAction(action_export_settings); |
| |
| QAction *action_export_env_variables_bash_script = new QAction( |
| format("Generate%s configuration %s...", name.c_str(), GetLabel(GENERATE_SETTINGS_BASH)).c_str(), nullptr); |
| action_export_env_variables_bash_script->setEnabled(item != nullptr); |
| menu.addAction(action_export_env_variables_bash_script); |
| |
| QAction *action_export_env_variables_cmd_script = new QAction( |
| format("Generate%s configuration %s...", name.c_str(), GetLabel(GENERATE_SETTINGS_CMD)).c_str(), nullptr); |
| action_export_env_variables_cmd_script->setEnabled(item != nullptr); |
| menu.addAction(action_export_env_variables_cmd_script); |
| |
| QAction *action_export_extension_code = new QAction( |
| format("Generate%s configuration %s...", name.c_str(), GetLabel(GENERATE_SETTINGS_HPP)).c_str(), nullptr); |
| action_export_extension_code->setEnabled(item != nullptr); |
| menu.addAction(action_export_extension_code); |
| |
| QPoint point(right_click->globalX(), right_click->globalY()); |
| QAction *action = menu.exec(point); |
| |
| if (action == action_new) { |
| this->OnContextMenuNewClicked(item); |
| } else if (action == action_import) { |
| this->OnContextMenuImportClicked(item); |
| } else if (action == action_rename) { |
| this->OnContextMenuRenameClicked(item); |
| } else if (action == action_duplicate) { |
| this->OnContextMenuDuplicateClicked(item); |
| } else if (action == action_delete) { |
| this->OnContextMenuDeleteClicked(item); |
| } else if (action == action_reset_one) { |
| this->OnContextMenuResetOneClicked(item); |
| } else if (action == action_reset_all) { |
| this->OnContextMenuResetAllClicked(item); |
| } else if (action == action_export_config) { |
| this->OnContextMenuExportConfigsClicked(item); |
| } else if (action == action_export_env_variables_bash_script) { |
| this->GenerateClicked(GENERATE_SETTINGS_BASH); |
| } else if (action == action_export_env_variables_cmd_script) { |
| this->GenerateClicked(GENERATE_SETTINGS_CMD); |
| } else if (action == action_export_extension_code) { |
| this->GenerateClicked(GENERATE_SETTINGS_HPP); |
| } else if (action == action_export_settings) { |
| this->GenerateClicked(GENERATE_SETTINGS_TXT); |
| } else if (action == action_export_markdown) { |
| this->GenerateClicked(GENERATE_SETTINGS_MARKDOWN); |
| } else if (action == action_export_html) { |
| this->GenerateClicked(GENERATE_SETTINGS_HTML); |
| } else if (action == action_use_external_settings) { |
| this->on_configuration_settings_file_search_pressed(); |
| } else if (action == action_disable_external_settings) { |
| this->on_configuration_settings_file_disable_pressed(); |
| } |
| } |
| } else if (target == this->ui->configurations_layers_list) { |
| QContextMenuEvent *right_click = dynamic_cast<QContextMenuEvent *>(event); |
| if (right_click) { |
| ListItem *item = static_cast<ListItem *>(this->ui->configurations_layers_list->itemAt(right_click->pos())); |
| |
| if (item != nullptr) { |
| const Configuration *configuration = configurator.GetActiveConfiguration(); |
| const Parameter *parameter = configuration->Find(item->key); |
| |
| const Layer *layer = configurator.layers.FindFromManifest(parameter->manifest); |
| |
| QMenu menu(this->ui->configurations_layers_list); |
| |
| QAction *action_description = new QAction("Open the Layer Description...", nullptr); |
| action_description->setEnabled(layer != nullptr); |
| menu.addAction(action_description); |
| |
| QAction *export_html_action = new QAction("Open the Layer HTML Documentation...", nullptr); |
| export_html_action->setEnabled(layer != nullptr); |
| menu.addAction(export_html_action); |
| |
| QAction *export_markdown_action = new QAction("Open the Layer Markdown Documentation...", nullptr); |
| export_markdown_action->setEnabled(layer != nullptr); |
| menu.addAction(export_markdown_action); |
| |
| QAction *visit_layer_website_action = new QAction("Visit the Layer Website...", nullptr); |
| visit_layer_website_action->setEnabled(layer != nullptr ? !layer->url.Empty() : false); |
| menu.addAction(visit_layer_website_action); |
| /* |
| menu.addSeparator(); |
| |
| std::string name; |
| if (layer != nullptr) { |
| name = format(" '%s'", layer->key.c_str()); |
| } |
| |
| QAction *action_export_html = new QAction( |
| format("Generate%s layer settings %s ...", name.c_str(), |
| GetLabel(GENERATE_SETTINGS_HTML)).c_str(), nullptr); action_export_html->setEnabled(layer != nullptr); |
| menu.addAction(action_export_html); |
| |
| QAction *action_export_markdown = new QAction( |
| format("Generate%s layer settings %s...", name.c_str(), |
| GetLabel(GENERATE_SETTINGS_MARKDOWN)).c_str(), nullptr); action_export_markdown->setEnabled(layer != nullptr); |
| menu.addAction(action_export_markdown); |
| |
| QAction *action_export_settings = new QAction( |
| format("Generate%s layer settings %s...", name.c_str(), |
| GetLabel(GENERATE_SETTINGS_TXT)).c_str(), nullptr); action_export_settings->setEnabled(layer != nullptr); |
| menu.addAction(action_export_settings); |
| |
| QAction *action_export_env_variables_bash_script = new QAction( |
| format("Generate%s layer settings %s...", name.c_str(), |
| GetLabel(GENERATE_SETTINGS_BASH)).c_str(), nullptr); action_export_env_variables_bash_script->setEnabled(layer != |
| nullptr); menu.addAction(action_export_env_variables_bash_script); |
| |
| QAction *action_export_env_variables_cmd_script = new QAction( |
| format("Generate%s layer settings %s...", name.c_str(), |
| GetLabel(GENERATE_SETTINGS_CMD)).c_str(), nullptr); action_export_env_variables_cmd_script->setEnabled(layer != |
| nullptr); menu.addAction(action_export_env_variables_cmd_script); |
| |
| QAction *action_export_extension_code = new QAction( |
| format("Generate%s layer settings %s...", name.c_str(), |
| GetLabel(GENERATE_SETTINGS_HPP)).c_str(), nullptr); action_export_extension_code->setEnabled(layer != nullptr); |
| menu.addAction(action_export_extension_code); |
| */ |
| QPoint point(right_click->globalX(), right_click->globalY()); |
| QAction *action = menu.exec(point); |
| |
| if (action == action_description) { |
| assert(layer != nullptr); |
| |
| std::string title = layer->key; |
| if (layer->status != STATUS_STABLE) { |
| title += format(" (%s)", GetToken(layer->status)); |
| } |
| |
| std::string text; |
| if (!layer->introduction.empty()) { |
| text += layer->introduction + "\n\n"; |
| } |
| text += BuildPropertiesLog(*layer); |
| |
| QMessageBox alert; |
| alert.setWindowTitle(title.c_str()); |
| alert.setText(text.c_str()); |
| alert.setStandardButtons(QMessageBox::Ok); |
| alert.setDefaultButton(QMessageBox::Ok); |
| alert.setIcon(QMessageBox::Information); |
| alert.exec(); |
| } else if (action == visit_layer_website_action) { |
| QDesktopServices::openUrl(QUrl(layer->url.AbsolutePath(false).c_str())); |
| } else if (action == export_html_action) { |
| const std::string path = format("%s/%s.html", AbsolutePath(Path::APPDATA).c_str(), layer->key.c_str()); |
| ExportHtmlDoc(configurator, layer, path); |
| std::string url = "file:///" + path; |
| QDesktopServices::openUrl(QUrl(url.c_str())); |
| } else if (action == export_markdown_action) { |
| const std::string path = format("%s/%s.md", AbsolutePath(Path::APPDATA).c_str(), layer->key.c_str()); |
| ExportMarkdownDoc(configurator, layer, path); |
| QDesktopServices::openUrl(QUrl(("file:///" + path).c_str())); |
| } |
| /* |
| else if (action == action_export_html) { |
| this->GenerateClicked(GENERATE_SETTINGS_HTML); |
| } else if (action == action_export_markdown) { |
| this->GenerateClicked(GENERATE_SETTINGS_MARKDOWN); |
| } else if (action == action_export_settings) { |
| this->GenerateClicked(GENERATE_SETTINGS_TXT); |
| } else if (action == action_export_env_variables_bash_script) { |
| this->GenerateClicked(GENERATE_SETTINGS_BASH); |
| } else if (action == action_export_env_variables_cmd_script) { |
| this->GenerateClicked(GENERATE_SETTINGS_CMD); |
| } else if (action == action_export_extension_code) { |
| this->GenerateClicked(GENERATE_SETTINGS_HPP); |
| }*/ |
| } |
| } |
| } else if (target == this->ui->configurations_settings) { |
| QContextMenuEvent *right_click = dynamic_cast<QContextMenuEvent *>(event); |
| if (right_click) { |
| TreeItem *item = static_cast<TreeItem *>(this->ui->configurations_settings->itemAt(right_click->pos())); |
| |
| const Configuration *configuration = configurator.GetActiveConfiguration(); |
| const Parameter *parameter = configuration->GetActiveParameter(); |
| |
| const Layer *layer = configurator.layers.FindFromManifest(parameter->manifest); |
| |
| if (item != nullptr) { |
| const SettingMeta *setting = ::FindSetting(layer->settings, item->key.c_str()); |
| assert(setting != nullptr); |
| |
| QMenu menu(this->ui->configurations_settings); |
| |
| QAction *action_description = new QAction("Open the brief setting description...", nullptr); |
| action_description->setEnabled(layer != nullptr); |
| menu.addAction(action_description); |
| |
| QAction *export_html_action = new QAction("Open the detailed setting HTML documentation...", nullptr); |
| export_html_action->setEnabled(layer != nullptr); |
| menu.addAction(export_html_action); |
| |
| QAction *export_url_action = new QAction("Open the dedicated feature documentation...", nullptr); |
| export_url_action->setEnabled(layer != nullptr); |
| if (layer != nullptr) { |
| export_url_action->setEnabled(!setting->url.Empty()); |
| } |
| menu.addAction(export_url_action); |
| |
| QPoint point(right_click->globalX(), right_click->globalY()); |
| QAction *action = menu.exec(point); |
| |
| if (action == action_description) { |
| std::string title = format("%s (%s)", setting->label.c_str(), setting->key.c_str()); |
| if (setting->status != STATUS_STABLE) { |
| title += format(" (%s)", ::GetToken(setting->status)); |
| } |
| |
| std::string text = setting->description; |
| text += "\n\n"; |
| if (!setting->detailed.empty()) { |
| text += setting->detailed; |
| text += "\n\n"; |
| } |
| |
| if (setting->type != SETTING_GROUP) { |
| text += "VK_EXT_layer_settings name:\n"; |
| text += format(" %s\n", setting->key.c_str()); |
| text += "vk_layer_settings.txt variable:\n"; |
| text += format(" %s\n", (GetLayerSettingPrefix(layer->key) + setting->key).c_str()); |
| text += "Environment variables:\n"; |
| std::vector<std::string> envs = BuildEnvVariablesList(layer->key.c_str(), setting->key.c_str()); |
| if (!setting->env.empty()) { |
| envs.push_back(setting->env); |
| } |
| for (std::size_t i = 0, n = envs.size(); i < n; ++i) { |
| text += format(" %s\n", envs[i].c_str()); |
| } |
| text += "\n"; |
| |
| text += format("Type: %s\n", ::GetToken(setting->type)); |
| text += format("Default Value: %s\n", setting->Export(EXPORT_MODE_DOC).c_str()); |
| if (setting->type == SETTING_ENUM || setting->type == SETTING_FLAGS) { |
| text += "Possible Values:\n"; |
| const SettingMetaEnumeration *setting_enum = static_cast<const SettingMetaEnumeration *>(setting); |
| for (std::size_t i = 0, n = setting_enum->enum_values.size(); i < n; ++i) { |
| if (configurator.GetUseLayerDebugMode()) { |
| if (setting_enum->enum_values[i].view == SETTING_VIEW_HIDDEN) { |
| continue; |
| } |
| } else { |
| if (setting_enum->enum_values[i].view != SETTING_VIEW_STANDARD) { |
| continue; |
| } |
| } |
| |
| text += format("- %s\n", setting_enum->enum_values[i].key.c_str()); |
| } |
| text += "\n"; |
| } |
| } |
| |
| text += ::BuildPlatformsLog(setting->platform_flags); |
| |
| QMessageBox alert; |
| alert.setWindowTitle(title.c_str()); |
| alert.setText(text.c_str()); |
| alert.setStandardButtons(QMessageBox::Ok); |
| alert.setDefaultButton(QMessageBox::Ok); |
| alert.setIcon(QMessageBox::Information); |
| alert.exec(); |
| } else if (action == export_html_action) { |
| const std::string path = format("%s/%s.html", AbsolutePath(Path::APPDATA).c_str(), layer->key.c_str()); |
| ExportHtmlDoc(configurator, layer, path); |
| |
| std::string url = ConvertStandardSeparators(format("file:///%s#%s-detailed", path.c_str(), item->key.c_str())); |
| QDesktopServices::openUrl(QUrl(url.c_str())); |
| } else if (action == export_url_action) { |
| const SettingMeta *setting = ::FindSetting(layer->settings, item->key.c_str()); |
| |
| const std::string url = ConvertStandardSeparators(setting->url.AbsolutePath()); |
| QDesktopServices::openUrl(QUrl(url.c_str())); |
| } |
| } |
| } |
| } |
| |
| // Pass it on |
| return false; |
| } |
| |
| void TabConfigurations::OnRenameConfiguration(QListWidgetItem *list_item) { |
| ListItem *item = dynamic_cast<ListItem *>(list_item); |
| if (item == nullptr) { |
| return; |
| } |
| |
| // This is the new name we want to use for the configuration |
| const std::string &new_name = item->text().toStdString(); |
| bool valid_new_name = true; |
| |
| if (new_name.empty()) { |
| valid_new_name = false; |
| QMessageBox alert; |
| alert.setWindowTitle("Renaming of the layers configuration failed..."); |
| alert.setText("The configuration name is empty."); |
| alert.setInformativeText("The configuration name is required."); |
| alert.setStandardButtons(QMessageBox::Ok); |
| alert.setDefaultButton(QMessageBox::Ok); |
| alert.setIcon(QMessageBox::Warning); |
| alert.exec(); |
| } else if (!IsPortableFilename(new_name)) { |
| valid_new_name = false; |
| QMessageBox alert; |
| alert.setWindowTitle("Invalid name for a configuration..."); |
| alert.setText("The configuration name is used to build a filename."); |
| alert.setInformativeText("The name can't contain any of the following characters: \\ / : * \" < > |."); |
| alert.setStandardButtons(QMessageBox::Ok); |
| alert.setDefaultButton(QMessageBox::Ok); |
| alert.setIcon(QMessageBox::Warning); |
| alert.exec(); |
| } else if (new_name.size() > 255) { |
| valid_new_name = false; |
| QMessageBox alert; |
| alert.setWindowTitle("Configuration name is too long..."); |
| alert.setText("The configuration name is used to build a filename."); |
| alert.setInformativeText("The name must be a maximum of 255 characters."); |
| alert.setStandardButtons(QMessageBox::Ok); |
| alert.setDefaultButton(QMessageBox::Ok); |
| alert.setIcon(QMessageBox::Warning); |
| alert.exec(); |
| } |
| |
| Configurator &configurator = Configurator::Get(); |
| |
| if (configurator.configurations.FindConfiguration(new_name) != nullptr) { |
| valid_new_name = false; |
| |
| QMessageBox alert; |
| alert.setWindowTitle("Renaming of the layers configuration failed..."); |
| alert.setText("There is already a configuration with the same name."); |
| alert.setInformativeText("Use a different name for the configuration."); |
| alert.setStandardButtons(QMessageBox::Ok); |
| alert.setDefaultButton(QMessageBox::Ok); |
| alert.setIcon(QMessageBox::Warning); |
| alert.exec(); |
| } |
| |
| if (valid_new_name) { |
| configurator.configurations.RenameConfiguration(item->key, new_name); |
| item->key = new_name; |
| configurator.SetActiveConfigurationName(new_name); |
| |
| this->UpdateUI_Configurations(UPDATE_REBUILD_UI); |
| } else { |
| // If the configurate name is empty or the configuration name is taken, keep old configuration name |
| ui->configurations_list->blockSignals(true); |
| item->setText(item->key.c_str()); // "item->key" stored configuration old name |
| ui->configurations_list->blockSignals(false); |
| |
| configurator.SetActiveConfigurationName(item->key); |
| } |
| |
| configurator.Override(OVERRIDE_AREA_LOADER_SETTINGS_BIT); |
| } |
| |
| void TabConfigurations::OnContextMenuNewClicked(ListItem *item) { |
| (void)item; // We don't need this |
| |
| Configurator &configurator = Configurator::Get(); |
| |
| Configuration &configuration = configurator.configurations.CreateConfiguration(configurator.layers, "New Configuration"); |
| configurator.SetActiveConfigurationName(configuration.key); |
| configurator.Override(OVERRIDE_AREA_ALL); |
| |
| this->UpdateUI_Configurations(UPDATE_REBUILD_UI); |
| this->UpdateUI_Layers(UPDATE_REBUILD_UI); |
| this->UpdateUI_Settings(UPDATE_REBUILD_UI); |
| } |
| |
| void TabConfigurations::OnContextMenuImportClicked(ListItem *item) { |
| (void)item; // We don't need this |
| |
| Configurator &configurator = Configurator::Get(); |
| |
| const Path &path_import = configurator.configurations.last_path_import_config; |
| const std::string selected_path = QFileDialog::getOpenFileName(&this->window, "Import Layers Configuration File", |
| path_import.AbsolutePath().c_str(), "JSON configuration(*.json)") |
| .toStdString(); |
| |
| if (selected_path.empty()) { |
| return; |
| } |
| |
| std::string configuration_name; |
| const bool result = configurator.configurations.ImportConfiguration(configurator.layers, selected_path, configuration_name); |
| |
| if (result) { |
| configurator.SetActiveConfigurationName(configuration_name); |
| configurator.Override(OVERRIDE_AREA_ALL); |
| |
| this->UpdateUI_Configurations(UPDATE_REBUILD_UI); |
| this->UpdateUI_Layers(UPDATE_REBUILD_UI); |
| this->UpdateUI_Settings(UPDATE_REBUILD_UI); |
| } else { |
| QMessageBox msg; |
| msg.setIcon(QMessageBox::Critical); |
| msg.setWindowTitle("Importing of a layers Configuration file failed..."); |
| msg.setText(format("%s is not a valid layers configuration file or it could not be read.", selected_path.c_str()).c_str()); |
| msg.exec(); |
| } |
| } |
| |
| void TabConfigurations::OnContextMenuRenameClicked(ListItem *item) { |
| assert(item); |
| |
| ui->configurations_list->editItem(item); |
| } |
| |
| void TabConfigurations::OnContextMenuDuplicateClicked(ListItem *item) { |
| assert(item); |
| assert(!item->key.empty()); |
| |
| Configurator &configurator = Configurator::Get(); |
| const Configuration &duplicated_configuration = |
| configurator.configurations.DuplicateConfiguration(configurator.layers, item->key); |
| |
| item->key = duplicated_configuration.key; |
| configurator.SetActiveConfigurationName(item->key); |
| |
| configurator.Override(OVERRIDE_AREA_LOADER_SETTINGS_BIT); |
| |
| this->UpdateUI_Configurations(UPDATE_REBUILD_UI); |
| } |
| |
| void TabConfigurations::OnContextMenuDeleteClicked(ListItem *item) { |
| assert(item); |
| assert(!item->key.empty()); |
| |
| // Let make sure... |
| QMessageBox alert; |
| alert.setWindowTitle(format("Removing *%s* configuration...", item->key.c_str()).c_str()); |
| alert.setText(format("Are you sure you want to remove the *%s* configuration?", item->key.c_str()).c_str()); |
| alert.setInformativeText("All the data from this configuration will be lost."); |
| alert.setStandardButtons(QMessageBox::Yes | QMessageBox::No); |
| alert.setDefaultButton(QMessageBox::Yes); |
| alert.setIcon(QMessageBox::Warning); |
| if (alert.exec() == QMessageBox::No) { |
| return; |
| } |
| |
| Configurator &configurator = Configurator::Get(); |
| configurator.configurations.RemoveConfiguration(item->key); |
| configurator.SetActiveConfigurationName(""); |
| |
| this->UpdateUI(UPDATE_REBUILD_UI); |
| } |
| |
| void TabConfigurations::OnContextMenuResetOneClicked(ListItem *item) { |
| assert(item); |
| assert(!item->key.empty()); |
| |
| Configurator &configurator = Configurator::Get(); |
| Configuration *configuration = configurator.configurations.FindConfiguration(item->key); |
| assert(configuration != nullptr); |
| |
| QMessageBox alert; |
| alert.setWindowTitle(format("Resetting *%s* loader configuration...", configuration->key.c_str()).c_str()); |
| alert.setText(format("Are you sure you want to reset the *%s* loader configuration?", configuration->key.c_str()).c_str()); |
| if (configuration->IsDefault()) |
| alert.setInformativeText( |
| format("The loader configuration, including layers settings, will be restored to default built-in *%s* configuration.", |
| configuration->key.c_str()) |
| .c_str()); |
| else if (configurator.configurations.HasFile(*configuration)) |
| alert.setInformativeText(format("The loader configuration, including layers settings, will be reloaded using the *%s* " |
| "saved file from previous %s run.", |
| configuration->key.c_str(), VKCONFIG_NAME) |
| .c_str()); |
| else |
| alert.setInformativeText("The configuration layers and settings will be reset to zero."); |
| alert.setStandardButtons(QMessageBox::Yes | QMessageBox::No); |
| alert.setDefaultButton(QMessageBox::Yes); |
| alert.setIcon(QMessageBox::Warning); |
| if (alert.exec() == QMessageBox::No) { |
| return; |
| } |
| |
| configuration->Reset(configurator.layers); |
| |
| this->UpdateUI(UPDATE_REBUILD_UI); |
| } |
| |
| void TabConfigurations::OnContextMenuResetAllClicked(ListItem *item) { |
| (void)item; |
| |
| Configurator &configurator = Configurator::Get(); |
| |
| QMessageBox alert; |
| alert.setWindowTitle("Resetting all default loader configurations..."); |
| alert.setText("Are you sure you want to reset the default loader configurations?"); |
| alert.setInformativeText( |
| "The loader configurations, including layers settings, will be restored to default built-in configurations."); |
| alert.setStandardButtons(QMessageBox::Yes | QMessageBox::No); |
| alert.setDefaultButton(QMessageBox::Yes); |
| alert.setIcon(QMessageBox::Warning); |
| if (alert.exec() == QMessageBox::No) { |
| return; |
| } |
| |
| configurator.configurations.ResetDefaultConfigurations(configurator.layers); |
| configurator.Override(OVERRIDE_AREA_ALL); |
| |
| this->UpdateUI(UPDATE_REBUILD_UI); |
| } |
| |
| void TabConfigurations::OnContextMenuExportConfigsClicked(ListItem *item) { |
| assert(item); |
| |
| Configurator &configurator = Configurator::Get(); |
| |
| const Path path_export = configurator.configurations.last_path_export_config.RelativePath() + "/" + item->key + ".json"; |
| const std::string &selected_path = |
| QFileDialog::getSaveFileName(&this->window, "Export Loader Configuration File", path_export.AbsolutePath().c_str(), |
| "JSON configuration(*.json)") |
| .toStdString(); |
| |
| if (selected_path.empty()) { |
| return; |
| } |
| |
| const bool result = configurator.configurations.ExportConfiguration(configurator.layers, selected_path, item->key); |
| |
| if (!result) { |
| QMessageBox msg; |
| msg.setIcon(QMessageBox::Critical); |
| msg.setWindowTitle("Exporting of a Loader Configuration file failed..."); |
| msg.setText(format("Couldn't be create '%s' Loader configuration file.", selected_path.c_str()).c_str()); |
| msg.exec(); |
| } else { |
| QDesktopServices::openUrl(QUrl::fromLocalFile(selected_path.c_str())); |
| } |
| } |
| |
| void TabConfigurations::GenerateClicked(GenerateSettingsMode mode) { |
| Configurator &configurator = Configurator::Get(); |
| |
| const Configuration *configuration = configurator.GetActiveConfiguration(); |
| if (configuration == nullptr) { |
| return; |
| } |
| |
| const Path path_export = |
| configurator.configurations.last_path_export_settings.AbsolutePath() + "/" + configuration->key + ::GetDefaultFileExt(mode); |
| const std::string caption = format("Generate '%s' configuration %s", configuration->key.c_str(), ::GetLabel(mode)); |
| const std::string filter = format("%s (*%s)", ::GetLabel(mode), ::GetDefaultFileExt(mode)); |
| const std::string &selected_path = |
| QFileDialog::getSaveFileName(&this->window, caption.c_str(), path_export.AbsolutePath().c_str(), filter.c_str()) |
| .toStdString(); |
| |
| if (selected_path.empty()) { |
| return; |
| } |
| |
| const bool result = configurator.Generate(mode, selected_path.c_str()); |
| |
| if (!result) { |
| const std::string title = |
| format("Generation of the '%s' configuration %s failed...", configuration->key.c_str(), ::GetLabel(mode)); |
| |
| QMessageBox msg; |
| msg.setIcon(QMessageBox::Critical); |
| msg.setWindowTitle(title.c_str()); |
| msg.setText(format("Couldn't create '%s' file.", selected_path.c_str()).c_str()); |
| msg.exec(); |
| } else { |
| const Path saved_path(selected_path); |
| configurator.configurations.last_path_export_settings = saved_path.AbsoluteDir(); |
| QDesktopServices::openUrl(QUrl::fromLocalFile(saved_path.AbsoluteDir().c_str())); |
| } |
| } |
| |
| void TabConfigurations::on_configurations_advanced_toggle_pressed() { |
| Configurator &configurator = Configurator::Get(); |
| configurator.advanced = !configurator.advanced; |
| |
| this->UpdateUI(UPDATE_REBUILD_UI); |
| } |
| |
| void TabConfigurations::on_configurations_executable_scope_currentIndexChanged(int index) { |
| Configurator &configurator = Configurator::Get(); |
| |
| const ExecutableScope scope = static_cast<ExecutableScope>(index); |
| switch (scope) { |
| default: { |
| configurator.SetExecutableScope(scope); |
| configurator.Override(OVERRIDE_AREA_ALL); |
| break; |
| } |
| case EXECUTABLE_PER: { |
| if (!(configurator.Get(HIDE_MESSAGE_NOTIFICATION_EXECUTABLE_PER))) { |
| QMessageBox message; |
| message.setWindowTitle(format("Selected scope: '%s'", ::GetLabel(scope)).c_str()); |
| message.setText(::GetTooltip(scope)); |
| message.setInformativeText( |
| "As the vk_layer_settings.txt file is written in the executable working directory, all the executables " |
| "with the same working directory will share the same loader configuration.\n\nDo you want to continue?"); |
| message.setIcon(QMessageBox::Information); |
| message.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); |
| message.setDefaultButton(QMessageBox::Ok); |
| message.setCheckBox(new QCheckBox("Do not show again.")); |
| int retval = message.exec(); |
| |
| if (message.checkBox()->isChecked()) { |
| configurator.Set(HIDE_MESSAGE_NOTIFICATION_EXECUTABLE_PER); |
| } |
| |
| if (retval == QMessageBox::Cancel) { |
| break; |
| } |
| } |
| |
| configurator.SetExecutableScope(scope); |
| configurator.Override(OVERRIDE_AREA_ALL); |
| break; |
| } |
| } |
| |
| this->UpdateUI(UPDATE_REFRESH_UI); |
| this->window.UpdateUI_Status(); |
| } |
| |
| void TabConfigurations::on_configurations_executable_list_currentIndexChanged(int index) { |
| Configurator &configurator = Configurator::Get(); |
| configurator.executables.SetActiveExecutable(index); |
| |
| this->UpdateUI(UPDATE_REFRESH_UI); |
| this->window.UpdateUI_Status(); |
| } |
| |
| void TabConfigurations::on_configurations_executable_append_pressed() { |
| Configurator &configurator = Configurator::Get(); |
| |
| const Path &last_path = configurator.executables.last_path_executable; |
| const Path selected_path = |
| QFileDialog::getOpenFileName(&this->window, "Executable Path", last_path.AbsolutePath().c_str(), ::GetExecutableFilter()) |
| .toStdString(); |
| |
| if (selected_path.Empty()) { |
| return; |
| } |
| |
| configurator.executables.AppendExecutable(selected_path); |
| |
| this->UpdateUI(UPDATE_REBUILD_UI); |
| } |
| |
| void TabConfigurations::on_configurations_executable_remove_pressed() { |
| Configurator &configurator = Configurator::Get(); |
| const Executable *executable = configurator.executables.GetActiveExecutable(); |
| assert(executable != nullptr); |
| |
| if (!(configurator.Get(HIDE_MESSAGE_WARN_REMOVE_EXECUTABLE))) { |
| QMessageBox message; |
| message.setWindowTitle(format("Removing an executable from %s", VKCONFIG_NAME).c_str()); |
| message.setText(format("The '%s' executable '%s' is being removed, and its options will be lost.", VKCONFIG_NAME, |
| executable->path.AbsolutePath().c_str()) |
| .c_str()); |
| message.setInformativeText("Do you want to continue?"); |
| message.setIcon(QMessageBox::Warning); |
| message.setStandardButtons(QMessageBox::Yes | QMessageBox::No); |
| message.setDefaultButton(QMessageBox::Yes); |
| message.setCheckBox(new QCheckBox("Do not show again.")); |
| int ret_val = message.exec(); |
| |
| if (message.checkBox()->isChecked()) { |
| configurator.Set(HIDE_MESSAGE_WARN_REMOVE_EXECUTABLE); |
| } |
| |
| if (ret_val == QMessageBox::No) { |
| return; |
| } |
| } |
| |
| configurator.Surrender(OVERRIDE_AREA_ALL); |
| configurator.executables.RemoveExecutable(); |
| configurator.Override(OVERRIDE_AREA_ALL); |
| |
| this->UpdateUI(UPDATE_REBUILD_UI); |
| } |
| |
| void TabConfigurations::on_configurations_list_toggled(bool checked) { |
| Configurator &configurator = Configurator::Get(); |
| Executable *executable = configurator.GetActiveExecutable(); |
| if (executable != nullptr) { |
| executable->enabled = checked; |
| |
| this->UpdatePerExecutableConfigurations(); |
| |
| configurator.Override(OVERRIDE_AREA_ALL); |
| } |
| |
| this->UpdateUI(UPDATE_REFRESH_UI); |
| } |
| |
| void TabConfigurations::on_configurations_layers_settings_toggled(bool checked) { |
| Configurator &configurator = Configurator::Get(); |
| |
| Parameter *parameter = configurator.GetActiveParameter(); |
| if (parameter != nullptr) { |
| parameter->override_settings = checked; |
| |
| configurator.Override(OVERRIDE_AREA_LAYERS_SETTINGS_BIT); |
| } |
| |
| // The layer version combobox is on even when the layer settings group is unchecked |
| this->UpdateUI_Settings(UPDATE_REFRESH_UI); |
| } |
| |
| void TabConfigurations::on_configurations_list_itemDoubleClicked(QListWidgetItem *item) { ui->configurations_list->editItem(item); } |
| |
| /// An item has been changed. Check for edit of the items name (configuration name) |
| void TabConfigurations::on_configurations_list_itemChanged(QListWidgetItem *item) { this->OnRenameConfiguration(item); } |
| |
| void TabConfigurations::UpdatePerExecutableConfigurations() { |
| Configurator &configurator = Configurator::Get(); |
| if (configurator.GetExecutableScope() != EXECUTABLE_PER) { |
| return; |
| } |
| |
| Configuration *configuration = configurator.GetActiveConfiguration(); |
| if (configuration == nullptr) { |
| return; |
| } |
| |
| std::vector<Path> updated_executable_paths; |
| if (configurator.executables.UpdateConfigurations(updated_executable_paths)) { |
| if (!configurator.Get(HIDE_MESSAGE_NOTIFICATION_PER_CONFIG_UPDATE)) { |
| QMessageBox message; |
| message.setWindowTitle("Vulkan Executable Loader Configuration Updated"); |
| message.setText( |
| format("Per Executable Loader Configuration Scope requires that all executables with the same working " |
| "directory use the same loader configuration. The following executables were switch to '%s' configuration:", |
| configuration->key.c_str()) |
| .c_str()); |
| std::string informative; |
| for (std::size_t i = 0, n = updated_executable_paths.size(); i < n; ++i) { |
| informative += format("- %s\n", updated_executable_paths[i].RelativePath().c_str()); |
| } |
| |
| message.setInformativeText(informative.c_str()); |
| message.setIcon(QMessageBox::Warning); |
| message.setCheckBox(new QCheckBox("Do not show again.")); |
| message.exec(); |
| |
| if (message.checkBox()->isChecked()) { |
| configurator.Set(HIDE_MESSAGE_NOTIFICATION_PER_CONFIG_UPDATE); |
| } |
| } |
| } |
| } |
| |
| void TabConfigurations::on_configurations_list_currentRowChanged(int currentRow) { |
| this->_settings_tree_manager.CleanupGUI(); |
| |
| if (currentRow == -1) { |
| return; // No row selected |
| } |
| |
| QListWidgetItem *list_item = ui->configurations_list->item(currentRow); |
| ListItem *item = dynamic_cast<ListItem *>(list_item); |
| |
| if (item == nullptr) { |
| return; |
| } |
| |
| Configurator &configurator = Configurator::Get(); |
| const Configuration *selected_configuration = configurator.configurations.FindConfiguration(item->key); |
| |
| if (configurator.GetActiveConfiguration() != selected_configuration) { |
| configurator.SetActiveConfigurationName(item->key); |
| |
| if (!configurator.Get(HIDE_MESSAGE_WARN_MISSING_LAYERS_IGNORE)) { |
| std::vector<std::string> missing_layers; |
| |
| const Configuration *configuration = configurator.GetActiveConfiguration(); |
| if (configuration->HasMissingLayer(configurator.layers, missing_layers)) { |
| std::string text = format("The selected '%s' configuration is missing the layers:\n", configuration->key.c_str()); |
| for (std::size_t i = 0, n = missing_layers.size(); i < n; ++i) { |
| text += format(" - %s\n", missing_layers[i].c_str()); |
| } |
| text += "These layers will be ignored."; |
| |
| QMessageBox alert; |
| alert.setWindowTitle("Missing Vulkan layers..."); |
| alert.setText(text.c_str()); |
| alert.setIcon(QMessageBox::Warning); |
| alert.setCheckBox(new QCheckBox("Do not show again.")); |
| alert.setInformativeText(format("Use the '%s' tab to add the missing layers.", GetLabel(TAB_LAYERS)).c_str()); |
| |
| alert.exec(); |
| if (alert.checkBox()->isChecked()) { |
| configurator.Set(HIDE_MESSAGE_WARN_MISSING_LAYERS_IGNORE); |
| } |
| } |
| } |
| |
| this->UpdatePerExecutableConfigurations(); |
| |
| configurator.Override(OVERRIDE_AREA_ALL); |
| |
| this->UpdateUI(UPDATE_REBUILD_UI); |
| } |
| } |
| |
| void TabConfigurations::on_configuration_settings_file_search_pressed() { |
| Configurator &configurator = Configurator::Get(); |
| |
| if (!configurator.Get(HIDE_MESSAGE_NOTIFICATION_EXTERNAL_LAYERS_SETTINGS)) { |
| QMessageBox message; |
| message.setWindowTitle("Using an external layer settings file to control the Vulkan layers"); |
| message.setText( |
| "When selecting the layers configuration, the Vulkan layers settings will be controled by the selected file instead of " |
| "Vulkan Configurator UI"); |
| message.setInformativeText("Do you want to continue?"); |
| message.setIcon(QMessageBox::Information); |
| message.setStandardButtons(QMessageBox::Yes | QMessageBox::No); |
| message.setDefaultButton(QMessageBox::Yes); |
| message.setCheckBox(new QCheckBox("Do not show again.")); |
| |
| int ret_val = message.exec(); |
| if (message.checkBox()->isChecked()) { |
| configurator.Set(HIDE_MESSAGE_NOTIFICATION_EXTERNAL_LAYERS_SETTINGS); |
| } |
| |
| if (ret_val == QMessageBox::No) { |
| return; |
| } |
| } |
| |
| Configuration *configuration = configurator.GetActiveConfiguration(); |
| assert(configuration != nullptr); |
| |
| const std::string input_path = configuration->override_settings_path.Empty() |
| ? Path(Path::HOME).AbsolutePath() |
| : configuration->override_settings_path.AbsolutePath(); |
| |
| const std::string selected_path = QFileDialog::getOpenFileName(&this->window, "Locate a Layers Settings File", |
| input_path.c_str(), "vk_layer_settings.txt(*.txt)") |
| .toStdString(); |
| |
| if (!selected_path.empty()) { |
| configuration->override_settings = true; |
| configuration->override_settings_path = selected_path; |
| } |
| |
| configurator.Override(OVERRIDE_AREA_LOADER_SETTINGS_BIT); |
| |
| this->UpdateUI_Configurations(UPDATE_REFRESH_UI); |
| this->UpdateUI_Settings(UPDATE_REFRESH_UI); |
| } |
| |
| void TabConfigurations::on_configuration_settings_file_disable_pressed() { |
| Configurator &configurator = Configurator::Get(); |
| Configuration *configuration = configurator.GetActiveConfiguration(); |
| assert(configuration != nullptr); |
| |
| configuration->override_settings = false; |
| |
| configurator.Override(OVERRIDE_AREA_LOADER_SETTINGS_BIT); |
| this->UpdateUI_Configurations(UPDATE_REFRESH_UI); |
| this->UpdateUI_Settings(UPDATE_REFRESH_UI); |
| } |
| |
| void TabConfigurations::on_configurations_layers_list_currentRowChanged(int currentRow) { |
| this->_settings_tree_manager.CleanupGUI(); |
| |
| if (currentRow == -1) { |
| return; // No row selected |
| } |
| |
| QWidget *widget = this->ui->configurations_layers_list->itemWidget(this->ui->configurations_layers_list->item(currentRow)); |
| if (widget == nullptr) { |
| return; |
| } |
| |
| const std::string &layer_string = static_cast<ConfigurationLayerWidget *>(widget)->layer_name; |
| |
| Configurator &configurator = Configurator::Get(); |
| |
| Configuration *configuration = configurator.GetActiveConfiguration(); |
| assert(configuration != nullptr); |
| |
| if (configuration->selected_layer_name != layer_string) { |
| configuration->selected_layer_name = layer_string; |
| |
| this->UpdateUI_Settings(UPDATE_REBUILD_UI); |
| } |
| } |
| |
| void TabConfigurations::on_configurations_layerVersionChanged() { this->UpdateUI_Layers(UPDATE_REBUILD_UI); } |