blob: cf704046ffaf902c6f19e6f76c57dc2b71c627de [file] [edit]
/*
* 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 &parameter = 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); }