mirror of
https://github.com/ciphervance/supercell-wx.git
synced 2025-11-01 00:10:04 +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 |
|
||||
| [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) |
|
||||
| [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 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) |
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ class SupercellWxConan(ConanFile):
|
|||
settings = ("os", "compiler", "build_type", "arch")
|
||||
requires = ("boost/1.81.0",
|
||||
"cpr/1.9.3",
|
||||
"fontconfig/2.14.2",
|
||||
"freetype/2.12.1",
|
||||
"geographiclib/1.52",
|
||||
"glew/2.2.0",
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ set(CMAKE_CXX_STANDARD 20)
|
|||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(Boost)
|
||||
find_package(Fontconfig)
|
||||
find_package(Freetype)
|
||||
find_package(geographiclib)
|
||||
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_triangles.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_notifier.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/timeline_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_notifier.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
|
||||
source/scwx/qt/types/font_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/qt_types.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)
|
||||
set(SRC_TYPES source/scwx/qt/types/alert_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/radar_product_record.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
|
||||
qmaplibregl
|
||||
$<$<CXX_COMPILER_ID:MSVC>:opengl32>
|
||||
Fontconfig::Fontconfig
|
||||
freetype-gl
|
||||
GeographicLib::GeographicLib
|
||||
glm::glm
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
#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/tooltip.hpp>
|
||||
#include <scwx/util/logger.hpp>
|
||||
|
|
@ -37,6 +39,7 @@ public:
|
|||
const std::string& text,
|
||||
const std::string& hoverText,
|
||||
boost::gil::rgba8_pixel_t color,
|
||||
std::size_t fontNumber,
|
||||
float x,
|
||||
float y);
|
||||
|
||||
|
|
@ -62,6 +65,9 @@ public:
|
|||
std::mutex listMutex_ {};
|
||||
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<types::ImGuiFont>> fonts_ {};
|
||||
std::vector<std::shared_ptr<types::ImGuiFont>> newFonts_ {};
|
||||
};
|
||||
|
||||
PlacefileText::PlacefileText(const std::shared_ptr<GlContext>& context,
|
||||
|
|
@ -155,6 +161,7 @@ void PlacefileText::Impl::RenderTextDrawItem(
|
|||
di->text_,
|
||||
di->hoverText_,
|
||||
di->color_,
|
||||
std::clamp<std::size_t>(di->fontNumber_, 1, 8),
|
||||
rotatedX + di->x_ + halfWidth_,
|
||||
rotatedY + di->y_ + halfHeight_);
|
||||
}
|
||||
|
|
@ -165,6 +172,7 @@ void PlacefileText::Impl::RenderText(
|
|||
const std::string& text,
|
||||
const std::string& hoverText,
|
||||
boost::gil::rgba8_pixel_t color,
|
||||
std::size_t fontNumber,
|
||||
float x,
|
||||
float y)
|
||||
{
|
||||
|
|
@ -184,10 +192,12 @@ void PlacefileText::Impl::RenderText(
|
|||
ImGuiWindowFlags_NoBackground);
|
||||
|
||||
// Render text
|
||||
ImGui::PushFont(fonts_[fontNumber - 1]->font());
|
||||
ImGui::PushStyleColor(ImGuiCol_Text,
|
||||
IM_COL32(color[0], color[1], color[2], color[3]));
|
||||
ImGui::TextUnformatted(text.c_str());
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::PopFont();
|
||||
|
||||
// Store hover text for mouse picking pass
|
||||
if (!hoverText.empty() && ImGui::IsItemHovered())
|
||||
|
|
@ -231,6 +241,28 @@ void PlacefileText::StartText()
|
|||
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(
|
||||
const std::shared_ptr<gr::Placefile::TextDrawItem>& di)
|
||||
{
|
||||
|
|
@ -246,9 +278,11 @@ void PlacefileText::FinishText()
|
|||
|
||||
// Swap text lists
|
||||
p->textList_.swap(p->newList_);
|
||||
p->fonts_.swap(p->newFonts_);
|
||||
|
||||
// Clear the new list
|
||||
p->newList_.clear();
|
||||
p->newFonts_.clear();
|
||||
}
|
||||
|
||||
} // namespace draw
|
||||
|
|
|
|||
|
|
@ -2,8 +2,11 @@
|
|||
|
||||
#include <scwx/qt/gl/gl_context.hpp>
|
||||
#include <scwx/qt/gl/draw/draw_item.hpp>
|
||||
#include <scwx/qt/types/imgui_font.hpp>
|
||||
#include <scwx/gr/placefile.hpp>
|
||||
|
||||
#include <boost/unordered/unordered_flat_map.hpp>
|
||||
|
||||
namespace scwx
|
||||
{
|
||||
namespace qt
|
||||
|
|
@ -44,6 +47,16 @@ public:
|
|||
*/
|
||||
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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ int main(int argc, char* argv[])
|
|||
|
||||
// Initialize application
|
||||
scwx::qt::config::RadarSite::Initialize();
|
||||
scwx::qt::manager::SettingsManager::Initialize();
|
||||
scwx::qt::manager::SettingsManager::Instance().Initialize();
|
||||
scwx::qt::manager::ResourceManager::Initialize();
|
||||
|
||||
// Run Qt main loop
|
||||
|
|
@ -89,7 +89,7 @@ int main(int argc, char* argv[])
|
|||
|
||||
// Shutdown application
|
||||
scwx::qt::manager::ResourceManager::Shutdown();
|
||||
scwx::qt::manager::SettingsManager::Shutdown();
|
||||
scwx::qt::manager::SettingsManager::Instance().Shutdown();
|
||||
|
||||
// Shutdown AWS SDK
|
||||
Aws::ShutdownAPI(awsSdkOptions);
|
||||
|
|
|
|||
|
|
@ -7,13 +7,14 @@
|
|||
#include <scwx/qt/main/versions.hpp>
|
||||
#include <scwx/qt/manager/placefile_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/timeline_manager.hpp>
|
||||
#include <scwx/qt/manager/update_manager.hpp>
|
||||
#include <scwx/qt/map/map_provider.hpp>
|
||||
#include <scwx/qt/map/map_widget.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/ui/about_dialog.hpp>
|
||||
#include <scwx/qt/ui/alert_dock_widget.hpp>
|
||||
|
|
@ -89,10 +90,8 @@ public:
|
|||
elevationButtonsChanged_ {false},
|
||||
resizeElevationButtons_ {false}
|
||||
{
|
||||
mapProvider_ =
|
||||
map::GetMapProvider(manager::SettingsManager::general_settings()
|
||||
.map_provider()
|
||||
.GetValue());
|
||||
mapProvider_ = map::GetMapProvider(
|
||||
settings::GeneralSettings::Instance().map_provider().GetValue());
|
||||
const map::MapProviderInfo& mapProviderInfo =
|
||||
map::GetMapProviderInfo(mapProvider_);
|
||||
|
||||
|
|
@ -230,7 +229,7 @@ MainWindow::MainWindow(QWidget* parent) :
|
|||
ui->actionAlerts->setVisible(false);
|
||||
|
||||
ui->menuDebug->menuAction()->setVisible(
|
||||
manager::SettingsManager::general_settings().debug_enabled().GetValue());
|
||||
settings::GeneralSettings::Instance().debug_enabled().GetValue());
|
||||
|
||||
// Configure Resource Explorer Dock
|
||||
ui->resourceExplorerDock->setVisible(false);
|
||||
|
|
@ -306,7 +305,7 @@ MainWindow::MainWindow(QWidget* parent) :
|
|||
// Update Dialog
|
||||
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++)
|
||||
{
|
||||
p->SelectRadarProduct(p->maps_.at(i),
|
||||
|
|
@ -582,7 +581,7 @@ void MainWindow::on_resourceTreeView_doubleClicked(const QModelIndex& index)
|
|||
|
||||
void MainWindowImpl::AsyncSetup()
|
||||
{
|
||||
auto& generalSettings = manager::SettingsManager::general_settings();
|
||||
auto& generalSettings = settings::GeneralSettings::Instance();
|
||||
|
||||
// Check for updates
|
||||
if (generalSettings.update_notifications_enabled().GetValue())
|
||||
|
|
@ -595,7 +594,7 @@ void MainWindowImpl::AsyncSetup()
|
|||
|
||||
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 gridHeight = generalSettings.grid_height().GetValue();
|
||||
|
|
@ -646,7 +645,7 @@ void MainWindowImpl::ConfigureMapLayout()
|
|||
void MainWindowImpl::ConfigureMapStyles()
|
||||
{
|
||||
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++)
|
||||
{
|
||||
|
|
@ -897,8 +896,7 @@ void MainWindowImpl::ConnectOtherSignals()
|
|||
{
|
||||
if (maps_[i] == activeMap_)
|
||||
{
|
||||
auto& mapSettings =
|
||||
manager::SettingsManager::map_settings();
|
||||
auto& mapSettings = settings::MapSettings::Instance();
|
||||
mapSettings.map_style(i).StageValue(text.toStdString());
|
||||
break;
|
||||
}
|
||||
|
|
@ -1075,7 +1073,7 @@ void MainWindowImpl::UpdateMapStyle(const std::string& styleName)
|
|||
{
|
||||
if (maps_[i] == activeMap_)
|
||||
{
|
||||
auto& mapSettings = manager::SettingsManager::map_settings();
|
||||
auto& mapSettings = settings::MapSettings::Instance();
|
||||
mapSettings.map_style(i).StageValue(styleName);
|
||||
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/font_manager.hpp>
|
||||
#include <scwx/qt/manager/resource_manager.hpp>
|
||||
#include <scwx/qt/main/application.hpp>
|
||||
#include <scwx/qt/util/json.hpp>
|
||||
|
|
@ -51,8 +52,11 @@ public:
|
|||
void ReadPlacefileSettings();
|
||||
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>>
|
||||
LoadResources(const std::shared_ptr<gr::Placefile>& placefile);
|
||||
LoadImageResources(const std::shared_ptr<gr::Placefile>& placefile);
|
||||
|
||||
boost::asio::thread_pool threadPool_ {1u};
|
||||
|
||||
|
|
@ -63,7 +67,7 @@ public:
|
|||
std::shared_ptr<config::RadarSite> radarSite_ {};
|
||||
|
||||
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_ {};
|
||||
std::shared_mutex placefileRecordLock_ {};
|
||||
};
|
||||
|
|
@ -134,6 +138,10 @@ public:
|
|||
std::mutex refreshMutex_ {};
|
||||
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::string lastRadarSite_ {};
|
||||
|
|
@ -208,6 +216,20 @@ PlacefileManager::placefile(const std::string& name)
|
|||
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,
|
||||
bool enabled)
|
||||
{
|
||||
|
|
@ -278,6 +300,7 @@ void PlacefileManager::set_placefile_url(const std::string& name,
|
|||
auto placefileRecord = it->second;
|
||||
placefileRecord->name_ = normalizedUrl;
|
||||
placefileRecord->placefile_ = nullptr;
|
||||
placefileRecord->fonts_.clear();
|
||||
placefileRecord->images_.clear();
|
||||
p->placefileRecordMap_.erase(it);
|
||||
p->placefileRecordMap_.insert_or_assign(normalizedUrl, placefileRecord);
|
||||
|
|
@ -587,7 +610,8 @@ void PlacefileManager::Impl::PlacefileRecord::Update()
|
|||
if (updatedPlacefile != nullptr)
|
||||
{
|
||||
// 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
|
||||
if (name_ == name)
|
||||
|
|
@ -597,6 +621,13 @@ void PlacefileManager::Impl::PlacefileRecord::Update()
|
|||
title_ = placefile_->title();
|
||||
lastUpdateTime_ = std::chrono::system_clock::now();
|
||||
|
||||
// Update font resources
|
||||
{
|
||||
std::unique_lock fontsLock {fontsMutex_};
|
||||
fonts_.swap(newFonts);
|
||||
newFonts.clear();
|
||||
}
|
||||
|
||||
// Update image resources
|
||||
images_.swap(newImages);
|
||||
newImages.clear();
|
||||
|
|
@ -684,8 +715,38 @@ std::shared_ptr<PlacefileManager> PlacefileManager::Instance()
|
|||
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>>
|
||||
PlacefileManager::Impl::LoadResources(
|
||||
PlacefileManager::Impl::LoadImageResources(
|
||||
const std::shared_ptr<gr::Placefile>& placefile)
|
||||
{
|
||||
const auto iconFiles = placefile->icon_files();
|
||||
|
|
|
|||
|
|
@ -2,8 +2,10 @@
|
|||
|
||||
#include <scwx/gr/placefile.hpp>
|
||||
#include <scwx/qt/config/radar_site.hpp>
|
||||
#include <scwx/qt/types/imgui_font.hpp>
|
||||
|
||||
#include <QObject>
|
||||
#include <boost/unordered/unordered_flat_map.hpp>
|
||||
|
||||
namespace scwx
|
||||
{
|
||||
|
|
@ -24,6 +26,8 @@ public:
|
|||
bool placefile_thresholded(const std::string& name);
|
||||
std::string placefile_title(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_thresholded(const std::string& name, bool thresholded);
|
||||
|
|
|
|||
|
|
@ -1,14 +1,13 @@
|
|||
#include <scwx/qt/manager/resource_manager.hpp>
|
||||
#include <scwx/qt/manager/font_manager.hpp>
|
||||
#include <scwx/qt/config/county_database.hpp>
|
||||
#include <scwx/qt/model/imgui_context_model.hpp>
|
||||
#include <scwx/qt/util/font.hpp>
|
||||
#include <scwx/qt/util/texture_atlas.hpp>
|
||||
#include <scwx/util/logger.hpp>
|
||||
|
||||
#include <execution>
|
||||
#include <mutex>
|
||||
|
||||
#include <QFontDatabase>
|
||||
#include <imgui.h>
|
||||
|
||||
namespace scwx
|
||||
|
|
@ -26,14 +25,11 @@ static const auto logger_ = scwx::util::Logger::Create(logPrefix_);
|
|||
static void LoadFonts();
|
||||
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_g, ":/res/fonts/din1451alt_g.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()
|
||||
{
|
||||
config::CountyDatabase::Initialize();
|
||||
|
|
@ -44,26 +40,6 @@ void Initialize()
|
|||
|
||||
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>
|
||||
LoadImageResource(const std::string& urlString)
|
||||
{
|
||||
|
|
@ -102,18 +78,14 @@ LoadImageResources(const std::vector<std::string>& urlStrings)
|
|||
|
||||
static void LoadFonts()
|
||||
{
|
||||
auto& fontManager = FontManager::Instance();
|
||||
|
||||
for (auto& fontName : fontNames_)
|
||||
{
|
||||
int fontId = QFontDatabase::addApplicationFont(
|
||||
QString::fromStdString(fontName.second));
|
||||
fontIds_.emplace(fontName.first, fontId);
|
||||
|
||||
auto font = util::Font::Create(fontName.second);
|
||||
fonts_.emplace(fontName.first, font);
|
||||
fontManager.LoadApplicationFont(fontName.first, fontName.second);
|
||||
}
|
||||
|
||||
ImFontAtlas* fontAtlas = model::ImGuiContextModel::Instance().font_atlas();
|
||||
fontAtlas->AddFontDefault();
|
||||
fontManager.InitializeFonts();
|
||||
}
|
||||
|
||||
static void LoadTextures()
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <scwx/qt/types/font_types.hpp>
|
||||
#include <scwx/qt/util/font.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
|
@ -19,9 +18,6 @@ namespace ResourceManager
|
|||
void Initialize();
|
||||
void Shutdown();
|
||||
|
||||
int FontId(types::Font font);
|
||||
std::shared_ptr<util::Font> Font(types::Font font);
|
||||
|
||||
std::shared_ptr<boost::gil::rgba8_image_t>
|
||||
LoadImageResource(const std::string& urlString);
|
||||
std::vector<std::shared_ptr<boost::gil::rgba8_image_t>>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
#include <scwx/qt/manager/settings_manager.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/ui_settings.hpp>
|
||||
#include <scwx/qt/util/json.hpp>
|
||||
|
|
@ -18,21 +21,33 @@ namespace qt
|
|||
{
|
||||
namespace manager
|
||||
{
|
||||
namespace SettingsManager
|
||||
{
|
||||
|
||||
static const std::string logPrefix_ = "scwx::qt::manager::settings_manager";
|
||||
static const auto logger_ = scwx::util::Logger::Create(logPrefix_);
|
||||
|
||||
class SettingsManager::Impl
|
||||
{
|
||||
public:
|
||||
explicit Impl(SettingsManager* self) : self_ {self} {}
|
||||
~Impl() = default;
|
||||
|
||||
void ValidateSettings();
|
||||
|
||||
static boost::json::value ConvertSettingsToJson();
|
||||
static void GenerateDefaultSettings();
|
||||
static bool LoadSettings(const boost::json::object& settingsJson);
|
||||
static void ValidateSettings();
|
||||
|
||||
static bool initialized_ {false};
|
||||
static std::string settingsPath_ {};
|
||||
SettingsManager* self_;
|
||||
|
||||
void Initialize()
|
||||
bool initialized_ {false};
|
||||
std::string settingsPath_ {};
|
||||
};
|
||||
|
||||
SettingsManager::SettingsManager() : p(std::make_unique<Impl>(this)) {}
|
||||
|
||||
SettingsManager::~SettingsManager() {};
|
||||
|
||||
void SettingsManager::Initialize()
|
||||
{
|
||||
std::string appDataPath {
|
||||
QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)
|
||||
|
|
@ -47,14 +62,14 @@ void Initialize()
|
|||
}
|
||||
}
|
||||
|
||||
settingsPath_ = appDataPath + "/settings.json";
|
||||
initialized_ = true;
|
||||
p->settingsPath_ = appDataPath + "/settings.json";
|
||||
p->initialized_ = true;
|
||||
|
||||
ReadSettings(settingsPath_);
|
||||
ValidateSettings();
|
||||
ReadSettings(p->settingsPath_);
|
||||
p->ValidateSettings();
|
||||
}
|
||||
|
||||
void ReadSettings(const std::string& settingsPath)
|
||||
void SettingsManager::ReadSettings(const std::string& settingsPath)
|
||||
{
|
||||
boost::json::value settingsJson = nullptr;
|
||||
|
||||
|
|
@ -65,39 +80,41 @@ void ReadSettings(const std::string& settingsPath)
|
|||
|
||||
if (settingsJson == nullptr || !settingsJson.is_object())
|
||||
{
|
||||
GenerateDefaultSettings();
|
||||
settingsJson = ConvertSettingsToJson();
|
||||
Impl::GenerateDefaultSettings();
|
||||
settingsJson = Impl::ConvertSettingsToJson();
|
||||
util::json::WriteJsonFile(settingsPath, settingsJson);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool jsonDirty = LoadSettings(settingsJson.as_object());
|
||||
bool jsonDirty = Impl::LoadSettings(settingsJson.as_object());
|
||||
|
||||
if (jsonDirty)
|
||||
{
|
||||
settingsJson = ConvertSettingsToJson();
|
||||
settingsJson = Impl::ConvertSettingsToJson();
|
||||
util::json::WriteJsonFile(settingsPath, settingsJson);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void SaveSettings()
|
||||
void SettingsManager::SaveSettings()
|
||||
{
|
||||
if (initialized_)
|
||||
if (p->initialized_)
|
||||
{
|
||||
logger_->info("Saving settings");
|
||||
|
||||
boost::json::value settingsJson = ConvertSettingsToJson();
|
||||
util::json::WriteJsonFile(settingsPath_, settingsJson);
|
||||
boost::json::value settingsJson = Impl::ConvertSettingsToJson();
|
||||
util::json::WriteJsonFile(p->settingsPath_, settingsJson);
|
||||
|
||||
Q_EMIT SettingsSaved();
|
||||
}
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
void SettingsManager::Shutdown()
|
||||
{
|
||||
bool dataChanged = false;
|
||||
|
||||
dataChanged |= general_settings().Shutdown();
|
||||
dataChanged |= map_settings().Shutdown();
|
||||
dataChanged |= settings::GeneralSettings::Instance().Shutdown();
|
||||
dataChanged |= settings::MapSettings::Instance().Shutdown();
|
||||
dataChanged |= settings::UiSettings::Instance().Shutdown();
|
||||
|
||||
if (dataChanged)
|
||||
|
|
@ -106,70 +123,53 @@ void Shutdown()
|
|||
}
|
||||
}
|
||||
|
||||
settings::GeneralSettings& general_settings()
|
||||
{
|
||||
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::value SettingsManager::Impl::ConvertSettingsToJson()
|
||||
{
|
||||
boost::json::object settingsJson;
|
||||
|
||||
general_settings().WriteJson(settingsJson);
|
||||
map_settings().WriteJson(settingsJson);
|
||||
palette_settings().WriteJson(settingsJson);
|
||||
settings::GeneralSettings::Instance().WriteJson(settingsJson);
|
||||
settings::MapSettings::Instance().WriteJson(settingsJson);
|
||||
settings::PaletteSettings::Instance().WriteJson(settingsJson);
|
||||
settings::TextSettings::Instance().WriteJson(settingsJson);
|
||||
settings::UiSettings::Instance().WriteJson(settingsJson);
|
||||
|
||||
return settingsJson;
|
||||
}
|
||||
|
||||
static void GenerateDefaultSettings()
|
||||
void SettingsManager::Impl::GenerateDefaultSettings()
|
||||
{
|
||||
logger_->info("Generating default settings");
|
||||
|
||||
general_settings().SetDefaults();
|
||||
map_settings().SetDefaults();
|
||||
palette_settings().SetDefaults();
|
||||
settings::GeneralSettings::Instance().SetDefaults();
|
||||
settings::MapSettings::Instance().SetDefaults();
|
||||
settings::PaletteSettings::Instance().SetDefaults();
|
||||
settings::TextSettings::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");
|
||||
|
||||
bool jsonDirty = false;
|
||||
|
||||
jsonDirty |= !general_settings().ReadJson(settingsJson);
|
||||
jsonDirty |= !map_settings().ReadJson(settingsJson);
|
||||
jsonDirty |= !palette_settings().ReadJson(settingsJson);
|
||||
jsonDirty |= !settings::GeneralSettings::Instance().ReadJson(settingsJson);
|
||||
jsonDirty |= !settings::MapSettings::Instance().ReadJson(settingsJson);
|
||||
jsonDirty |= !settings::PaletteSettings::Instance().ReadJson(settingsJson);
|
||||
jsonDirty |= !settings::TextSettings::Instance().ReadJson(settingsJson);
|
||||
jsonDirty |= !settings::UiSettings::Instance().ReadJson(settingsJson);
|
||||
|
||||
return jsonDirty;
|
||||
}
|
||||
|
||||
static void ValidateSettings()
|
||||
void SettingsManager::Impl::ValidateSettings()
|
||||
{
|
||||
logger_->debug("Validating settings");
|
||||
|
||||
bool settingsChanged = false;
|
||||
|
||||
auto& generalSettings = general_settings();
|
||||
auto& generalSettings = settings::GeneralSettings::Instance();
|
||||
|
||||
// Validate map provider
|
||||
std::string mapProviderName = generalSettings.map_provider().GetValue();
|
||||
|
|
@ -200,11 +200,16 @@ static void ValidateSettings()
|
|||
|
||||
if (settingsChanged)
|
||||
{
|
||||
SaveSettings();
|
||||
self_->SaveSettings();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace SettingsManager
|
||||
SettingsManager& SettingsManager::Instance()
|
||||
{
|
||||
static SettingsManager instance_ {};
|
||||
return instance_;
|
||||
}
|
||||
|
||||
} // namespace manager
|
||||
} // namespace qt
|
||||
} // namespace scwx
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#include <scwx/qt/settings/general_settings.hpp>
|
||||
#include <scwx/qt/settings/map_settings.hpp>
|
||||
#include <scwx/qt/settings/palette_settings.hpp>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace scwx
|
||||
{
|
||||
|
|
@ -10,19 +11,31 @@ namespace qt
|
|||
{
|
||||
namespace manager
|
||||
{
|
||||
namespace SettingsManager
|
||||
|
||||
class SettingsManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY_MOVE(SettingsManager)
|
||||
|
||||
public:
|
||||
explicit SettingsManager();
|
||||
~SettingsManager();
|
||||
|
||||
void Initialize();
|
||||
void ReadSettings(const std::string& settingsPath);
|
||||
void SaveSettings();
|
||||
void Shutdown();
|
||||
|
||||
settings::GeneralSettings& general_settings();
|
||||
settings::MapSettings& map_settings();
|
||||
settings::PaletteSettings& palette_settings();
|
||||
static SettingsManager& Instance();
|
||||
|
||||
signals:
|
||||
void SettingsSaved();
|
||||
|
||||
private:
|
||||
class Impl;
|
||||
std::unique_ptr<Impl> p;
|
||||
};
|
||||
|
||||
} // namespace SettingsManager
|
||||
} // namespace manager
|
||||
} // namespace qt
|
||||
} // namespace scwx
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include <scwx/qt/manager/timeline_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/map.hpp>
|
||||
#include <scwx/util/time.hpp>
|
||||
|
|
@ -39,7 +39,7 @@ class TimelineManager::Impl
|
|||
public:
|
||||
explicit Impl(TimelineManager* self) : self_ {self}
|
||||
{
|
||||
auto& generalSettings = SettingsManager::general_settings();
|
||||
auto& generalSettings = settings::GeneralSettings::Instance();
|
||||
|
||||
loopDelay_ =
|
||||
std::chrono::milliseconds(generalSettings.loop_delay().GetValue());
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#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/settings/palette_settings.hpp>
|
||||
#include <scwx/qt/util/color.hpp>
|
||||
#include <scwx/util/logger.hpp>
|
||||
#include <scwx/util/threads.hpp>
|
||||
|
|
@ -394,7 +394,7 @@ static void AddAlertLayer(std::shared_ptr<QMapLibreGL::Map> map,
|
|||
const QString& beforeLayer)
|
||||
{
|
||||
settings::PaletteSettings& paletteSettings =
|
||||
manager::SettingsManager::palette_settings();
|
||||
settings::PaletteSettings::Instance();
|
||||
|
||||
QString sourceId = GetSourceId(phenomenon, alertActive);
|
||||
QString idSuffix = GetSuffix(phenomenon, alertActive);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#include <scwx/qt/map/map_provider.hpp>
|
||||
#include <scwx/qt/manager/settings_manager.hpp>
|
||||
#include <scwx/qt/settings/general_settings.hpp>
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
|
|
@ -128,12 +128,10 @@ std::string GetMapProviderApiKey(MapProvider mapProvider)
|
|||
switch (mapProvider)
|
||||
{
|
||||
case MapProvider::Mapbox:
|
||||
return manager::SettingsManager::general_settings()
|
||||
.mapbox_api_key()
|
||||
.GetValue();
|
||||
return settings::GeneralSettings::Instance().mapbox_api_key().GetValue();
|
||||
|
||||
case MapProvider::MapTiler:
|
||||
return manager::SettingsManager::general_settings()
|
||||
return settings::GeneralSettings::Instance()
|
||||
.maptiler_api_key()
|
||||
.GetValue();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
#include <scwx/qt/map/map_widget.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/radar_product_manager.hpp>
|
||||
#include <scwx/qt/manager/settings_manager.hpp>
|
||||
#include <scwx/qt/map/alert_layer.hpp>
|
||||
#include <scwx/qt/map/color_table_layer.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_range_layer.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/maplibre.hpp>
|
||||
#include <scwx/qt/util/tooltip.hpp>
|
||||
|
|
@ -80,8 +82,7 @@ public:
|
|||
prevBearing_ {0.0},
|
||||
prevPitch_ {0.0}
|
||||
{
|
||||
auto& generalSettings =
|
||||
scwx::qt::manager::SettingsManager::general_settings();
|
||||
auto& generalSettings = settings::GeneralSettings::Instance();
|
||||
|
||||
SetRadarSite(generalSettings.default_radar_site().GetValue());
|
||||
|
||||
|
|
@ -123,6 +124,7 @@ public:
|
|||
std::shared_ptr<GenericLayer> layer,
|
||||
const std::string& before = {});
|
||||
void ConnectSignals();
|
||||
void ImGuiCheckFonts();
|
||||
void InitializeNewRadarProductView(const std::string& colorPalette);
|
||||
void RadarProductManagerConnect();
|
||||
void RadarProductManagerDisconnect();
|
||||
|
|
@ -154,6 +156,7 @@ public:
|
|||
ImGuiContext* imGuiContext_;
|
||||
std::string imGuiContextName_;
|
||||
bool imGuiRendererInitialized_;
|
||||
std::uint64_t imGuiFontsBuildCount_ {};
|
||||
|
||||
std::shared_ptr<manager::PlacefileManager> placefileManager_ {
|
||||
manager::PlacefileManager::Instance()};
|
||||
|
|
@ -980,9 +983,15 @@ void MapWidget::initializeGL()
|
|||
makeCurrent();
|
||||
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
|
||||
ImGui::SetCurrentContext(p->imGuiContext_);
|
||||
ImGui_ImplOpenGL3_Init();
|
||||
p->imGuiFontsBuildCount_ =
|
||||
manager::FontManager::Instance().imgui_fonts_build_count();
|
||||
p->imGuiRendererInitialized_ = true;
|
||||
|
||||
p->map_.reset(
|
||||
|
|
@ -1023,16 +1032,27 @@ void MapWidget::initializeGL()
|
|||
|
||||
void MapWidget::paintGL()
|
||||
{
|
||||
auto defaultFont = manager::FontManager::Instance().GetImGuiFont(
|
||||
types::FontCategory::Default);
|
||||
|
||||
p->frameDraws_++;
|
||||
|
||||
// Setup ImGui Frame
|
||||
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
|
||||
ImGui_ImplQt_NewFrame(this);
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
p->ImGuiCheckFonts();
|
||||
ImGui::NewFrame();
|
||||
|
||||
// Set default font
|
||||
ImGui::PushFont(defaultFont->font());
|
||||
|
||||
// Update pixel ratio
|
||||
p->context_->set_pixel_ratio(pixelRatio());
|
||||
|
||||
|
|
@ -1055,14 +1075,36 @@ void MapWidget::paintGL()
|
|||
p->lastItemPicked_ = false;
|
||||
}
|
||||
|
||||
// Pop default font
|
||||
ImGui::PopFont();
|
||||
|
||||
// Render ImGui Frame
|
||||
ImGui::Render();
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
|
||||
// Unlock ImGui font atlas after rendering
|
||||
imguiFontAtlasLock.unlock();
|
||||
|
||||
// Paint complete
|
||||
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()
|
||||
{
|
||||
const QMapLibreGL::CustomLayerRenderParameters params =
|
||||
|
|
@ -1203,7 +1245,7 @@ void MapWidgetImpl::InitializeNewRadarProductView(
|
|||
auto radarProductView = context_->radar_product_view();
|
||||
|
||||
std::string colorTableFile =
|
||||
manager::SettingsManager::palette_settings()
|
||||
settings::PaletteSettings::Instance()
|
||||
.palette(colorPalette)
|
||||
.GetValue();
|
||||
if (!colorTableFile.empty())
|
||||
|
|
|
|||
|
|
@ -197,6 +197,8 @@ void PlacefileLayer::ReloadData()
|
|||
|
||||
p->placefileIcons_->SetIconFiles(placefile->icon_files(),
|
||||
placefile->name());
|
||||
p->placefileText_->SetFonts(
|
||||
placefileManager->placefile_fonts(p->placefileName_));
|
||||
|
||||
for (auto& drawItem : placefile->GetDrawItems())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -16,10 +16,10 @@ namespace settings
|
|||
|
||||
static const std::string logPrefix_ = "scwx::qt::settings::general_settings";
|
||||
|
||||
class GeneralSettingsImpl
|
||||
class GeneralSettings::Impl
|
||||
{
|
||||
public:
|
||||
explicit GeneralSettingsImpl()
|
||||
explicit Impl()
|
||||
{
|
||||
std::string defaultDefaultAlertActionValue =
|
||||
types::GetAlertActionName(types::AlertAction::Go);
|
||||
|
|
@ -102,7 +102,7 @@ public:
|
|||
{ return !value.empty(); });
|
||||
}
|
||||
|
||||
~GeneralSettingsImpl() {}
|
||||
~Impl() {}
|
||||
|
||||
SettingsVariable<bool> debugEnabled_ {"debug_enabled"};
|
||||
SettingsVariable<std::string> defaultAlertAction_ {"default_alert_action"};
|
||||
|
|
@ -120,7 +120,7 @@ public:
|
|||
};
|
||||
|
||||
GeneralSettings::GeneralSettings() :
|
||||
SettingsCategory("general"), p(std::make_unique<GeneralSettingsImpl>())
|
||||
SettingsCategory("general"), p(std::make_unique<Impl>())
|
||||
{
|
||||
RegisterVariables({&p->debugEnabled_,
|
||||
&p->defaultAlertAction_,
|
||||
|
|
@ -221,6 +221,12 @@ bool GeneralSettings::Shutdown()
|
|||
return dataChanged;
|
||||
}
|
||||
|
||||
GeneralSettings& GeneralSettings::Instance()
|
||||
{
|
||||
static GeneralSettings generalSettings_;
|
||||
return generalSettings_;
|
||||
}
|
||||
|
||||
bool operator==(const GeneralSettings& lhs, const GeneralSettings& rhs)
|
||||
{
|
||||
return (lhs.p->debugEnabled_ == rhs.p->debugEnabled_ &&
|
||||
|
|
|
|||
|
|
@ -13,8 +13,6 @@ namespace qt
|
|||
namespace settings
|
||||
{
|
||||
|
||||
class GeneralSettingsImpl;
|
||||
|
||||
class GeneralSettings : public SettingsCategory
|
||||
{
|
||||
public:
|
||||
|
|
@ -41,13 +39,16 @@ public:
|
|||
SettingsVariable<std::string>& maptiler_api_key() const;
|
||||
SettingsVariable<bool>& update_notifications_enabled() const;
|
||||
|
||||
static GeneralSettings& Instance();
|
||||
|
||||
friend bool operator==(const GeneralSettings& lhs,
|
||||
const GeneralSettings& rhs);
|
||||
|
||||
bool Shutdown();
|
||||
|
||||
private:
|
||||
std::unique_ptr<GeneralSettingsImpl> p;
|
||||
class Impl;
|
||||
std::unique_ptr<Impl> p;
|
||||
};
|
||||
|
||||
} // namespace settings
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ static const std::string kDefaultRadarProductGroupString_ = "L3";
|
|||
static const std::array<std::string, kCount_> kDefaultRadarProduct_ {
|
||||
"N0B", "N0G", "N0C", "N0X"};
|
||||
|
||||
class MapSettingsImpl
|
||||
class MapSettings::Impl
|
||||
{
|
||||
public:
|
||||
struct MapData
|
||||
|
|
@ -47,7 +47,7 @@ public:
|
|||
SettingsVariable<std::string> radarProduct_ {kRadarProductName_};
|
||||
};
|
||||
|
||||
explicit MapSettingsImpl()
|
||||
explicit Impl()
|
||||
{
|
||||
for (std::size_t i = 0; i < kCount_; i++)
|
||||
{
|
||||
|
|
@ -101,7 +101,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
~MapSettingsImpl() {}
|
||||
~Impl() {}
|
||||
|
||||
void SetDefaults(std::size_t i)
|
||||
{
|
||||
|
|
@ -111,12 +111,30 @@ public:
|
|||
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::vector<SettingsVariableBase*> variables_ {};
|
||||
};
|
||||
|
||||
MapSettings::MapSettings() :
|
||||
SettingsCategory("maps"), p(std::make_unique<MapSettingsImpl>())
|
||||
SettingsCategory("maps"), p(std::make_unique<Impl>())
|
||||
{
|
||||
RegisterVariables(p->variables_);
|
||||
SetDefaults();
|
||||
|
|
@ -161,7 +179,7 @@ bool MapSettings::Shutdown()
|
|||
// Commit settings that are managed separate from the settings dialog
|
||||
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();
|
||||
}
|
||||
|
|
@ -184,7 +202,7 @@ bool MapSettings::ReadJson(const boost::json::object& json)
|
|||
if (i < mapArray.size() && mapArray.at(i).is_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
|
||||
validated &= mapRecordSettings.mapStyle_.ReadValue(mapRecord);
|
||||
|
|
@ -234,14 +252,10 @@ void MapSettings::WriteJson(boost::json::object& json) const
|
|||
json.insert_or_assign(name(), object);
|
||||
}
|
||||
|
||||
void tag_invoke(boost::json::value_from_tag,
|
||||
boost::json::value& jv,
|
||||
const MapSettingsImpl::MapData& data)
|
||||
MapSettings& MapSettings::Instance()
|
||||
{
|
||||
jv = {{kMapStyleName_, data.mapStyle_.GetValue()},
|
||||
{kRadarSiteName_, data.radarSite_.GetValue()},
|
||||
{kRadarProductGroupName_, data.radarProductGroup_.GetValue()},
|
||||
{kRadarProductName_, data.radarProduct_.GetValue()}};
|
||||
static MapSettings mapSettings_;
|
||||
return mapSettings_;
|
||||
}
|
||||
|
||||
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_);
|
||||
}
|
||||
|
||||
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 qt
|
||||
} // namespace scwx
|
||||
|
|
|
|||
|
|
@ -13,8 +13,6 @@ namespace qt
|
|||
namespace settings
|
||||
{
|
||||
|
||||
class MapSettingsImpl;
|
||||
|
||||
class MapSettings : public SettingsCategory
|
||||
{
|
||||
public:
|
||||
|
|
@ -52,10 +50,13 @@ public:
|
|||
*/
|
||||
void WriteJson(boost::json::object& json) const override;
|
||||
|
||||
static MapSettings& Instance();
|
||||
|
||||
friend bool operator==(const MapSettings& lhs, const MapSettings& rhs);
|
||||
|
||||
private:
|
||||
std::unique_ptr<MapSettingsImpl> p;
|
||||
class Impl;
|
||||
std::unique_ptr<Impl> p;
|
||||
};
|
||||
|
||||
} // namespace settings
|
||||
|
|
|
|||
|
|
@ -72,10 +72,10 @@ static const std::map<
|
|||
static const std::string kDefaultKey_ {"???"};
|
||||
static const awips::Phenomenon kDefaultPhenomenon_ {awips::Phenomenon::Marine};
|
||||
|
||||
class PaletteSettingsImpl
|
||||
class PaletteSettings::Impl
|
||||
{
|
||||
public:
|
||||
explicit PaletteSettingsImpl()
|
||||
explicit Impl()
|
||||
{
|
||||
for (const auto& name : kPaletteKeys_)
|
||||
{
|
||||
|
|
@ -120,7 +120,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
~PaletteSettingsImpl() {}
|
||||
~Impl() {}
|
||||
|
||||
static bool ValidateColor(const std::string& value);
|
||||
|
||||
|
|
@ -132,14 +132,14 @@ public:
|
|||
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}"};
|
||||
return std::regex_match(value, re);
|
||||
}
|
||||
|
||||
PaletteSettings::PaletteSettings() :
|
||||
SettingsCategory("palette"), p(std::make_unique<PaletteSettingsImpl>())
|
||||
SettingsCategory("palette"), p(std::make_unique<Impl>())
|
||||
{
|
||||
RegisterVariables(p->variables_);
|
||||
SetDefaults();
|
||||
|
|
@ -200,6 +200,12 @@ const std::vector<awips::Phenomenon>& PaletteSettings::alert_phenomena()
|
|||
return kAlertPhenomena_;
|
||||
}
|
||||
|
||||
PaletteSettings& PaletteSettings::Instance()
|
||||
{
|
||||
static PaletteSettings paletteSettings_;
|
||||
return paletteSettings_;
|
||||
}
|
||||
|
||||
bool operator==(const PaletteSettings& lhs, const PaletteSettings& rhs)
|
||||
{
|
||||
return lhs.p->palette_ == rhs.p->palette_;
|
||||
|
|
|
|||
|
|
@ -14,8 +14,6 @@ namespace qt
|
|||
namespace settings
|
||||
{
|
||||
|
||||
class PaletteSettingsImpl;
|
||||
|
||||
class PaletteSettings : public SettingsCategory
|
||||
{
|
||||
public:
|
||||
|
|
@ -34,11 +32,14 @@ public:
|
|||
|
||||
static const std::vector<awips::Phenomenon>& alert_phenomena();
|
||||
|
||||
static PaletteSettings& Instance();
|
||||
|
||||
friend bool operator==(const PaletteSettings& lhs,
|
||||
const PaletteSettings& rhs);
|
||||
|
||||
private:
|
||||
std::unique_ptr<PaletteSettingsImpl> p;
|
||||
class Impl;
|
||||
std::unique_ptr<Impl> p;
|
||||
};
|
||||
|
||||
} // namespace settings
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
#include <scwx/qt/util/json.hpp>
|
||||
#include <scwx/util/logger.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace scwx
|
||||
{
|
||||
namespace qt
|
||||
|
|
@ -21,6 +23,8 @@ public:
|
|||
|
||||
const std::string name_;
|
||||
|
||||
std::vector<std::pair<std::string, std::vector<SettingsCategory*>>>
|
||||
subcategoryArrays_;
|
||||
std::vector<SettingsVariableBase*> variables_;
|
||||
};
|
||||
|
||||
|
|
@ -41,6 +45,16 @@ std::string SettingsCategory::name() const
|
|||
|
||||
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_)
|
||||
{
|
||||
variable->SetValueToDefault();
|
||||
|
|
@ -57,6 +71,47 @@ bool SettingsCategory::ReadJson(const boost::json::object& json)
|
|||
{
|
||||
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_)
|
||||
{
|
||||
validated &= variable->ReadValue(object);
|
||||
|
|
@ -66,7 +121,7 @@ bool SettingsCategory::ReadJson(const boost::json::object& json)
|
|||
{
|
||||
if (value == nullptr)
|
||||
{
|
||||
logger_->warn("Key {} is not present, resetting to defaults",
|
||||
logger_->debug("Key {} is not present, resetting to defaults",
|
||||
p->name_);
|
||||
}
|
||||
else if (!value->is_object())
|
||||
|
|
@ -86,6 +141,20 @@ void SettingsCategory::WriteJson(boost::json::object& json) const
|
|||
{
|
||||
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_)
|
||||
{
|
||||
variable->WriteValue(object);
|
||||
|
|
@ -94,6 +163,18 @@ void SettingsCategory::WriteJson(boost::json::object& json) const
|
|||
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(
|
||||
std::initializer_list<SettingsVariableBase*> variables)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -50,7 +50,8 @@ public:
|
|||
*/
|
||||
virtual void WriteJson(boost::json::object& json) const;
|
||||
|
||||
protected:
|
||||
void RegisterSubcategoryArray(const std::string& name,
|
||||
std::vector<SettingsCategory>& subcategories);
|
||||
void
|
||||
RegisterVariables(std::initializer_list<SettingsVariableBase*> variables);
|
||||
void RegisterVariables(std::vector<SettingsVariableBase*> variables);
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include <QCheckBox>
|
||||
#include <QComboBox>
|
||||
#include <QCoreApplication>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QSpinBox>
|
||||
#include <QWidget>
|
||||
|
|
@ -26,16 +27,21 @@ template<class T>
|
|||
class SettingsInterface<T>::Impl
|
||||
{
|
||||
public:
|
||||
explicit Impl()
|
||||
explicit Impl(SettingsInterface* self) : self_ {self}
|
||||
{
|
||||
context_->moveToThread(QCoreApplication::instance()->thread());
|
||||
}
|
||||
|
||||
~Impl() {}
|
||||
|
||||
template<class U>
|
||||
void SetWidgetText(U* widget, const T& currentValue);
|
||||
|
||||
void UpdateEditWidget();
|
||||
void UpdateResetButton();
|
||||
|
||||
SettingsInterface<T>* self_;
|
||||
|
||||
SettingsVariable<T>* variable_ {nullptr};
|
||||
bool stagedValid_ {true};
|
||||
|
||||
|
|
@ -49,17 +55,27 @@ public:
|
|||
|
||||
template<class T>
|
||||
SettingsInterface<T>::SettingsInterface() :
|
||||
SettingsInterfaceBase(), p(std::make_unique<Impl>())
|
||||
SettingsInterfaceBase(), p(std::make_unique<Impl>(this))
|
||||
{
|
||||
}
|
||||
template<class T>
|
||||
SettingsInterface<T>::~SettingsInterface() = default;
|
||||
|
||||
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>
|
||||
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>
|
||||
void SettingsInterface<T>::SetSettingsVariable(SettingsVariable<T>& variable)
|
||||
|
|
@ -73,6 +89,27 @@ SettingsVariable<T>* SettingsInterface<T>::GetSettingsVariable() const
|
|||
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>
|
||||
bool SettingsInterface<T>::Commit()
|
||||
{
|
||||
|
|
@ -95,6 +132,14 @@ void SettingsInterface<T>::StageDefault()
|
|||
p->UpdateResetButton();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void SettingsInterface<T>::StageValue(const T& value)
|
||||
{
|
||||
p->variable_->StageValue(value);
|
||||
p->UpdateEditWidget();
|
||||
p->UpdateResetButton();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void SettingsInterface<T>::SetEditWidget(QWidget* widget)
|
||||
{
|
||||
|
|
@ -105,6 +150,11 @@ void SettingsInterface<T>::SetEditWidget(QWidget* widget)
|
|||
|
||||
p->editWidget_ = widget;
|
||||
|
||||
if (widget == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (QLineEdit* lineEdit = dynamic_cast<QLineEdit*>(widget))
|
||||
{
|
||||
if constexpr (std::is_same_v<T, std::string>)
|
||||
|
|
@ -274,6 +324,8 @@ void SettingsInterface<T>::SetResetButton(QAbstractButton* button)
|
|||
|
||||
p->resetButton_ = button;
|
||||
|
||||
if (p->resetButton_ != nullptr)
|
||||
{
|
||||
QObject::connect(p->resetButton_,
|
||||
&QAbstractButton::clicked,
|
||||
p->context_.get(),
|
||||
|
|
@ -283,8 +335,8 @@ void SettingsInterface<T>::SetResetButton(QAbstractButton* button)
|
|||
|
||||
if (p->variable_->GetValue() == defaultValue)
|
||||
{
|
||||
// If the current value is default, reset the staged
|
||||
// value
|
||||
// If the current value is default, reset the
|
||||
// staged value
|
||||
p->variable_->Reset();
|
||||
p->stagedValid_ = true;
|
||||
p->UpdateEditWidget();
|
||||
|
|
@ -302,6 +354,7 @@ void SettingsInterface<T>::SetResetButton(QAbstractButton* button)
|
|||
|
||||
p->UpdateResetButton();
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void SettingsInterface<T>::SetMapFromValueFunction(
|
||||
|
|
@ -317,6 +370,39 @@ void SettingsInterface<T>::SetMapToValueFunction(
|
|||
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>
|
||||
void SettingsInterface<T>::Impl::UpdateEditWidget()
|
||||
{
|
||||
|
|
@ -327,35 +413,11 @@ void SettingsInterface<T>::Impl::UpdateEditWidget()
|
|||
|
||||
if (QLineEdit* lineEdit = dynamic_cast<QLineEdit*>(editWidget_))
|
||||
{
|
||||
if constexpr (std::is_integral_v<T>)
|
||||
{
|
||||
lineEdit->setText(QString::number(currentValue));
|
||||
SetWidgetText(lineEdit, currentValue);
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, std::string>)
|
||||
else if (QLabel* label = dynamic_cast<QLabel*>(editWidget_))
|
||||
{
|
||||
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, ", "))));
|
||||
}
|
||||
}
|
||||
SetWidgetText(label, currentValue);
|
||||
}
|
||||
else if (QCheckBox* checkBox = dynamic_cast<QCheckBox*>(editWidget_))
|
||||
{
|
||||
|
|
@ -391,20 +453,9 @@ void SettingsInterface<T>::Impl::UpdateEditWidget()
|
|||
template<class T>
|
||||
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 (staged.has_value())
|
||||
{
|
||||
resetButton_->setVisible(!stagedValid_ || *staged != defaultValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
resetButton_->setVisible(value != defaultValue);
|
||||
}
|
||||
resetButton_->setVisible(!self_->IsDefault());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -45,6 +45,14 @@ public:
|
|||
*/
|
||||
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
|
||||
* value.
|
||||
|
|
@ -64,6 +72,11 @@ public:
|
|||
*/
|
||||
void StageDefault() override;
|
||||
|
||||
/**
|
||||
* Stages a value to the associated settings variable.
|
||||
*/
|
||||
void StageValue(const T& value);
|
||||
|
||||
/**
|
||||
* Sets the edit widget from the settings dialog.
|
||||
*
|
||||
|
|
@ -103,6 +116,7 @@ private:
|
|||
|
||||
#ifdef SETTINGS_INTERFACE_IMPLEMENTATION
|
||||
template class SettingsInterface<bool>;
|
||||
template class SettingsInterface<double>;
|
||||
template class SettingsInterface<std::int64_t>;
|
||||
template class SettingsInterface<std::string>;
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,14 @@ public:
|
|||
SettingsInterfaceBase(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
|
||||
* value.
|
||||
|
|
|
|||
|
|
@ -239,6 +239,12 @@ std::optional<T> SettingsVariable<T>::GetStaged() const
|
|||
return p->staged_;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T SettingsVariable<T>::GetStagedOrValue() const
|
||||
{
|
||||
return p->staged_.value_or(GetValue());
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T SettingsVariable<T>::GetDefault() const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -103,6 +103,14 @@ public:
|
|||
*/
|
||||
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
|
||||
* variable.
|
||||
|
|
|
|||
|
|
@ -12,10 +12,34 @@ namespace 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
|
||||
{
|
||||
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 =
|
||||
types::GetTooltipMethodName(types::TooltipMethod::ImGui);
|
||||
|
|
@ -47,16 +71,32 @@ public:
|
|||
// No match found, invalid
|
||||
return false;
|
||||
});
|
||||
|
||||
InitializeFontVariables();
|
||||
}
|
||||
|
||||
~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::string> tooltipMethod_ {"tooltip_method"};
|
||||
};
|
||||
|
||||
TextSettings::TextSettings() :
|
||||
SettingsCategory("text"), p(std::make_unique<Impl>())
|
||||
SettingsCategory("text"), p(std::make_unique<Impl>(this))
|
||||
{
|
||||
RegisterVariables({&p->hoverTextWrap_, &p->tooltipMethod_});
|
||||
SetDefaults();
|
||||
|
|
@ -66,6 +106,57 @@ TextSettings::~TextSettings() = default;
|
|||
TextSettings::TextSettings(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
|
||||
{
|
||||
return p->hoverTextWrap_;
|
||||
|
|
@ -78,13 +169,14 @@ SettingsVariable<std::string>& TextSettings::tooltip_method() const
|
|||
|
||||
TextSettings& TextSettings::Instance()
|
||||
{
|
||||
static TextSettings TextSettings_;
|
||||
return TextSettings_;
|
||||
static TextSettings textSettings_;
|
||||
return textSettings_;
|
||||
}
|
||||
|
||||
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_);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <scwx/qt/settings/settings_category.hpp>
|
||||
#include <scwx/qt/settings/settings_variable.hpp>
|
||||
#include <scwx/qt/types/text_types.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
|
@ -25,6 +26,13 @@ public:
|
|||
TextSettings(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::string>& tooltip_method() const;
|
||||
|
||||
|
|
|
|||
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
|
||||
{
|
||||
|
||||
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_ {
|
||||
{TooltipMethod::ImGui, "ImGui"},
|
||||
{TooltipMethod::QToolTip, "Native Tooltip"},
|
||||
{TooltipMethod::QLabel, "Floating Label"},
|
||||
{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)
|
||||
{
|
||||
auto result = std::find_if(
|
||||
|
|
|
|||
|
|
@ -11,6 +11,16 @@ namespace qt
|
|||
namespace types
|
||||
{
|
||||
|
||||
enum class FontCategory
|
||||
{
|
||||
Default,
|
||||
Tooltip,
|
||||
Unknown
|
||||
};
|
||||
typedef scwx::util::
|
||||
Iterator<FontCategory, FontCategory::Default, FontCategory::Tooltip>
|
||||
FontCategoryIterator;
|
||||
|
||||
enum class TooltipMethod
|
||||
{
|
||||
ImGui,
|
||||
|
|
@ -22,6 +32,8 @@ typedef scwx::util::
|
|||
Iterator<TooltipMethod, TooltipMethod::ImGui, TooltipMethod::QLabel>
|
||||
TooltipMethodIterator;
|
||||
|
||||
FontCategory GetFontCategory(const std::string& name);
|
||||
std::string GetFontCategoryName(FontCategory fontCategory);
|
||||
TooltipMethod GetTooltipMethod(const std::string& name);
|
||||
std::string GetTooltipMethodName(TooltipMethod tooltipMethod);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#include "about_dialog.hpp"
|
||||
#include "ui_about_dialog.h"
|
||||
#include <scwx/qt/main/versions.hpp>
|
||||
#include <scwx/qt/manager/resource_manager.hpp>
|
||||
#include <scwx/qt/manager/font_manager.hpp>
|
||||
|
||||
#include <QFontDatabase>
|
||||
|
||||
|
|
@ -27,7 +27,7 @@ AboutDialog::AboutDialog(QWidget* parent) :
|
|||
ui->setupUi(this);
|
||||
|
||||
int titleFontId =
|
||||
manager::ResourceManager::FontId(types::Font::din1451alt_g);
|
||||
manager::FontManager::Instance().GetFontId(types::Font::din1451alt_g);
|
||||
QString titleFontFamily =
|
||||
QFontDatabase::applicationFontFamilies(titleFontId).at(0);
|
||||
QFont titleFont(titleFontFamily, 14);
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
#include "alert_dock_widget.hpp"
|
||||
#include "ui_alert_dock_widget.h"
|
||||
|
||||
#include <scwx/qt/manager/settings_manager.hpp>
|
||||
#include <scwx/qt/manager/text_event_manager.hpp>
|
||||
#include <scwx/qt/model/alert_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/qt_types.hpp>
|
||||
#include <scwx/qt/ui/alert_dialog.hpp>
|
||||
|
|
@ -175,8 +175,8 @@ void AlertDockWidgetImpl::ConnectSignals()
|
|||
// If an item is selected
|
||||
if (selectedAlertKey_ != types::TextEventKey {})
|
||||
{
|
||||
types::AlertAction alertAction = types::GetAlertAction(
|
||||
manager::SettingsManager::general_settings()
|
||||
types::AlertAction alertAction =
|
||||
types::GetAlertAction(settings::GeneralSettings::Instance()
|
||||
.default_alert_action()
|
||||
.GetValue());
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#include "animation_dock_widget.hpp"
|
||||
#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/util/logger.hpp>
|
||||
|
||||
|
|
@ -101,7 +101,7 @@ AnimationDockWidget::AnimationDockWidget(QWidget* parent) :
|
|||
maxDateTimer->start(15000);
|
||||
|
||||
// Set loop defaults
|
||||
auto& generalSettings = manager::SettingsManager::general_settings();
|
||||
auto& generalSettings = settings::GeneralSettings::Instance();
|
||||
ui->loopTimeSpinBox->setValue(generalSettings.loop_time().GetValue());
|
||||
ui->loopSpeedSpinBox->setValue(generalSettings.loop_speed().GetValue());
|
||||
ui->loopDelaySpinBox->setValue(generalSettings.loop_delay().GetValue() *
|
||||
|
|
@ -175,7 +175,7 @@ void AnimationDockWidgetImpl::ConnectSignals()
|
|||
self_,
|
||||
[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));
|
||||
});
|
||||
QObject::connect(
|
||||
|
|
@ -184,8 +184,7 @@ void AnimationDockWidgetImpl::ConnectSignals()
|
|||
self_,
|
||||
[this](double d)
|
||||
{
|
||||
manager::SettingsManager::general_settings().loop_speed().StageValue(
|
||||
d);
|
||||
settings::GeneralSettings::Instance().loop_speed().StageValue(d);
|
||||
Q_EMIT self_->LoopSpeedChanged(d);
|
||||
});
|
||||
QObject::connect(
|
||||
|
|
@ -194,7 +193,7 @@ void AnimationDockWidgetImpl::ConnectSignals()
|
|||
self_,
|
||||
[this](double d)
|
||||
{
|
||||
manager::SettingsManager::general_settings().loop_delay().StageValue(
|
||||
settings::GeneralSettings::Instance().loop_delay().StageValue(
|
||||
static_cast<std::int64_t>(d * 1000.0));
|
||||
Q_EMIT self_->LoopDelayChanged(std::chrono::milliseconds(
|
||||
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/manager/font_manager.hpp>
|
||||
#include <scwx/qt/model/imgui_context_model.hpp>
|
||||
|
||||
#include <set>
|
||||
|
|
@ -50,6 +51,8 @@ public:
|
|||
model::ImGuiContextModel::Instance().DestroyContext(contextName_);
|
||||
}
|
||||
|
||||
void ImGuiCheckFonts();
|
||||
|
||||
ImGuiDebugWidget* self_;
|
||||
ImGuiContext* context_;
|
||||
std::string contextName_;
|
||||
|
|
@ -58,6 +61,7 @@ public:
|
|||
|
||||
std::set<ImGuiContext*> renderedSet_ {};
|
||||
bool imGuiRendererInitialized_ {false};
|
||||
std::uint64_t imGuiFontsBuildCount_ {};
|
||||
};
|
||||
|
||||
ImGuiDebugWidget::ImGuiDebugWidget(QWidget* parent) :
|
||||
|
|
@ -102,6 +106,8 @@ void ImGuiDebugWidget::initializeGL()
|
|||
// Initialize ImGui OpenGL3 backend
|
||||
ImGui::SetCurrentContext(p->context_);
|
||||
ImGui_ImplOpenGL3_Init();
|
||||
p->imGuiFontsBuildCount_ =
|
||||
manager::FontManager::Instance().imgui_fonts_build_count();
|
||||
p->imGuiRendererInitialized_ = true;
|
||||
}
|
||||
|
||||
|
|
@ -109,9 +115,13 @@ void ImGuiDebugWidget::paintGL()
|
|||
{
|
||||
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_ImplOpenGL3_NewFrame();
|
||||
|
||||
p->ImGuiCheckFonts();
|
||||
ImGui::NewFrame();
|
||||
|
||||
if (!p->renderedSet_.contains(p->currentContext_))
|
||||
|
|
@ -131,6 +141,29 @@ void ImGuiDebugWidget::paintGL()
|
|||
|
||||
ImGui::Render();
|
||||
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
|
||||
|
|
|
|||
|
|
@ -6,9 +6,12 @@
|
|||
#include <scwx/qt/config/radar_site.hpp>
|
||||
#include <scwx/qt/manager/settings_manager.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/text_settings.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/ui/placefile_settings_widget.hpp>
|
||||
#include <scwx/qt/ui/radar_site_dialog.hpp>
|
||||
|
|
@ -21,6 +24,8 @@
|
|||
#include <fmt/format.h>
|
||||
#include <QColorDialog>
|
||||
#include <QFileDialog>
|
||||
#include <QFontDialog>
|
||||
#include <QStandardItemModel>
|
||||
#include <QToolButton>
|
||||
|
||||
namespace scwx
|
||||
|
|
@ -84,9 +89,10 @@ public:
|
|||
explicit SettingsDialogImpl(SettingsDialog* self) :
|
||||
self_ {self},
|
||||
radarSiteDialog_ {new RadarSiteDialog(self)},
|
||||
fontDialog_ {new QFontDialog(self)},
|
||||
fontCategoryModel_ {new QStandardItemModel(self)},
|
||||
settings_ {std::initializer_list<settings::SettingsInterfaceBase*> {
|
||||
&defaultRadarSite_,
|
||||
&fontSizes_,
|
||||
&gridWidth_,
|
||||
&gridHeight_,
|
||||
&mapProvider_,
|
||||
|
|
@ -99,7 +105,7 @@ public:
|
|||
&tooltipMethod_}}
|
||||
{
|
||||
// Configure default alert phenomena colors
|
||||
auto& paletteSettings = manager::SettingsManager::palette_settings();
|
||||
auto& paletteSettings = settings::PaletteSettings::Instance();
|
||||
int index = 0;
|
||||
|
||||
for (auto& phenomenon : settings::PaletteSettings::alert_phenomena())
|
||||
|
|
@ -113,6 +119,12 @@ public:
|
|||
QColor(QString::fromStdString(
|
||||
paletteSettings.alert_color(phenomenon, false).GetDefault())));
|
||||
}
|
||||
|
||||
// Configure font dialog
|
||||
fontDialog_->setOptions(
|
||||
QFontDialog::FontDialogOption::DontUseNativeDialog |
|
||||
QFontDialog::FontDialogOption::ScalableFonts);
|
||||
fontDialog_->setWindowModality(Qt::WindowModality::WindowModal);
|
||||
}
|
||||
~SettingsDialogImpl() = default;
|
||||
|
||||
|
|
@ -126,6 +138,10 @@ public:
|
|||
void ShowColorDialog(QLineEdit* lineEdit, QFrame* frame = nullptr);
|
||||
void UpdateRadarDialogLocation(const std::string& id);
|
||||
|
||||
QFont GetSelectedFont();
|
||||
void SelectFontCategory(types::FontCategory fontCategory);
|
||||
void UpdateFontDisplayData();
|
||||
|
||||
void ApplyChanges();
|
||||
void DiscardChanges();
|
||||
void ResetToDefault();
|
||||
|
|
@ -146,9 +162,13 @@ public:
|
|||
SettingsDialog* self_;
|
||||
PlacefileSettingsWidget* placefileSettingsWidget_ {nullptr};
|
||||
RadarSiteDialog* radarSiteDialog_;
|
||||
QFontDialog* fontDialog_;
|
||||
|
||||
QStandardItemModel* fontCategoryModel_;
|
||||
|
||||
types::FontCategory selectedFontCategory_ {types::FontCategory::Unknown};
|
||||
|
||||
settings::SettingsInterface<std::string> defaultRadarSite_ {};
|
||||
settings::SettingsInterface<std::vector<std::int64_t>> fontSizes_ {};
|
||||
settings::SettingsInterface<std::int64_t> gridWidth_ {};
|
||||
settings::SettingsInterface<std::int64_t> gridHeight_ {};
|
||||
settings::SettingsInterface<std::string> mapProvider_ {};
|
||||
|
|
@ -167,6 +187,15 @@ public:
|
|||
settings::SettingsInterface<std::string>>
|
||||
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::string> tooltipMethod_ {};
|
||||
|
||||
|
|
@ -239,6 +268,72 @@ void SettingsDialogImpl::ConnectSignals()
|
|||
[this](const std::string& 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(
|
||||
self_->ui->buttonBox,
|
||||
&QDialogButtonBox::clicked,
|
||||
|
|
@ -289,7 +384,7 @@ void SettingsDialogImpl::SetupGeneralTab()
|
|||
}
|
||||
|
||||
settings::GeneralSettings& generalSettings =
|
||||
manager::SettingsManager::general_settings();
|
||||
settings::GeneralSettings::Instance();
|
||||
|
||||
defaultRadarSite_.SetSettingsVariable(generalSettings.default_radar_site());
|
||||
defaultRadarSite_.SetMapFromValueFunction(
|
||||
|
|
@ -327,10 +422,6 @@ void SettingsDialogImpl::SetupGeneralTab()
|
|||
defaultRadarSite_.SetResetButton(self_->ui->resetRadarSiteButton);
|
||||
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_.SetEditWidget(self_->ui->gridWidthSpinBox);
|
||||
gridWidth_.SetResetButton(self_->ui->resetGridWidthButton);
|
||||
|
|
@ -430,7 +521,7 @@ void SettingsDialogImpl::SetupGeneralTab()
|
|||
void SettingsDialogImpl::SetupPalettesColorTablesTab()
|
||||
{
|
||||
settings::PaletteSettings& paletteSettings =
|
||||
manager::SettingsManager::palette_settings();
|
||||
settings::PaletteSettings::Instance();
|
||||
|
||||
// Palettes > Color Tables
|
||||
QGridLayout* colorTableLayout =
|
||||
|
|
@ -522,7 +613,7 @@ void SettingsDialogImpl::SetupPalettesColorTablesTab()
|
|||
void SettingsDialogImpl::SetupPalettesAlertsTab()
|
||||
{
|
||||
settings::PaletteSettings& paletteSettings =
|
||||
manager::SettingsManager::palette_settings();
|
||||
settings::PaletteSettings::Instance();
|
||||
|
||||
// Palettes > Alerts
|
||||
QGridLayout* alertsLayout =
|
||||
|
|
@ -645,6 +736,39 @@ void SettingsDialogImpl::SetupTextTab()
|
|||
{
|
||||
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_.SetEditWidget(self_->ui->hoverTextWrapSpinBox);
|
||||
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()
|
||||
{
|
||||
logger_->info("Applying settings changes");
|
||||
|
|
@ -812,7 +983,7 @@ void SettingsDialogImpl::ApplyChanges()
|
|||
|
||||
if (committed)
|
||||
{
|
||||
manager::SettingsManager::SaveSettings();
|
||||
manager::SettingsManager::Instance().SaveSettings();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -127,27 +127,7 @@
|
|||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="5" column="2">
|
||||
<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">
|
||||
<item row="4" column="4">
|
||||
<widget class="QToolButton" name="resetMapProviderButton">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
|
|
@ -158,45 +138,14 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QLineEdit" name="fontSizesLineEdit"/>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Mapbox API Key</string>
|
||||
<string>Grid Width</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<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">
|
||||
<item row="2" column="4">
|
||||
<widget class="QToolButton" name="resetGridHeightButton">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
|
|
@ -207,16 +156,6 @@
|
|||
</property>
|
||||
</widget>
|
||||
</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">
|
||||
<widget class="QToolButton" name="resetRadarSiteButton">
|
||||
<property name="text">
|
||||
|
|
@ -228,32 +167,14 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Grid Height</string>
|
||||
<string>MapTiler API Key</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" 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">
|
||||
<item row="5" column="4">
|
||||
<widget class="QToolButton" name="resetMapboxApiKeyButton">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
|
|
@ -264,21 +185,97 @@
|
|||
</property>
|
||||
</widget>
|
||||
</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">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<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>
|
||||
</widget>
|
||||
</item>
|
||||
<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">
|
||||
<property name="text">
|
||||
<string>Map Provider</string>
|
||||
</property>
|
||||
</widget>
|
||||
</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">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
|
|
@ -289,26 +286,8 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="defaultAlertActionLabel">
|
||||
<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 row="0" column="2">
|
||||
<widget class="QComboBox" name="radarSiteComboBox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
|
@ -438,6 +417,194 @@
|
|||
</widget>
|
||||
<widget class="QWidget" name="text">
|
||||
<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>
|
||||
<widget class="QFrame" name="frame_3">
|
||||
<property name="frameShape">
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#include "update_dialog.hpp"
|
||||
#include "ui_update_dialog.h"
|
||||
#include <scwx/qt/main/versions.hpp>
|
||||
#include <scwx/qt/manager/resource_manager.hpp>
|
||||
#include <scwx/qt/manager/font_manager.hpp>
|
||||
|
||||
#include <QDesktopServices>
|
||||
#include <QFontDatabase>
|
||||
|
|
@ -30,7 +30,7 @@ UpdateDialog::UpdateDialog(QWidget* parent) :
|
|||
ui->setupUi(this);
|
||||
|
||||
int titleFontId =
|
||||
manager::ResourceManager::FontId(types::Font::din1451alt_g);
|
||||
manager::FontManager::Instance().GetFontId(types::Font::din1451alt_g);
|
||||
QString titleFontFamily =
|
||||
QFontDatabase::applicationFontFamilies(titleFontId).at(0);
|
||||
QFont titleFont(titleFontFamily, 12);
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
#define _CRT_SECURE_NO_WARNINGS
|
||||
|
||||
#include <scwx/qt/util/font.hpp>
|
||||
#include <scwx/qt/manager/settings_manager.hpp>
|
||||
#include <scwx/qt/model/imgui_context_model.hpp>
|
||||
#include <scwx/qt/settings/general_settings.hpp>
|
||||
#include <scwx/util/logger.hpp>
|
||||
|
||||
#include <codecvt>
|
||||
|
|
@ -126,9 +126,6 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void CreateImGuiFont(QFile& fontFile,
|
||||
QByteArray& fontData,
|
||||
const std::vector<int64_t>& fontSizes);
|
||||
void ParseNames(FT_Face face);
|
||||
|
||||
const std::string resource_;
|
||||
|
|
@ -266,39 +263,6 @@ GLuint Font::GenerateTexture(gl::OpenGLFunctions& gl)
|
|||
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)
|
||||
{
|
||||
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);
|
||||
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);
|
||||
ftgl::texture_font_t* textureFont = ftgl::texture_font_new_from_memory(
|
||||
font->p->atlas_, BASE_POINT_SIZE, fontData.constData(), fontData.size());
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
#include <scwx/qt/util/imgui.hpp>
|
||||
#include <scwx/qt/manager/resource_manager.hpp>
|
||||
#include <scwx/qt/manager/settings_manager.hpp>
|
||||
#include <scwx/qt/manager/font_manager.hpp>
|
||||
#include <scwx/util/logger.hpp>
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
namespace scwx
|
||||
|
|
@ -22,13 +19,6 @@ class ImGui::Impl
|
|||
public:
|
||||
explicit Impl() {}
|
||||
~Impl() {}
|
||||
|
||||
void Initialize();
|
||||
void UpdateMonospaceFont();
|
||||
|
||||
bool initialized_ {false};
|
||||
|
||||
ImFont* monospaceFont_ {nullptr};
|
||||
};
|
||||
|
||||
ImGui::ImGui() : p(std::make_unique<Impl>()) {}
|
||||
|
|
@ -37,58 +27,13 @@ ImGui::~ImGui() = default;
|
|||
ImGui::ImGui(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)
|
||||
{
|
||||
p->Initialize();
|
||||
auto tooltipFont = manager::FontManager::Instance().GetImGuiFont(
|
||||
types::FontCategory::Tooltip);
|
||||
|
||||
::ImGui::BeginTooltip();
|
||||
::ImGui::PushFont(p->monospaceFont_);
|
||||
::ImGui::PushFont(tooltipFont->font());
|
||||
::ImGui::TextUnformatted(hoverText.c_str());
|
||||
::ImGui::PopFont();
|
||||
::ImGui::EndTooltip();
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
#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/types/font_types.hpp>
|
||||
#include <scwx/qt/types/text_types.hpp>
|
||||
#include <scwx/qt/util/imgui.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)
|
||||
{
|
||||
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;
|
||||
QToolTip::showText(
|
||||
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("Inconsolata")
|
||||
.arg(fontFamily)
|
||||
.arg(fontStyle)
|
||||
.arg(fontPointSize)
|
||||
.arg(QString::fromStdString(displayText).replace("\n", "<br/>")),
|
||||
tooltipParent_.get(),
|
||||
{},
|
||||
|
|
@ -97,22 +105,9 @@ void Show(const std::string& text, const QPointF& mouseGlobalPos)
|
|||
}
|
||||
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
|
||||
QFont font("Inconsolata");
|
||||
font.setPointSizeF(units::font_size::points<double>(fontSize).value());
|
||||
QFont font = manager::FontManager::Instance().GetQFont(
|
||||
types::FontCategory::Tooltip);
|
||||
tooltipLabel_->setFont(font);
|
||||
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/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 <fstream>
|
||||
|
|
@ -39,10 +44,14 @@ void VerifyDefaults()
|
|||
settings::GeneralSettings defaultGeneralSettings {};
|
||||
settings::MapSettings defaultMapSettings {};
|
||||
settings::PaletteSettings defaultPaletteSettings {};
|
||||
settings::TextSettings defaultTextSettings {};
|
||||
settings::UiSettings defaultUiSettings {};
|
||||
|
||||
EXPECT_EQ(defaultGeneralSettings, SettingsManager::general_settings());
|
||||
EXPECT_EQ(defaultMapSettings, SettingsManager::map_settings());
|
||||
EXPECT_EQ(defaultPaletteSettings, SettingsManager::palette_settings());
|
||||
EXPECT_EQ(defaultGeneralSettings, settings::GeneralSettings::Instance());
|
||||
EXPECT_EQ(defaultMapSettings, settings::MapSettings::Instance());
|
||||
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)
|
||||
|
|
@ -67,7 +76,7 @@ TEST_F(SettingsManagerTest, CreateJson)
|
|||
// Verify file doesn't exist prior to test start
|
||||
EXPECT_EQ(std::filesystem::exists(filename), false);
|
||||
|
||||
SettingsManager::ReadSettings(filename);
|
||||
SettingsManager::Instance().ReadSettings(filename);
|
||||
|
||||
EXPECT_EQ(std::filesystem::exists(filename), true);
|
||||
|
||||
|
|
@ -83,14 +92,14 @@ TEST_F(SettingsManagerTest, SettingsKeax)
|
|||
std::string filename(std::string(SCWX_TEST_DATA_DIR) +
|
||||
"/json/settings/settings-keax.json");
|
||||
|
||||
SettingsManager::ReadSettings(filename);
|
||||
SettingsManager::Instance().ReadSettings(filename);
|
||||
|
||||
EXPECT_EQ(
|
||||
SettingsManager::general_settings().default_radar_site().GetValue(),
|
||||
settings::GeneralSettings::Instance().default_radar_site().GetValue(),
|
||||
"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");
|
||||
}
|
||||
}
|
||||
|
|
@ -103,7 +112,7 @@ TEST_P(DefaultSettingsTest, DefaultSettings)
|
|||
|
||||
std::filesystem::copy_file(sourceFile, filename);
|
||||
|
||||
SettingsManager::ReadSettings(filename);
|
||||
SettingsManager::Instance().ReadSettings(filename);
|
||||
|
||||
VerifyDefaults();
|
||||
CompareFiles(filename, DEFAULT_SETTINGS_FILE);
|
||||
|
|
@ -131,7 +140,7 @@ TEST_P(BadSettingsTest, BadSettings)
|
|||
|
||||
std::filesystem::copy_file(sourceFile, filename);
|
||||
|
||||
SettingsManager::ReadSettings(filename);
|
||||
SettingsManager::Instance().ReadSettings(filename);
|
||||
|
||||
CompareFiles(filename, goodFile);
|
||||
|
||||
|
|
|
|||
|
|
@ -67,6 +67,9 @@ public:
|
|||
std::size_t pixels_ {};
|
||||
std::int32_t flags_ {};
|
||||
std::string face_ {};
|
||||
|
||||
bool IsBold() { return flags_ & 1; }
|
||||
bool IsItalic() { return flags_ & 2; }
|
||||
};
|
||||
|
||||
struct DrawItem
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue