mirror of
https://github.com/ciphervance/supercell-wx.git
synced 2025-11-01 20:50:06 +00:00
Merge branch 'feature/placefiles-font' into feature/placefiles
This commit is contained in:
commit
cfa62d5fbc
52 changed files with 1988 additions and 542 deletions
|
|
@ -18,6 +18,7 @@ Supercell Wx uses code from the following dependencies:
|
||||||
| [CSS Color Parser](https://github.com/deanm/css-color-parser-js) | [MIT License](https://spdx.org/licenses/MIT.html) | Ported to C++ for MapLibre Native |
|
| [CSS Color Parser](https://github.com/deanm/css-color-parser-js) | [MIT License](https://spdx.org/licenses/MIT.html) | Ported to C++ for MapLibre Native |
|
||||||
| [Date](https://github.com/HowardHinnant/date) | [MIT License](https://spdx.org/licenses/MIT.html) |
|
| [Date](https://github.com/HowardHinnant/date) | [MIT License](https://spdx.org/licenses/MIT.html) |
|
||||||
| [Dear ImGui](https://github.com/ocornut/imgui) | [MIT License](https://spdx.org/licenses/MIT.html) |
|
| [Dear ImGui](https://github.com/ocornut/imgui) | [MIT License](https://spdx.org/licenses/MIT.html) |
|
||||||
|
| [fontconfig](http://fontconfig.org/) | [MIT License](https://spdx.org/licenses/MIT.html) |
|
||||||
| [FreeType](https://freetype.org/) | [Freetype Project License](https://spdx.org/licenses/FTL.html) |
|
| [FreeType](https://freetype.org/) | [Freetype Project License](https://spdx.org/licenses/FTL.html) |
|
||||||
| [FreeType GL](https://github.com/rougier/freetype-gl) | [BSD 2-Clause with views sentence](https://spdx.org/licenses/BSD-2-Clause-Views.html) |
|
| [FreeType GL](https://github.com/rougier/freetype-gl) | [BSD 2-Clause with views sentence](https://spdx.org/licenses/BSD-2-Clause-Views.html) |
|
||||||
| [GeographicLib](https://geographiclib.sourceforge.io/) | [MIT License](https://spdx.org/licenses/MIT.html) |
|
| [GeographicLib](https://geographiclib.sourceforge.io/) | [MIT License](https://spdx.org/licenses/MIT.html) |
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ class SupercellWxConan(ConanFile):
|
||||||
settings = ("os", "compiler", "build_type", "arch")
|
settings = ("os", "compiler", "build_type", "arch")
|
||||||
requires = ("boost/1.81.0",
|
requires = ("boost/1.81.0",
|
||||||
"cpr/1.9.3",
|
"cpr/1.9.3",
|
||||||
|
"fontconfig/2.14.2",
|
||||||
"freetype/2.12.1",
|
"freetype/2.12.1",
|
||||||
"geographiclib/1.52",
|
"geographiclib/1.52",
|
||||||
"glew/2.2.0",
|
"glew/2.2.0",
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ set(CMAKE_CXX_STANDARD 20)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
find_package(Boost)
|
find_package(Boost)
|
||||||
|
find_package(Fontconfig)
|
||||||
find_package(Freetype)
|
find_package(Freetype)
|
||||||
find_package(geographiclib)
|
find_package(geographiclib)
|
||||||
find_package(glm)
|
find_package(glm)
|
||||||
|
|
@ -73,7 +74,8 @@ set(SRC_GL_DRAW source/scwx/qt/gl/draw/draw_item.cpp
|
||||||
source/scwx/qt/gl/draw/placefile_text.cpp
|
source/scwx/qt/gl/draw/placefile_text.cpp
|
||||||
source/scwx/qt/gl/draw/placefile_triangles.cpp
|
source/scwx/qt/gl/draw/placefile_triangles.cpp
|
||||||
source/scwx/qt/gl/draw/rectangle.cpp)
|
source/scwx/qt/gl/draw/rectangle.cpp)
|
||||||
set(HDR_MANAGER source/scwx/qt/manager/placefile_manager.hpp
|
set(HDR_MANAGER source/scwx/qt/manager/font_manager.hpp
|
||||||
|
source/scwx/qt/manager/placefile_manager.hpp
|
||||||
source/scwx/qt/manager/radar_product_manager.hpp
|
source/scwx/qt/manager/radar_product_manager.hpp
|
||||||
source/scwx/qt/manager/radar_product_manager_notifier.hpp
|
source/scwx/qt/manager/radar_product_manager_notifier.hpp
|
||||||
source/scwx/qt/manager/resource_manager.hpp
|
source/scwx/qt/manager/resource_manager.hpp
|
||||||
|
|
@ -81,7 +83,8 @@ set(HDR_MANAGER source/scwx/qt/manager/placefile_manager.hpp
|
||||||
source/scwx/qt/manager/text_event_manager.hpp
|
source/scwx/qt/manager/text_event_manager.hpp
|
||||||
source/scwx/qt/manager/timeline_manager.hpp
|
source/scwx/qt/manager/timeline_manager.hpp
|
||||||
source/scwx/qt/manager/update_manager.hpp)
|
source/scwx/qt/manager/update_manager.hpp)
|
||||||
set(SRC_MANAGER source/scwx/qt/manager/placefile_manager.cpp
|
set(SRC_MANAGER source/scwx/qt/manager/font_manager.cpp
|
||||||
|
source/scwx/qt/manager/placefile_manager.cpp
|
||||||
source/scwx/qt/manager/radar_product_manager.cpp
|
source/scwx/qt/manager/radar_product_manager.cpp
|
||||||
source/scwx/qt/manager/radar_product_manager_notifier.cpp
|
source/scwx/qt/manager/radar_product_manager_notifier.cpp
|
||||||
source/scwx/qt/manager/resource_manager.cpp
|
source/scwx/qt/manager/resource_manager.cpp
|
||||||
|
|
@ -157,6 +160,7 @@ set(SRC_SETTINGS source/scwx/qt/settings/general_settings.cpp
|
||||||
set(HDR_TYPES source/scwx/qt/types/alert_types.hpp
|
set(HDR_TYPES source/scwx/qt/types/alert_types.hpp
|
||||||
source/scwx/qt/types/font_types.hpp
|
source/scwx/qt/types/font_types.hpp
|
||||||
source/scwx/qt/types/github_types.hpp
|
source/scwx/qt/types/github_types.hpp
|
||||||
|
source/scwx/qt/types/imgui_font.hpp
|
||||||
source/scwx/qt/types/map_types.hpp
|
source/scwx/qt/types/map_types.hpp
|
||||||
source/scwx/qt/types/qt_types.hpp
|
source/scwx/qt/types/qt_types.hpp
|
||||||
source/scwx/qt/types/radar_product_record.hpp
|
source/scwx/qt/types/radar_product_record.hpp
|
||||||
|
|
@ -164,6 +168,7 @@ set(HDR_TYPES source/scwx/qt/types/alert_types.hpp
|
||||||
source/scwx/qt/types/text_types.hpp)
|
source/scwx/qt/types/text_types.hpp)
|
||||||
set(SRC_TYPES source/scwx/qt/types/alert_types.cpp
|
set(SRC_TYPES source/scwx/qt/types/alert_types.cpp
|
||||||
source/scwx/qt/types/github_types.cpp
|
source/scwx/qt/types/github_types.cpp
|
||||||
|
source/scwx/qt/types/imgui_font.cpp
|
||||||
source/scwx/qt/types/map_types.cpp
|
source/scwx/qt/types/map_types.cpp
|
||||||
source/scwx/qt/types/radar_product_record.cpp
|
source/scwx/qt/types/radar_product_record.cpp
|
||||||
source/scwx/qt/types/text_event_key.cpp
|
source/scwx/qt/types/text_event_key.cpp
|
||||||
|
|
@ -476,6 +481,7 @@ target_link_libraries(scwx-qt PUBLIC Qt${QT_VERSION_MAJOR}::Widgets
|
||||||
Boost::timer
|
Boost::timer
|
||||||
qmaplibregl
|
qmaplibregl
|
||||||
$<$<CXX_COMPILER_ID:MSVC>:opengl32>
|
$<$<CXX_COMPILER_ID:MSVC>:opengl32>
|
||||||
|
Fontconfig::Fontconfig
|
||||||
freetype-gl
|
freetype-gl
|
||||||
GeographicLib::GeographicLib
|
GeographicLib::GeographicLib
|
||||||
glm::glm
|
glm::glm
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
#include <scwx/qt/gl/draw/placefile_text.hpp>
|
#include <scwx/qt/gl/draw/placefile_text.hpp>
|
||||||
|
#include <scwx/qt/manager/font_manager.hpp>
|
||||||
|
#include <scwx/qt/manager/placefile_manager.hpp>
|
||||||
#include <scwx/qt/util/maplibre.hpp>
|
#include <scwx/qt/util/maplibre.hpp>
|
||||||
#include <scwx/qt/util/tooltip.hpp>
|
#include <scwx/qt/util/tooltip.hpp>
|
||||||
#include <scwx/util/logger.hpp>
|
#include <scwx/util/logger.hpp>
|
||||||
|
|
@ -37,6 +39,7 @@ public:
|
||||||
const std::string& text,
|
const std::string& text,
|
||||||
const std::string& hoverText,
|
const std::string& hoverText,
|
||||||
boost::gil::rgba8_pixel_t color,
|
boost::gil::rgba8_pixel_t color,
|
||||||
|
std::size_t fontNumber,
|
||||||
float x,
|
float x,
|
||||||
float y);
|
float y);
|
||||||
|
|
||||||
|
|
@ -62,6 +65,9 @@ public:
|
||||||
std::mutex listMutex_ {};
|
std::mutex listMutex_ {};
|
||||||
std::vector<std::shared_ptr<const gr::Placefile::TextDrawItem>> textList_ {};
|
std::vector<std::shared_ptr<const gr::Placefile::TextDrawItem>> textList_ {};
|
||||||
std::vector<std::shared_ptr<const gr::Placefile::TextDrawItem>> newList_ {};
|
std::vector<std::shared_ptr<const gr::Placefile::TextDrawItem>> newList_ {};
|
||||||
|
|
||||||
|
std::vector<std::shared_ptr<types::ImGuiFont>> fonts_ {};
|
||||||
|
std::vector<std::shared_ptr<types::ImGuiFont>> newFonts_ {};
|
||||||
};
|
};
|
||||||
|
|
||||||
PlacefileText::PlacefileText(const std::shared_ptr<GlContext>& context,
|
PlacefileText::PlacefileText(const std::shared_ptr<GlContext>& context,
|
||||||
|
|
@ -155,6 +161,7 @@ void PlacefileText::Impl::RenderTextDrawItem(
|
||||||
di->text_,
|
di->text_,
|
||||||
di->hoverText_,
|
di->hoverText_,
|
||||||
di->color_,
|
di->color_,
|
||||||
|
std::clamp<std::size_t>(di->fontNumber_, 1, 8),
|
||||||
rotatedX + di->x_ + halfWidth_,
|
rotatedX + di->x_ + halfWidth_,
|
||||||
rotatedY + di->y_ + halfHeight_);
|
rotatedY + di->y_ + halfHeight_);
|
||||||
}
|
}
|
||||||
|
|
@ -165,6 +172,7 @@ void PlacefileText::Impl::RenderText(
|
||||||
const std::string& text,
|
const std::string& text,
|
||||||
const std::string& hoverText,
|
const std::string& hoverText,
|
||||||
boost::gil::rgba8_pixel_t color,
|
boost::gil::rgba8_pixel_t color,
|
||||||
|
std::size_t fontNumber,
|
||||||
float x,
|
float x,
|
||||||
float y)
|
float y)
|
||||||
{
|
{
|
||||||
|
|
@ -184,10 +192,12 @@ void PlacefileText::Impl::RenderText(
|
||||||
ImGuiWindowFlags_NoBackground);
|
ImGuiWindowFlags_NoBackground);
|
||||||
|
|
||||||
// Render text
|
// Render text
|
||||||
|
ImGui::PushFont(fonts_[fontNumber - 1]->font());
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text,
|
ImGui::PushStyleColor(ImGuiCol_Text,
|
||||||
IM_COL32(color[0], color[1], color[2], color[3]));
|
IM_COL32(color[0], color[1], color[2], color[3]));
|
||||||
ImGui::TextUnformatted(text.c_str());
|
ImGui::TextUnformatted(text.c_str());
|
||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
|
ImGui::PopFont();
|
||||||
|
|
||||||
// Store hover text for mouse picking pass
|
// Store hover text for mouse picking pass
|
||||||
if (!hoverText.empty() && ImGui::IsItemHovered())
|
if (!hoverText.empty() && ImGui::IsItemHovered())
|
||||||
|
|
@ -231,6 +241,28 @@ void PlacefileText::StartText()
|
||||||
p->newList_.clear();
|
p->newList_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PlacefileText::SetFonts(
|
||||||
|
const boost::unordered_flat_map<std::size_t,
|
||||||
|
std::shared_ptr<types::ImGuiFont>>& fonts)
|
||||||
|
{
|
||||||
|
auto defaultFont = manager::FontManager::Instance().GetImGuiFont(
|
||||||
|
types::FontCategory::Default);
|
||||||
|
|
||||||
|
// Valid font numbers are from 1 to 8, place in 0-based font vector
|
||||||
|
for (std::size_t i = 1; i <= 8; ++i)
|
||||||
|
{
|
||||||
|
auto it = fonts.find(i);
|
||||||
|
if (it != fonts.cend())
|
||||||
|
{
|
||||||
|
p->newFonts_.push_back(it->second);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p->newFonts_.push_back(defaultFont);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PlacefileText::AddText(
|
void PlacefileText::AddText(
|
||||||
const std::shared_ptr<gr::Placefile::TextDrawItem>& di)
|
const std::shared_ptr<gr::Placefile::TextDrawItem>& di)
|
||||||
{
|
{
|
||||||
|
|
@ -246,9 +278,11 @@ void PlacefileText::FinishText()
|
||||||
|
|
||||||
// Swap text lists
|
// Swap text lists
|
||||||
p->textList_.swap(p->newList_);
|
p->textList_.swap(p->newList_);
|
||||||
|
p->fonts_.swap(p->newFonts_);
|
||||||
|
|
||||||
// Clear the new list
|
// Clear the new list
|
||||||
p->newList_.clear();
|
p->newList_.clear();
|
||||||
|
p->newFonts_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace draw
|
} // namespace draw
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,11 @@
|
||||||
|
|
||||||
#include <scwx/qt/gl/gl_context.hpp>
|
#include <scwx/qt/gl/gl_context.hpp>
|
||||||
#include <scwx/qt/gl/draw/draw_item.hpp>
|
#include <scwx/qt/gl/draw/draw_item.hpp>
|
||||||
|
#include <scwx/qt/types/imgui_font.hpp>
|
||||||
#include <scwx/gr/placefile.hpp>
|
#include <scwx/gr/placefile.hpp>
|
||||||
|
|
||||||
|
#include <boost/unordered/unordered_flat_map.hpp>
|
||||||
|
|
||||||
namespace scwx
|
namespace scwx
|
||||||
{
|
{
|
||||||
namespace qt
|
namespace qt
|
||||||
|
|
@ -44,6 +47,16 @@ public:
|
||||||
*/
|
*/
|
||||||
void StartText();
|
void StartText();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the fonts for drawing the placefile text.
|
||||||
|
*
|
||||||
|
* @param [in] fonts A map of ImGui fonts
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
SetFonts(const boost::unordered_flat_map<std::size_t,
|
||||||
|
std::shared_ptr<types::ImGuiFont>>&
|
||||||
|
fonts);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds placefile text to the internal draw list.
|
* Adds placefile text to the internal draw list.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
// Initialize application
|
// Initialize application
|
||||||
scwx::qt::config::RadarSite::Initialize();
|
scwx::qt::config::RadarSite::Initialize();
|
||||||
scwx::qt::manager::SettingsManager::Initialize();
|
scwx::qt::manager::SettingsManager::Instance().Initialize();
|
||||||
scwx::qt::manager::ResourceManager::Initialize();
|
scwx::qt::manager::ResourceManager::Initialize();
|
||||||
|
|
||||||
// Run Qt main loop
|
// Run Qt main loop
|
||||||
|
|
@ -89,7 +89,7 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
// Shutdown application
|
// Shutdown application
|
||||||
scwx::qt::manager::ResourceManager::Shutdown();
|
scwx::qt::manager::ResourceManager::Shutdown();
|
||||||
scwx::qt::manager::SettingsManager::Shutdown();
|
scwx::qt::manager::SettingsManager::Instance().Shutdown();
|
||||||
|
|
||||||
// Shutdown AWS SDK
|
// Shutdown AWS SDK
|
||||||
Aws::ShutdownAPI(awsSdkOptions);
|
Aws::ShutdownAPI(awsSdkOptions);
|
||||||
|
|
|
||||||
|
|
@ -7,13 +7,14 @@
|
||||||
#include <scwx/qt/main/versions.hpp>
|
#include <scwx/qt/main/versions.hpp>
|
||||||
#include <scwx/qt/manager/placefile_manager.hpp>
|
#include <scwx/qt/manager/placefile_manager.hpp>
|
||||||
#include <scwx/qt/manager/radar_product_manager.hpp>
|
#include <scwx/qt/manager/radar_product_manager.hpp>
|
||||||
#include <scwx/qt/manager/settings_manager.hpp>
|
|
||||||
#include <scwx/qt/manager/text_event_manager.hpp>
|
#include <scwx/qt/manager/text_event_manager.hpp>
|
||||||
#include <scwx/qt/manager/timeline_manager.hpp>
|
#include <scwx/qt/manager/timeline_manager.hpp>
|
||||||
#include <scwx/qt/manager/update_manager.hpp>
|
#include <scwx/qt/manager/update_manager.hpp>
|
||||||
#include <scwx/qt/map/map_provider.hpp>
|
#include <scwx/qt/map/map_provider.hpp>
|
||||||
#include <scwx/qt/map/map_widget.hpp>
|
#include <scwx/qt/map/map_widget.hpp>
|
||||||
#include <scwx/qt/model/radar_product_model.hpp>
|
#include <scwx/qt/model/radar_product_model.hpp>
|
||||||
|
#include <scwx/qt/settings/general_settings.hpp>
|
||||||
|
#include <scwx/qt/settings/map_settings.hpp>
|
||||||
#include <scwx/qt/settings/ui_settings.hpp>
|
#include <scwx/qt/settings/ui_settings.hpp>
|
||||||
#include <scwx/qt/ui/about_dialog.hpp>
|
#include <scwx/qt/ui/about_dialog.hpp>
|
||||||
#include <scwx/qt/ui/alert_dock_widget.hpp>
|
#include <scwx/qt/ui/alert_dock_widget.hpp>
|
||||||
|
|
@ -89,10 +90,8 @@ public:
|
||||||
elevationButtonsChanged_ {false},
|
elevationButtonsChanged_ {false},
|
||||||
resizeElevationButtons_ {false}
|
resizeElevationButtons_ {false}
|
||||||
{
|
{
|
||||||
mapProvider_ =
|
mapProvider_ = map::GetMapProvider(
|
||||||
map::GetMapProvider(manager::SettingsManager::general_settings()
|
settings::GeneralSettings::Instance().map_provider().GetValue());
|
||||||
.map_provider()
|
|
||||||
.GetValue());
|
|
||||||
const map::MapProviderInfo& mapProviderInfo =
|
const map::MapProviderInfo& mapProviderInfo =
|
||||||
map::GetMapProviderInfo(mapProvider_);
|
map::GetMapProviderInfo(mapProvider_);
|
||||||
|
|
||||||
|
|
@ -230,7 +229,7 @@ MainWindow::MainWindow(QWidget* parent) :
|
||||||
ui->actionAlerts->setVisible(false);
|
ui->actionAlerts->setVisible(false);
|
||||||
|
|
||||||
ui->menuDebug->menuAction()->setVisible(
|
ui->menuDebug->menuAction()->setVisible(
|
||||||
manager::SettingsManager::general_settings().debug_enabled().GetValue());
|
settings::GeneralSettings::Instance().debug_enabled().GetValue());
|
||||||
|
|
||||||
// Configure Resource Explorer Dock
|
// Configure Resource Explorer Dock
|
||||||
ui->resourceExplorerDock->setVisible(false);
|
ui->resourceExplorerDock->setVisible(false);
|
||||||
|
|
@ -306,7 +305,7 @@ MainWindow::MainWindow(QWidget* parent) :
|
||||||
// Update Dialog
|
// Update Dialog
|
||||||
p->updateDialog_ = new ui::UpdateDialog(this);
|
p->updateDialog_ = new ui::UpdateDialog(this);
|
||||||
|
|
||||||
auto& mapSettings = manager::SettingsManager::map_settings();
|
auto& mapSettings = settings::MapSettings::Instance();
|
||||||
for (size_t i = 0; i < p->maps_.size(); i++)
|
for (size_t i = 0; i < p->maps_.size(); i++)
|
||||||
{
|
{
|
||||||
p->SelectRadarProduct(p->maps_.at(i),
|
p->SelectRadarProduct(p->maps_.at(i),
|
||||||
|
|
@ -582,7 +581,7 @@ void MainWindow::on_resourceTreeView_doubleClicked(const QModelIndex& index)
|
||||||
|
|
||||||
void MainWindowImpl::AsyncSetup()
|
void MainWindowImpl::AsyncSetup()
|
||||||
{
|
{
|
||||||
auto& generalSettings = manager::SettingsManager::general_settings();
|
auto& generalSettings = settings::GeneralSettings::Instance();
|
||||||
|
|
||||||
// Check for updates
|
// Check for updates
|
||||||
if (generalSettings.update_notifications_enabled().GetValue())
|
if (generalSettings.update_notifications_enabled().GetValue())
|
||||||
|
|
@ -595,7 +594,7 @@ void MainWindowImpl::AsyncSetup()
|
||||||
|
|
||||||
void MainWindowImpl::ConfigureMapLayout()
|
void MainWindowImpl::ConfigureMapLayout()
|
||||||
{
|
{
|
||||||
auto& generalSettings = manager::SettingsManager::general_settings();
|
auto& generalSettings = settings::GeneralSettings::Instance();
|
||||||
|
|
||||||
const int64_t gridWidth = generalSettings.grid_width().GetValue();
|
const int64_t gridWidth = generalSettings.grid_width().GetValue();
|
||||||
const int64_t gridHeight = generalSettings.grid_height().GetValue();
|
const int64_t gridHeight = generalSettings.grid_height().GetValue();
|
||||||
|
|
@ -646,7 +645,7 @@ void MainWindowImpl::ConfigureMapLayout()
|
||||||
void MainWindowImpl::ConfigureMapStyles()
|
void MainWindowImpl::ConfigureMapStyles()
|
||||||
{
|
{
|
||||||
const auto& mapProviderInfo = map::GetMapProviderInfo(mapProvider_);
|
const auto& mapProviderInfo = map::GetMapProviderInfo(mapProvider_);
|
||||||
auto& mapSettings = manager::SettingsManager::map_settings();
|
auto& mapSettings = settings::MapSettings::Instance();
|
||||||
|
|
||||||
for (std::size_t i = 0; i < maps_.size(); i++)
|
for (std::size_t i = 0; i < maps_.size(); i++)
|
||||||
{
|
{
|
||||||
|
|
@ -897,8 +896,7 @@ void MainWindowImpl::ConnectOtherSignals()
|
||||||
{
|
{
|
||||||
if (maps_[i] == activeMap_)
|
if (maps_[i] == activeMap_)
|
||||||
{
|
{
|
||||||
auto& mapSettings =
|
auto& mapSettings = settings::MapSettings::Instance();
|
||||||
manager::SettingsManager::map_settings();
|
|
||||||
mapSettings.map_style(i).StageValue(text.toStdString());
|
mapSettings.map_style(i).StageValue(text.toStdString());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -1075,7 +1073,7 @@ void MainWindowImpl::UpdateMapStyle(const std::string& styleName)
|
||||||
{
|
{
|
||||||
if (maps_[i] == activeMap_)
|
if (maps_[i] == activeMap_)
|
||||||
{
|
{
|
||||||
auto& mapSettings = manager::SettingsManager::map_settings();
|
auto& mapSettings = settings::MapSettings::Instance();
|
||||||
mapSettings.map_style(i).StageValue(styleName);
|
mapSettings.map_style(i).StageValue(styleName);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
512
scwx-qt/source/scwx/qt/manager/font_manager.cpp
Normal file
512
scwx-qt/source/scwx/qt/manager/font_manager.cpp
Normal file
|
|
@ -0,0 +1,512 @@
|
||||||
|
#include <scwx/qt/manager/font_manager.hpp>
|
||||||
|
#include <scwx/qt/manager/settings_manager.hpp>
|
||||||
|
#include <scwx/qt/settings/text_settings.hpp>
|
||||||
|
#include <scwx/util/logger.hpp>
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
#include <QFile>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QFontDatabase>
|
||||||
|
#include <QStandardPaths>
|
||||||
|
#include <boost/container_hash/hash.hpp>
|
||||||
|
#include <boost/unordered/unordered_flat_map.hpp>
|
||||||
|
#include <boost/unordered/unordered_flat_set.hpp>
|
||||||
|
#include <fontconfig/fontconfig.h>
|
||||||
|
|
||||||
|
namespace scwx
|
||||||
|
{
|
||||||
|
namespace qt
|
||||||
|
{
|
||||||
|
namespace manager
|
||||||
|
{
|
||||||
|
|
||||||
|
static const std::string logPrefix_ = "scwx::qt::manager::font_manager";
|
||||||
|
static const auto logger_ = scwx::util::Logger::Create(logPrefix_);
|
||||||
|
|
||||||
|
static const std::string kFcTrueType_ {"TrueType"};
|
||||||
|
|
||||||
|
struct FontRecord
|
||||||
|
{
|
||||||
|
std::string family_ {};
|
||||||
|
std::string style_ {};
|
||||||
|
std::string filename_ {};
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::pair<FontRecord, units::font_size::pixels<int>> FontRecordPair;
|
||||||
|
|
||||||
|
template<class Key>
|
||||||
|
struct FontRecordHash;
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct FontRecordHash<FontRecordPair>
|
||||||
|
{
|
||||||
|
size_t operator()(const FontRecordPair& x) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FontManager::Impl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit Impl(FontManager* self) : self_ {self}
|
||||||
|
{
|
||||||
|
InitializeFontCache();
|
||||||
|
InitializeFontconfig();
|
||||||
|
ConnectSignals();
|
||||||
|
}
|
||||||
|
~Impl() { FinalizeFontconfig(); }
|
||||||
|
|
||||||
|
void ConnectSignals();
|
||||||
|
void FinalizeFontconfig();
|
||||||
|
void InitializeFontCache();
|
||||||
|
void InitializeFontconfig();
|
||||||
|
void UpdateImGuiFont(types::FontCategory fontCategory);
|
||||||
|
|
||||||
|
const std::vector<char>& GetRawFontData(const std::string& filename);
|
||||||
|
|
||||||
|
static FontRecord MatchFontFile(const std::string& family,
|
||||||
|
const std::vector<std::string>& styles);
|
||||||
|
|
||||||
|
FontManager* self_;
|
||||||
|
|
||||||
|
std::string fontCachePath_ {};
|
||||||
|
|
||||||
|
std::shared_mutex imguiFontAtlasMutex_ {};
|
||||||
|
|
||||||
|
std::uint64_t imguiFontsBuildCount_ {};
|
||||||
|
|
||||||
|
boost::unordered_flat_map<FontRecordPair,
|
||||||
|
std::shared_ptr<types::ImGuiFont>,
|
||||||
|
FontRecordHash<FontRecordPair>>
|
||||||
|
imguiFonts_ {};
|
||||||
|
std::shared_mutex imguiFontsMutex_ {};
|
||||||
|
|
||||||
|
boost::unordered_flat_map<std::string, std::vector<char>> rawFontData_ {};
|
||||||
|
std::mutex rawFontDataMutex_ {};
|
||||||
|
|
||||||
|
std::shared_ptr<types::ImGuiFont> defaultFont_ {};
|
||||||
|
boost::unordered_flat_map<types::FontCategory,
|
||||||
|
std::shared_ptr<types::ImGuiFont>>
|
||||||
|
fontCategoryMap_ {};
|
||||||
|
std::mutex fontCategoryMutex_ {};
|
||||||
|
|
||||||
|
boost::unordered_flat_set<types::FontCategory> dirtyFonts_ {};
|
||||||
|
std::mutex dirtyFontsMutex_ {};
|
||||||
|
|
||||||
|
boost::unordered_flat_map<types::Font, int> fontIds_ {};
|
||||||
|
};
|
||||||
|
|
||||||
|
FontManager::FontManager() : p(std::make_unique<Impl>(this)) {}
|
||||||
|
|
||||||
|
FontManager::~FontManager() {};
|
||||||
|
|
||||||
|
void FontManager::Impl::ConnectSignals()
|
||||||
|
{
|
||||||
|
auto& textSettings = settings::TextSettings::Instance();
|
||||||
|
|
||||||
|
for (auto fontCategory : types::FontCategoryIterator())
|
||||||
|
{
|
||||||
|
textSettings.font_family(fontCategory)
|
||||||
|
.RegisterValueChangedCallback(
|
||||||
|
[this, fontCategory](const auto&)
|
||||||
|
{
|
||||||
|
std::unique_lock lock {dirtyFontsMutex_};
|
||||||
|
dirtyFonts_.insert(fontCategory);
|
||||||
|
});
|
||||||
|
textSettings.font_style(fontCategory)
|
||||||
|
.RegisterValueChangedCallback(
|
||||||
|
[this, fontCategory](const auto&)
|
||||||
|
{
|
||||||
|
std::unique_lock lock {dirtyFontsMutex_};
|
||||||
|
dirtyFonts_.insert(fontCategory);
|
||||||
|
});
|
||||||
|
textSettings.font_point_size(fontCategory)
|
||||||
|
.RegisterValueChangedCallback(
|
||||||
|
[this, fontCategory](const auto&)
|
||||||
|
{
|
||||||
|
std::unique_lock lock {dirtyFontsMutex_};
|
||||||
|
dirtyFonts_.insert(fontCategory);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QObject::connect(
|
||||||
|
&SettingsManager::Instance(),
|
||||||
|
&SettingsManager::SettingsSaved,
|
||||||
|
self_,
|
||||||
|
[this]()
|
||||||
|
{
|
||||||
|
std::scoped_lock lock {dirtyFontsMutex_, fontCategoryMutex_};
|
||||||
|
|
||||||
|
for (auto fontCategory : dirtyFonts_)
|
||||||
|
{
|
||||||
|
UpdateImGuiFont(fontCategory);
|
||||||
|
}
|
||||||
|
|
||||||
|
dirtyFonts_.clear();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void FontManager::InitializeFonts()
|
||||||
|
{
|
||||||
|
for (auto fontCategory : types::FontCategoryIterator())
|
||||||
|
{
|
||||||
|
p->UpdateImGuiFont(fontCategory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FontManager::Impl::UpdateImGuiFont(types::FontCategory fontCategory)
|
||||||
|
{
|
||||||
|
auto& textSettings = settings::TextSettings::Instance();
|
||||||
|
|
||||||
|
auto family = textSettings.font_family(fontCategory).GetValue();
|
||||||
|
auto styles = textSettings.font_style(fontCategory).GetValue();
|
||||||
|
units::font_size::points<double> size {
|
||||||
|
textSettings.font_point_size(fontCategory).GetValue()};
|
||||||
|
|
||||||
|
fontCategoryMap_.insert_or_assign(
|
||||||
|
fontCategory, self_->LoadImGuiFont(family, {styles}, size));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_mutex& FontManager::imgui_font_atlas_mutex()
|
||||||
|
{
|
||||||
|
return p->imguiFontAtlasMutex_;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint64_t FontManager::imgui_fonts_build_count() const
|
||||||
|
{
|
||||||
|
return p->imguiFontsBuildCount_;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FontManager::GetFontId(types::Font font) const
|
||||||
|
{
|
||||||
|
auto it = p->fontIds_.find(font);
|
||||||
|
if (it != p->fontIds_.cend())
|
||||||
|
{
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<types::ImGuiFont>
|
||||||
|
FontManager::GetImGuiFont(types::FontCategory fontCategory)
|
||||||
|
{
|
||||||
|
std::unique_lock lock {p->fontCategoryMutex_};
|
||||||
|
|
||||||
|
auto it = p->fontCategoryMap_.find(fontCategory);
|
||||||
|
if (it != p->fontCategoryMap_.cend())
|
||||||
|
{
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return p->defaultFont_;
|
||||||
|
}
|
||||||
|
|
||||||
|
QFont FontManager::GetQFont(types::FontCategory fontCategory)
|
||||||
|
{
|
||||||
|
auto& textSettings = settings::TextSettings::Instance();
|
||||||
|
|
||||||
|
auto family = textSettings.font_family(fontCategory).GetValue();
|
||||||
|
auto styles = textSettings.font_style(fontCategory).GetValue();
|
||||||
|
units::font_size::points<double> size {
|
||||||
|
textSettings.font_point_size(fontCategory).GetValue()};
|
||||||
|
|
||||||
|
QFont font(QString::fromStdString(family));
|
||||||
|
font.setStyleName(QString::fromStdString(styles));
|
||||||
|
font.setPointSizeF(size.value());
|
||||||
|
|
||||||
|
return font;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<types::ImGuiFont>
|
||||||
|
FontManager::LoadImGuiFont(const std::string& family,
|
||||||
|
const std::vector<std::string>& styles,
|
||||||
|
units::font_size::points<double> size,
|
||||||
|
bool loadIfNotFound)
|
||||||
|
{
|
||||||
|
const std::string styleString = fmt::format("{}", fmt::join(styles, " "));
|
||||||
|
const std::string fontString =
|
||||||
|
fmt::format("{}-{}:{}", family, size.value(), styleString);
|
||||||
|
|
||||||
|
logger_->debug("LoadFontResource: {}", fontString);
|
||||||
|
|
||||||
|
FontRecord fontRecord = Impl::MatchFontFile(family, styles);
|
||||||
|
|
||||||
|
// Only allow whole pixels, and clamp to 6-72 pt
|
||||||
|
units::font_size::pixels<double> pixels {size};
|
||||||
|
units::font_size::pixels<int> imFontSize {
|
||||||
|
std::clamp(static_cast<int>(pixels.value()), 8, 96)};
|
||||||
|
auto imguiFontKey = std::make_pair(fontRecord, imFontSize);
|
||||||
|
|
||||||
|
// Search for a loaded ImGui font
|
||||||
|
{
|
||||||
|
std::shared_lock imguiFontLock {p->imguiFontsMutex_};
|
||||||
|
|
||||||
|
// Search for the associated ImGui font
|
||||||
|
auto it = p->imguiFonts_.find(imguiFontKey);
|
||||||
|
if (it != p->imguiFonts_.end())
|
||||||
|
{
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No ImGui font was found, we need to create one
|
||||||
|
}
|
||||||
|
|
||||||
|
// No font was found, return an empty shared pointer if not loading
|
||||||
|
if (!loadIfNotFound)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get raw font data
|
||||||
|
const auto& rawFontData = p->GetRawFontData(fontRecord.filename_);
|
||||||
|
|
||||||
|
// The font atlas mutex might already be locked within an ImGui render frame.
|
||||||
|
// Lock the font atlas mutex before the fonts mutex to prevent deadlock.
|
||||||
|
std::unique_lock imguiFontAtlasLock {p->imguiFontAtlasMutex_};
|
||||||
|
std::unique_lock imguiFontsLock {p->imguiFontsMutex_};
|
||||||
|
|
||||||
|
// Search for the associated ImGui font again, to prevent loading the same
|
||||||
|
// font twice
|
||||||
|
auto it = p->imguiFonts_.find(imguiFontKey);
|
||||||
|
if (it != p->imguiFonts_.end())
|
||||||
|
{
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define a name for the ImGui font
|
||||||
|
std::string fontName;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
fontName = fmt::format(
|
||||||
|
"{}:{}",
|
||||||
|
std::filesystem::path(fontRecord.filename_).filename().string(),
|
||||||
|
imFontSize.value());
|
||||||
|
}
|
||||||
|
catch (const std::exception& ex)
|
||||||
|
{
|
||||||
|
logger_->warn(ex.what());
|
||||||
|
fontName = fmt::format("{}:{}", fontRecord.filename_, imFontSize.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create an ImGui font
|
||||||
|
std::shared_ptr<types::ImGuiFont> imguiFont =
|
||||||
|
std::make_shared<types::ImGuiFont>(fontName, rawFontData, imFontSize);
|
||||||
|
|
||||||
|
// Store the ImGui font
|
||||||
|
p->imguiFonts_.insert_or_assign(imguiFontKey, imguiFont);
|
||||||
|
|
||||||
|
// Increment ImGui font build count
|
||||||
|
++p->imguiFontsBuildCount_;
|
||||||
|
|
||||||
|
// Return the ImGui font
|
||||||
|
return imguiFont;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<char>&
|
||||||
|
FontManager::Impl::GetRawFontData(const std::string& filename)
|
||||||
|
{
|
||||||
|
std::unique_lock rawFontDataLock {rawFontDataMutex_};
|
||||||
|
|
||||||
|
auto it = rawFontData_.find(filename);
|
||||||
|
if (it != rawFontData_.end())
|
||||||
|
{
|
||||||
|
// Raw font data has already been loaded
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Raw font data needs to be loaded
|
||||||
|
std::basic_ifstream<char> ifs {filename, std::ios::binary};
|
||||||
|
ifs.seekg(0, std::ios_base::end);
|
||||||
|
std::size_t dataSize = ifs.tellg();
|
||||||
|
ifs.seekg(0, std::ios_base::beg);
|
||||||
|
|
||||||
|
// Store the font data in a buffer
|
||||||
|
std::vector<char> buffer {};
|
||||||
|
buffer.reserve(dataSize);
|
||||||
|
std::copy(std::istreambuf_iterator<char>(ifs),
|
||||||
|
std::istreambuf_iterator<char>(),
|
||||||
|
std::back_inserter(buffer));
|
||||||
|
|
||||||
|
// Place the buffer in the cache
|
||||||
|
auto result = rawFontData_.emplace(filename, std::move(buffer));
|
||||||
|
|
||||||
|
// Return the cached buffer
|
||||||
|
return result.first->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FontManager::LoadApplicationFont(types::Font font,
|
||||||
|
const std::string& filename)
|
||||||
|
{
|
||||||
|
// If the font cache failed to create, don't attempt to cache any fonts
|
||||||
|
if (p->fontCachePath_.empty())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make a copy of the font in the cache (if it doesn't exist)
|
||||||
|
QFile fontFile(QString::fromStdString(filename));
|
||||||
|
QFileInfo fontFileInfo(fontFile);
|
||||||
|
|
||||||
|
QFile cacheFile(QString::fromStdString(p->fontCachePath_) +
|
||||||
|
fontFileInfo.fileName());
|
||||||
|
QFileInfo cacheFileInfo(cacheFile);
|
||||||
|
std::string cacheFilename = cacheFile.fileName().toStdString();
|
||||||
|
|
||||||
|
if (fontFile.exists())
|
||||||
|
{
|
||||||
|
// If the file has not been cached, or the font file size has changed
|
||||||
|
if (!cacheFile.exists() || fontFileInfo.size() != cacheFileInfo.size())
|
||||||
|
{
|
||||||
|
logger_->info("Caching font: {}", filename);
|
||||||
|
if (!fontFile.copy(cacheFile.fileName()))
|
||||||
|
{
|
||||||
|
logger_->error("Could not cache font: {}", filename);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger_->error("Font does not exist: {}", filename);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load the file into the Qt Font Database
|
||||||
|
int fontId =
|
||||||
|
QFontDatabase::addApplicationFont(QString::fromStdString(cacheFilename));
|
||||||
|
p->fontIds_.emplace(font, fontId);
|
||||||
|
|
||||||
|
// Load the file into fontconfig
|
||||||
|
FcBool result = FcConfigAppFontAddFile(
|
||||||
|
nullptr, reinterpret_cast<const FcChar8*>(cacheFilename.c_str()));
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
logger_->error("Could not load font into fontconfig database", filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FontManager::Impl::InitializeFontCache()
|
||||||
|
{
|
||||||
|
std::string cachePath {
|
||||||
|
QStandardPaths::writableLocation(QStandardPaths::CacheLocation)
|
||||||
|
.toStdString() +
|
||||||
|
"/fonts"};
|
||||||
|
|
||||||
|
fontCachePath_ = cachePath + "/";
|
||||||
|
|
||||||
|
if (!std::filesystem::exists(cachePath))
|
||||||
|
{
|
||||||
|
std::error_code error;
|
||||||
|
if (!std::filesystem::create_directories(cachePath, error))
|
||||||
|
{
|
||||||
|
logger_->error("Unable to create font cache directory: \"{}\" ({})",
|
||||||
|
cachePath,
|
||||||
|
error.message());
|
||||||
|
fontCachePath_.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FontManager::Impl::InitializeFontconfig()
|
||||||
|
{
|
||||||
|
FcConfig* fcConfig = FcInitLoadConfigAndFonts();
|
||||||
|
FcConfigSetCurrent(fcConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FontManager::Impl::FinalizeFontconfig()
|
||||||
|
{
|
||||||
|
FcFini();
|
||||||
|
}
|
||||||
|
|
||||||
|
FontRecord
|
||||||
|
FontManager::Impl::MatchFontFile(const std::string& family,
|
||||||
|
const std::vector<std::string>& styles)
|
||||||
|
{
|
||||||
|
const std::string styleString = fmt::format("{}", fmt::join(styles, " "));
|
||||||
|
const std::string fontString = fmt::format("{}:{}", family, styleString);
|
||||||
|
|
||||||
|
// Build fontconfig pattern
|
||||||
|
FcPattern* pattern = FcPatternCreate();
|
||||||
|
|
||||||
|
FcPatternAddString(
|
||||||
|
pattern, FC_FAMILY, reinterpret_cast<const FcChar8*>(family.c_str()));
|
||||||
|
FcPatternAddString(pattern,
|
||||||
|
FC_FONTFORMAT,
|
||||||
|
reinterpret_cast<const FcChar8*>(kFcTrueType_.c_str()));
|
||||||
|
|
||||||
|
if (!styles.empty())
|
||||||
|
{
|
||||||
|
FcPatternAddString(pattern,
|
||||||
|
FC_STYLE,
|
||||||
|
reinterpret_cast<const FcChar8*>(styleString.c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform font pattern match substitution
|
||||||
|
FcConfigSubstitute(nullptr, pattern, FcMatchPattern);
|
||||||
|
FcDefaultSubstitute(pattern);
|
||||||
|
|
||||||
|
// Find matching font
|
||||||
|
FcResult result;
|
||||||
|
FcPattern* match = FcFontMatch(nullptr, pattern, &result);
|
||||||
|
FontRecord record {};
|
||||||
|
|
||||||
|
if (match != nullptr)
|
||||||
|
{
|
||||||
|
FcChar8* fcFamily;
|
||||||
|
FcChar8* fcStyle;
|
||||||
|
FcChar8* fcFile;
|
||||||
|
|
||||||
|
// Match was found, get properties
|
||||||
|
if (FcPatternGetString(match, FC_FAMILY, 0, &fcFamily) == FcResultMatch &&
|
||||||
|
FcPatternGetString(match, FC_STYLE, 0, &fcStyle) == FcResultMatch &&
|
||||||
|
FcPatternGetString(match, FC_FILE, 0, &fcFile) == FcResultMatch)
|
||||||
|
{
|
||||||
|
record.family_ = reinterpret_cast<char*>(fcFamily);
|
||||||
|
record.style_ = reinterpret_cast<char*>(fcStyle);
|
||||||
|
record.filename_ = reinterpret_cast<char*>(fcFile);
|
||||||
|
|
||||||
|
logger_->debug("Found matching font: {}:{} ({})",
|
||||||
|
record.family_,
|
||||||
|
record.style_,
|
||||||
|
record.filename_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (record.filename_.empty())
|
||||||
|
{
|
||||||
|
logger_->warn("Could not find matching font: {}", fontString);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
FcPatternDestroy(match);
|
||||||
|
FcPatternDestroy(pattern);
|
||||||
|
|
||||||
|
return record;
|
||||||
|
}
|
||||||
|
|
||||||
|
FontManager& FontManager::Instance()
|
||||||
|
{
|
||||||
|
static FontManager instance_ {};
|
||||||
|
return instance_;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t FontRecordHash<FontRecordPair>::operator()(const FontRecordPair& x) const
|
||||||
|
{
|
||||||
|
size_t seed = 0;
|
||||||
|
boost::hash_combine(seed, x.first.family_);
|
||||||
|
boost::hash_combine(seed, x.first.style_);
|
||||||
|
boost::hash_combine(seed, x.first.filename_);
|
||||||
|
boost::hash_combine(seed, x.second.value());
|
||||||
|
return seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const FontRecord& lhs, const FontRecord& rhs)
|
||||||
|
{
|
||||||
|
return lhs.family_ == rhs.family_ && //
|
||||||
|
lhs.style_ == rhs.style_ && //
|
||||||
|
lhs.filename_ == rhs.filename_;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace manager
|
||||||
|
} // namespace qt
|
||||||
|
} // namespace scwx
|
||||||
54
scwx-qt/source/scwx/qt/manager/font_manager.hpp
Normal file
54
scwx-qt/source/scwx/qt/manager/font_manager.hpp
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <scwx/qt/types/imgui_font.hpp>
|
||||||
|
#include <scwx/qt/types/font_types.hpp>
|
||||||
|
#include <scwx/qt/types/text_types.hpp>
|
||||||
|
|
||||||
|
#include <shared_mutex>
|
||||||
|
|
||||||
|
#include <QFont>
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
namespace scwx
|
||||||
|
{
|
||||||
|
namespace qt
|
||||||
|
{
|
||||||
|
namespace manager
|
||||||
|
{
|
||||||
|
|
||||||
|
class FontManager : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_DISABLE_COPY_MOVE(FontManager)
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit FontManager();
|
||||||
|
~FontManager();
|
||||||
|
|
||||||
|
std::shared_mutex& imgui_font_atlas_mutex();
|
||||||
|
std::uint64_t imgui_fonts_build_count() const;
|
||||||
|
|
||||||
|
int GetFontId(types::Font font) const;
|
||||||
|
std::shared_ptr<types::ImGuiFont>
|
||||||
|
GetImGuiFont(types::FontCategory fontCategory);
|
||||||
|
std::shared_ptr<types::ImGuiFont>
|
||||||
|
LoadImGuiFont(const std::string& family,
|
||||||
|
const std::vector<std::string>& styles,
|
||||||
|
units::font_size::points<double> size,
|
||||||
|
bool loadIfNotFound = true);
|
||||||
|
|
||||||
|
void LoadApplicationFont(types::Font font, const std::string& filename);
|
||||||
|
void InitializeFonts();
|
||||||
|
|
||||||
|
static QFont GetQFont(types::FontCategory fontCategory);
|
||||||
|
|
||||||
|
static FontManager& Instance();
|
||||||
|
|
||||||
|
private:
|
||||||
|
class Impl;
|
||||||
|
std::unique_ptr<Impl> p;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace manager
|
||||||
|
} // namespace qt
|
||||||
|
} // namespace scwx
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
#include <scwx/qt/manager/placefile_manager.hpp>
|
#include <scwx/qt/manager/placefile_manager.hpp>
|
||||||
|
#include <scwx/qt/manager/font_manager.hpp>
|
||||||
#include <scwx/qt/manager/resource_manager.hpp>
|
#include <scwx/qt/manager/resource_manager.hpp>
|
||||||
#include <scwx/qt/main/application.hpp>
|
#include <scwx/qt/main/application.hpp>
|
||||||
#include <scwx/qt/util/json.hpp>
|
#include <scwx/qt/util/json.hpp>
|
||||||
|
|
@ -51,8 +52,11 @@ public:
|
||||||
void ReadPlacefileSettings();
|
void ReadPlacefileSettings();
|
||||||
void WritePlacefileSettings();
|
void WritePlacefileSettings();
|
||||||
|
|
||||||
|
static boost::unordered_flat_map<std::size_t,
|
||||||
|
std::shared_ptr<types::ImGuiFont>>
|
||||||
|
LoadFontResources(const std::shared_ptr<gr::Placefile>& placefile);
|
||||||
static std::vector<std::shared_ptr<boost::gil::rgba8_image_t>>
|
static std::vector<std::shared_ptr<boost::gil::rgba8_image_t>>
|
||||||
LoadResources(const std::shared_ptr<gr::Placefile>& placefile);
|
LoadImageResources(const std::shared_ptr<gr::Placefile>& placefile);
|
||||||
|
|
||||||
boost::asio::thread_pool threadPool_ {1u};
|
boost::asio::thread_pool threadPool_ {1u};
|
||||||
|
|
||||||
|
|
@ -63,7 +67,7 @@ public:
|
||||||
std::shared_ptr<config::RadarSite> radarSite_ {};
|
std::shared_ptr<config::RadarSite> radarSite_ {};
|
||||||
|
|
||||||
std::vector<std::shared_ptr<PlacefileRecord>> placefileRecords_ {};
|
std::vector<std::shared_ptr<PlacefileRecord>> placefileRecords_ {};
|
||||||
std::unordered_map<std::string, std::shared_ptr<PlacefileRecord>>
|
boost::unordered_flat_map<std::string, std::shared_ptr<PlacefileRecord>>
|
||||||
placefileRecordMap_ {};
|
placefileRecordMap_ {};
|
||||||
std::shared_mutex placefileRecordLock_ {};
|
std::shared_mutex placefileRecordLock_ {};
|
||||||
};
|
};
|
||||||
|
|
@ -134,6 +138,10 @@ public:
|
||||||
std::mutex refreshMutex_ {};
|
std::mutex refreshMutex_ {};
|
||||||
std::mutex timerMutex_ {};
|
std::mutex timerMutex_ {};
|
||||||
|
|
||||||
|
boost::unordered_flat_map<std::size_t, std::shared_ptr<types::ImGuiFont>>
|
||||||
|
fonts_ {};
|
||||||
|
std::mutex fontsMutex_ {};
|
||||||
|
|
||||||
std::vector<std::shared_ptr<boost::gil::rgba8_image_t>> images_ {};
|
std::vector<std::shared_ptr<boost::gil::rgba8_image_t>> images_ {};
|
||||||
|
|
||||||
std::string lastRadarSite_ {};
|
std::string lastRadarSite_ {};
|
||||||
|
|
@ -208,6 +216,20 @@ PlacefileManager::placefile(const std::string& name)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boost::unordered_flat_map<std::size_t, std::shared_ptr<types::ImGuiFont>>
|
||||||
|
PlacefileManager::placefile_fonts(const std::string& name)
|
||||||
|
{
|
||||||
|
std::shared_lock lock(p->placefileRecordLock_);
|
||||||
|
|
||||||
|
auto it = p->placefileRecordMap_.find(name);
|
||||||
|
if (it != p->placefileRecordMap_.cend())
|
||||||
|
{
|
||||||
|
std::unique_lock fontsLock {it->second->fontsMutex_};
|
||||||
|
return it->second->fonts_;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
void PlacefileManager::set_placefile_enabled(const std::string& name,
|
void PlacefileManager::set_placefile_enabled(const std::string& name,
|
||||||
bool enabled)
|
bool enabled)
|
||||||
{
|
{
|
||||||
|
|
@ -278,6 +300,7 @@ void PlacefileManager::set_placefile_url(const std::string& name,
|
||||||
auto placefileRecord = it->second;
|
auto placefileRecord = it->second;
|
||||||
placefileRecord->name_ = normalizedUrl;
|
placefileRecord->name_ = normalizedUrl;
|
||||||
placefileRecord->placefile_ = nullptr;
|
placefileRecord->placefile_ = nullptr;
|
||||||
|
placefileRecord->fonts_.clear();
|
||||||
placefileRecord->images_.clear();
|
placefileRecord->images_.clear();
|
||||||
p->placefileRecordMap_.erase(it);
|
p->placefileRecordMap_.erase(it);
|
||||||
p->placefileRecordMap_.insert_or_assign(normalizedUrl, placefileRecord);
|
p->placefileRecordMap_.insert_or_assign(normalizedUrl, placefileRecord);
|
||||||
|
|
@ -587,7 +610,8 @@ void PlacefileManager::Impl::PlacefileRecord::Update()
|
||||||
if (updatedPlacefile != nullptr)
|
if (updatedPlacefile != nullptr)
|
||||||
{
|
{
|
||||||
// Load placefile resources
|
// Load placefile resources
|
||||||
auto newImages = Impl::LoadResources(updatedPlacefile);
|
auto newFonts = Impl::LoadFontResources(updatedPlacefile);
|
||||||
|
auto newImages = Impl::LoadImageResources(updatedPlacefile);
|
||||||
|
|
||||||
// Check the name matches, in case the name updated
|
// Check the name matches, in case the name updated
|
||||||
if (name_ == name)
|
if (name_ == name)
|
||||||
|
|
@ -597,6 +621,13 @@ void PlacefileManager::Impl::PlacefileRecord::Update()
|
||||||
title_ = placefile_->title();
|
title_ = placefile_->title();
|
||||||
lastUpdateTime_ = std::chrono::system_clock::now();
|
lastUpdateTime_ = std::chrono::system_clock::now();
|
||||||
|
|
||||||
|
// Update font resources
|
||||||
|
{
|
||||||
|
std::unique_lock fontsLock {fontsMutex_};
|
||||||
|
fonts_.swap(newFonts);
|
||||||
|
newFonts.clear();
|
||||||
|
}
|
||||||
|
|
||||||
// Update image resources
|
// Update image resources
|
||||||
images_.swap(newImages);
|
images_.swap(newImages);
|
||||||
newImages.clear();
|
newImages.clear();
|
||||||
|
|
@ -684,8 +715,38 @@ std::shared_ptr<PlacefileManager> PlacefileManager::Instance()
|
||||||
return placefileManager;
|
return placefileManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boost::unordered_flat_map<std::size_t, std::shared_ptr<types::ImGuiFont>>
|
||||||
|
PlacefileManager::Impl::LoadFontResources(
|
||||||
|
const std::shared_ptr<gr::Placefile>& placefile)
|
||||||
|
{
|
||||||
|
boost::unordered_flat_map<std::size_t, std::shared_ptr<types::ImGuiFont>>
|
||||||
|
imGuiFonts {};
|
||||||
|
auto fonts = placefile->fonts();
|
||||||
|
|
||||||
|
for (auto& font : fonts)
|
||||||
|
{
|
||||||
|
units::font_size::pixels<double> size {font.second->pixels_};
|
||||||
|
std::vector<std::string> styles {};
|
||||||
|
|
||||||
|
if (font.second->IsBold())
|
||||||
|
{
|
||||||
|
styles.push_back("bold");
|
||||||
|
}
|
||||||
|
if (font.second->IsItalic())
|
||||||
|
{
|
||||||
|
styles.push_back("italic");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto imGuiFont = FontManager::Instance().LoadImGuiFont(
|
||||||
|
font.second->face_, styles, size);
|
||||||
|
imGuiFonts.emplace(font.first, std::move(imGuiFont));
|
||||||
|
}
|
||||||
|
|
||||||
|
return imGuiFonts;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<std::shared_ptr<boost::gil::rgba8_image_t>>
|
std::vector<std::shared_ptr<boost::gil::rgba8_image_t>>
|
||||||
PlacefileManager::Impl::LoadResources(
|
PlacefileManager::Impl::LoadImageResources(
|
||||||
const std::shared_ptr<gr::Placefile>& placefile)
|
const std::shared_ptr<gr::Placefile>& placefile)
|
||||||
{
|
{
|
||||||
const auto iconFiles = placefile->icon_files();
|
const auto iconFiles = placefile->icon_files();
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,10 @@
|
||||||
|
|
||||||
#include <scwx/gr/placefile.hpp>
|
#include <scwx/gr/placefile.hpp>
|
||||||
#include <scwx/qt/config/radar_site.hpp>
|
#include <scwx/qt/config/radar_site.hpp>
|
||||||
|
#include <scwx/qt/types/imgui_font.hpp>
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <boost/unordered/unordered_flat_map.hpp>
|
||||||
|
|
||||||
namespace scwx
|
namespace scwx
|
||||||
{
|
{
|
||||||
|
|
@ -24,6 +26,8 @@ public:
|
||||||
bool placefile_thresholded(const std::string& name);
|
bool placefile_thresholded(const std::string& name);
|
||||||
std::string placefile_title(const std::string& name);
|
std::string placefile_title(const std::string& name);
|
||||||
std::shared_ptr<gr::Placefile> placefile(const std::string& name);
|
std::shared_ptr<gr::Placefile> placefile(const std::string& name);
|
||||||
|
boost::unordered_flat_map<std::size_t, std::shared_ptr<types::ImGuiFont>>
|
||||||
|
placefile_fonts(const std::string& name);
|
||||||
|
|
||||||
void set_placefile_enabled(const std::string& name, bool enabled);
|
void set_placefile_enabled(const std::string& name, bool enabled);
|
||||||
void set_placefile_thresholded(const std::string& name, bool thresholded);
|
void set_placefile_thresholded(const std::string& name, bool thresholded);
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,13 @@
|
||||||
#include <scwx/qt/manager/resource_manager.hpp>
|
#include <scwx/qt/manager/resource_manager.hpp>
|
||||||
|
#include <scwx/qt/manager/font_manager.hpp>
|
||||||
#include <scwx/qt/config/county_database.hpp>
|
#include <scwx/qt/config/county_database.hpp>
|
||||||
#include <scwx/qt/model/imgui_context_model.hpp>
|
#include <scwx/qt/model/imgui_context_model.hpp>
|
||||||
#include <scwx/qt/util/font.hpp>
|
|
||||||
#include <scwx/qt/util/texture_atlas.hpp>
|
#include <scwx/qt/util/texture_atlas.hpp>
|
||||||
#include <scwx/util/logger.hpp>
|
#include <scwx/util/logger.hpp>
|
||||||
|
|
||||||
#include <execution>
|
#include <execution>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
#include <QFontDatabase>
|
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
|
|
||||||
namespace scwx
|
namespace scwx
|
||||||
|
|
@ -26,14 +25,11 @@ static const auto logger_ = scwx::util::Logger::Create(logPrefix_);
|
||||||
static void LoadFonts();
|
static void LoadFonts();
|
||||||
static void LoadTextures();
|
static void LoadTextures();
|
||||||
|
|
||||||
static const std::unordered_map<types::Font, std::string> fontNames_ {
|
static const std::vector<std::pair<types::Font, std::string>> fontNames_ {
|
||||||
{types::Font::din1451alt, ":/res/fonts/din1451alt.ttf"},
|
{types::Font::din1451alt, ":/res/fonts/din1451alt.ttf"},
|
||||||
{types::Font::din1451alt_g, ":/res/fonts/din1451alt_g.ttf"},
|
{types::Font::din1451alt_g, ":/res/fonts/din1451alt_g.ttf"},
|
||||||
{types::Font::Inconsolata_Regular, ":/res/fonts/Inconsolata-Regular.ttf"}};
|
{types::Font::Inconsolata_Regular, ":/res/fonts/Inconsolata-Regular.ttf"}};
|
||||||
|
|
||||||
static std::unordered_map<types::Font, int> fontIds_ {};
|
|
||||||
static std::unordered_map<types::Font, std::shared_ptr<util::Font>> fonts_ {};
|
|
||||||
|
|
||||||
void Initialize()
|
void Initialize()
|
||||||
{
|
{
|
||||||
config::CountyDatabase::Initialize();
|
config::CountyDatabase::Initialize();
|
||||||
|
|
@ -44,26 +40,6 @@ void Initialize()
|
||||||
|
|
||||||
void Shutdown() {}
|
void Shutdown() {}
|
||||||
|
|
||||||
int FontId(types::Font font)
|
|
||||||
{
|
|
||||||
auto it = fontIds_.find(font);
|
|
||||||
if (it != fontIds_.cend())
|
|
||||||
{
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<util::Font> Font(types::Font font)
|
|
||||||
{
|
|
||||||
auto it = fonts_.find(font);
|
|
||||||
if (it != fonts_.cend())
|
|
||||||
{
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<boost::gil::rgba8_image_t>
|
std::shared_ptr<boost::gil::rgba8_image_t>
|
||||||
LoadImageResource(const std::string& urlString)
|
LoadImageResource(const std::string& urlString)
|
||||||
{
|
{
|
||||||
|
|
@ -102,18 +78,14 @@ LoadImageResources(const std::vector<std::string>& urlStrings)
|
||||||
|
|
||||||
static void LoadFonts()
|
static void LoadFonts()
|
||||||
{
|
{
|
||||||
|
auto& fontManager = FontManager::Instance();
|
||||||
|
|
||||||
for (auto& fontName : fontNames_)
|
for (auto& fontName : fontNames_)
|
||||||
{
|
{
|
||||||
int fontId = QFontDatabase::addApplicationFont(
|
fontManager.LoadApplicationFont(fontName.first, fontName.second);
|
||||||
QString::fromStdString(fontName.second));
|
|
||||||
fontIds_.emplace(fontName.first, fontId);
|
|
||||||
|
|
||||||
auto font = util::Font::Create(fontName.second);
|
|
||||||
fonts_.emplace(fontName.first, font);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImFontAtlas* fontAtlas = model::ImGuiContextModel::Instance().font_atlas();
|
fontManager.InitializeFonts();
|
||||||
fontAtlas->AddFontDefault();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void LoadTextures()
|
static void LoadTextures()
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <scwx/qt/types/font_types.hpp>
|
#include <scwx/qt/types/font_types.hpp>
|
||||||
#include <scwx/qt/util/font.hpp>
|
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
@ -19,9 +18,6 @@ namespace ResourceManager
|
||||||
void Initialize();
|
void Initialize();
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
int FontId(types::Font font);
|
|
||||||
std::shared_ptr<util::Font> Font(types::Font font);
|
|
||||||
|
|
||||||
std::shared_ptr<boost::gil::rgba8_image_t>
|
std::shared_ptr<boost::gil::rgba8_image_t>
|
||||||
LoadImageResource(const std::string& urlString);
|
LoadImageResource(const std::string& urlString);
|
||||||
std::vector<std::shared_ptr<boost::gil::rgba8_image_t>>
|
std::vector<std::shared_ptr<boost::gil::rgba8_image_t>>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
#include <scwx/qt/manager/settings_manager.hpp>
|
#include <scwx/qt/manager/settings_manager.hpp>
|
||||||
#include <scwx/qt/map/map_provider.hpp>
|
#include <scwx/qt/map/map_provider.hpp>
|
||||||
|
#include <scwx/qt/settings/general_settings.hpp>
|
||||||
|
#include <scwx/qt/settings/map_settings.hpp>
|
||||||
|
#include <scwx/qt/settings/palette_settings.hpp>
|
||||||
#include <scwx/qt/settings/text_settings.hpp>
|
#include <scwx/qt/settings/text_settings.hpp>
|
||||||
#include <scwx/qt/settings/ui_settings.hpp>
|
#include <scwx/qt/settings/ui_settings.hpp>
|
||||||
#include <scwx/qt/util/json.hpp>
|
#include <scwx/qt/util/json.hpp>
|
||||||
|
|
@ -18,21 +21,33 @@ namespace qt
|
||||||
{
|
{
|
||||||
namespace manager
|
namespace manager
|
||||||
{
|
{
|
||||||
namespace SettingsManager
|
|
||||||
{
|
|
||||||
|
|
||||||
static const std::string logPrefix_ = "scwx::qt::manager::settings_manager";
|
static const std::string logPrefix_ = "scwx::qt::manager::settings_manager";
|
||||||
static const auto logger_ = scwx::util::Logger::Create(logPrefix_);
|
static const auto logger_ = scwx::util::Logger::Create(logPrefix_);
|
||||||
|
|
||||||
static boost::json::value ConvertSettingsToJson();
|
class SettingsManager::Impl
|
||||||
static void GenerateDefaultSettings();
|
{
|
||||||
static bool LoadSettings(const boost::json::object& settingsJson);
|
public:
|
||||||
static void ValidateSettings();
|
explicit Impl(SettingsManager* self) : self_ {self} {}
|
||||||
|
~Impl() = default;
|
||||||
|
|
||||||
static bool initialized_ {false};
|
void ValidateSettings();
|
||||||
static std::string settingsPath_ {};
|
|
||||||
|
|
||||||
void Initialize()
|
static boost::json::value ConvertSettingsToJson();
|
||||||
|
static void GenerateDefaultSettings();
|
||||||
|
static bool LoadSettings(const boost::json::object& settingsJson);
|
||||||
|
|
||||||
|
SettingsManager* self_;
|
||||||
|
|
||||||
|
bool initialized_ {false};
|
||||||
|
std::string settingsPath_ {};
|
||||||
|
};
|
||||||
|
|
||||||
|
SettingsManager::SettingsManager() : p(std::make_unique<Impl>(this)) {}
|
||||||
|
|
||||||
|
SettingsManager::~SettingsManager() {};
|
||||||
|
|
||||||
|
void SettingsManager::Initialize()
|
||||||
{
|
{
|
||||||
std::string appDataPath {
|
std::string appDataPath {
|
||||||
QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)
|
QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)
|
||||||
|
|
@ -47,14 +62,14 @@ void Initialize()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
settingsPath_ = appDataPath + "/settings.json";
|
p->settingsPath_ = appDataPath + "/settings.json";
|
||||||
initialized_ = true;
|
p->initialized_ = true;
|
||||||
|
|
||||||
ReadSettings(settingsPath_);
|
ReadSettings(p->settingsPath_);
|
||||||
ValidateSettings();
|
p->ValidateSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReadSettings(const std::string& settingsPath)
|
void SettingsManager::ReadSettings(const std::string& settingsPath)
|
||||||
{
|
{
|
||||||
boost::json::value settingsJson = nullptr;
|
boost::json::value settingsJson = nullptr;
|
||||||
|
|
||||||
|
|
@ -65,39 +80,41 @@ void ReadSettings(const std::string& settingsPath)
|
||||||
|
|
||||||
if (settingsJson == nullptr || !settingsJson.is_object())
|
if (settingsJson == nullptr || !settingsJson.is_object())
|
||||||
{
|
{
|
||||||
GenerateDefaultSettings();
|
Impl::GenerateDefaultSettings();
|
||||||
settingsJson = ConvertSettingsToJson();
|
settingsJson = Impl::ConvertSettingsToJson();
|
||||||
util::json::WriteJsonFile(settingsPath, settingsJson);
|
util::json::WriteJsonFile(settingsPath, settingsJson);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bool jsonDirty = LoadSettings(settingsJson.as_object());
|
bool jsonDirty = Impl::LoadSettings(settingsJson.as_object());
|
||||||
|
|
||||||
if (jsonDirty)
|
if (jsonDirty)
|
||||||
{
|
{
|
||||||
settingsJson = ConvertSettingsToJson();
|
settingsJson = Impl::ConvertSettingsToJson();
|
||||||
util::json::WriteJsonFile(settingsPath, settingsJson);
|
util::json::WriteJsonFile(settingsPath, settingsJson);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void SaveSettings()
|
void SettingsManager::SaveSettings()
|
||||||
{
|
{
|
||||||
if (initialized_)
|
if (p->initialized_)
|
||||||
{
|
{
|
||||||
logger_->info("Saving settings");
|
logger_->info("Saving settings");
|
||||||
|
|
||||||
boost::json::value settingsJson = ConvertSettingsToJson();
|
boost::json::value settingsJson = Impl::ConvertSettingsToJson();
|
||||||
util::json::WriteJsonFile(settingsPath_, settingsJson);
|
util::json::WriteJsonFile(p->settingsPath_, settingsJson);
|
||||||
|
|
||||||
|
Q_EMIT SettingsSaved();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shutdown()
|
void SettingsManager::Shutdown()
|
||||||
{
|
{
|
||||||
bool dataChanged = false;
|
bool dataChanged = false;
|
||||||
|
|
||||||
dataChanged |= general_settings().Shutdown();
|
dataChanged |= settings::GeneralSettings::Instance().Shutdown();
|
||||||
dataChanged |= map_settings().Shutdown();
|
dataChanged |= settings::MapSettings::Instance().Shutdown();
|
||||||
dataChanged |= settings::UiSettings::Instance().Shutdown();
|
dataChanged |= settings::UiSettings::Instance().Shutdown();
|
||||||
|
|
||||||
if (dataChanged)
|
if (dataChanged)
|
||||||
|
|
@ -106,70 +123,53 @@ void Shutdown()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
settings::GeneralSettings& general_settings()
|
boost::json::value SettingsManager::Impl::ConvertSettingsToJson()
|
||||||
{
|
|
||||||
static settings::GeneralSettings generalSettings_;
|
|
||||||
return generalSettings_;
|
|
||||||
}
|
|
||||||
|
|
||||||
settings::MapSettings& map_settings()
|
|
||||||
{
|
|
||||||
static settings::MapSettings mapSettings_;
|
|
||||||
return mapSettings_;
|
|
||||||
}
|
|
||||||
|
|
||||||
settings::PaletteSettings& palette_settings()
|
|
||||||
{
|
|
||||||
static settings::PaletteSettings paletteSettings_;
|
|
||||||
return paletteSettings_;
|
|
||||||
}
|
|
||||||
|
|
||||||
static boost::json::value ConvertSettingsToJson()
|
|
||||||
{
|
{
|
||||||
boost::json::object settingsJson;
|
boost::json::object settingsJson;
|
||||||
|
|
||||||
general_settings().WriteJson(settingsJson);
|
settings::GeneralSettings::Instance().WriteJson(settingsJson);
|
||||||
map_settings().WriteJson(settingsJson);
|
settings::MapSettings::Instance().WriteJson(settingsJson);
|
||||||
palette_settings().WriteJson(settingsJson);
|
settings::PaletteSettings::Instance().WriteJson(settingsJson);
|
||||||
settings::TextSettings::Instance().WriteJson(settingsJson);
|
settings::TextSettings::Instance().WriteJson(settingsJson);
|
||||||
settings::UiSettings::Instance().WriteJson(settingsJson);
|
settings::UiSettings::Instance().WriteJson(settingsJson);
|
||||||
|
|
||||||
return settingsJson;
|
return settingsJson;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GenerateDefaultSettings()
|
void SettingsManager::Impl::GenerateDefaultSettings()
|
||||||
{
|
{
|
||||||
logger_->info("Generating default settings");
|
logger_->info("Generating default settings");
|
||||||
|
|
||||||
general_settings().SetDefaults();
|
settings::GeneralSettings::Instance().SetDefaults();
|
||||||
map_settings().SetDefaults();
|
settings::MapSettings::Instance().SetDefaults();
|
||||||
palette_settings().SetDefaults();
|
settings::PaletteSettings::Instance().SetDefaults();
|
||||||
settings::TextSettings::Instance().SetDefaults();
|
settings::TextSettings::Instance().SetDefaults();
|
||||||
settings::UiSettings::Instance().SetDefaults();
|
settings::UiSettings::Instance().SetDefaults();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool LoadSettings(const boost::json::object& settingsJson)
|
bool SettingsManager::Impl::LoadSettings(
|
||||||
|
const boost::json::object& settingsJson)
|
||||||
{
|
{
|
||||||
logger_->info("Loading settings");
|
logger_->info("Loading settings");
|
||||||
|
|
||||||
bool jsonDirty = false;
|
bool jsonDirty = false;
|
||||||
|
|
||||||
jsonDirty |= !general_settings().ReadJson(settingsJson);
|
jsonDirty |= !settings::GeneralSettings::Instance().ReadJson(settingsJson);
|
||||||
jsonDirty |= !map_settings().ReadJson(settingsJson);
|
jsonDirty |= !settings::MapSettings::Instance().ReadJson(settingsJson);
|
||||||
jsonDirty |= !palette_settings().ReadJson(settingsJson);
|
jsonDirty |= !settings::PaletteSettings::Instance().ReadJson(settingsJson);
|
||||||
jsonDirty |= !settings::TextSettings::Instance().ReadJson(settingsJson);
|
jsonDirty |= !settings::TextSettings::Instance().ReadJson(settingsJson);
|
||||||
jsonDirty |= !settings::UiSettings::Instance().ReadJson(settingsJson);
|
jsonDirty |= !settings::UiSettings::Instance().ReadJson(settingsJson);
|
||||||
|
|
||||||
return jsonDirty;
|
return jsonDirty;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ValidateSettings()
|
void SettingsManager::Impl::ValidateSettings()
|
||||||
{
|
{
|
||||||
logger_->debug("Validating settings");
|
logger_->debug("Validating settings");
|
||||||
|
|
||||||
bool settingsChanged = false;
|
bool settingsChanged = false;
|
||||||
|
|
||||||
auto& generalSettings = general_settings();
|
auto& generalSettings = settings::GeneralSettings::Instance();
|
||||||
|
|
||||||
// Validate map provider
|
// Validate map provider
|
||||||
std::string mapProviderName = generalSettings.map_provider().GetValue();
|
std::string mapProviderName = generalSettings.map_provider().GetValue();
|
||||||
|
|
@ -200,11 +200,16 @@ static void ValidateSettings()
|
||||||
|
|
||||||
if (settingsChanged)
|
if (settingsChanged)
|
||||||
{
|
{
|
||||||
SaveSettings();
|
self_->SaveSettings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace SettingsManager
|
SettingsManager& SettingsManager::Instance()
|
||||||
|
{
|
||||||
|
static SettingsManager instance_ {};
|
||||||
|
return instance_;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace manager
|
} // namespace manager
|
||||||
} // namespace qt
|
} // namespace qt
|
||||||
} // namespace scwx
|
} // namespace scwx
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <scwx/qt/settings/general_settings.hpp>
|
#include <string>
|
||||||
#include <scwx/qt/settings/map_settings.hpp>
|
#include <memory>
|
||||||
#include <scwx/qt/settings/palette_settings.hpp>
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
namespace scwx
|
namespace scwx
|
||||||
{
|
{
|
||||||
|
|
@ -10,19 +11,31 @@ namespace qt
|
||||||
{
|
{
|
||||||
namespace manager
|
namespace manager
|
||||||
{
|
{
|
||||||
namespace SettingsManager
|
|
||||||
|
class SettingsManager : public QObject
|
||||||
{
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_DISABLE_COPY_MOVE(SettingsManager)
|
||||||
|
|
||||||
void Initialize();
|
public:
|
||||||
void ReadSettings(const std::string& settingsPath);
|
explicit SettingsManager();
|
||||||
void SaveSettings();
|
~SettingsManager();
|
||||||
void Shutdown();
|
|
||||||
|
|
||||||
settings::GeneralSettings& general_settings();
|
void Initialize();
|
||||||
settings::MapSettings& map_settings();
|
void ReadSettings(const std::string& settingsPath);
|
||||||
settings::PaletteSettings& palette_settings();
|
void SaveSettings();
|
||||||
|
void Shutdown();
|
||||||
|
|
||||||
|
static SettingsManager& Instance();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void SettingsSaved();
|
||||||
|
|
||||||
|
private:
|
||||||
|
class Impl;
|
||||||
|
std::unique_ptr<Impl> p;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace SettingsManager
|
|
||||||
} // namespace manager
|
} // namespace manager
|
||||||
} // namespace qt
|
} // namespace qt
|
||||||
} // namespace scwx
|
} // namespace scwx
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include <scwx/qt/manager/timeline_manager.hpp>
|
#include <scwx/qt/manager/timeline_manager.hpp>
|
||||||
#include <scwx/qt/manager/radar_product_manager.hpp>
|
#include <scwx/qt/manager/radar_product_manager.hpp>
|
||||||
#include <scwx/qt/manager/settings_manager.hpp>
|
#include <scwx/qt/settings/general_settings.hpp>
|
||||||
#include <scwx/util/logger.hpp>
|
#include <scwx/util/logger.hpp>
|
||||||
#include <scwx/util/map.hpp>
|
#include <scwx/util/map.hpp>
|
||||||
#include <scwx/util/time.hpp>
|
#include <scwx/util/time.hpp>
|
||||||
|
|
@ -39,7 +39,7 @@ class TimelineManager::Impl
|
||||||
public:
|
public:
|
||||||
explicit Impl(TimelineManager* self) : self_ {self}
|
explicit Impl(TimelineManager* self) : self_ {self}
|
||||||
{
|
{
|
||||||
auto& generalSettings = SettingsManager::general_settings();
|
auto& generalSettings = settings::GeneralSettings::Instance();
|
||||||
|
|
||||||
loopDelay_ =
|
loopDelay_ =
|
||||||
std::chrono::milliseconds(generalSettings.loop_delay().GetValue());
|
std::chrono::milliseconds(generalSettings.loop_delay().GetValue());
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#include <scwx/qt/map/alert_layer.hpp>
|
#include <scwx/qt/map/alert_layer.hpp>
|
||||||
#include <scwx/qt/manager/settings_manager.hpp>
|
|
||||||
#include <scwx/qt/manager/text_event_manager.hpp>
|
#include <scwx/qt/manager/text_event_manager.hpp>
|
||||||
|
#include <scwx/qt/settings/palette_settings.hpp>
|
||||||
#include <scwx/qt/util/color.hpp>
|
#include <scwx/qt/util/color.hpp>
|
||||||
#include <scwx/util/logger.hpp>
|
#include <scwx/util/logger.hpp>
|
||||||
#include <scwx/util/threads.hpp>
|
#include <scwx/util/threads.hpp>
|
||||||
|
|
@ -394,7 +394,7 @@ static void AddAlertLayer(std::shared_ptr<QMapLibreGL::Map> map,
|
||||||
const QString& beforeLayer)
|
const QString& beforeLayer)
|
||||||
{
|
{
|
||||||
settings::PaletteSettings& paletteSettings =
|
settings::PaletteSettings& paletteSettings =
|
||||||
manager::SettingsManager::palette_settings();
|
settings::PaletteSettings::Instance();
|
||||||
|
|
||||||
QString sourceId = GetSourceId(phenomenon, alertActive);
|
QString sourceId = GetSourceId(phenomenon, alertActive);
|
||||||
QString idSuffix = GetSuffix(phenomenon, alertActive);
|
QString idSuffix = GetSuffix(phenomenon, alertActive);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#include <scwx/qt/map/map_provider.hpp>
|
#include <scwx/qt/map/map_provider.hpp>
|
||||||
#include <scwx/qt/manager/settings_manager.hpp>
|
#include <scwx/qt/settings/general_settings.hpp>
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
|
@ -128,12 +128,10 @@ std::string GetMapProviderApiKey(MapProvider mapProvider)
|
||||||
switch (mapProvider)
|
switch (mapProvider)
|
||||||
{
|
{
|
||||||
case MapProvider::Mapbox:
|
case MapProvider::Mapbox:
|
||||||
return manager::SettingsManager::general_settings()
|
return settings::GeneralSettings::Instance().mapbox_api_key().GetValue();
|
||||||
.mapbox_api_key()
|
|
||||||
.GetValue();
|
|
||||||
|
|
||||||
case MapProvider::MapTiler:
|
case MapProvider::MapTiler:
|
||||||
return manager::SettingsManager::general_settings()
|
return settings::GeneralSettings::Instance()
|
||||||
.maptiler_api_key()
|
.maptiler_api_key()
|
||||||
.GetValue();
|
.GetValue();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
#include <scwx/qt/map/map_widget.hpp>
|
#include <scwx/qt/map/map_widget.hpp>
|
||||||
#include <scwx/qt/gl/gl.hpp>
|
#include <scwx/qt/gl/gl.hpp>
|
||||||
|
#include <scwx/qt/manager/font_manager.hpp>
|
||||||
#include <scwx/qt/manager/placefile_manager.hpp>
|
#include <scwx/qt/manager/placefile_manager.hpp>
|
||||||
#include <scwx/qt/manager/radar_product_manager.hpp>
|
#include <scwx/qt/manager/radar_product_manager.hpp>
|
||||||
#include <scwx/qt/manager/settings_manager.hpp>
|
|
||||||
#include <scwx/qt/map/alert_layer.hpp>
|
#include <scwx/qt/map/alert_layer.hpp>
|
||||||
#include <scwx/qt/map/color_table_layer.hpp>
|
#include <scwx/qt/map/color_table_layer.hpp>
|
||||||
#include <scwx/qt/map/layer_wrapper.hpp>
|
#include <scwx/qt/map/layer_wrapper.hpp>
|
||||||
|
|
@ -12,6 +12,8 @@
|
||||||
#include <scwx/qt/map/radar_product_layer.hpp>
|
#include <scwx/qt/map/radar_product_layer.hpp>
|
||||||
#include <scwx/qt/map/radar_range_layer.hpp>
|
#include <scwx/qt/map/radar_range_layer.hpp>
|
||||||
#include <scwx/qt/model/imgui_context_model.hpp>
|
#include <scwx/qt/model/imgui_context_model.hpp>
|
||||||
|
#include <scwx/qt/settings/general_settings.hpp>
|
||||||
|
#include <scwx/qt/settings/palette_settings.hpp>
|
||||||
#include <scwx/qt/util/file.hpp>
|
#include <scwx/qt/util/file.hpp>
|
||||||
#include <scwx/qt/util/maplibre.hpp>
|
#include <scwx/qt/util/maplibre.hpp>
|
||||||
#include <scwx/qt/util/tooltip.hpp>
|
#include <scwx/qt/util/tooltip.hpp>
|
||||||
|
|
@ -80,8 +82,7 @@ public:
|
||||||
prevBearing_ {0.0},
|
prevBearing_ {0.0},
|
||||||
prevPitch_ {0.0}
|
prevPitch_ {0.0}
|
||||||
{
|
{
|
||||||
auto& generalSettings =
|
auto& generalSettings = settings::GeneralSettings::Instance();
|
||||||
scwx::qt::manager::SettingsManager::general_settings();
|
|
||||||
|
|
||||||
SetRadarSite(generalSettings.default_radar_site().GetValue());
|
SetRadarSite(generalSettings.default_radar_site().GetValue());
|
||||||
|
|
||||||
|
|
@ -123,6 +124,7 @@ public:
|
||||||
std::shared_ptr<GenericLayer> layer,
|
std::shared_ptr<GenericLayer> layer,
|
||||||
const std::string& before = {});
|
const std::string& before = {});
|
||||||
void ConnectSignals();
|
void ConnectSignals();
|
||||||
|
void ImGuiCheckFonts();
|
||||||
void InitializeNewRadarProductView(const std::string& colorPalette);
|
void InitializeNewRadarProductView(const std::string& colorPalette);
|
||||||
void RadarProductManagerConnect();
|
void RadarProductManagerConnect();
|
||||||
void RadarProductManagerDisconnect();
|
void RadarProductManagerDisconnect();
|
||||||
|
|
@ -154,6 +156,7 @@ public:
|
||||||
ImGuiContext* imGuiContext_;
|
ImGuiContext* imGuiContext_;
|
||||||
std::string imGuiContextName_;
|
std::string imGuiContextName_;
|
||||||
bool imGuiRendererInitialized_;
|
bool imGuiRendererInitialized_;
|
||||||
|
std::uint64_t imGuiFontsBuildCount_ {};
|
||||||
|
|
||||||
std::shared_ptr<manager::PlacefileManager> placefileManager_ {
|
std::shared_ptr<manager::PlacefileManager> placefileManager_ {
|
||||||
manager::PlacefileManager::Instance()};
|
manager::PlacefileManager::Instance()};
|
||||||
|
|
@ -980,9 +983,15 @@ void MapWidget::initializeGL()
|
||||||
makeCurrent();
|
makeCurrent();
|
||||||
p->context_->gl().initializeOpenGLFunctions();
|
p->context_->gl().initializeOpenGLFunctions();
|
||||||
|
|
||||||
|
// Lock ImGui font atlas prior to new ImGui frame
|
||||||
|
std::shared_lock imguiFontAtlasLock {
|
||||||
|
manager::FontManager::Instance().imgui_font_atlas_mutex()};
|
||||||
|
|
||||||
// Initialize ImGui OpenGL3 backend
|
// Initialize ImGui OpenGL3 backend
|
||||||
ImGui::SetCurrentContext(p->imGuiContext_);
|
ImGui::SetCurrentContext(p->imGuiContext_);
|
||||||
ImGui_ImplOpenGL3_Init();
|
ImGui_ImplOpenGL3_Init();
|
||||||
|
p->imGuiFontsBuildCount_ =
|
||||||
|
manager::FontManager::Instance().imgui_fonts_build_count();
|
||||||
p->imGuiRendererInitialized_ = true;
|
p->imGuiRendererInitialized_ = true;
|
||||||
|
|
||||||
p->map_.reset(
|
p->map_.reset(
|
||||||
|
|
@ -1023,16 +1032,27 @@ void MapWidget::initializeGL()
|
||||||
|
|
||||||
void MapWidget::paintGL()
|
void MapWidget::paintGL()
|
||||||
{
|
{
|
||||||
|
auto defaultFont = manager::FontManager::Instance().GetImGuiFont(
|
||||||
|
types::FontCategory::Default);
|
||||||
|
|
||||||
p->frameDraws_++;
|
p->frameDraws_++;
|
||||||
|
|
||||||
// Setup ImGui Frame
|
// Setup ImGui Frame
|
||||||
ImGui::SetCurrentContext(p->imGuiContext_);
|
ImGui::SetCurrentContext(p->imGuiContext_);
|
||||||
|
|
||||||
|
// Lock ImGui font atlas prior to new ImGui frame
|
||||||
|
std::shared_lock imguiFontAtlasLock {
|
||||||
|
manager::FontManager::Instance().imgui_font_atlas_mutex()};
|
||||||
|
|
||||||
// Start ImGui Frame
|
// Start ImGui Frame
|
||||||
ImGui_ImplQt_NewFrame(this);
|
ImGui_ImplQt_NewFrame(this);
|
||||||
ImGui_ImplOpenGL3_NewFrame();
|
ImGui_ImplOpenGL3_NewFrame();
|
||||||
|
p->ImGuiCheckFonts();
|
||||||
ImGui::NewFrame();
|
ImGui::NewFrame();
|
||||||
|
|
||||||
|
// Set default font
|
||||||
|
ImGui::PushFont(defaultFont->font());
|
||||||
|
|
||||||
// Update pixel ratio
|
// Update pixel ratio
|
||||||
p->context_->set_pixel_ratio(pixelRatio());
|
p->context_->set_pixel_ratio(pixelRatio());
|
||||||
|
|
||||||
|
|
@ -1055,14 +1075,36 @@ void MapWidget::paintGL()
|
||||||
p->lastItemPicked_ = false;
|
p->lastItemPicked_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pop default font
|
||||||
|
ImGui::PopFont();
|
||||||
|
|
||||||
// Render ImGui Frame
|
// Render ImGui Frame
|
||||||
ImGui::Render();
|
ImGui::Render();
|
||||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||||
|
|
||||||
|
// Unlock ImGui font atlas after rendering
|
||||||
|
imguiFontAtlasLock.unlock();
|
||||||
|
|
||||||
// Paint complete
|
// Paint complete
|
||||||
Q_EMIT WidgetPainted();
|
Q_EMIT WidgetPainted();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MapWidgetImpl::ImGuiCheckFonts()
|
||||||
|
{
|
||||||
|
// Update ImGui Fonts if required
|
||||||
|
std::uint64_t currentImGuiFontsBuildCount =
|
||||||
|
manager::FontManager::Instance().imgui_fonts_build_count();
|
||||||
|
|
||||||
|
if (imGuiFontsBuildCount_ != currentImGuiFontsBuildCount ||
|
||||||
|
!model::ImGuiContextModel::Instance().font_atlas()->IsBuilt())
|
||||||
|
{
|
||||||
|
ImGui_ImplOpenGL3_DestroyFontsTexture();
|
||||||
|
ImGui_ImplOpenGL3_CreateFontsTexture();
|
||||||
|
}
|
||||||
|
|
||||||
|
imGuiFontsBuildCount_ = currentImGuiFontsBuildCount;
|
||||||
|
}
|
||||||
|
|
||||||
void MapWidgetImpl::RunMousePicking()
|
void MapWidgetImpl::RunMousePicking()
|
||||||
{
|
{
|
||||||
const QMapLibreGL::CustomLayerRenderParameters params =
|
const QMapLibreGL::CustomLayerRenderParameters params =
|
||||||
|
|
@ -1203,7 +1245,7 @@ void MapWidgetImpl::InitializeNewRadarProductView(
|
||||||
auto radarProductView = context_->radar_product_view();
|
auto radarProductView = context_->radar_product_view();
|
||||||
|
|
||||||
std::string colorTableFile =
|
std::string colorTableFile =
|
||||||
manager::SettingsManager::palette_settings()
|
settings::PaletteSettings::Instance()
|
||||||
.palette(colorPalette)
|
.palette(colorPalette)
|
||||||
.GetValue();
|
.GetValue();
|
||||||
if (!colorTableFile.empty())
|
if (!colorTableFile.empty())
|
||||||
|
|
|
||||||
|
|
@ -197,6 +197,8 @@ void PlacefileLayer::ReloadData()
|
||||||
|
|
||||||
p->placefileIcons_->SetIconFiles(placefile->icon_files(),
|
p->placefileIcons_->SetIconFiles(placefile->icon_files(),
|
||||||
placefile->name());
|
placefile->name());
|
||||||
|
p->placefileText_->SetFonts(
|
||||||
|
placefileManager->placefile_fonts(p->placefileName_));
|
||||||
|
|
||||||
for (auto& drawItem : placefile->GetDrawItems())
|
for (auto& drawItem : placefile->GetDrawItems())
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,10 @@ namespace settings
|
||||||
|
|
||||||
static const std::string logPrefix_ = "scwx::qt::settings::general_settings";
|
static const std::string logPrefix_ = "scwx::qt::settings::general_settings";
|
||||||
|
|
||||||
class GeneralSettingsImpl
|
class GeneralSettings::Impl
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit GeneralSettingsImpl()
|
explicit Impl()
|
||||||
{
|
{
|
||||||
std::string defaultDefaultAlertActionValue =
|
std::string defaultDefaultAlertActionValue =
|
||||||
types::GetAlertActionName(types::AlertAction::Go);
|
types::GetAlertActionName(types::AlertAction::Go);
|
||||||
|
|
@ -102,7 +102,7 @@ public:
|
||||||
{ return !value.empty(); });
|
{ return !value.empty(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
~GeneralSettingsImpl() {}
|
~Impl() {}
|
||||||
|
|
||||||
SettingsVariable<bool> debugEnabled_ {"debug_enabled"};
|
SettingsVariable<bool> debugEnabled_ {"debug_enabled"};
|
||||||
SettingsVariable<std::string> defaultAlertAction_ {"default_alert_action"};
|
SettingsVariable<std::string> defaultAlertAction_ {"default_alert_action"};
|
||||||
|
|
@ -120,7 +120,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
GeneralSettings::GeneralSettings() :
|
GeneralSettings::GeneralSettings() :
|
||||||
SettingsCategory("general"), p(std::make_unique<GeneralSettingsImpl>())
|
SettingsCategory("general"), p(std::make_unique<Impl>())
|
||||||
{
|
{
|
||||||
RegisterVariables({&p->debugEnabled_,
|
RegisterVariables({&p->debugEnabled_,
|
||||||
&p->defaultAlertAction_,
|
&p->defaultAlertAction_,
|
||||||
|
|
@ -221,6 +221,12 @@ bool GeneralSettings::Shutdown()
|
||||||
return dataChanged;
|
return dataChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GeneralSettings& GeneralSettings::Instance()
|
||||||
|
{
|
||||||
|
static GeneralSettings generalSettings_;
|
||||||
|
return generalSettings_;
|
||||||
|
}
|
||||||
|
|
||||||
bool operator==(const GeneralSettings& lhs, const GeneralSettings& rhs)
|
bool operator==(const GeneralSettings& lhs, const GeneralSettings& rhs)
|
||||||
{
|
{
|
||||||
return (lhs.p->debugEnabled_ == rhs.p->debugEnabled_ &&
|
return (lhs.p->debugEnabled_ == rhs.p->debugEnabled_ &&
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,6 @@ namespace qt
|
||||||
namespace settings
|
namespace settings
|
||||||
{
|
{
|
||||||
|
|
||||||
class GeneralSettingsImpl;
|
|
||||||
|
|
||||||
class GeneralSettings : public SettingsCategory
|
class GeneralSettings : public SettingsCategory
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -41,13 +39,16 @@ public:
|
||||||
SettingsVariable<std::string>& maptiler_api_key() const;
|
SettingsVariable<std::string>& maptiler_api_key() const;
|
||||||
SettingsVariable<bool>& update_notifications_enabled() const;
|
SettingsVariable<bool>& update_notifications_enabled() const;
|
||||||
|
|
||||||
|
static GeneralSettings& Instance();
|
||||||
|
|
||||||
friend bool operator==(const GeneralSettings& lhs,
|
friend bool operator==(const GeneralSettings& lhs,
|
||||||
const GeneralSettings& rhs);
|
const GeneralSettings& rhs);
|
||||||
|
|
||||||
bool Shutdown();
|
bool Shutdown();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<GeneralSettingsImpl> p;
|
class Impl;
|
||||||
|
std::unique_ptr<Impl> p;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace settings
|
} // namespace settings
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ static const std::string kDefaultRadarProductGroupString_ = "L3";
|
||||||
static const std::array<std::string, kCount_> kDefaultRadarProduct_ {
|
static const std::array<std::string, kCount_> kDefaultRadarProduct_ {
|
||||||
"N0B", "N0G", "N0C", "N0X"};
|
"N0B", "N0G", "N0C", "N0X"};
|
||||||
|
|
||||||
class MapSettingsImpl
|
class MapSettings::Impl
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
struct MapData
|
struct MapData
|
||||||
|
|
@ -47,7 +47,7 @@ public:
|
||||||
SettingsVariable<std::string> radarProduct_ {kRadarProductName_};
|
SettingsVariable<std::string> radarProduct_ {kRadarProductName_};
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit MapSettingsImpl()
|
explicit Impl()
|
||||||
{
|
{
|
||||||
for (std::size_t i = 0; i < kCount_; i++)
|
for (std::size_t i = 0; i < kCount_; i++)
|
||||||
{
|
{
|
||||||
|
|
@ -101,7 +101,7 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
~MapSettingsImpl() {}
|
~Impl() {}
|
||||||
|
|
||||||
void SetDefaults(std::size_t i)
|
void SetDefaults(std::size_t i)
|
||||||
{
|
{
|
||||||
|
|
@ -111,12 +111,30 @@ public:
|
||||||
map_[i].radarProduct_.SetValueToDefault();
|
map_[i].radarProduct_.SetValueToDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
friend void tag_invoke(boost::json::value_from_tag,
|
||||||
|
boost::json::value& jv,
|
||||||
|
const MapData& data)
|
||||||
|
{
|
||||||
|
jv = {{kMapStyleName_, data.mapStyle_.GetValue()},
|
||||||
|
{kRadarSiteName_, data.radarSite_.GetValue()},
|
||||||
|
{kRadarProductGroupName_, data.radarProductGroup_.GetValue()},
|
||||||
|
{kRadarProductName_, data.radarProduct_.GetValue()}};
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool operator==(const MapData& lhs, const MapData& rhs)
|
||||||
|
{
|
||||||
|
return (lhs.mapStyle_ == rhs.mapStyle_ && //
|
||||||
|
lhs.radarSite_ == rhs.radarSite_ &&
|
||||||
|
lhs.radarProductGroup_ == rhs.radarProductGroup_ &&
|
||||||
|
lhs.radarProduct_ == rhs.radarProduct_);
|
||||||
|
}
|
||||||
|
|
||||||
std::array<MapData, kCount_> map_ {};
|
std::array<MapData, kCount_> map_ {};
|
||||||
std::vector<SettingsVariableBase*> variables_ {};
|
std::vector<SettingsVariableBase*> variables_ {};
|
||||||
};
|
};
|
||||||
|
|
||||||
MapSettings::MapSettings() :
|
MapSettings::MapSettings() :
|
||||||
SettingsCategory("maps"), p(std::make_unique<MapSettingsImpl>())
|
SettingsCategory("maps"), p(std::make_unique<Impl>())
|
||||||
{
|
{
|
||||||
RegisterVariables(p->variables_);
|
RegisterVariables(p->variables_);
|
||||||
SetDefaults();
|
SetDefaults();
|
||||||
|
|
@ -161,7 +179,7 @@ bool MapSettings::Shutdown()
|
||||||
// Commit settings that are managed separate from the settings dialog
|
// Commit settings that are managed separate from the settings dialog
|
||||||
for (std::size_t i = 0; i < kCount_; ++i)
|
for (std::size_t i = 0; i < kCount_; ++i)
|
||||||
{
|
{
|
||||||
MapSettingsImpl::MapData& mapRecordSettings = p->map_[i];
|
Impl::MapData& mapRecordSettings = p->map_[i];
|
||||||
|
|
||||||
dataChanged |= mapRecordSettings.mapStyle_.Commit();
|
dataChanged |= mapRecordSettings.mapStyle_.Commit();
|
||||||
}
|
}
|
||||||
|
|
@ -184,7 +202,7 @@ bool MapSettings::ReadJson(const boost::json::object& json)
|
||||||
if (i < mapArray.size() && mapArray.at(i).is_object())
|
if (i < mapArray.size() && mapArray.at(i).is_object())
|
||||||
{
|
{
|
||||||
const boost::json::object& mapRecord = mapArray.at(i).as_object();
|
const boost::json::object& mapRecord = mapArray.at(i).as_object();
|
||||||
MapSettingsImpl::MapData& mapRecordSettings = p->map_[i];
|
Impl::MapData& mapRecordSettings = p->map_[i];
|
||||||
|
|
||||||
// Load JSON Elements
|
// Load JSON Elements
|
||||||
validated &= mapRecordSettings.mapStyle_.ReadValue(mapRecord);
|
validated &= mapRecordSettings.mapStyle_.ReadValue(mapRecord);
|
||||||
|
|
@ -234,14 +252,10 @@ void MapSettings::WriteJson(boost::json::object& json) const
|
||||||
json.insert_or_assign(name(), object);
|
json.insert_or_assign(name(), object);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tag_invoke(boost::json::value_from_tag,
|
MapSettings& MapSettings::Instance()
|
||||||
boost::json::value& jv,
|
|
||||||
const MapSettingsImpl::MapData& data)
|
|
||||||
{
|
{
|
||||||
jv = {{kMapStyleName_, data.mapStyle_.GetValue()},
|
static MapSettings mapSettings_;
|
||||||
{kRadarSiteName_, data.radarSite_.GetValue()},
|
return mapSettings_;
|
||||||
{kRadarProductGroupName_, data.radarProductGroup_.GetValue()},
|
|
||||||
{kRadarProductName_, data.radarProduct_.GetValue()}};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const MapSettings& lhs, const MapSettings& rhs)
|
bool operator==(const MapSettings& lhs, const MapSettings& rhs)
|
||||||
|
|
@ -249,15 +263,6 @@ bool operator==(const MapSettings& lhs, const MapSettings& rhs)
|
||||||
return (lhs.p->map_ == rhs.p->map_);
|
return (lhs.p->map_ == rhs.p->map_);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const MapSettingsImpl::MapData& lhs,
|
|
||||||
const MapSettingsImpl::MapData& rhs)
|
|
||||||
{
|
|
||||||
return (lhs.mapStyle_ == rhs.mapStyle_ && //
|
|
||||||
lhs.radarSite_ == rhs.radarSite_ &&
|
|
||||||
lhs.radarProductGroup_ == rhs.radarProductGroup_ &&
|
|
||||||
lhs.radarProduct_ == rhs.radarProduct_);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace settings
|
} // namespace settings
|
||||||
} // namespace qt
|
} // namespace qt
|
||||||
} // namespace scwx
|
} // namespace scwx
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,6 @@ namespace qt
|
||||||
namespace settings
|
namespace settings
|
||||||
{
|
{
|
||||||
|
|
||||||
class MapSettingsImpl;
|
|
||||||
|
|
||||||
class MapSettings : public SettingsCategory
|
class MapSettings : public SettingsCategory
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -52,10 +50,13 @@ public:
|
||||||
*/
|
*/
|
||||||
void WriteJson(boost::json::object& json) const override;
|
void WriteJson(boost::json::object& json) const override;
|
||||||
|
|
||||||
|
static MapSettings& Instance();
|
||||||
|
|
||||||
friend bool operator==(const MapSettings& lhs, const MapSettings& rhs);
|
friend bool operator==(const MapSettings& lhs, const MapSettings& rhs);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<MapSettingsImpl> p;
|
class Impl;
|
||||||
|
std::unique_ptr<Impl> p;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace settings
|
} // namespace settings
|
||||||
|
|
|
||||||
|
|
@ -72,10 +72,10 @@ static const std::map<
|
||||||
static const std::string kDefaultKey_ {"???"};
|
static const std::string kDefaultKey_ {"???"};
|
||||||
static const awips::Phenomenon kDefaultPhenomenon_ {awips::Phenomenon::Marine};
|
static const awips::Phenomenon kDefaultPhenomenon_ {awips::Phenomenon::Marine};
|
||||||
|
|
||||||
class PaletteSettingsImpl
|
class PaletteSettings::Impl
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit PaletteSettingsImpl()
|
explicit Impl()
|
||||||
{
|
{
|
||||||
for (const auto& name : kPaletteKeys_)
|
for (const auto& name : kPaletteKeys_)
|
||||||
{
|
{
|
||||||
|
|
@ -120,7 +120,7 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
~PaletteSettingsImpl() {}
|
~Impl() {}
|
||||||
|
|
||||||
static bool ValidateColor(const std::string& value);
|
static bool ValidateColor(const std::string& value);
|
||||||
|
|
||||||
|
|
@ -132,14 +132,14 @@ public:
|
||||||
std::vector<SettingsVariableBase*> variables_ {};
|
std::vector<SettingsVariableBase*> variables_ {};
|
||||||
};
|
};
|
||||||
|
|
||||||
bool PaletteSettingsImpl::ValidateColor(const std::string& value)
|
bool PaletteSettings::Impl::ValidateColor(const std::string& value)
|
||||||
{
|
{
|
||||||
static const std::regex re {"#[0-9A-Za-z]{8}"};
|
static const std::regex re {"#[0-9A-Za-z]{8}"};
|
||||||
return std::regex_match(value, re);
|
return std::regex_match(value, re);
|
||||||
}
|
}
|
||||||
|
|
||||||
PaletteSettings::PaletteSettings() :
|
PaletteSettings::PaletteSettings() :
|
||||||
SettingsCategory("palette"), p(std::make_unique<PaletteSettingsImpl>())
|
SettingsCategory("palette"), p(std::make_unique<Impl>())
|
||||||
{
|
{
|
||||||
RegisterVariables(p->variables_);
|
RegisterVariables(p->variables_);
|
||||||
SetDefaults();
|
SetDefaults();
|
||||||
|
|
@ -200,6 +200,12 @@ const std::vector<awips::Phenomenon>& PaletteSettings::alert_phenomena()
|
||||||
return kAlertPhenomena_;
|
return kAlertPhenomena_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PaletteSettings& PaletteSettings::Instance()
|
||||||
|
{
|
||||||
|
static PaletteSettings paletteSettings_;
|
||||||
|
return paletteSettings_;
|
||||||
|
}
|
||||||
|
|
||||||
bool operator==(const PaletteSettings& lhs, const PaletteSettings& rhs)
|
bool operator==(const PaletteSettings& lhs, const PaletteSettings& rhs)
|
||||||
{
|
{
|
||||||
return lhs.p->palette_ == rhs.p->palette_;
|
return lhs.p->palette_ == rhs.p->palette_;
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,6 @@ namespace qt
|
||||||
namespace settings
|
namespace settings
|
||||||
{
|
{
|
||||||
|
|
||||||
class PaletteSettingsImpl;
|
|
||||||
|
|
||||||
class PaletteSettings : public SettingsCategory
|
class PaletteSettings : public SettingsCategory
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -34,11 +32,14 @@ public:
|
||||||
|
|
||||||
static const std::vector<awips::Phenomenon>& alert_phenomena();
|
static const std::vector<awips::Phenomenon>& alert_phenomena();
|
||||||
|
|
||||||
|
static PaletteSettings& Instance();
|
||||||
|
|
||||||
friend bool operator==(const PaletteSettings& lhs,
|
friend bool operator==(const PaletteSettings& lhs,
|
||||||
const PaletteSettings& rhs);
|
const PaletteSettings& rhs);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<PaletteSettingsImpl> p;
|
class Impl;
|
||||||
|
std::unique_ptr<Impl> p;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace settings
|
} // namespace settings
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
#include <scwx/qt/util/json.hpp>
|
#include <scwx/qt/util/json.hpp>
|
||||||
#include <scwx/util/logger.hpp>
|
#include <scwx/util/logger.hpp>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace scwx
|
namespace scwx
|
||||||
{
|
{
|
||||||
namespace qt
|
namespace qt
|
||||||
|
|
@ -21,6 +23,8 @@ public:
|
||||||
|
|
||||||
const std::string name_;
|
const std::string name_;
|
||||||
|
|
||||||
|
std::vector<std::pair<std::string, std::vector<SettingsCategory*>>>
|
||||||
|
subcategoryArrays_;
|
||||||
std::vector<SettingsVariableBase*> variables_;
|
std::vector<SettingsVariableBase*> variables_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -41,6 +45,16 @@ std::string SettingsCategory::name() const
|
||||||
|
|
||||||
void SettingsCategory::SetDefaults()
|
void SettingsCategory::SetDefaults()
|
||||||
{
|
{
|
||||||
|
// Set subcategory array defaults
|
||||||
|
for (auto& subcategoryArray : p->subcategoryArrays_)
|
||||||
|
{
|
||||||
|
for (auto& subcategory : subcategoryArray.second)
|
||||||
|
{
|
||||||
|
subcategory->SetDefaults();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set variable defaults
|
||||||
for (auto& variable : p->variables_)
|
for (auto& variable : p->variables_)
|
||||||
{
|
{
|
||||||
variable->SetValueToDefault();
|
variable->SetValueToDefault();
|
||||||
|
|
@ -57,6 +71,47 @@ bool SettingsCategory::ReadJson(const boost::json::object& json)
|
||||||
{
|
{
|
||||||
const boost::json::object& object = value->as_object();
|
const boost::json::object& object = value->as_object();
|
||||||
|
|
||||||
|
// Read subcategory arrays
|
||||||
|
for (auto& subcategoryArray : p->subcategoryArrays_)
|
||||||
|
{
|
||||||
|
const boost::json::value* arrayValue =
|
||||||
|
object.if_contains(subcategoryArray.first);
|
||||||
|
|
||||||
|
if (arrayValue != nullptr && arrayValue->is_object())
|
||||||
|
{
|
||||||
|
const boost::json::object& arrayObject = arrayValue->as_object();
|
||||||
|
|
||||||
|
for (auto& subcategory : subcategoryArray.second)
|
||||||
|
{
|
||||||
|
validated &= subcategory->ReadJson(arrayObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (arrayValue == nullptr)
|
||||||
|
{
|
||||||
|
logger_->debug(
|
||||||
|
"Subcategory array key {} is not present, resetting to "
|
||||||
|
"defaults",
|
||||||
|
subcategoryArray.first);
|
||||||
|
}
|
||||||
|
else if (!arrayValue->is_object())
|
||||||
|
{
|
||||||
|
logger_->warn(
|
||||||
|
"Invalid json for subcategory array key {}, resetting to "
|
||||||
|
"defaults",
|
||||||
|
p->name_);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& subcategory : subcategoryArray.second)
|
||||||
|
{
|
||||||
|
subcategory->SetDefaults();
|
||||||
|
}
|
||||||
|
validated = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read variables
|
||||||
for (auto& variable : p->variables_)
|
for (auto& variable : p->variables_)
|
||||||
{
|
{
|
||||||
validated &= variable->ReadValue(object);
|
validated &= variable->ReadValue(object);
|
||||||
|
|
@ -66,8 +121,8 @@ bool SettingsCategory::ReadJson(const boost::json::object& json)
|
||||||
{
|
{
|
||||||
if (value == nullptr)
|
if (value == nullptr)
|
||||||
{
|
{
|
||||||
logger_->warn("Key {} is not present, resetting to defaults",
|
logger_->debug("Key {} is not present, resetting to defaults",
|
||||||
p->name_);
|
p->name_);
|
||||||
}
|
}
|
||||||
else if (!value->is_object())
|
else if (!value->is_object())
|
||||||
{
|
{
|
||||||
|
|
@ -86,6 +141,20 @@ void SettingsCategory::WriteJson(boost::json::object& json) const
|
||||||
{
|
{
|
||||||
boost::json::object object;
|
boost::json::object object;
|
||||||
|
|
||||||
|
// Write subcategory arrays
|
||||||
|
for (auto& subcategoryArray : p->subcategoryArrays_)
|
||||||
|
{
|
||||||
|
boost::json::object arrayObject;
|
||||||
|
|
||||||
|
for (auto& subcategory : subcategoryArray.second)
|
||||||
|
{
|
||||||
|
subcategory->WriteJson(arrayObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
object.insert_or_assign(subcategoryArray.first, arrayObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write variables
|
||||||
for (auto& variable : p->variables_)
|
for (auto& variable : p->variables_)
|
||||||
{
|
{
|
||||||
variable->WriteValue(object);
|
variable->WriteValue(object);
|
||||||
|
|
@ -94,6 +163,18 @@ void SettingsCategory::WriteJson(boost::json::object& json) const
|
||||||
json.insert_or_assign(p->name_, object);
|
json.insert_or_assign(p->name_, object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SettingsCategory::RegisterSubcategoryArray(
|
||||||
|
const std::string& name, std::vector<SettingsCategory>& subcategories)
|
||||||
|
{
|
||||||
|
auto& newSubcategories = p->subcategoryArrays_.emplace_back(
|
||||||
|
name, std::vector<SettingsCategory*> {});
|
||||||
|
|
||||||
|
std::transform(subcategories.begin(),
|
||||||
|
subcategories.end(),
|
||||||
|
std::back_inserter(newSubcategories.second),
|
||||||
|
[](SettingsCategory& subcategory) { return &subcategory; });
|
||||||
|
}
|
||||||
|
|
||||||
void SettingsCategory::RegisterVariables(
|
void SettingsCategory::RegisterVariables(
|
||||||
std::initializer_list<SettingsVariableBase*> variables)
|
std::initializer_list<SettingsVariableBase*> variables)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,8 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual void WriteJson(boost::json::object& json) const;
|
virtual void WriteJson(boost::json::object& json) const;
|
||||||
|
|
||||||
protected:
|
void RegisterSubcategoryArray(const std::string& name,
|
||||||
|
std::vector<SettingsCategory>& subcategories);
|
||||||
void
|
void
|
||||||
RegisterVariables(std::initializer_list<SettingsVariableBase*> variables);
|
RegisterVariables(std::initializer_list<SettingsVariableBase*> variables);
|
||||||
void RegisterVariables(std::vector<SettingsVariableBase*> variables);
|
void RegisterVariables(std::vector<SettingsVariableBase*> variables);
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
|
#include <QLabel>
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
#include <QSpinBox>
|
#include <QSpinBox>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
@ -26,16 +27,21 @@ template<class T>
|
||||||
class SettingsInterface<T>::Impl
|
class SettingsInterface<T>::Impl
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit Impl()
|
explicit Impl(SettingsInterface* self) : self_ {self}
|
||||||
{
|
{
|
||||||
context_->moveToThread(QCoreApplication::instance()->thread());
|
context_->moveToThread(QCoreApplication::instance()->thread());
|
||||||
}
|
}
|
||||||
|
|
||||||
~Impl() {}
|
~Impl() {}
|
||||||
|
|
||||||
|
template<class U>
|
||||||
|
void SetWidgetText(U* widget, const T& currentValue);
|
||||||
|
|
||||||
void UpdateEditWidget();
|
void UpdateEditWidget();
|
||||||
void UpdateResetButton();
|
void UpdateResetButton();
|
||||||
|
|
||||||
|
SettingsInterface<T>* self_;
|
||||||
|
|
||||||
SettingsVariable<T>* variable_ {nullptr};
|
SettingsVariable<T>* variable_ {nullptr};
|
||||||
bool stagedValid_ {true};
|
bool stagedValid_ {true};
|
||||||
|
|
||||||
|
|
@ -49,17 +55,27 @@ public:
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
SettingsInterface<T>::SettingsInterface() :
|
SettingsInterface<T>::SettingsInterface() :
|
||||||
SettingsInterfaceBase(), p(std::make_unique<Impl>())
|
SettingsInterfaceBase(), p(std::make_unique<Impl>(this))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
template<class T>
|
template<class T>
|
||||||
SettingsInterface<T>::~SettingsInterface() = default;
|
SettingsInterface<T>::~SettingsInterface() = default;
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
SettingsInterface<T>::SettingsInterface(SettingsInterface&&) noexcept = default;
|
SettingsInterface<T>::SettingsInterface(SettingsInterface&& o) noexcept :
|
||||||
|
p {std::move(o.p)}
|
||||||
|
{
|
||||||
|
p->self_ = this;
|
||||||
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
SettingsInterface<T>&
|
SettingsInterface<T>&
|
||||||
SettingsInterface<T>::operator=(SettingsInterface&&) noexcept = default;
|
SettingsInterface<T>::operator=(SettingsInterface&& o) noexcept
|
||||||
|
{
|
||||||
|
p = std::move(o.p);
|
||||||
|
p->self_ = this;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
void SettingsInterface<T>::SetSettingsVariable(SettingsVariable<T>& variable)
|
void SettingsInterface<T>::SetSettingsVariable(SettingsVariable<T>& variable)
|
||||||
|
|
@ -73,6 +89,27 @@ SettingsVariable<T>* SettingsInterface<T>::GetSettingsVariable() const
|
||||||
return p->variable_;
|
return p->variable_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
bool SettingsInterface<T>::IsDefault()
|
||||||
|
{
|
||||||
|
bool isDefault = false;
|
||||||
|
|
||||||
|
const std::optional<T> staged = p->variable_->GetStaged();
|
||||||
|
const T defaultValue = p->variable_->GetDefault();
|
||||||
|
const T value = p->variable_->GetValue();
|
||||||
|
|
||||||
|
if (staged.has_value())
|
||||||
|
{
|
||||||
|
isDefault = (p->stagedValid_ && *staged == defaultValue);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
isDefault = (value == defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
return isDefault;
|
||||||
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
bool SettingsInterface<T>::Commit()
|
bool SettingsInterface<T>::Commit()
|
||||||
{
|
{
|
||||||
|
|
@ -95,6 +132,14 @@ void SettingsInterface<T>::StageDefault()
|
||||||
p->UpdateResetButton();
|
p->UpdateResetButton();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
void SettingsInterface<T>::StageValue(const T& value)
|
||||||
|
{
|
||||||
|
p->variable_->StageValue(value);
|
||||||
|
p->UpdateEditWidget();
|
||||||
|
p->UpdateResetButton();
|
||||||
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
void SettingsInterface<T>::SetEditWidget(QWidget* widget)
|
void SettingsInterface<T>::SetEditWidget(QWidget* widget)
|
||||||
{
|
{
|
||||||
|
|
@ -105,6 +150,11 @@ void SettingsInterface<T>::SetEditWidget(QWidget* widget)
|
||||||
|
|
||||||
p->editWidget_ = widget;
|
p->editWidget_ = widget;
|
||||||
|
|
||||||
|
if (widget == nullptr)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (QLineEdit* lineEdit = dynamic_cast<QLineEdit*>(widget))
|
if (QLineEdit* lineEdit = dynamic_cast<QLineEdit*>(widget))
|
||||||
{
|
{
|
||||||
if constexpr (std::is_same_v<T, std::string>)
|
if constexpr (std::is_same_v<T, std::string>)
|
||||||
|
|
@ -274,33 +324,36 @@ void SettingsInterface<T>::SetResetButton(QAbstractButton* button)
|
||||||
|
|
||||||
p->resetButton_ = button;
|
p->resetButton_ = button;
|
||||||
|
|
||||||
QObject::connect(p->resetButton_,
|
if (p->resetButton_ != nullptr)
|
||||||
&QAbstractButton::clicked,
|
{
|
||||||
p->context_.get(),
|
QObject::connect(p->resetButton_,
|
||||||
[this]()
|
&QAbstractButton::clicked,
|
||||||
{
|
p->context_.get(),
|
||||||
T defaultValue = p->variable_->GetDefault();
|
[this]()
|
||||||
|
|
||||||
if (p->variable_->GetValue() == defaultValue)
|
|
||||||
{
|
{
|
||||||
// If the current value is default, reset the staged
|
T defaultValue = p->variable_->GetDefault();
|
||||||
// value
|
|
||||||
p->variable_->Reset();
|
|
||||||
p->stagedValid_ = true;
|
|
||||||
p->UpdateEditWidget();
|
|
||||||
p->UpdateResetButton();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Stage the default value
|
|
||||||
p->stagedValid_ =
|
|
||||||
p->variable_->StageValue(defaultValue);
|
|
||||||
p->UpdateEditWidget();
|
|
||||||
p->UpdateResetButton();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
p->UpdateResetButton();
|
if (p->variable_->GetValue() == defaultValue)
|
||||||
|
{
|
||||||
|
// If the current value is default, reset the
|
||||||
|
// staged value
|
||||||
|
p->variable_->Reset();
|
||||||
|
p->stagedValid_ = true;
|
||||||
|
p->UpdateEditWidget();
|
||||||
|
p->UpdateResetButton();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Stage the default value
|
||||||
|
p->stagedValid_ =
|
||||||
|
p->variable_->StageValue(defaultValue);
|
||||||
|
p->UpdateEditWidget();
|
||||||
|
p->UpdateResetButton();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
p->UpdateResetButton();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
|
|
@ -317,6 +370,39 @@ void SettingsInterface<T>::SetMapToValueFunction(
|
||||||
p->mapToValue_ = function;
|
p->mapToValue_ = function;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
template<class U>
|
||||||
|
void SettingsInterface<T>::Impl::SetWidgetText(U* widget, const T& currentValue)
|
||||||
|
{
|
||||||
|
if constexpr (std::is_integral_v<T>)
|
||||||
|
{
|
||||||
|
widget->setText(QString::number(currentValue));
|
||||||
|
}
|
||||||
|
else if constexpr (std::is_same_v<T, std::string>)
|
||||||
|
{
|
||||||
|
if (mapFromValue_ != nullptr)
|
||||||
|
{
|
||||||
|
widget->setText(QString::fromStdString(mapFromValue_(currentValue)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
widget->setText(QString::fromStdString(currentValue));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if constexpr (std::is_same_v<T, std::vector<std::int64_t>>)
|
||||||
|
{
|
||||||
|
if (mapFromValue_ != nullptr)
|
||||||
|
{
|
||||||
|
widget->setText(QString::fromStdString(mapFromValue_(currentValue)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
widget->setText(QString::fromStdString(
|
||||||
|
fmt::format("{}", fmt::join(currentValue, ", "))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
void SettingsInterface<T>::Impl::UpdateEditWidget()
|
void SettingsInterface<T>::Impl::UpdateEditWidget()
|
||||||
{
|
{
|
||||||
|
|
@ -327,35 +413,11 @@ void SettingsInterface<T>::Impl::UpdateEditWidget()
|
||||||
|
|
||||||
if (QLineEdit* lineEdit = dynamic_cast<QLineEdit*>(editWidget_))
|
if (QLineEdit* lineEdit = dynamic_cast<QLineEdit*>(editWidget_))
|
||||||
{
|
{
|
||||||
if constexpr (std::is_integral_v<T>)
|
SetWidgetText(lineEdit, currentValue);
|
||||||
{
|
}
|
||||||
lineEdit->setText(QString::number(currentValue));
|
else if (QLabel* label = dynamic_cast<QLabel*>(editWidget_))
|
||||||
}
|
{
|
||||||
else if constexpr (std::is_same_v<T, std::string>)
|
SetWidgetText(label, currentValue);
|
||||||
{
|
|
||||||
if (mapFromValue_ != nullptr)
|
|
||||||
{
|
|
||||||
lineEdit->setText(
|
|
||||||
QString::fromStdString(mapFromValue_(currentValue)));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lineEdit->setText(QString::fromStdString(currentValue));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if constexpr (std::is_same_v<T, std::vector<std::int64_t>>)
|
|
||||||
{
|
|
||||||
if (mapFromValue_ != nullptr)
|
|
||||||
{
|
|
||||||
lineEdit->setText(
|
|
||||||
QString::fromStdString(mapFromValue_(currentValue)));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lineEdit->setText(QString::fromStdString(
|
|
||||||
fmt::format("{}", fmt::join(currentValue, ", "))));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (QCheckBox* checkBox = dynamic_cast<QCheckBox*>(editWidget_))
|
else if (QCheckBox* checkBox = dynamic_cast<QCheckBox*>(editWidget_))
|
||||||
{
|
{
|
||||||
|
|
@ -391,20 +453,9 @@ void SettingsInterface<T>::Impl::UpdateEditWidget()
|
||||||
template<class T>
|
template<class T>
|
||||||
void SettingsInterface<T>::Impl::UpdateResetButton()
|
void SettingsInterface<T>::Impl::UpdateResetButton()
|
||||||
{
|
{
|
||||||
const std::optional<T> staged = variable_->GetStaged();
|
|
||||||
const T defaultValue = variable_->GetDefault();
|
|
||||||
const T value = variable_->GetValue();
|
|
||||||
|
|
||||||
if (resetButton_ != nullptr)
|
if (resetButton_ != nullptr)
|
||||||
{
|
{
|
||||||
if (staged.has_value())
|
resetButton_->setVisible(!self_->IsDefault());
|
||||||
{
|
|
||||||
resetButton_->setVisible(!stagedValid_ || *staged != defaultValue);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
resetButton_->setVisible(value != defaultValue);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,14 @@ public:
|
||||||
*/
|
*/
|
||||||
SettingsVariable<T>* GetSettingsVariable() const;
|
SettingsVariable<T>* GetSettingsVariable() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets whether the staged value (or current value, if none staged) is
|
||||||
|
* set to the default value.
|
||||||
|
*
|
||||||
|
* @return true if the settings variable is set to default, otherwise false.
|
||||||
|
*/
|
||||||
|
bool IsDefault() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the current value of the associated settings variable to the staged
|
* Sets the current value of the associated settings variable to the staged
|
||||||
* value.
|
* value.
|
||||||
|
|
@ -64,6 +72,11 @@ public:
|
||||||
*/
|
*/
|
||||||
void StageDefault() override;
|
void StageDefault() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stages a value to the associated settings variable.
|
||||||
|
*/
|
||||||
|
void StageValue(const T& value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the edit widget from the settings dialog.
|
* Sets the edit widget from the settings dialog.
|
||||||
*
|
*
|
||||||
|
|
@ -103,6 +116,7 @@ private:
|
||||||
|
|
||||||
#ifdef SETTINGS_INTERFACE_IMPLEMENTATION
|
#ifdef SETTINGS_INTERFACE_IMPLEMENTATION
|
||||||
template class SettingsInterface<bool>;
|
template class SettingsInterface<bool>;
|
||||||
|
template class SettingsInterface<double>;
|
||||||
template class SettingsInterface<std::int64_t>;
|
template class SettingsInterface<std::int64_t>;
|
||||||
template class SettingsInterface<std::string>;
|
template class SettingsInterface<std::string>;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,10 +24,18 @@ public:
|
||||||
SettingsInterfaceBase(SettingsInterfaceBase&&) noexcept;
|
SettingsInterfaceBase(SettingsInterfaceBase&&) noexcept;
|
||||||
SettingsInterfaceBase& operator=(SettingsInterfaceBase&&) noexcept;
|
SettingsInterfaceBase& operator=(SettingsInterfaceBase&&) noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets whether the staged value (or current value, if none staged) is
|
||||||
|
* set to the default value.
|
||||||
|
*
|
||||||
|
* @return true if the settings variable is set to default, otherwise false.
|
||||||
|
*/
|
||||||
|
virtual bool IsDefault() = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the current value of the associated settings variable to the staged
|
* Sets the current value of the associated settings variable to the staged
|
||||||
* value.
|
* value.
|
||||||
*
|
*
|
||||||
* @return true if the staged value was committed, false if no staged value
|
* @return true if the staged value was committed, false if no staged value
|
||||||
* is present.
|
* is present.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -239,6 +239,12 @@ std::optional<T> SettingsVariable<T>::GetStaged() const
|
||||||
return p->staged_;
|
return p->staged_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
T SettingsVariable<T>::GetStagedOrValue() const
|
||||||
|
{
|
||||||
|
return p->staged_.value_or(GetValue());
|
||||||
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
T SettingsVariable<T>::GetDefault() const
|
T SettingsVariable<T>::GetDefault() const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -103,6 +103,14 @@ public:
|
||||||
*/
|
*/
|
||||||
std::optional<T> GetStaged() const;
|
std::optional<T> GetStaged() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the staged value of the settings variable, if defined, otherwise the
|
||||||
|
* current value.
|
||||||
|
*
|
||||||
|
* @return Staged value or current value
|
||||||
|
*/
|
||||||
|
T GetStagedOrValue() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate the value against the defined parameters of the settings
|
* Validate the value against the defined parameters of the settings
|
||||||
* variable.
|
* variable.
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,34 @@ namespace settings
|
||||||
|
|
||||||
static const std::string logPrefix_ = "scwx::qt::settings::text_settings";
|
static const std::string logPrefix_ = "scwx::qt::settings::text_settings";
|
||||||
|
|
||||||
|
static const std::string kAlteDIN1451Mittelscrhift_ {
|
||||||
|
"Alte DIN 1451 Mittelschrift"};
|
||||||
|
static const std::string kInconsolata_ {"Inconsolata"};
|
||||||
|
|
||||||
|
static const std::string kRegular_ {"Regular"};
|
||||||
|
|
||||||
|
static const std::unordered_map<types::FontCategory, std::string>
|
||||||
|
kDefaultFontFamily_ {
|
||||||
|
{types::FontCategory::Default, kAlteDIN1451Mittelscrhift_},
|
||||||
|
{types::FontCategory::Tooltip, kInconsolata_}};
|
||||||
|
static const std::unordered_map<types::FontCategory, std::string>
|
||||||
|
kDefaultFontStyle_ {{types::FontCategory::Default, kRegular_},
|
||||||
|
{types::FontCategory::Tooltip, kRegular_}};
|
||||||
|
static const std::unordered_map<types::FontCategory, double>
|
||||||
|
kDefaultFontPointSize_ {{types::FontCategory::Default, 12.0},
|
||||||
|
{types::FontCategory::Tooltip, 10.5}};
|
||||||
|
|
||||||
class TextSettings::Impl
|
class TextSettings::Impl
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit Impl()
|
struct FontData
|
||||||
|
{
|
||||||
|
SettingsVariable<std::string> fontFamily_ {"font_family"};
|
||||||
|
SettingsVariable<std::string> fontStyle_ {"font_style"};
|
||||||
|
SettingsVariable<double> fontPointSize_ {"font_point_size"};
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit Impl(TextSettings* self) : self_ {self}
|
||||||
{
|
{
|
||||||
std::string defaultTooltipMethodValue =
|
std::string defaultTooltipMethodValue =
|
||||||
types::GetTooltipMethodName(types::TooltipMethod::ImGui);
|
types::GetTooltipMethodName(types::TooltipMethod::ImGui);
|
||||||
|
|
@ -47,16 +71,32 @@ public:
|
||||||
// No match found, invalid
|
// No match found, invalid
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
InitializeFontVariables();
|
||||||
}
|
}
|
||||||
|
|
||||||
~Impl() {}
|
~Impl() {}
|
||||||
|
|
||||||
|
void InitializeFontVariables();
|
||||||
|
|
||||||
|
friend bool operator==(const FontData& lhs, const FontData& rhs)
|
||||||
|
{
|
||||||
|
return (lhs.fontFamily_ == rhs.fontFamily_ &&
|
||||||
|
lhs.fontStyle_ == rhs.fontStyle_ &&
|
||||||
|
lhs.fontPointSize_ == rhs.fontPointSize_);
|
||||||
|
}
|
||||||
|
|
||||||
|
TextSettings* self_;
|
||||||
|
|
||||||
|
std::unordered_map<types::FontCategory, FontData> fontData_ {};
|
||||||
|
std::vector<SettingsCategory> fontSettings_ {};
|
||||||
|
|
||||||
SettingsVariable<std::int64_t> hoverTextWrap_ {"hover_text_wrap"};
|
SettingsVariable<std::int64_t> hoverTextWrap_ {"hover_text_wrap"};
|
||||||
SettingsVariable<std::string> tooltipMethod_ {"tooltip_method"};
|
SettingsVariable<std::string> tooltipMethod_ {"tooltip_method"};
|
||||||
};
|
};
|
||||||
|
|
||||||
TextSettings::TextSettings() :
|
TextSettings::TextSettings() :
|
||||||
SettingsCategory("text"), p(std::make_unique<Impl>())
|
SettingsCategory("text"), p(std::make_unique<Impl>(this))
|
||||||
{
|
{
|
||||||
RegisterVariables({&p->hoverTextWrap_, &p->tooltipMethod_});
|
RegisterVariables({&p->hoverTextWrap_, &p->tooltipMethod_});
|
||||||
SetDefaults();
|
SetDefaults();
|
||||||
|
|
@ -66,6 +106,57 @@ TextSettings::~TextSettings() = default;
|
||||||
TextSettings::TextSettings(TextSettings&&) noexcept = default;
|
TextSettings::TextSettings(TextSettings&&) noexcept = default;
|
||||||
TextSettings& TextSettings::operator=(TextSettings&&) noexcept = default;
|
TextSettings& TextSettings::operator=(TextSettings&&) noexcept = default;
|
||||||
|
|
||||||
|
void TextSettings::Impl::InitializeFontVariables()
|
||||||
|
{
|
||||||
|
for (auto fontCategory : types::FontCategoryIterator())
|
||||||
|
{
|
||||||
|
auto result = fontData_.emplace(fontCategory, FontData {});
|
||||||
|
auto& pair = *result.first;
|
||||||
|
auto& font = pair.second;
|
||||||
|
|
||||||
|
font.fontFamily_.SetDefault(kDefaultFontFamily_.at(fontCategory));
|
||||||
|
font.fontStyle_.SetDefault(kDefaultFontStyle_.at(fontCategory));
|
||||||
|
font.fontPointSize_.SetDefault(kDefaultFontPointSize_.at(fontCategory));
|
||||||
|
|
||||||
|
// String values must not be empty
|
||||||
|
font.fontFamily_.SetValidator([](const std::string& value)
|
||||||
|
{ return !value.empty(); });
|
||||||
|
font.fontStyle_.SetValidator([](const std::string& value)
|
||||||
|
{ return !value.empty(); });
|
||||||
|
|
||||||
|
// Font point size must be between 6 and 72
|
||||||
|
font.fontPointSize_.SetMinimum(6.0);
|
||||||
|
font.fontPointSize_.SetMaximum(72.0);
|
||||||
|
|
||||||
|
// Variable registration
|
||||||
|
auto& settings = fontSettings_.emplace_back(
|
||||||
|
SettingsCategory {types::GetFontCategoryName(fontCategory)});
|
||||||
|
|
||||||
|
settings.RegisterVariables(
|
||||||
|
{&font.fontFamily_, &font.fontStyle_, &font.fontPointSize_});
|
||||||
|
}
|
||||||
|
|
||||||
|
self_->RegisterSubcategoryArray("fonts", fontSettings_);
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsVariable<std::string>&
|
||||||
|
TextSettings::font_family(types::FontCategory fontCategory) const
|
||||||
|
{
|
||||||
|
return p->fontData_.at(fontCategory).fontFamily_;
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsVariable<std::string>&
|
||||||
|
TextSettings::font_style(types::FontCategory fontCategory) const
|
||||||
|
{
|
||||||
|
return p->fontData_.at(fontCategory).fontStyle_;
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsVariable<double>&
|
||||||
|
TextSettings::font_point_size(types::FontCategory fontCategory) const
|
||||||
|
{
|
||||||
|
return p->fontData_.at(fontCategory).fontPointSize_;
|
||||||
|
}
|
||||||
|
|
||||||
SettingsVariable<std::int64_t>& TextSettings::hover_text_wrap() const
|
SettingsVariable<std::int64_t>& TextSettings::hover_text_wrap() const
|
||||||
{
|
{
|
||||||
return p->hoverTextWrap_;
|
return p->hoverTextWrap_;
|
||||||
|
|
@ -78,13 +169,14 @@ SettingsVariable<std::string>& TextSettings::tooltip_method() const
|
||||||
|
|
||||||
TextSettings& TextSettings::Instance()
|
TextSettings& TextSettings::Instance()
|
||||||
{
|
{
|
||||||
static TextSettings TextSettings_;
|
static TextSettings textSettings_;
|
||||||
return TextSettings_;
|
return textSettings_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const TextSettings& lhs, const TextSettings& rhs)
|
bool operator==(const TextSettings& lhs, const TextSettings& rhs)
|
||||||
{
|
{
|
||||||
return (lhs.p->hoverTextWrap_ == rhs.p->hoverTextWrap_ &&
|
return (lhs.p->fontData_ == rhs.p->fontData_ &&
|
||||||
|
lhs.p->hoverTextWrap_ == rhs.p->hoverTextWrap_ &&
|
||||||
lhs.p->tooltipMethod_ == rhs.p->tooltipMethod_);
|
lhs.p->tooltipMethod_ == rhs.p->tooltipMethod_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <scwx/qt/settings/settings_category.hpp>
|
#include <scwx/qt/settings/settings_category.hpp>
|
||||||
#include <scwx/qt/settings/settings_variable.hpp>
|
#include <scwx/qt/settings/settings_variable.hpp>
|
||||||
|
#include <scwx/qt/types/text_types.hpp>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
@ -25,8 +26,15 @@ public:
|
||||||
TextSettings(TextSettings&&) noexcept;
|
TextSettings(TextSettings&&) noexcept;
|
||||||
TextSettings& operator=(TextSettings&&) noexcept;
|
TextSettings& operator=(TextSettings&&) noexcept;
|
||||||
|
|
||||||
|
SettingsVariable<std::string>&
|
||||||
|
font_family(types::FontCategory fontCategory) const;
|
||||||
|
SettingsVariable<std::string>&
|
||||||
|
font_style(types::FontCategory fontCategory) const;
|
||||||
|
SettingsVariable<double>&
|
||||||
|
font_point_size(types::FontCategory fontCategory) const;
|
||||||
|
|
||||||
SettingsVariable<std::int64_t>& hover_text_wrap() const;
|
SettingsVariable<std::int64_t>& hover_text_wrap() const;
|
||||||
SettingsVariable<std::string>& tooltip_method() const;
|
SettingsVariable<std::string>& tooltip_method() const;
|
||||||
|
|
||||||
static TextSettings& Instance();
|
static TextSettings& Instance();
|
||||||
|
|
||||||
|
|
|
||||||
83
scwx-qt/source/scwx/qt/types/imgui_font.cpp
Normal file
83
scwx-qt/source/scwx/qt/types/imgui_font.cpp
Normal file
|
|
@ -0,0 +1,83 @@
|
||||||
|
// Disable strncpy warning
|
||||||
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
|
|
||||||
|
#include <scwx/qt/types/imgui_font.hpp>
|
||||||
|
#include <scwx/qt/model/imgui_context_model.hpp>
|
||||||
|
#include <scwx/util/logger.hpp>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
#include <imgui.h>
|
||||||
|
|
||||||
|
namespace scwx
|
||||||
|
{
|
||||||
|
namespace qt
|
||||||
|
{
|
||||||
|
namespace types
|
||||||
|
{
|
||||||
|
|
||||||
|
static const std::string logPrefix_ = "scwx::qt::types::imgui_font";
|
||||||
|
static const auto logger_ = scwx::util::Logger::Create(logPrefix_);
|
||||||
|
|
||||||
|
class ImGuiFont::Impl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit Impl(const std::string& fontName,
|
||||||
|
const std::vector<char>& fontData,
|
||||||
|
units::font_size::pixels<int> size) :
|
||||||
|
fontName_ {fontName}, size_ {size}
|
||||||
|
{
|
||||||
|
CreateImGuiFont(fontData);
|
||||||
|
}
|
||||||
|
|
||||||
|
~Impl() {}
|
||||||
|
|
||||||
|
void CreateImGuiFont(const std::vector<char>& fontData);
|
||||||
|
|
||||||
|
const std::string fontName_;
|
||||||
|
const units::font_size::pixels<int> size_;
|
||||||
|
|
||||||
|
ImFont* imFont_ {nullptr};
|
||||||
|
};
|
||||||
|
|
||||||
|
ImGuiFont::ImGuiFont(const std::string& fontName,
|
||||||
|
const std::vector<char>& fontData,
|
||||||
|
units::font_size::pixels<int> size) :
|
||||||
|
p(std::make_unique<Impl>(fontName, fontData, size))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
ImGuiFont::~ImGuiFont() = default;
|
||||||
|
|
||||||
|
void ImGuiFont::Impl::CreateImGuiFont(const std::vector<char>& fontData)
|
||||||
|
{
|
||||||
|
logger_->debug("Creating Font: {}", fontName_);
|
||||||
|
|
||||||
|
ImFontAtlas* fontAtlas = model::ImGuiContextModel::Instance().font_atlas();
|
||||||
|
ImFontConfig fontConfig {};
|
||||||
|
|
||||||
|
const float sizePixels = static_cast<float>(size_.value());
|
||||||
|
|
||||||
|
// Do not transfer ownership of font data to ImGui, makes const_cast safe
|
||||||
|
fontConfig.FontDataOwnedByAtlas = false;
|
||||||
|
|
||||||
|
// Assign name to font
|
||||||
|
strncpy(fontConfig.Name, fontName_.c_str(), sizeof(fontConfig.Name) - 1);
|
||||||
|
fontConfig.Name[sizeof(fontConfig.Name) - 1] = 0;
|
||||||
|
|
||||||
|
imFont_ = fontAtlas->AddFontFromMemoryTTF(
|
||||||
|
const_cast<void*>(static_cast<const void*>(fontData.data())),
|
||||||
|
static_cast<int>(std::clamp<std::size_t>(
|
||||||
|
fontData.size(), 0, std::numeric_limits<int>::max())),
|
||||||
|
sizePixels,
|
||||||
|
&fontConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImFont* ImGuiFont::font()
|
||||||
|
{
|
||||||
|
return p->imFont_;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace types
|
||||||
|
} // namespace qt
|
||||||
|
} // namespace scwx
|
||||||
41
scwx-qt/source/scwx/qt/types/imgui_font.hpp
Normal file
41
scwx-qt/source/scwx/qt/types/imgui_font.hpp
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <scwx/qt/types/font_types.hpp>
|
||||||
|
|
||||||
|
struct ImFont;
|
||||||
|
|
||||||
|
namespace scwx
|
||||||
|
{
|
||||||
|
namespace qt
|
||||||
|
{
|
||||||
|
namespace types
|
||||||
|
{
|
||||||
|
|
||||||
|
class ImGuiFont
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit ImGuiFont(const std::string& fontName,
|
||||||
|
const std::vector<char>& fontData,
|
||||||
|
units::font_size::pixels<int> size);
|
||||||
|
~ImGuiFont();
|
||||||
|
|
||||||
|
ImGuiFont(const ImGuiFont&) = delete;
|
||||||
|
ImGuiFont& operator=(const ImGuiFont&) = delete;
|
||||||
|
|
||||||
|
ImGuiFont(ImGuiFont&&) = delete;
|
||||||
|
ImGuiFont& operator=(ImGuiFont&&) = delete;
|
||||||
|
|
||||||
|
ImFont* font();
|
||||||
|
|
||||||
|
private:
|
||||||
|
class Impl;
|
||||||
|
std::unique_ptr<Impl> p;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace types
|
||||||
|
} // namespace qt
|
||||||
|
} // namespace scwx
|
||||||
|
|
@ -11,12 +11,40 @@ namespace qt
|
||||||
namespace types
|
namespace types
|
||||||
{
|
{
|
||||||
|
|
||||||
|
static const std::unordered_map<FontCategory, std::string> fontCategoryName_ {
|
||||||
|
{FontCategory::Default, "Default"},
|
||||||
|
{FontCategory::Tooltip, "Tooltip"},
|
||||||
|
{FontCategory::Unknown, "?"}};
|
||||||
|
|
||||||
static const std::unordered_map<TooltipMethod, std::string> tooltipMethodName_ {
|
static const std::unordered_map<TooltipMethod, std::string> tooltipMethodName_ {
|
||||||
{TooltipMethod::ImGui, "ImGui"},
|
{TooltipMethod::ImGui, "ImGui"},
|
||||||
{TooltipMethod::QToolTip, "Native Tooltip"},
|
{TooltipMethod::QToolTip, "Native Tooltip"},
|
||||||
{TooltipMethod::QLabel, "Floating Label"},
|
{TooltipMethod::QLabel, "Floating Label"},
|
||||||
{TooltipMethod::Unknown, "?"}};
|
{TooltipMethod::Unknown, "?"}};
|
||||||
|
|
||||||
|
FontCategory GetFontCategory(const std::string& name)
|
||||||
|
{
|
||||||
|
auto result =
|
||||||
|
std::find_if(fontCategoryName_.cbegin(),
|
||||||
|
fontCategoryName_.cend(),
|
||||||
|
[&](const std::pair<FontCategory, std::string>& pair) -> bool
|
||||||
|
{ return boost::iequals(pair.second, name); });
|
||||||
|
|
||||||
|
if (result != fontCategoryName_.cend())
|
||||||
|
{
|
||||||
|
return result->first;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return FontCategory::Unknown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GetFontCategoryName(FontCategory fontCategory)
|
||||||
|
{
|
||||||
|
return fontCategoryName_.at(fontCategory);
|
||||||
|
}
|
||||||
|
|
||||||
TooltipMethod GetTooltipMethod(const std::string& name)
|
TooltipMethod GetTooltipMethod(const std::string& name)
|
||||||
{
|
{
|
||||||
auto result = std::find_if(
|
auto result = std::find_if(
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,16 @@ namespace qt
|
||||||
namespace types
|
namespace types
|
||||||
{
|
{
|
||||||
|
|
||||||
|
enum class FontCategory
|
||||||
|
{
|
||||||
|
Default,
|
||||||
|
Tooltip,
|
||||||
|
Unknown
|
||||||
|
};
|
||||||
|
typedef scwx::util::
|
||||||
|
Iterator<FontCategory, FontCategory::Default, FontCategory::Tooltip>
|
||||||
|
FontCategoryIterator;
|
||||||
|
|
||||||
enum class TooltipMethod
|
enum class TooltipMethod
|
||||||
{
|
{
|
||||||
ImGui,
|
ImGui,
|
||||||
|
|
@ -22,6 +32,8 @@ typedef scwx::util::
|
||||||
Iterator<TooltipMethod, TooltipMethod::ImGui, TooltipMethod::QLabel>
|
Iterator<TooltipMethod, TooltipMethod::ImGui, TooltipMethod::QLabel>
|
||||||
TooltipMethodIterator;
|
TooltipMethodIterator;
|
||||||
|
|
||||||
|
FontCategory GetFontCategory(const std::string& name);
|
||||||
|
std::string GetFontCategoryName(FontCategory fontCategory);
|
||||||
TooltipMethod GetTooltipMethod(const std::string& name);
|
TooltipMethod GetTooltipMethod(const std::string& name);
|
||||||
std::string GetTooltipMethodName(TooltipMethod tooltipMethod);
|
std::string GetTooltipMethodName(TooltipMethod tooltipMethod);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#include "about_dialog.hpp"
|
#include "about_dialog.hpp"
|
||||||
#include "ui_about_dialog.h"
|
#include "ui_about_dialog.h"
|
||||||
#include <scwx/qt/main/versions.hpp>
|
#include <scwx/qt/main/versions.hpp>
|
||||||
#include <scwx/qt/manager/resource_manager.hpp>
|
#include <scwx/qt/manager/font_manager.hpp>
|
||||||
|
|
||||||
#include <QFontDatabase>
|
#include <QFontDatabase>
|
||||||
|
|
||||||
|
|
@ -27,7 +27,7 @@ AboutDialog::AboutDialog(QWidget* parent) :
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
int titleFontId =
|
int titleFontId =
|
||||||
manager::ResourceManager::FontId(types::Font::din1451alt_g);
|
manager::FontManager::Instance().GetFontId(types::Font::din1451alt_g);
|
||||||
QString titleFontFamily =
|
QString titleFontFamily =
|
||||||
QFontDatabase::applicationFontFamilies(titleFontId).at(0);
|
QFontDatabase::applicationFontFamilies(titleFontId).at(0);
|
||||||
QFont titleFont(titleFontFamily, 14);
|
QFont titleFont(titleFontFamily, 14);
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
#include "alert_dock_widget.hpp"
|
#include "alert_dock_widget.hpp"
|
||||||
#include "ui_alert_dock_widget.h"
|
#include "ui_alert_dock_widget.h"
|
||||||
|
|
||||||
#include <scwx/qt/manager/settings_manager.hpp>
|
|
||||||
#include <scwx/qt/manager/text_event_manager.hpp>
|
#include <scwx/qt/manager/text_event_manager.hpp>
|
||||||
#include <scwx/qt/model/alert_model.hpp>
|
#include <scwx/qt/model/alert_model.hpp>
|
||||||
#include <scwx/qt/model/alert_proxy_model.hpp>
|
#include <scwx/qt/model/alert_proxy_model.hpp>
|
||||||
|
#include <scwx/qt/settings/general_settings.hpp>
|
||||||
#include <scwx/qt/types/alert_types.hpp>
|
#include <scwx/qt/types/alert_types.hpp>
|
||||||
#include <scwx/qt/types/qt_types.hpp>
|
#include <scwx/qt/types/qt_types.hpp>
|
||||||
#include <scwx/qt/ui/alert_dialog.hpp>
|
#include <scwx/qt/ui/alert_dialog.hpp>
|
||||||
|
|
@ -175,10 +175,10 @@ void AlertDockWidgetImpl::ConnectSignals()
|
||||||
// If an item is selected
|
// If an item is selected
|
||||||
if (selectedAlertKey_ != types::TextEventKey {})
|
if (selectedAlertKey_ != types::TextEventKey {})
|
||||||
{
|
{
|
||||||
types::AlertAction alertAction = types::GetAlertAction(
|
types::AlertAction alertAction =
|
||||||
manager::SettingsManager::general_settings()
|
types::GetAlertAction(settings::GeneralSettings::Instance()
|
||||||
.default_alert_action()
|
.default_alert_action()
|
||||||
.GetValue());
|
.GetValue());
|
||||||
|
|
||||||
switch (alertAction)
|
switch (alertAction)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#include "animation_dock_widget.hpp"
|
#include "animation_dock_widget.hpp"
|
||||||
#include "ui_animation_dock_widget.h"
|
#include "ui_animation_dock_widget.h"
|
||||||
|
|
||||||
#include <scwx/qt/manager/settings_manager.hpp>
|
#include <scwx/qt/settings/general_settings.hpp>
|
||||||
#include <scwx/qt/util/time.hpp>
|
#include <scwx/qt/util/time.hpp>
|
||||||
#include <scwx/util/logger.hpp>
|
#include <scwx/util/logger.hpp>
|
||||||
|
|
||||||
|
|
@ -101,7 +101,7 @@ AnimationDockWidget::AnimationDockWidget(QWidget* parent) :
|
||||||
maxDateTimer->start(15000);
|
maxDateTimer->start(15000);
|
||||||
|
|
||||||
// Set loop defaults
|
// Set loop defaults
|
||||||
auto& generalSettings = manager::SettingsManager::general_settings();
|
auto& generalSettings = settings::GeneralSettings::Instance();
|
||||||
ui->loopTimeSpinBox->setValue(generalSettings.loop_time().GetValue());
|
ui->loopTimeSpinBox->setValue(generalSettings.loop_time().GetValue());
|
||||||
ui->loopSpeedSpinBox->setValue(generalSettings.loop_speed().GetValue());
|
ui->loopSpeedSpinBox->setValue(generalSettings.loop_speed().GetValue());
|
||||||
ui->loopDelaySpinBox->setValue(generalSettings.loop_delay().GetValue() *
|
ui->loopDelaySpinBox->setValue(generalSettings.loop_delay().GetValue() *
|
||||||
|
|
@ -175,7 +175,7 @@ void AnimationDockWidgetImpl::ConnectSignals()
|
||||||
self_,
|
self_,
|
||||||
[this](int i)
|
[this](int i)
|
||||||
{
|
{
|
||||||
manager::SettingsManager::general_settings().loop_time().StageValue(i);
|
settings::GeneralSettings::Instance().loop_time().StageValue(i);
|
||||||
Q_EMIT self_->LoopTimeChanged(std::chrono::minutes(i));
|
Q_EMIT self_->LoopTimeChanged(std::chrono::minutes(i));
|
||||||
});
|
});
|
||||||
QObject::connect(
|
QObject::connect(
|
||||||
|
|
@ -184,8 +184,7 @@ void AnimationDockWidgetImpl::ConnectSignals()
|
||||||
self_,
|
self_,
|
||||||
[this](double d)
|
[this](double d)
|
||||||
{
|
{
|
||||||
manager::SettingsManager::general_settings().loop_speed().StageValue(
|
settings::GeneralSettings::Instance().loop_speed().StageValue(d);
|
||||||
d);
|
|
||||||
Q_EMIT self_->LoopSpeedChanged(d);
|
Q_EMIT self_->LoopSpeedChanged(d);
|
||||||
});
|
});
|
||||||
QObject::connect(
|
QObject::connect(
|
||||||
|
|
@ -194,7 +193,7 @@ void AnimationDockWidgetImpl::ConnectSignals()
|
||||||
self_,
|
self_,
|
||||||
[this](double d)
|
[this](double d)
|
||||||
{
|
{
|
||||||
manager::SettingsManager::general_settings().loop_delay().StageValue(
|
settings::GeneralSettings::Instance().loop_delay().StageValue(
|
||||||
static_cast<std::int64_t>(d * 1000.0));
|
static_cast<std::int64_t>(d * 1000.0));
|
||||||
Q_EMIT self_->LoopDelayChanged(std::chrono::milliseconds(
|
Q_EMIT self_->LoopDelayChanged(std::chrono::milliseconds(
|
||||||
static_cast<typename std::chrono::milliseconds::rep>(d * 1000.0)));
|
static_cast<typename std::chrono::milliseconds::rep>(d * 1000.0)));
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
#include <scwx/qt/ui/imgui_debug_widget.hpp>
|
#include <scwx/qt/ui/imgui_debug_widget.hpp>
|
||||||
|
#include <scwx/qt/manager/font_manager.hpp>
|
||||||
#include <scwx/qt/model/imgui_context_model.hpp>
|
#include <scwx/qt/model/imgui_context_model.hpp>
|
||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
@ -50,6 +51,8 @@ public:
|
||||||
model::ImGuiContextModel::Instance().DestroyContext(contextName_);
|
model::ImGuiContextModel::Instance().DestroyContext(contextName_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ImGuiCheckFonts();
|
||||||
|
|
||||||
ImGuiDebugWidget* self_;
|
ImGuiDebugWidget* self_;
|
||||||
ImGuiContext* context_;
|
ImGuiContext* context_;
|
||||||
std::string contextName_;
|
std::string contextName_;
|
||||||
|
|
@ -58,6 +61,7 @@ public:
|
||||||
|
|
||||||
std::set<ImGuiContext*> renderedSet_ {};
|
std::set<ImGuiContext*> renderedSet_ {};
|
||||||
bool imGuiRendererInitialized_ {false};
|
bool imGuiRendererInitialized_ {false};
|
||||||
|
std::uint64_t imGuiFontsBuildCount_ {};
|
||||||
};
|
};
|
||||||
|
|
||||||
ImGuiDebugWidget::ImGuiDebugWidget(QWidget* parent) :
|
ImGuiDebugWidget::ImGuiDebugWidget(QWidget* parent) :
|
||||||
|
|
@ -102,6 +106,8 @@ void ImGuiDebugWidget::initializeGL()
|
||||||
// Initialize ImGui OpenGL3 backend
|
// Initialize ImGui OpenGL3 backend
|
||||||
ImGui::SetCurrentContext(p->context_);
|
ImGui::SetCurrentContext(p->context_);
|
||||||
ImGui_ImplOpenGL3_Init();
|
ImGui_ImplOpenGL3_Init();
|
||||||
|
p->imGuiFontsBuildCount_ =
|
||||||
|
manager::FontManager::Instance().imgui_fonts_build_count();
|
||||||
p->imGuiRendererInitialized_ = true;
|
p->imGuiRendererInitialized_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -109,9 +115,13 @@ void ImGuiDebugWidget::paintGL()
|
||||||
{
|
{
|
||||||
ImGui::SetCurrentContext(p->currentContext_);
|
ImGui::SetCurrentContext(p->currentContext_);
|
||||||
|
|
||||||
|
// Lock ImGui font atlas prior to new ImGui frame
|
||||||
|
std::shared_lock imguiFontAtlasLock {
|
||||||
|
manager::FontManager::Instance().imgui_font_atlas_mutex()};
|
||||||
|
|
||||||
ImGui_ImplQt_NewFrame(this);
|
ImGui_ImplQt_NewFrame(this);
|
||||||
ImGui_ImplOpenGL3_NewFrame();
|
ImGui_ImplOpenGL3_NewFrame();
|
||||||
|
p->ImGuiCheckFonts();
|
||||||
ImGui::NewFrame();
|
ImGui::NewFrame();
|
||||||
|
|
||||||
if (!p->renderedSet_.contains(p->currentContext_))
|
if (!p->renderedSet_.contains(p->currentContext_))
|
||||||
|
|
@ -131,6 +141,29 @@ void ImGuiDebugWidget::paintGL()
|
||||||
|
|
||||||
ImGui::Render();
|
ImGui::Render();
|
||||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||||
|
|
||||||
|
// Unlock ImGui font atlas after rendering
|
||||||
|
imguiFontAtlasLock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGuiDebugWidgetImpl::ImGuiCheckFonts()
|
||||||
|
{
|
||||||
|
// Update ImGui Fonts if required
|
||||||
|
std::uint64_t currentImGuiFontsBuildCount =
|
||||||
|
manager::FontManager::Instance().imgui_fonts_build_count();
|
||||||
|
|
||||||
|
if ((context_ == currentContext_ &&
|
||||||
|
imGuiFontsBuildCount_ != currentImGuiFontsBuildCount) ||
|
||||||
|
!model::ImGuiContextModel::Instance().font_atlas()->IsBuilt())
|
||||||
|
{
|
||||||
|
ImGui_ImplOpenGL3_DestroyFontsTexture();
|
||||||
|
ImGui_ImplOpenGL3_CreateFontsTexture();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context_ == currentContext_)
|
||||||
|
{
|
||||||
|
imGuiFontsBuildCount_ = currentImGuiFontsBuildCount;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ui
|
} // namespace ui
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,12 @@
|
||||||
#include <scwx/qt/config/radar_site.hpp>
|
#include <scwx/qt/config/radar_site.hpp>
|
||||||
#include <scwx/qt/manager/settings_manager.hpp>
|
#include <scwx/qt/manager/settings_manager.hpp>
|
||||||
#include <scwx/qt/map/map_provider.hpp>
|
#include <scwx/qt/map/map_provider.hpp>
|
||||||
|
#include <scwx/qt/settings/general_settings.hpp>
|
||||||
|
#include <scwx/qt/settings/palette_settings.hpp>
|
||||||
#include <scwx/qt/settings/settings_interface.hpp>
|
#include <scwx/qt/settings/settings_interface.hpp>
|
||||||
#include <scwx/qt/settings/text_settings.hpp>
|
#include <scwx/qt/settings/text_settings.hpp>
|
||||||
#include <scwx/qt/types/alert_types.hpp>
|
#include <scwx/qt/types/alert_types.hpp>
|
||||||
|
#include <scwx/qt/types/font_types.hpp>
|
||||||
#include <scwx/qt/types/text_types.hpp>
|
#include <scwx/qt/types/text_types.hpp>
|
||||||
#include <scwx/qt/ui/placefile_settings_widget.hpp>
|
#include <scwx/qt/ui/placefile_settings_widget.hpp>
|
||||||
#include <scwx/qt/ui/radar_site_dialog.hpp>
|
#include <scwx/qt/ui/radar_site_dialog.hpp>
|
||||||
|
|
@ -21,6 +24,8 @@
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
#include <QColorDialog>
|
#include <QColorDialog>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
|
#include <QFontDialog>
|
||||||
|
#include <QStandardItemModel>
|
||||||
#include <QToolButton>
|
#include <QToolButton>
|
||||||
|
|
||||||
namespace scwx
|
namespace scwx
|
||||||
|
|
@ -84,9 +89,10 @@ public:
|
||||||
explicit SettingsDialogImpl(SettingsDialog* self) :
|
explicit SettingsDialogImpl(SettingsDialog* self) :
|
||||||
self_ {self},
|
self_ {self},
|
||||||
radarSiteDialog_ {new RadarSiteDialog(self)},
|
radarSiteDialog_ {new RadarSiteDialog(self)},
|
||||||
|
fontDialog_ {new QFontDialog(self)},
|
||||||
|
fontCategoryModel_ {new QStandardItemModel(self)},
|
||||||
settings_ {std::initializer_list<settings::SettingsInterfaceBase*> {
|
settings_ {std::initializer_list<settings::SettingsInterfaceBase*> {
|
||||||
&defaultRadarSite_,
|
&defaultRadarSite_,
|
||||||
&fontSizes_,
|
|
||||||
&gridWidth_,
|
&gridWidth_,
|
||||||
&gridHeight_,
|
&gridHeight_,
|
||||||
&mapProvider_,
|
&mapProvider_,
|
||||||
|
|
@ -99,7 +105,7 @@ public:
|
||||||
&tooltipMethod_}}
|
&tooltipMethod_}}
|
||||||
{
|
{
|
||||||
// Configure default alert phenomena colors
|
// Configure default alert phenomena colors
|
||||||
auto& paletteSettings = manager::SettingsManager::palette_settings();
|
auto& paletteSettings = settings::PaletteSettings::Instance();
|
||||||
int index = 0;
|
int index = 0;
|
||||||
|
|
||||||
for (auto& phenomenon : settings::PaletteSettings::alert_phenomena())
|
for (auto& phenomenon : settings::PaletteSettings::alert_phenomena())
|
||||||
|
|
@ -113,6 +119,12 @@ public:
|
||||||
QColor(QString::fromStdString(
|
QColor(QString::fromStdString(
|
||||||
paletteSettings.alert_color(phenomenon, false).GetDefault())));
|
paletteSettings.alert_color(phenomenon, false).GetDefault())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Configure font dialog
|
||||||
|
fontDialog_->setOptions(
|
||||||
|
QFontDialog::FontDialogOption::DontUseNativeDialog |
|
||||||
|
QFontDialog::FontDialogOption::ScalableFonts);
|
||||||
|
fontDialog_->setWindowModality(Qt::WindowModality::WindowModal);
|
||||||
}
|
}
|
||||||
~SettingsDialogImpl() = default;
|
~SettingsDialogImpl() = default;
|
||||||
|
|
||||||
|
|
@ -126,6 +138,10 @@ public:
|
||||||
void ShowColorDialog(QLineEdit* lineEdit, QFrame* frame = nullptr);
|
void ShowColorDialog(QLineEdit* lineEdit, QFrame* frame = nullptr);
|
||||||
void UpdateRadarDialogLocation(const std::string& id);
|
void UpdateRadarDialogLocation(const std::string& id);
|
||||||
|
|
||||||
|
QFont GetSelectedFont();
|
||||||
|
void SelectFontCategory(types::FontCategory fontCategory);
|
||||||
|
void UpdateFontDisplayData();
|
||||||
|
|
||||||
void ApplyChanges();
|
void ApplyChanges();
|
||||||
void DiscardChanges();
|
void DiscardChanges();
|
||||||
void ResetToDefault();
|
void ResetToDefault();
|
||||||
|
|
@ -146,17 +162,21 @@ public:
|
||||||
SettingsDialog* self_;
|
SettingsDialog* self_;
|
||||||
PlacefileSettingsWidget* placefileSettingsWidget_ {nullptr};
|
PlacefileSettingsWidget* placefileSettingsWidget_ {nullptr};
|
||||||
RadarSiteDialog* radarSiteDialog_;
|
RadarSiteDialog* radarSiteDialog_;
|
||||||
|
QFontDialog* fontDialog_;
|
||||||
|
|
||||||
settings::SettingsInterface<std::string> defaultRadarSite_ {};
|
QStandardItemModel* fontCategoryModel_;
|
||||||
settings::SettingsInterface<std::vector<std::int64_t>> fontSizes_ {};
|
|
||||||
settings::SettingsInterface<std::int64_t> gridWidth_ {};
|
types::FontCategory selectedFontCategory_ {types::FontCategory::Unknown};
|
||||||
settings::SettingsInterface<std::int64_t> gridHeight_ {};
|
|
||||||
settings::SettingsInterface<std::string> mapProvider_ {};
|
settings::SettingsInterface<std::string> defaultRadarSite_ {};
|
||||||
settings::SettingsInterface<std::string> mapboxApiKey_ {};
|
settings::SettingsInterface<std::int64_t> gridWidth_ {};
|
||||||
settings::SettingsInterface<std::string> mapTilerApiKey_ {};
|
settings::SettingsInterface<std::int64_t> gridHeight_ {};
|
||||||
settings::SettingsInterface<std::string> defaultAlertAction_ {};
|
settings::SettingsInterface<std::string> mapProvider_ {};
|
||||||
settings::SettingsInterface<bool> updateNotificationsEnabled_ {};
|
settings::SettingsInterface<std::string> mapboxApiKey_ {};
|
||||||
settings::SettingsInterface<bool> debugEnabled_ {};
|
settings::SettingsInterface<std::string> mapTilerApiKey_ {};
|
||||||
|
settings::SettingsInterface<std::string> defaultAlertAction_ {};
|
||||||
|
settings::SettingsInterface<bool> updateNotificationsEnabled_ {};
|
||||||
|
settings::SettingsInterface<bool> debugEnabled_ {};
|
||||||
|
|
||||||
std::unordered_map<std::string, settings::SettingsInterface<std::string>>
|
std::unordered_map<std::string, settings::SettingsInterface<std::string>>
|
||||||
colorTables_ {};
|
colorTables_ {};
|
||||||
|
|
@ -167,6 +187,15 @@ public:
|
||||||
settings::SettingsInterface<std::string>>
|
settings::SettingsInterface<std::string>>
|
||||||
inactiveAlertColors_ {};
|
inactiveAlertColors_ {};
|
||||||
|
|
||||||
|
std::unordered_map<types::FontCategory,
|
||||||
|
settings::SettingsInterface<std::string>>
|
||||||
|
fontFamilies_ {};
|
||||||
|
std::unordered_map<types::FontCategory,
|
||||||
|
settings::SettingsInterface<std::string>>
|
||||||
|
fontStyles_ {};
|
||||||
|
std::unordered_map<types::FontCategory, settings::SettingsInterface<double>>
|
||||||
|
fontPointSizes_ {};
|
||||||
|
|
||||||
settings::SettingsInterface<std::int64_t> hoverTextWrap_ {};
|
settings::SettingsInterface<std::int64_t> hoverTextWrap_ {};
|
||||||
settings::SettingsInterface<std::string> tooltipMethod_ {};
|
settings::SettingsInterface<std::string> tooltipMethod_ {};
|
||||||
|
|
||||||
|
|
@ -239,6 +268,72 @@ void SettingsDialogImpl::ConnectSignals()
|
||||||
[this](const std::string& newValue)
|
[this](const std::string& newValue)
|
||||||
{ UpdateRadarDialogLocation(newValue); });
|
{ UpdateRadarDialogLocation(newValue); });
|
||||||
|
|
||||||
|
QObject::connect(
|
||||||
|
self_->ui->fontListView->selectionModel(),
|
||||||
|
&QItemSelectionModel::selectionChanged,
|
||||||
|
self_,
|
||||||
|
[this](const QItemSelection& selected, const QItemSelection& deselected)
|
||||||
|
{
|
||||||
|
if (selected.size() == 0 && deselected.size() == 0)
|
||||||
|
{
|
||||||
|
// Items which stay selected but change their index are not
|
||||||
|
// included in selected and deselected. Thus, this signal might
|
||||||
|
// be emitted with both selected and deselected empty, if only
|
||||||
|
// the indices of selected items change.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selected.size() > 0)
|
||||||
|
{
|
||||||
|
QModelIndex selectedIndex = selected[0].indexes()[0];
|
||||||
|
QVariant variantData =
|
||||||
|
self_->ui->fontListView->model()->data(selectedIndex);
|
||||||
|
if (variantData.typeId() == QMetaType::QString)
|
||||||
|
{
|
||||||
|
types::FontCategory fontCategory =
|
||||||
|
types::GetFontCategory(variantData.toString().toStdString());
|
||||||
|
SelectFontCategory(fontCategory);
|
||||||
|
UpdateFontDisplayData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
QObject::connect(self_->ui->fontSelectButton,
|
||||||
|
&QAbstractButton::clicked,
|
||||||
|
self_,
|
||||||
|
[this]()
|
||||||
|
{
|
||||||
|
fontDialog_->setCurrentFont(GetSelectedFont());
|
||||||
|
fontDialog_->show();
|
||||||
|
});
|
||||||
|
|
||||||
|
QObject::connect(fontDialog_,
|
||||||
|
&QFontDialog::fontSelected,
|
||||||
|
self_,
|
||||||
|
[this](const QFont& font)
|
||||||
|
{
|
||||||
|
fontFamilies_.at(selectedFontCategory_)
|
||||||
|
.StageValue(font.family().toStdString());
|
||||||
|
fontStyles_.at(selectedFontCategory_)
|
||||||
|
.StageValue(font.styleName().toStdString());
|
||||||
|
fontPointSizes_.at(selectedFontCategory_)
|
||||||
|
.StageValue(font.pointSizeF());
|
||||||
|
|
||||||
|
UpdateFontDisplayData();
|
||||||
|
});
|
||||||
|
|
||||||
|
QObject::connect(self_->ui->resetFontButton,
|
||||||
|
&QAbstractButton::clicked,
|
||||||
|
self_,
|
||||||
|
[this]()
|
||||||
|
{
|
||||||
|
fontFamilies_.at(selectedFontCategory_).StageDefault();
|
||||||
|
fontStyles_.at(selectedFontCategory_).StageDefault();
|
||||||
|
fontPointSizes_.at(selectedFontCategory_).StageDefault();
|
||||||
|
|
||||||
|
UpdateFontDisplayData();
|
||||||
|
});
|
||||||
|
|
||||||
QObject::connect(
|
QObject::connect(
|
||||||
self_->ui->buttonBox,
|
self_->ui->buttonBox,
|
||||||
&QDialogButtonBox::clicked,
|
&QDialogButtonBox::clicked,
|
||||||
|
|
@ -289,7 +384,7 @@ void SettingsDialogImpl::SetupGeneralTab()
|
||||||
}
|
}
|
||||||
|
|
||||||
settings::GeneralSettings& generalSettings =
|
settings::GeneralSettings& generalSettings =
|
||||||
manager::SettingsManager::general_settings();
|
settings::GeneralSettings::Instance();
|
||||||
|
|
||||||
defaultRadarSite_.SetSettingsVariable(generalSettings.default_radar_site());
|
defaultRadarSite_.SetSettingsVariable(generalSettings.default_radar_site());
|
||||||
defaultRadarSite_.SetMapFromValueFunction(
|
defaultRadarSite_.SetMapFromValueFunction(
|
||||||
|
|
@ -327,10 +422,6 @@ void SettingsDialogImpl::SetupGeneralTab()
|
||||||
defaultRadarSite_.SetResetButton(self_->ui->resetRadarSiteButton);
|
defaultRadarSite_.SetResetButton(self_->ui->resetRadarSiteButton);
|
||||||
UpdateRadarDialogLocation(generalSettings.default_radar_site().GetValue());
|
UpdateRadarDialogLocation(generalSettings.default_radar_site().GetValue());
|
||||||
|
|
||||||
fontSizes_.SetSettingsVariable(generalSettings.font_sizes());
|
|
||||||
fontSizes_.SetEditWidget(self_->ui->fontSizesLineEdit);
|
|
||||||
fontSizes_.SetResetButton(self_->ui->resetFontSizesButton);
|
|
||||||
|
|
||||||
gridWidth_.SetSettingsVariable(generalSettings.grid_width());
|
gridWidth_.SetSettingsVariable(generalSettings.grid_width());
|
||||||
gridWidth_.SetEditWidget(self_->ui->gridWidthSpinBox);
|
gridWidth_.SetEditWidget(self_->ui->gridWidthSpinBox);
|
||||||
gridWidth_.SetResetButton(self_->ui->resetGridWidthButton);
|
gridWidth_.SetResetButton(self_->ui->resetGridWidthButton);
|
||||||
|
|
@ -430,7 +521,7 @@ void SettingsDialogImpl::SetupGeneralTab()
|
||||||
void SettingsDialogImpl::SetupPalettesColorTablesTab()
|
void SettingsDialogImpl::SetupPalettesColorTablesTab()
|
||||||
{
|
{
|
||||||
settings::PaletteSettings& paletteSettings =
|
settings::PaletteSettings& paletteSettings =
|
||||||
manager::SettingsManager::palette_settings();
|
settings::PaletteSettings::Instance();
|
||||||
|
|
||||||
// Palettes > Color Tables
|
// Palettes > Color Tables
|
||||||
QGridLayout* colorTableLayout =
|
QGridLayout* colorTableLayout =
|
||||||
|
|
@ -522,7 +613,7 @@ void SettingsDialogImpl::SetupPalettesColorTablesTab()
|
||||||
void SettingsDialogImpl::SetupPalettesAlertsTab()
|
void SettingsDialogImpl::SetupPalettesAlertsTab()
|
||||||
{
|
{
|
||||||
settings::PaletteSettings& paletteSettings =
|
settings::PaletteSettings& paletteSettings =
|
||||||
manager::SettingsManager::palette_settings();
|
settings::PaletteSettings::Instance();
|
||||||
|
|
||||||
// Palettes > Alerts
|
// Palettes > Alerts
|
||||||
QGridLayout* alertsLayout =
|
QGridLayout* alertsLayout =
|
||||||
|
|
@ -645,6 +736,39 @@ void SettingsDialogImpl::SetupTextTab()
|
||||||
{
|
{
|
||||||
settings::TextSettings& textSettings = settings::TextSettings::Instance();
|
settings::TextSettings& textSettings = settings::TextSettings::Instance();
|
||||||
|
|
||||||
|
self_->ui->fontListView->setModel(fontCategoryModel_);
|
||||||
|
for (const auto& fontCategory : types::FontCategoryIterator())
|
||||||
|
{
|
||||||
|
// Add font category to list view
|
||||||
|
fontCategoryModel_->appendRow(new QStandardItem(
|
||||||
|
QString::fromStdString(types::GetFontCategoryName(fontCategory))));
|
||||||
|
|
||||||
|
// Create settings interface
|
||||||
|
auto fontFamilyResult = fontFamilies_.emplace(
|
||||||
|
fontCategory, settings::SettingsInterface<std::string> {});
|
||||||
|
auto fontStyleResult = fontStyles_.emplace(
|
||||||
|
fontCategory, settings::SettingsInterface<std::string> {});
|
||||||
|
auto fontSizeResult = fontPointSizes_.emplace(
|
||||||
|
fontCategory, settings::SettingsInterface<double> {});
|
||||||
|
|
||||||
|
auto& fontFamily = (*fontFamilyResult.first).second;
|
||||||
|
auto& fontStyle = (*fontStyleResult.first).second;
|
||||||
|
auto& fontSize = (*fontSizeResult.first).second;
|
||||||
|
|
||||||
|
// Add to settings list
|
||||||
|
settings_.push_back(&fontFamily);
|
||||||
|
settings_.push_back(&fontStyle);
|
||||||
|
settings_.push_back(&fontSize);
|
||||||
|
|
||||||
|
// Set settings variables
|
||||||
|
fontFamily.SetSettingsVariable(textSettings.font_family(fontCategory));
|
||||||
|
fontStyle.SetSettingsVariable(textSettings.font_style(fontCategory));
|
||||||
|
fontSize.SetSettingsVariable(textSettings.font_point_size(fontCategory));
|
||||||
|
}
|
||||||
|
self_->ui->fontListView->setCurrentIndex(fontCategoryModel_->index(0, 0));
|
||||||
|
SelectFontCategory(*types::FontCategoryIterator().begin());
|
||||||
|
UpdateFontDisplayData();
|
||||||
|
|
||||||
hoverTextWrap_.SetSettingsVariable(textSettings.hover_text_wrap());
|
hoverTextWrap_.SetSettingsVariable(textSettings.hover_text_wrap());
|
||||||
hoverTextWrap_.SetEditWidget(self_->ui->hoverTextWrapSpinBox);
|
hoverTextWrap_.SetEditWidget(self_->ui->hoverTextWrapSpinBox);
|
||||||
hoverTextWrap_.SetResetButton(self_->ui->resetHoverTextWrapButton);
|
hoverTextWrap_.SetResetButton(self_->ui->resetHoverTextWrapButton);
|
||||||
|
|
@ -799,6 +923,53 @@ void SettingsDialogImpl::UpdateRadarDialogLocation(const std::string& id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QFont SettingsDialogImpl::GetSelectedFont()
|
||||||
|
{
|
||||||
|
std::string fontFamily = fontFamilies_.at(selectedFontCategory_)
|
||||||
|
.GetSettingsVariable()
|
||||||
|
->GetStagedOrValue();
|
||||||
|
std::string fontStyle = fontStyles_.at(selectedFontCategory_)
|
||||||
|
.GetSettingsVariable()
|
||||||
|
->GetStagedOrValue();
|
||||||
|
units::font_size::points<double> fontSize {
|
||||||
|
fontPointSizes_.at(selectedFontCategory_)
|
||||||
|
.GetSettingsVariable()
|
||||||
|
->GetStagedOrValue()};
|
||||||
|
|
||||||
|
QFont font(QString::fromStdString(fontFamily));
|
||||||
|
font.setStyleName(QString::fromStdString(fontStyle));
|
||||||
|
font.setPointSizeF(fontSize.value());
|
||||||
|
|
||||||
|
return font;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SettingsDialogImpl::SelectFontCategory(types::FontCategory fontCategory)
|
||||||
|
{
|
||||||
|
selectedFontCategory_ = fontCategory;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SettingsDialogImpl::UpdateFontDisplayData()
|
||||||
|
{
|
||||||
|
QFont font = GetSelectedFont();
|
||||||
|
|
||||||
|
self_->ui->fontNameLabel->setText(font.family());
|
||||||
|
self_->ui->fontStyleLabel->setText(font.styleName());
|
||||||
|
self_->ui->fontSizeLabel->setText(QString::number(font.pointSizeF()));
|
||||||
|
|
||||||
|
self_->ui->fontPreviewLabel->setFont(font);
|
||||||
|
|
||||||
|
if (selectedFontCategory_ != types::FontCategory::Unknown)
|
||||||
|
{
|
||||||
|
auto& fontFamily = fontFamilies_.at(selectedFontCategory_);
|
||||||
|
auto& fontStyle = fontStyles_.at(selectedFontCategory_);
|
||||||
|
auto& fontSize = fontPointSizes_.at(selectedFontCategory_);
|
||||||
|
|
||||||
|
self_->ui->resetFontButton->setVisible(!fontFamily.IsDefault() ||
|
||||||
|
!fontStyle.IsDefault() ||
|
||||||
|
!fontSize.IsDefault());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SettingsDialogImpl::ApplyChanges()
|
void SettingsDialogImpl::ApplyChanges()
|
||||||
{
|
{
|
||||||
logger_->info("Applying settings changes");
|
logger_->info("Applying settings changes");
|
||||||
|
|
@ -812,7 +983,7 @@ void SettingsDialogImpl::ApplyChanges()
|
||||||
|
|
||||||
if (committed)
|
if (committed)
|
||||||
{
|
{
|
||||||
manager::SettingsManager::SaveSettings();
|
manager::SettingsManager::Instance().SaveSettings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -127,27 +127,7 @@
|
||||||
<property name="bottomMargin">
|
<property name="bottomMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item row="5" column="2">
|
<item row="4" column="4">
|
||||||
<widget class="QComboBox" name="mapProviderComboBox"/>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="label_5">
|
|
||||||
<property name="text">
|
|
||||||
<string>Font Sizes</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="2">
|
|
||||||
<widget class="QComboBox" name="radarSiteComboBox"/>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="label">
|
|
||||||
<property name="text">
|
|
||||||
<string>Default Radar Site</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="4">
|
|
||||||
<widget class="QToolButton" name="resetMapProviderButton">
|
<widget class="QToolButton" name="resetMapProviderButton">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>...</string>
|
<string>...</string>
|
||||||
|
|
@ -158,45 +138,14 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="2">
|
<item row="1" column="0">
|
||||||
<widget class="QLineEdit" name="fontSizesLineEdit"/>
|
<widget class="QLabel" name="label_2">
|
||||||
</item>
|
|
||||||
<item row="6" column="0">
|
|
||||||
<widget class="QLabel" name="label_4">
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Mapbox API Key</string>
|
<string>Grid Width</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="0">
|
<item row="2" column="4">
|
||||||
<widget class="QLabel" name="label_6">
|
|
||||||
<property name="text">
|
|
||||||
<string>MapTiler API Key</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="2">
|
|
||||||
<widget class="QSpinBox" name="gridWidthSpinBox"/>
|
|
||||||
</item>
|
|
||||||
<item row="7" column="4">
|
|
||||||
<widget class="QToolButton" name="resetMapTilerApiKeyButton">
|
|
||||||
<property name="text">
|
|
||||||
<string>...</string>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset resource="../../../../scwx-qt.qrc">
|
|
||||||
<normaloff>:/res/icons/font-awesome-6/rotate-left-solid.svg</normaloff>:/res/icons/font-awesome-6/rotate-left-solid.svg</iconset>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="3">
|
|
||||||
<widget class="QToolButton" name="radarSiteSelectButton">
|
|
||||||
<property name="text">
|
|
||||||
<string>...</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="4">
|
|
||||||
<widget class="QToolButton" name="resetGridHeightButton">
|
<widget class="QToolButton" name="resetGridHeightButton">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>...</string>
|
<string>...</string>
|
||||||
|
|
@ -207,16 +156,6 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="2">
|
|
||||||
<widget class="QLineEdit" name="mapTilerApiKeyLineEdit">
|
|
||||||
<property name="echoMode">
|
|
||||||
<enum>QLineEdit::Password</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="2">
|
|
||||||
<widget class="QSpinBox" name="gridHeightSpinBox"/>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="4">
|
<item row="0" column="4">
|
||||||
<widget class="QToolButton" name="resetRadarSiteButton">
|
<widget class="QToolButton" name="resetRadarSiteButton">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
|
@ -228,32 +167,14 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0">
|
<item row="6" column="0">
|
||||||
<widget class="QLabel" name="label_3">
|
<widget class="QLabel" name="label_6">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Grid Height</string>
|
<string>MapTiler API Key</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="4">
|
<item row="5" column="4">
|
||||||
<widget class="QToolButton" name="resetFontSizesButton">
|
|
||||||
<property name="text">
|
|
||||||
<string>...</string>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset resource="../../../../scwx-qt.qrc">
|
|
||||||
<normaloff>:/res/icons/font-awesome-6/rotate-left-solid.svg</normaloff>:/res/icons/font-awesome-6/rotate-left-solid.svg</iconset>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="2">
|
|
||||||
<widget class="QLineEdit" name="mapboxApiKeyLineEdit">
|
|
||||||
<property name="echoMode">
|
|
||||||
<enum>QLineEdit::Password</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="4">
|
|
||||||
<widget class="QToolButton" name="resetMapboxApiKeyButton">
|
<widget class="QToolButton" name="resetMapboxApiKeyButton">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>...</string>
|
<string>...</string>
|
||||||
|
|
@ -264,21 +185,97 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="2" column="2">
|
||||||
|
<widget class="QSpinBox" name="gridHeightSpinBox"/>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="2">
|
||||||
|
<widget class="QSpinBox" name="gridWidthSpinBox"/>
|
||||||
|
</item>
|
||||||
<item row="2" column="0">
|
<item row="2" column="0">
|
||||||
<widget class="QLabel" name="label_2">
|
<widget class="QLabel" name="label_3">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Grid Width</string>
|
<string>Grid Height</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Default Radar Site</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="2">
|
||||||
|
<widget class="QLineEdit" name="mapTilerApiKeyLineEdit">
|
||||||
|
<property name="echoMode">
|
||||||
|
<enum>QLineEdit::Password</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="2">
|
||||||
|
<widget class="QLineEdit" name="mapboxApiKeyLineEdit">
|
||||||
|
<property name="echoMode">
|
||||||
|
<enum>QLineEdit::Password</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="0">
|
||||||
|
<widget class="QLabel" name="defaultAlertActionLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Default Alert Action</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="0">
|
<item row="5" column="0">
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="text">
|
||||||
|
<string>Mapbox API Key</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="4">
|
||||||
|
<widget class="QToolButton" name="resetDefaultAlertActionButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>...</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../../scwx-qt.qrc">
|
||||||
|
<normaloff>:/res/icons/font-awesome-6/rotate-left-solid.svg</normaloff>:/res/icons/font-awesome-6/rotate-left-solid.svg</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="2">
|
||||||
|
<widget class="QComboBox" name="mapProviderComboBox"/>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="3">
|
||||||
|
<widget class="QToolButton" name="radarSiteSelectButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>...</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
<widget class="QLabel" name="label_7">
|
<widget class="QLabel" name="label_7">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Map Provider</string>
|
<string>Map Provider</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="4">
|
<item row="6" column="4">
|
||||||
|
<widget class="QToolButton" name="resetMapTilerApiKeyButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>...</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../../scwx-qt.qrc">
|
||||||
|
<normaloff>:/res/icons/font-awesome-6/rotate-left-solid.svg</normaloff>:/res/icons/font-awesome-6/rotate-left-solid.svg</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="2">
|
||||||
|
<widget class="QComboBox" name="defaultAlertActionComboBox"/>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="4">
|
||||||
<widget class="QToolButton" name="resetGridWidthButton">
|
<widget class="QToolButton" name="resetGridWidthButton">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>...</string>
|
<string>...</string>
|
||||||
|
|
@ -289,26 +286,8 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="8" column="0">
|
<item row="0" column="2">
|
||||||
<widget class="QLabel" name="defaultAlertActionLabel">
|
<widget class="QComboBox" name="radarSiteComboBox"/>
|
||||||
<property name="text">
|
|
||||||
<string>Default Alert Action</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="8" column="2">
|
|
||||||
<widget class="QComboBox" name="defaultAlertActionComboBox"/>
|
|
||||||
</item>
|
|
||||||
<item row="8" column="4">
|
|
||||||
<widget class="QToolButton" name="resetDefaultAlertActionButton">
|
|
||||||
<property name="text">
|
|
||||||
<string>...</string>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset resource="../../../../scwx-qt.qrc">
|
|
||||||
<normaloff>:/res/icons/font-awesome-6/rotate-left-solid.svg</normaloff>:/res/icons/font-awesome-6/rotate-left-solid.svg</iconset>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
|
@ -438,6 +417,194 @@
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="text">
|
<widget class="QWidget" name="text">
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||||
|
<item>
|
||||||
|
<widget class="QFrame" name="frame_4">
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::StyledPanel</enum>
|
||||||
|
</property>
|
||||||
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Plain</enum>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_8" columnstretch="2,3">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QFrame" name="frame_5">
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::StyledPanel</enum>
|
||||||
|
</property>
|
||||||
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Raised</enum>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_9">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item row="0" column="0" colspan="2">
|
||||||
|
<widget class="QLabel" name="label_10">
|
||||||
|
<property name="text">
|
||||||
|
<string>Display Item:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0" colspan="2">
|
||||||
|
<widget class="QListView" name="fontListView"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QFrame" name="frame_6">
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::StyledPanel</enum>
|
||||||
|
</property>
|
||||||
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Raised</enum>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_6">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item row="8" column="0">
|
||||||
|
<spacer name="verticalSpacer_5">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="0" colspan="5">
|
||||||
|
<widget class="QFrame" name="frame_7">
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::Panel</enum>
|
||||||
|
</property>
|
||||||
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Plain</enum>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="fontPreviewLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Tornado Warning expires in 15 minutes</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="3">
|
||||||
|
<widget class="QToolButton" name="fontSelectButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>...</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="2">
|
||||||
|
<widget class="QLabel" name="fontStyleLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>[Style]</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="2">
|
||||||
|
<widget class="QLabel" name="fontNameLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>[Font Name]</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="2">
|
||||||
|
<widget class="QLabel" name="fontSizeLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>[Size]</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label_11">
|
||||||
|
<property name="text">
|
||||||
|
<string>Font:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QLabel" name="label_15">
|
||||||
|
<property name="text">
|
||||||
|
<string>Style:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="0">
|
||||||
|
<widget class="QLabel" name="label_18">
|
||||||
|
<property name="text">
|
||||||
|
<string>Size:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="0" colspan="2">
|
||||||
|
<widget class="QLabel" name="label_13">
|
||||||
|
<property name="text">
|
||||||
|
<string>Preview:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="2">
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="4">
|
||||||
|
<widget class="QToolButton" name="resetFontButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>...</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../../scwx-qt.qrc">
|
||||||
|
<normaloff>:/res/icons/font-awesome-6/rotate-left-solid.svg</normaloff>:/res/icons/font-awesome-6/rotate-left-solid.svg</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QFrame" name="frame_3">
|
<widget class="QFrame" name="frame_3">
|
||||||
<property name="frameShape">
|
<property name="frameShape">
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#include "update_dialog.hpp"
|
#include "update_dialog.hpp"
|
||||||
#include "ui_update_dialog.h"
|
#include "ui_update_dialog.h"
|
||||||
#include <scwx/qt/main/versions.hpp>
|
#include <scwx/qt/main/versions.hpp>
|
||||||
#include <scwx/qt/manager/resource_manager.hpp>
|
#include <scwx/qt/manager/font_manager.hpp>
|
||||||
|
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
#include <QFontDatabase>
|
#include <QFontDatabase>
|
||||||
|
|
@ -30,7 +30,7 @@ UpdateDialog::UpdateDialog(QWidget* parent) :
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
int titleFontId =
|
int titleFontId =
|
||||||
manager::ResourceManager::FontId(types::Font::din1451alt_g);
|
manager::FontManager::Instance().GetFontId(types::Font::din1451alt_g);
|
||||||
QString titleFontFamily =
|
QString titleFontFamily =
|
||||||
QFontDatabase::applicationFontFamilies(titleFontId).at(0);
|
QFontDatabase::applicationFontFamilies(titleFontId).at(0);
|
||||||
QFont titleFont(titleFontFamily, 12);
|
QFont titleFont(titleFontFamily, 12);
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,8 @@
|
||||||
#define _CRT_SECURE_NO_WARNINGS
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
|
|
||||||
#include <scwx/qt/util/font.hpp>
|
#include <scwx/qt/util/font.hpp>
|
||||||
#include <scwx/qt/manager/settings_manager.hpp>
|
|
||||||
#include <scwx/qt/model/imgui_context_model.hpp>
|
#include <scwx/qt/model/imgui_context_model.hpp>
|
||||||
|
#include <scwx/qt/settings/general_settings.hpp>
|
||||||
#include <scwx/util/logger.hpp>
|
#include <scwx/util/logger.hpp>
|
||||||
|
|
||||||
#include <codecvt>
|
#include <codecvt>
|
||||||
|
|
@ -126,9 +126,6 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateImGuiFont(QFile& fontFile,
|
|
||||||
QByteArray& fontData,
|
|
||||||
const std::vector<int64_t>& fontSizes);
|
|
||||||
void ParseNames(FT_Face face);
|
void ParseNames(FT_Face face);
|
||||||
|
|
||||||
const std::string resource_;
|
const std::string resource_;
|
||||||
|
|
@ -266,39 +263,6 @@ GLuint Font::GenerateTexture(gl::OpenGLFunctions& gl)
|
||||||
return p->atlas_->id;
|
return p->atlas_->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FontImpl::CreateImGuiFont(QFile& fontFile,
|
|
||||||
QByteArray& fontData,
|
|
||||||
const std::vector<int64_t>& fontSizes)
|
|
||||||
{
|
|
||||||
QFileInfo fileInfo(fontFile);
|
|
||||||
ImFontAtlas* fontAtlas = model::ImGuiContextModel::Instance().font_atlas();
|
|
||||||
ImFontConfig fontConfig {};
|
|
||||||
|
|
||||||
// Do not transfer ownership of font data to ImGui, makes const_cast safe
|
|
||||||
fontConfig.FontDataOwnedByAtlas = false;
|
|
||||||
|
|
||||||
for (int64_t fontSize : fontSizes)
|
|
||||||
{
|
|
||||||
const float sizePixels = static_cast<float>(fontSize);
|
|
||||||
|
|
||||||
// Assign name to font
|
|
||||||
strncpy(fontConfig.Name,
|
|
||||||
fmt::format("{}:{}", fileInfo.fileName().toStdString(), fontSize)
|
|
||||||
.c_str(),
|
|
||||||
sizeof(fontConfig.Name) - 1);
|
|
||||||
fontConfig.Name[sizeof(fontConfig.Name) - 1] = 0;
|
|
||||||
|
|
||||||
// Add font to atlas
|
|
||||||
imGuiFonts_.emplace(
|
|
||||||
fontSize,
|
|
||||||
fontAtlas->AddFontFromMemoryTTF(
|
|
||||||
const_cast<void*>(static_cast<const void*>(fontData.constData())),
|
|
||||||
fontData.size(),
|
|
||||||
sizePixels,
|
|
||||||
&fontConfig));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImFont* Font::ImGuiFont(std::size_t fontPixelSize)
|
ImFont* Font::ImGuiFont(std::size_t fontPixelSize)
|
||||||
{
|
{
|
||||||
auto it = p->imGuiFonts_.find(fontPixelSize);
|
auto it = p->imGuiFonts_.find(fontPixelSize);
|
||||||
|
|
@ -334,11 +298,6 @@ std::shared_ptr<Font> Font::Create(const std::string& resource)
|
||||||
font = std::make_shared<Font>(resource);
|
font = std::make_shared<Font>(resource);
|
||||||
QByteArray fontData = fontFile.readAll();
|
QByteArray fontData = fontFile.readAll();
|
||||||
|
|
||||||
font->p->CreateImGuiFont(
|
|
||||||
fontFile,
|
|
||||||
fontData,
|
|
||||||
manager::SettingsManager::general_settings().font_sizes().GetValue());
|
|
||||||
|
|
||||||
font->p->atlas_ = ftgl::texture_atlas_new(512, 512, 1);
|
font->p->atlas_ = ftgl::texture_atlas_new(512, 512, 1);
|
||||||
ftgl::texture_font_t* textureFont = ftgl::texture_font_new_from_memory(
|
ftgl::texture_font_t* textureFont = ftgl::texture_font_new_from_memory(
|
||||||
font->p->atlas_, BASE_POINT_SIZE, fontData.constData(), fontData.size());
|
font->p->atlas_, BASE_POINT_SIZE, fontData.constData(), fontData.size());
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,7 @@
|
||||||
#include <scwx/qt/util/imgui.hpp>
|
#include <scwx/qt/util/imgui.hpp>
|
||||||
#include <scwx/qt/manager/resource_manager.hpp>
|
#include <scwx/qt/manager/font_manager.hpp>
|
||||||
#include <scwx/qt/manager/settings_manager.hpp>
|
|
||||||
#include <scwx/util/logger.hpp>
|
#include <scwx/util/logger.hpp>
|
||||||
|
|
||||||
#include <mutex>
|
|
||||||
|
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
|
|
||||||
namespace scwx
|
namespace scwx
|
||||||
|
|
@ -22,13 +19,6 @@ class ImGui::Impl
|
||||||
public:
|
public:
|
||||||
explicit Impl() {}
|
explicit Impl() {}
|
||||||
~Impl() {}
|
~Impl() {}
|
||||||
|
|
||||||
void Initialize();
|
|
||||||
void UpdateMonospaceFont();
|
|
||||||
|
|
||||||
bool initialized_ {false};
|
|
||||||
|
|
||||||
ImFont* monospaceFont_ {nullptr};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ImGui::ImGui() : p(std::make_unique<Impl>()) {}
|
ImGui::ImGui() : p(std::make_unique<Impl>()) {}
|
||||||
|
|
@ -37,58 +27,13 @@ ImGui::~ImGui() = default;
|
||||||
ImGui::ImGui(ImGui&&) noexcept = default;
|
ImGui::ImGui(ImGui&&) noexcept = default;
|
||||||
ImGui& ImGui::operator=(ImGui&&) noexcept = default;
|
ImGui& ImGui::operator=(ImGui&&) noexcept = default;
|
||||||
|
|
||||||
void ImGui::Impl::Initialize()
|
|
||||||
{
|
|
||||||
if (initialized_)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
logger_->debug("Initialize");
|
|
||||||
|
|
||||||
// Configure monospace font
|
|
||||||
UpdateMonospaceFont();
|
|
||||||
manager::SettingsManager::general_settings()
|
|
||||||
.font_sizes()
|
|
||||||
.RegisterValueChangedCallback([this](const std::vector<std::int64_t>&)
|
|
||||||
{ UpdateMonospaceFont(); });
|
|
||||||
|
|
||||||
initialized_ = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGui::Impl::UpdateMonospaceFont()
|
|
||||||
{
|
|
||||||
// Get monospace font size
|
|
||||||
std::size_t fontSize = 16;
|
|
||||||
auto fontSizes =
|
|
||||||
manager::SettingsManager::general_settings().font_sizes().GetValue();
|
|
||||||
if (fontSizes.size() > 1)
|
|
||||||
{
|
|
||||||
fontSize = fontSizes[1];
|
|
||||||
}
|
|
||||||
else if (fontSizes.size() > 0)
|
|
||||||
{
|
|
||||||
fontSize = fontSizes[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get monospace font pointer
|
|
||||||
auto monospace =
|
|
||||||
manager::ResourceManager::Font(types::Font::Inconsolata_Regular);
|
|
||||||
auto monospaceFont = monospace->ImGuiFont(fontSize);
|
|
||||||
|
|
||||||
// Store monospace font pointer if not null
|
|
||||||
if (monospaceFont != nullptr)
|
|
||||||
{
|
|
||||||
monospaceFont_ = monospace->ImGuiFont(fontSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGui::DrawTooltip(const std::string& hoverText)
|
void ImGui::DrawTooltip(const std::string& hoverText)
|
||||||
{
|
{
|
||||||
p->Initialize();
|
auto tooltipFont = manager::FontManager::Instance().GetImGuiFont(
|
||||||
|
types::FontCategory::Tooltip);
|
||||||
|
|
||||||
::ImGui::BeginTooltip();
|
::ImGui::BeginTooltip();
|
||||||
::ImGui::PushFont(p->monospaceFont_);
|
::ImGui::PushFont(tooltipFont->font());
|
||||||
::ImGui::TextUnformatted(hoverText.c_str());
|
::ImGui::TextUnformatted(hoverText.c_str());
|
||||||
::ImGui::PopFont();
|
::ImGui::PopFont();
|
||||||
::ImGui::EndTooltip();
|
::ImGui::EndTooltip();
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
#include <scwx/qt/util/tooltip.hpp>
|
#include <scwx/qt/util/tooltip.hpp>
|
||||||
#include <scwx/qt/manager/settings_manager.hpp>
|
#include <scwx/qt/manager/font_manager.hpp>
|
||||||
#include <scwx/qt/settings/text_settings.hpp>
|
#include <scwx/qt/settings/text_settings.hpp>
|
||||||
#include <scwx/qt/types/font_types.hpp>
|
|
||||||
#include <scwx/qt/types/text_types.hpp>
|
|
||||||
#include <scwx/qt/util/imgui.hpp>
|
#include <scwx/qt/util/imgui.hpp>
|
||||||
#include <scwx/util/logger.hpp>
|
#include <scwx/util/logger.hpp>
|
||||||
|
|
||||||
|
|
@ -84,12 +82,22 @@ void Show(const std::string& text, const QPointF& mouseGlobalPos)
|
||||||
}
|
}
|
||||||
else if (tooltipMethod == types::TooltipMethod::QToolTip)
|
else if (tooltipMethod == types::TooltipMethod::QToolTip)
|
||||||
{
|
{
|
||||||
|
QString fontFamily = QString::fromStdString(
|
||||||
|
textSettings.font_family(types::FontCategory::Tooltip).GetValue());
|
||||||
|
QString fontStyle = QString::fromStdString(
|
||||||
|
textSettings.font_style(types::FontCategory::Tooltip).GetValue());
|
||||||
|
double fontPointSize =
|
||||||
|
textSettings.font_point_size(types::FontCategory::Tooltip).GetValue();
|
||||||
|
|
||||||
static std::size_t id = 0;
|
static std::size_t id = 0;
|
||||||
QToolTip::showText(
|
QToolTip::showText(
|
||||||
mouseGlobalPos.toPoint(),
|
mouseGlobalPos.toPoint(),
|
||||||
QString("<span id='%1' style='font-family:\"%2\"'>%3</span>")
|
QString("<span id='%1' style='font-family:\"%2\"; font-style:\"%3\"; "
|
||||||
|
"font-size:\"%4pt\";'>%5</span>")
|
||||||
.arg(++id)
|
.arg(++id)
|
||||||
.arg("Inconsolata")
|
.arg(fontFamily)
|
||||||
|
.arg(fontStyle)
|
||||||
|
.arg(fontPointSize)
|
||||||
.arg(QString::fromStdString(displayText).replace("\n", "<br/>")),
|
.arg(QString::fromStdString(displayText).replace("\n", "<br/>")),
|
||||||
tooltipParent_.get(),
|
tooltipParent_.get(),
|
||||||
{},
|
{},
|
||||||
|
|
@ -97,22 +105,9 @@ void Show(const std::string& text, const QPointF& mouseGlobalPos)
|
||||||
}
|
}
|
||||||
else if (tooltipMethod == types::TooltipMethod::QLabel)
|
else if (tooltipMethod == types::TooltipMethod::QLabel)
|
||||||
{
|
{
|
||||||
// Get monospace font size
|
|
||||||
units::font_size::pixels<double> fontSize {16};
|
|
||||||
auto fontSizes =
|
|
||||||
manager::SettingsManager::general_settings().font_sizes().GetValue();
|
|
||||||
if (fontSizes.size() > 1)
|
|
||||||
{
|
|
||||||
fontSize = units::font_size::pixels<double> {fontSizes[1]};
|
|
||||||
}
|
|
||||||
else if (fontSizes.size() > 0)
|
|
||||||
{
|
|
||||||
fontSize = units::font_size::pixels<double> {fontSizes[0]};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configure the label
|
// Configure the label
|
||||||
QFont font("Inconsolata");
|
QFont font = manager::FontManager::Instance().GetQFont(
|
||||||
font.setPointSizeF(units::font_size::points<double>(fontSize).value());
|
types::FontCategory::Tooltip);
|
||||||
tooltipLabel_->setFont(font);
|
tooltipLabel_->setFont(font);
|
||||||
tooltipLabel_->setText(QString::fromStdString(displayText));
|
tooltipLabel_->setText(QString::fromStdString(displayText));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 33caca188b1007c643db75afa560fdfe348c0ee5
|
Subproject commit 1685e4048ef4a9f34bc11ecbb8db4905dd0a2e19
|
||||||
|
|
@ -1,5 +1,10 @@
|
||||||
#include <scwx/qt/manager/settings_manager.hpp>
|
#include <scwx/qt/manager/settings_manager.hpp>
|
||||||
#include <scwx/qt/config/radar_site.hpp>
|
#include <scwx/qt/config/radar_site.hpp>
|
||||||
|
#include <scwx/qt/settings/general_settings.hpp>
|
||||||
|
#include <scwx/qt/settings/map_settings.hpp>
|
||||||
|
#include <scwx/qt/settings/palette_settings.hpp>
|
||||||
|
#include <scwx/qt/settings/text_settings.hpp>
|
||||||
|
#include <scwx/qt/settings/ui_settings.hpp>
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
@ -39,10 +44,14 @@ void VerifyDefaults()
|
||||||
settings::GeneralSettings defaultGeneralSettings {};
|
settings::GeneralSettings defaultGeneralSettings {};
|
||||||
settings::MapSettings defaultMapSettings {};
|
settings::MapSettings defaultMapSettings {};
|
||||||
settings::PaletteSettings defaultPaletteSettings {};
|
settings::PaletteSettings defaultPaletteSettings {};
|
||||||
|
settings::TextSettings defaultTextSettings {};
|
||||||
|
settings::UiSettings defaultUiSettings {};
|
||||||
|
|
||||||
EXPECT_EQ(defaultGeneralSettings, SettingsManager::general_settings());
|
EXPECT_EQ(defaultGeneralSettings, settings::GeneralSettings::Instance());
|
||||||
EXPECT_EQ(defaultMapSettings, SettingsManager::map_settings());
|
EXPECT_EQ(defaultMapSettings, settings::MapSettings::Instance());
|
||||||
EXPECT_EQ(defaultPaletteSettings, SettingsManager::palette_settings());
|
EXPECT_EQ(defaultPaletteSettings, settings::PaletteSettings::Instance());
|
||||||
|
EXPECT_EQ(defaultTextSettings, settings::TextSettings::Instance());
|
||||||
|
EXPECT_EQ(defaultUiSettings, settings::UiSettings::Instance());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompareFiles(const std::string& file1, const std::string& file2)
|
void CompareFiles(const std::string& file1, const std::string& file2)
|
||||||
|
|
@ -67,7 +76,7 @@ TEST_F(SettingsManagerTest, CreateJson)
|
||||||
// Verify file doesn't exist prior to test start
|
// Verify file doesn't exist prior to test start
|
||||||
EXPECT_EQ(std::filesystem::exists(filename), false);
|
EXPECT_EQ(std::filesystem::exists(filename), false);
|
||||||
|
|
||||||
SettingsManager::ReadSettings(filename);
|
SettingsManager::Instance().ReadSettings(filename);
|
||||||
|
|
||||||
EXPECT_EQ(std::filesystem::exists(filename), true);
|
EXPECT_EQ(std::filesystem::exists(filename), true);
|
||||||
|
|
||||||
|
|
@ -83,14 +92,14 @@ TEST_F(SettingsManagerTest, SettingsKeax)
|
||||||
std::string filename(std::string(SCWX_TEST_DATA_DIR) +
|
std::string filename(std::string(SCWX_TEST_DATA_DIR) +
|
||||||
"/json/settings/settings-keax.json");
|
"/json/settings/settings-keax.json");
|
||||||
|
|
||||||
SettingsManager::ReadSettings(filename);
|
SettingsManager::Instance().ReadSettings(filename);
|
||||||
|
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
SettingsManager::general_settings().default_radar_site().GetValue(),
|
settings::GeneralSettings::Instance().default_radar_site().GetValue(),
|
||||||
"KEAX");
|
"KEAX");
|
||||||
for (size_t i = 0; i < SettingsManager::map_settings().count(); ++i)
|
for (size_t i = 0; i < settings::MapSettings::Instance().count(); ++i)
|
||||||
{
|
{
|
||||||
EXPECT_EQ(SettingsManager::map_settings().radar_site(i).GetValue(),
|
EXPECT_EQ(settings::MapSettings::Instance().radar_site(i).GetValue(),
|
||||||
"KEAX");
|
"KEAX");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -103,7 +112,7 @@ TEST_P(DefaultSettingsTest, DefaultSettings)
|
||||||
|
|
||||||
std::filesystem::copy_file(sourceFile, filename);
|
std::filesystem::copy_file(sourceFile, filename);
|
||||||
|
|
||||||
SettingsManager::ReadSettings(filename);
|
SettingsManager::Instance().ReadSettings(filename);
|
||||||
|
|
||||||
VerifyDefaults();
|
VerifyDefaults();
|
||||||
CompareFiles(filename, DEFAULT_SETTINGS_FILE);
|
CompareFiles(filename, DEFAULT_SETTINGS_FILE);
|
||||||
|
|
@ -131,7 +140,7 @@ TEST_P(BadSettingsTest, BadSettings)
|
||||||
|
|
||||||
std::filesystem::copy_file(sourceFile, filename);
|
std::filesystem::copy_file(sourceFile, filename);
|
||||||
|
|
||||||
SettingsManager::ReadSettings(filename);
|
SettingsManager::Instance().ReadSettings(filename);
|
||||||
|
|
||||||
CompareFiles(filename, goodFile);
|
CompareFiles(filename, goodFile);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,9 @@ public:
|
||||||
std::size_t pixels_ {};
|
std::size_t pixels_ {};
|
||||||
std::int32_t flags_ {};
|
std::int32_t flags_ {};
|
||||||
std::string face_ {};
|
std::string face_ {};
|
||||||
|
|
||||||
|
bool IsBold() { return flags_ & 1; }
|
||||||
|
bool IsItalic() { return flags_ & 2; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DrawItem
|
struct DrawItem
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue