From: PeterLValve Date: Mon, 24 Mar 2014 22:55:07 +0000 (-0700) Subject: UI: Add a settings file X-Git-Url: https://git.cworth.org/git?a=commitdiff_plain;h=1e67a55d82c08d8c2ce1ad4303d01607fca61e53;p=vogl UI: Add a settings file * When vogleditor is started, the settings file will be loaded / saved so that it contains all the latest settings. * The JSON settings file is stored in $XDG_CONFIG_HOME/vogleditor/ or $HOME/.config/vogleditor/ and is named vogleditor_settings.json. * Before manually editing the file, vogleditor should be closed; after editing the file, reopen vogleditor to read in the latest changes. * The file is automatically saved when vogleditor is closed, so manual edits while the file is open will cause the changes to be overwritten. * Current settings include: * Window position and dimensions (defaults to 0,0 and 1024x768) * The "trim_large_trace_prompt_size" (defaults to 200) which is the minimum number of frames a trace file must contain in order for the trim trace prompt to be displayed when loading a trace file. --- diff --git a/src/vogleditor/CMakeLists.txt b/src/vogleditor/CMakeLists.txt index 3132f70..03d91a1 100644 --- a/src/vogleditor/CMakeLists.txt +++ b/src/vogleditor/CMakeLists.txt @@ -54,6 +54,7 @@ set(SRC_LIST vogleditor_qtextureviewer.cpp vogleditor_qtimelineview.cpp vogleditor_qtrimdialog.cpp + vogleditor_settings.cpp vogleditor_statetreearbprogramitem.cpp vogleditor_statetreearbprogramenvitem.cpp vogleditor_statetreebufferitem.cpp @@ -103,6 +104,7 @@ set(HEADER_LIST vogleditor_apicalltreeitem.h vogleditor_frameitem.h vogleditor_gl_state_snapshot.h + vogleditor_settings.h vogleditor_snapshotitem.h vogleditor_statetreearbprogramitem.h vogleditor_statetreearbprogramenvitem.h diff --git a/src/vogleditor/vogleditor.cpp b/src/vogleditor/vogleditor.cpp index 1b976ca..7eb513e 100644 --- a/src/vogleditor/vogleditor.cpp +++ b/src/vogleditor/vogleditor.cpp @@ -48,6 +48,7 @@ #include "vogl_trace_file_reader.h" #include "vogl_trace_file_writer.h" #include "vogleditor_qstatetreemodel.h" +#include "vogleditor_settings.h" #include "vogleditor_statetreetextureitem.h" #include "vogleditor_statetreeprogramitem.h" #include "vogleditor_statetreeshaderitem.h" @@ -63,6 +64,8 @@ //---------------------------------------------------------------------------------------------------------------------- static void *g_actual_libgl_module_handle; static QString g_PROJECT_NAME = "Vogl Editor"; +static vogleditor_settings g_settings; +static const char* g_SETTINGS_FILE = "./vogleditor_settings.json"; //---------------------------------------------------------------------------------------------------------------------- // vogl_get_proc_address_helper @@ -136,6 +139,15 @@ VoglEditor::VoglEditor(QWidget *parent) : vogl_init_actual_gl_entrypoints(vogl_get_proc_address_helper); } + // load the settings file. This will only succeed if the file already exists + g_settings.load(g_SETTINGS_FILE); + + // always save/resave the file wiill either be created or so that new settings will be added + g_settings.save(g_SETTINGS_FILE); + + this->move(g_settings.window_position_left(), g_settings.window_position_top()); + this->resize(g_settings.window_size_width(), g_settings.window_size_height()); + m_pStatusLabel = new QLabel(ui->statusBar); m_pStatusLabel->setBaseSize(150, 12); ui->statusBar->addWidget(m_pStatusLabel, 1); @@ -201,98 +213,105 @@ VoglEditor::VoglEditor(QWidget *parent) : VoglEditor::~VoglEditor() { - close_trace_file(); - delete ui; + // update any settings and save the settings file + g_settings.set_window_position_left(this->x()); + g_settings.set_window_position_top(this->y()); + g_settings.set_window_size_width(this->width()); + g_settings.set_window_size_height(this->height()); + g_settings.save(g_SETTINGS_FILE); - if (m_pStatusLabel != NULL) - { - delete m_pStatusLabel; - m_pStatusLabel = NULL; - } + close_trace_file(); + delete ui; - if (m_pFramebufferExplorer != NULL) - { - delete m_pFramebufferExplorer; - m_pFramebufferExplorer = NULL; - } + if (m_pStatusLabel != NULL) + { + delete m_pStatusLabel; + m_pStatusLabel = NULL; + } - if (m_pTextureExplorer != NULL) - { - delete m_pTextureExplorer; - m_pTextureExplorer = NULL; - } + if (m_pFramebufferExplorer != NULL) + { + delete m_pFramebufferExplorer; + m_pFramebufferExplorer = NULL; + } - if (m_pRenderbufferExplorer != NULL) - { - delete m_pRenderbufferExplorer; - m_pRenderbufferExplorer = NULL; - } + if (m_pTextureExplorer != NULL) + { + delete m_pTextureExplorer; + m_pTextureExplorer = NULL; + } - if (m_pProgramExplorer != NULL) - { - delete m_pProgramExplorer; - m_pProgramExplorer = NULL; - } + if (m_pRenderbufferExplorer != NULL) + { + delete m_pRenderbufferExplorer; + m_pRenderbufferExplorer = NULL; + } - if (m_pShaderExplorer != NULL) - { - delete m_pShaderExplorer; - m_pShaderExplorer = NULL; - } + if (m_pProgramExplorer != NULL) + { + delete m_pProgramExplorer; + m_pProgramExplorer = NULL; + } - if (m_pPlayButton != NULL) - { - delete m_pPlayButton; - m_pPlayButton = NULL; - } + if (m_pShaderExplorer != NULL) + { + delete m_pShaderExplorer; + m_pShaderExplorer = NULL; + } - if (m_pTrimButton != NULL) - { - delete m_pTrimButton; - m_pTrimButton = NULL; - } + if (m_pPlayButton != NULL) + { + delete m_pPlayButton; + m_pPlayButton = NULL; + } - if (m_pFramebufferTab_layout != NULL) - { - delete m_pFramebufferTab_layout; - m_pFramebufferTab_layout = NULL; - } + if (m_pTrimButton != NULL) + { + delete m_pTrimButton; + m_pTrimButton = NULL; + } - if (m_pTextureTab_layout != NULL) - { - delete m_pTextureTab_layout; - m_pTextureTab_layout = NULL; - } + if (m_pFramebufferTab_layout != NULL) + { + delete m_pFramebufferTab_layout; + m_pFramebufferTab_layout = NULL; + } - if (m_pRenderbufferTab_layout != NULL) - { - delete m_pRenderbufferTab_layout; - m_pRenderbufferTab_layout = NULL; - } + if (m_pTextureTab_layout != NULL) + { + delete m_pTextureTab_layout; + m_pTextureTab_layout = NULL; + } - if (m_pProgramTab_layout != NULL) - { - delete m_pProgramTab_layout; - m_pProgramTab_layout = NULL; - } + if (m_pRenderbufferTab_layout != NULL) + { + delete m_pRenderbufferTab_layout; + m_pRenderbufferTab_layout = NULL; + } - if (m_pShaderTab_layout != NULL) - { - delete m_pShaderTab_layout; - m_pShaderTab_layout = NULL; - } + if (m_pProgramTab_layout != NULL) + { + delete m_pProgramTab_layout; + m_pProgramTab_layout = NULL; + } - if (m_pStateTreeModel != NULL) - { - delete m_pStateTreeModel; - m_pStateTreeModel = NULL; - } + if (m_pShaderTab_layout != NULL) + { + delete m_pShaderTab_layout; + m_pShaderTab_layout = NULL; + } - if (m_pVoglReplayProcess != NULL) - { - delete m_pVoglReplayProcess; - m_pVoglReplayProcess = NULL; - } + if (m_pStateTreeModel != NULL) + { + delete m_pStateTreeModel; + m_pStateTreeModel = NULL; + } + + if (m_pVoglReplayProcess != NULL) + { + delete m_pVoglReplayProcess; + m_pVoglReplayProcess = NULL; + } } void VoglEditor::playCurrentTraceFile() @@ -321,7 +340,7 @@ void VoglEditor::playCurrentTraceFile() void VoglEditor::trimCurrentTraceFile() { - trim_trace_file(m_openFilename, static_cast(m_pTraceReader->get_max_frame_index()), 200); + trim_trace_file(m_openFilename, static_cast(m_pTraceReader->get_max_frame_index()), g_settings.trim_large_trace_prompt_size()); } /// \return True if the new trim file is now open in the editor @@ -1027,14 +1046,14 @@ bool VoglEditor::open_trace_file(dynamic_string filename) m_pStatusLabel->clear(); } - if (tmpReader->get_max_frame_index() > 200) + if (tmpReader->get_max_frame_index() > g_settings.trim_large_trace_prompt_size()) { int ret = QMessageBox::warning(this, tr(g_PROJECT_NAME.toStdString().c_str()), tr("The loaded trace file has many frames and debugging may be difficult.\nWould you like to trim the trace?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); if (ret == QMessageBox::Yes) { - if (trim_trace_file(filename.c_str(), static_cast(tmpReader->get_max_frame_index()), 200)) + if (trim_trace_file(filename.c_str(), static_cast(tmpReader->get_max_frame_index()), g_settings.trim_large_trace_prompt_size())) { // user decided to open the new trim file, and the UI should already be updated // clean up here and return diff --git a/src/vogleditor/vogleditor_settings.cpp b/src/vogleditor/vogleditor_settings.cpp new file mode 100644 index 0000000..84d12b9 --- /dev/null +++ b/src/vogleditor/vogleditor_settings.cpp @@ -0,0 +1,120 @@ +#include "vogleditor_settings.h" +#include "vogl_common.h" +#include "vogl_file_utils.h" + +static const unsigned int VOGLEDITOR_SETTINGS_FILE_FORMAT_VERSION_1 = 1; +static const unsigned int VOGLEDITOR_SETTINGS_FILE_FORMAT_VERSION = VOGLEDITOR_SETTINGS_FILE_FORMAT_VERSION_1; + +vogleditor_settings::vogleditor_settings() + : m_file_format_version(VOGLEDITOR_SETTINGS_FILE_FORMAT_VERSION_1) +{ + m_defaults.trim_large_trace_prompt_size = 200; + m_defaults.window_position_left = 0; + m_defaults.window_position_top = 0; + m_defaults.window_size_width = 1024; + m_defaults.window_size_height = 768; + + m_settings = m_defaults; +} + +dynamic_string vogleditor_settings::get_settings_path(const char* settingsFilename) +{ + dynamic_string settingsPath; + const char* xdgConfigHome = getenv("XDG_CONFIG_HOME"); + const char* home = getenv("HOME"); + if (xdgConfigHome != NULL && strlen(xdgConfigHome) != 0) + { + settingsPath = xdgConfigHome; + settingsPath += "/vogleditor/"; + if (vogl::file_utils::does_dir_exist(settingsPath.c_str()) == false) + { + if (vogl::file_utils::create_directories_from_full_path(settingsPath) == false) + { + VOGL_ASSERT(!"Failed to create directories for settings file."); + } + } + } + else if (home != NULL && strlen(home) != 0) + { + settingsPath += home; + settingsPath += "/.config/vogleditor/"; + if (vogl::file_utils::does_dir_exist(settingsPath.c_str())== false) + { + if (vogl::file_utils::create_directories_from_full_path(settingsPath) == false) + { + VOGL_ASSERT(!"Failed to create directories for settings file."); + } + } + } + else + { + // the settings file will end up in the current working directory + } + + settingsPath += settingsFilename; + return settingsPath; +} + +bool vogleditor_settings::load(const char* settingsFile) +{ + bool bLoaded = false; + json_document settingsDoc; + dynamic_string path = get_settings_path(settingsFile); + if (settingsDoc.deserialize_file(path.c_str())) + { + // validate metadata + json_node* pMetadata = settingsDoc.get_root()->find_child_object("metadata"); + if (pMetadata == NULL) + { + return false; + } + + const json_value& rFormatVersion = pMetadata->find_value("vogleditor_settings_file_format_version"); + if (!rFormatVersion.is_valid() || rFormatVersion.as_uint32() != VOGLEDITOR_SETTINGS_FILE_FORMAT_VERSION_1) + { + return false; + } + + m_file_format_version = rFormatVersion.as_uint32(VOGLEDITOR_SETTINGS_FILE_FORMAT_VERSION); + + // validate that settings node exists + json_node* pSettingsNode = settingsDoc.get_root()->find_child_object("settings"); + if (pSettingsNode == NULL) + { + return false; + } + + // if so, consider the file successfully loaded + bLoaded = true; + + // all settings should be considered optional, if they are not in the file, then the default value is used + m_settings.trim_large_trace_prompt_size = pSettingsNode->value_as_uint32("trim_large_trace_prompt_size", m_defaults.trim_large_trace_prompt_size); + + m_settings.window_position_left = pSettingsNode->value_as_int("window_position_left", m_defaults.window_position_left); + m_settings.window_position_top = pSettingsNode->value_as_int("window_position_top", m_defaults.window_position_top); + m_settings.window_size_width = pSettingsNode->value_as_int("window_size_width", m_defaults.window_size_width); + m_settings.window_size_height = pSettingsNode->value_as_int("window_size_height", m_defaults.window_size_height); + } + + return bLoaded; +} + +bool vogleditor_settings::save(const char* settingsFile) +{ + json_document settingsDoc; + json_node& metadata = settingsDoc.get_root()->add_object("metadata"); + metadata.add_key_value("vogleditor_settings_file_format_version", to_hex_string(VOGLEDITOR_SETTINGS_FILE_FORMAT_VERSION)); + + // settings + json_node& settings = settingsDoc.get_root()->add_object("settings"); + settings.add_key_value("trim_large_trace_prompt_size", m_settings.trim_large_trace_prompt_size); + + settings.add_key_value("window_position_left", m_settings.window_position_left); + settings.add_key_value("window_position_top", m_settings.window_position_top); + settings.add_key_value("window_size_width", m_settings.window_size_width); + settings.add_key_value("window_size_height", m_settings.window_size_height); + + dynamic_string path = get_settings_path(settingsFile); + bool bSavedSuccessfully = settingsDoc.serialize_to_file(path.c_str()); + return bSavedSuccessfully; +} diff --git a/src/vogleditor/vogleditor_settings.h b/src/vogleditor/vogleditor_settings.h new file mode 100644 index 0000000..3da7a75 --- /dev/null +++ b/src/vogleditor/vogleditor_settings.h @@ -0,0 +1,44 @@ +#ifndef VOGLEDITOR_SETTINGS_H +#define VOGLEDITOR_SETTINGS_H + +#include "vogl_dynamic_string.h" + +struct vogleditor_setting_struct +{ + int window_position_left; + int window_position_top; + int window_size_width; + int window_size_height; + unsigned int trim_large_trace_prompt_size; +}; + +class vogleditor_settings +{ +public: + vogleditor_settings(); + virtual ~vogleditor_settings() {} + + bool load(const char* settingsFile); + bool save(const char* settingsFile); + + int window_position_left() { return m_settings.window_position_left; } + int window_position_top() { return m_settings.window_position_top; } + int window_size_width() { return m_settings.window_size_width; } + int window_size_height() { return m_settings.window_size_height; } + void set_window_position_left(int window_position_left) { m_settings.window_position_left = window_position_left; } + void set_window_position_top(int window_position_top) { m_settings.window_position_top = window_position_top; } + void set_window_size_width(int window_size_width) { m_settings.window_size_width = window_size_width; } + void set_window_size_height(int window_size_height) { m_settings.window_size_height = window_size_height; } + + unsigned int trim_large_trace_prompt_size() { return m_settings.trim_large_trace_prompt_size; } + void set_trim_large_trace_prompt_size(unsigned int trim_large_trace_prompt_size) { m_settings.trim_large_trace_prompt_size = trim_large_trace_prompt_size; } + +private: + unsigned int m_file_format_version; + vogleditor_setting_struct m_settings; + vogleditor_setting_struct m_defaults; + + vogl::dynamic_string get_settings_path(const char* settingsFilename); +}; + +#endif // VOGLEDITOR_SETTINGS_H