Merge pull request #288 from AdenKoperczak/add_qt6ct_darker_theme

Add qt6ct based fusion color palettes.
This commit is contained in:
Dan Paulat 2024-11-14 05:41:18 -06:00 committed by GitHub
commit 94bb3c9430
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 465 additions and 224 deletions

3
.gitmodules vendored
View file

@ -37,3 +37,6 @@
[submodule "external/maplibre-native"]
path = external/maplibre-native
url = https://github.com/dpaulat/maplibre-gl-native.git
[submodule "external/qt6ct"]
path = external/qt6ct
url = https://github.com/trialuser02/qt6ct.git

View file

@ -35,6 +35,7 @@ Supercell Wx uses code from the following dependencies:
| [nunicode](https://bitbucket.org/alekseyt/nunicode/src/master/) | [MIT License](https://spdx.org/licenses/MIT.html) | Modified for MapLibre Native |
| [OpenSSL](https://www.openssl.org/) | [OpenSSL License](https://spdx.org/licenses/OpenSSL.html) |
| [Qt](https://www.qt.io/) | [GNU Lesser General Public License v3.0 only](https://spdx.org/licenses/LGPL-3.0-only.html) | Qt Core, Qt GUI, Qt Multimedia, Qt Network, Qt OpenGL, Qt Positioning, Qt Serial Port, Qt SQL, Qt SVG, Qt Widgets<br/>Additional Licenses: https://doc.qt.io/qt-6/licenses-used-in-qt.html |
| [qt6ct](https://github.com/trialuser02/qt6ct) | [BSD 2-Clause "Simplified" License](https://spdx.org/licenses/BSD-2-Clause.html) |
| [re2](https://github.com/google/re2) | [BSD 3-Clause "New" or "Revised" License](https://spdx.org/licenses/BSD-3-Clause.html) |
| [spdlog](https://github.com/gabime/spdlog) | [MIT License](https://spdx.org/licenses/MIT.html) |
| [SQLite](https://www.sqlite.org/) | Public Domain |
@ -67,6 +68,7 @@ Supercell Wx uses assets from the following sources:
| [Font Awesome Free](https://fontawesome.com/) | CC BY 4.0 License |
| [Inconsolata](https://fonts.google.com/specimen/Inconsolata) | SIL Open Font License |
| [NOAA's Weather and Climate Toolkit](https://www.ncdc.noaa.gov/wct/) | Public Domain | Default Color Tables |
| [qt6ct](https://github.com/trialuser02/qt6ct) | [BSD 2-Clause "Simplified" License](https://spdx.org/licenses/BSD-2-Clause.html) |
| [Roboto Flex](https://fonts.google.com/specimen/Roboto+Flex) | SIL Open Font License |
| [Supercell thunderstorm with dramatic clouds](https://www.shutterstock.com/image-photo/supercell-thunderstorm-dramatic-clouds-1354353521) | Shutterstock Standard License | Photo by John Sirlin

View file

@ -11,7 +11,8 @@ set_property(DIRECTORY
maplibre-native-qt.cmake
stb.cmake
textflowcpp.cmake
units.cmake)
units.cmake
qt6ct.cmake)
include(aws-sdk-cpp.cmake)
include(date.cmake)
@ -21,3 +22,4 @@ include(maplibre-native-qt.cmake)
include(stb.cmake)
include(textflowcpp.cmake)
include(units.cmake)
include(qt6ct.cmake)

1
external/qt6ct vendored Submodule

@ -0,0 +1 @@
Subproject commit 55dba8704c0a748b0ce9f2d3cc2cf200ca3db464

43
external/qt6ct.cmake vendored Normal file
View file

@ -0,0 +1,43 @@
cmake_minimum_required(VERSION 3.16.0)
set(PROJECT_NAME scwx-qt6ct)
find_package(QT NAMES Qt6
COMPONENTS Gui
REQUIRED)
find_package(Qt${QT_VERSION_MAJOR}
COMPONENTS Gui
REQUIRED)
#extract version from qt6ct.h
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/qt6ct/src/qt6ct-common/qt6ct.h"
QT6CT_VERSION_DATA REGEX "^#define[ \t]+QT6CT_VERSION_[A-Z]+[ \t]+[0-9]+.*$")
if(QT6CT_VERSION_DATA)
foreach(item IN ITEMS MAJOR MINOR)
string(REGEX REPLACE ".*#define[ \t]+QT6CT_VERSION_${item}[ \t]+([0-9]+).*"
"\\1" QT6CT_VERSION_${item} ${QT6CT_VERSION_DATA})
endforeach()
set(QT6CT_VERSION "${QT6CT_VERSION_MAJOR}.${QT6CT_VERSION_MINOR}")
set(QT6CT_SOVERSION "${QT6CT_VERSION_MAJOR}")
message(STATUS "qt6ct version: ${QT6CT_VERSION}")
else()
message(FATAL_ERROR "invalid header")
endif()
set(app_SRCS
qt6ct/src/qt6ct-common/qt6ct.cpp
)
add_library(qt6ct-common STATIC ${app_SRCS})
set_target_properties(qt6ct-common PROPERTIES VERSION ${QT6CT_VERSION})
target_link_libraries(qt6ct-common PRIVATE Qt6::Gui)
target_compile_definitions(qt6ct-common PRIVATE QT6CT_LIBRARY)
if (MSVC)
# Produce PDB file for debug
target_compile_options(qt6ct-common PRIVATE "$<$<CONFIG:Release>:/Zi>")
else()
target_compile_options(qt6ct-common PRIVATE "$<$<CONFIG:Release>:-g>")
endif()
target_include_directories( qt6ct-common INTERFACE qt6ct/src )

View file

@ -21,7 +21,9 @@ find_package(Python COMPONENTS Interpreter)
find_package(SQLite3)
find_package(QT NAMES Qt6
COMPONENTS Gui
COMPONENTS BuildInternals
Core
Gui
LinguistTools
Multimedia
Network
@ -30,10 +32,14 @@ find_package(QT NAMES Qt6
Positioning
SerialPort
Svg
Widgets REQUIRED)
Widgets
Sql
REQUIRED)
find_package(Qt${QT_VERSION_MAJOR}
COMPONENTS Gui
COMPONENTS BuildInternals
Core
Gui
LinguistTools
Multimedia
Network
@ -685,6 +691,7 @@ target_link_libraries(scwx-qt PUBLIC Qt${QT_VERSION_MAJOR}::Widgets
GLEW::GLEW
glm::glm
imgui
qt6ct-common
SQLite::SQLite3
wxdata)

View file

@ -70,6 +70,13 @@
<file>res/palettes/wct/SW.pal</file>
<file>res/palettes/wct/VIL.pal</file>
<file>res/palettes/wct/ZDR.pal</file>
<file alias="res/qt6ct_colors/airy.conf">../external/qt6ct/colors/airy.conf</file>
<file alias="res/qt6ct_colors/darker.conf">../external/qt6ct/colors/darker.conf</file>
<file alias="res/qt6ct_colors/dusk.conf">../external/qt6ct/colors/dusk.conf</file>
<file alias="res/qt6ct_colors/ia_ora.conf">../external/qt6ct/colors/ia_ora.conf</file>
<file alias="res/qt6ct_colors/sand.conf">../external/qt6ct/colors/sand.conf</file>
<file alias="res/qt6ct_colors/simple.conf">../external/qt6ct/colors/simple.conf</file>
<file alias="res/qt6ct_colors/waves.conf">../external/qt6ct/colors/waves.conf</file>
<file>res/textures/lines/default-1x7.png</file>
<file>res/textures/lines/test-pattern.png</file>
<file>res/textures/images/cursor-17.png</file>

View file

@ -27,6 +27,12 @@
#include <QStandardPaths>
#include <QStyleHints>
#include <QTranslator>
#include <QPalette>
#include <QStyle>
#define QT6CT_LIBRARY
#include <qt6ct-common/qt6ct.h>
#undef QT6CT_LIBRARY
static const std::string logPrefix_ = "scwx::main";
static const auto logger_ = scwx::util::Logger::Create(logPrefix_);
@ -162,6 +168,33 @@ static void ConfigureTheme(const std::vector<std::string>& args)
}
QGuiApplication::styleHints()->setColorScheme(qtColorScheme);
std::optional<std::string> paletteFile;
if (uiStyle == scwx::qt::types::UiStyle::FusionCustom) {
paletteFile = generalSettings.theme_file().GetValue();
}
else
{
paletteFile = scwx::qt::types::GetQtPaletteFile(uiStyle);
}
if (paletteFile)
{
QPalette defaultPalette = QApplication::style()->standardPalette();
QPalette palette = Qt6CT::loadColorScheme(
QString::fromStdString(*paletteFile), defaultPalette);
if (defaultPalette == palette)
{
logger_->warn("Failed to load palette file '{}'", *paletteFile);
}
else
{
logger_->info("Loaded palette file '{}'", *paletteFile);
}
QApplication::setPalette(palette);
}
}
static void

View file

@ -73,6 +73,7 @@ public:
showMapCenter_.SetDefault(false);
showMapLogo_.SetDefault(true);
theme_.SetDefault(defaultThemeValue);
themeFile_.SetDefault("");
trackLocation_.SetDefault(false);
updateNotificationsEnabled_.SetDefault(true);
warningsProvider_.SetDefault(defaultWarningsProviderValue);
@ -161,6 +162,7 @@ public:
SettingsVariable<bool> showMapCenter_ {"show_map_center"};
SettingsVariable<bool> showMapLogo_ {"show_map_logo"};
SettingsVariable<std::string> theme_ {"theme"};
SettingsVariable<std::string> themeFile_ {"theme_file"};
SettingsVariable<bool> trackLocation_ {"track_location"};
SettingsVariable<bool> updateNotificationsEnabled_ {"update_notifications"};
SettingsVariable<std::string> warningsProvider_ {"warnings_provider"};
@ -193,6 +195,7 @@ GeneralSettings::GeneralSettings() :
&p->showMapCenter_,
&p->showMapLogo_,
&p->theme_,
&p->themeFile_,
&p->trackLocation_,
&p->updateNotificationsEnabled_,
&p->warningsProvider_});
@ -325,6 +328,11 @@ SettingsVariable<std::string>& GeneralSettings::theme() const
return p->theme_;
}
SettingsVariable<std::string>& GeneralSettings::theme_file() const
{
return p->themeFile_;
}
SettingsVariable<bool>& GeneralSettings::track_location() const
{
return p->trackLocation_;
@ -385,6 +393,7 @@ bool operator==(const GeneralSettings& lhs, const GeneralSettings& rhs)
lhs.p->showMapCenter_ == rhs.p->showMapCenter_ &&
lhs.p->showMapLogo_ == rhs.p->showMapLogo_ &&
lhs.p->theme_ == rhs.p->theme_ &&
lhs.p->themeFile_ == rhs.p->themeFile_ &&
lhs.p->trackLocation_ == rhs.p->trackLocation_ &&
lhs.p->updateNotificationsEnabled_ ==
rhs.p->updateNotificationsEnabled_ &&

View file

@ -49,6 +49,7 @@ public:
SettingsVariable<bool>& show_map_center() const;
SettingsVariable<bool>& show_map_logo() const;
SettingsVariable<std::string>& theme() const;
SettingsVariable<std::string>& theme_file() const;
SettingsVariable<bool>& track_location() const;
SettingsVariable<bool>& update_notifications_enabled() const;
SettingsVariable<std::string>& warnings_provider() const;

View file

@ -15,6 +15,13 @@ static const std::unordered_map<UiStyle, std::string> qtStyleName_ {
{UiStyle::Fusion, "Fusion"},
{UiStyle::FusionLight, "Fusion"},
{UiStyle::FusionDark, "Fusion"},
{UiStyle::FusionAiry, "Fusion"},
{UiStyle::FusionDarker, "Fusion"},
{UiStyle::FusionDusk, "Fusion"},
{UiStyle::FusionIaOra, "Fusion"},
{UiStyle::FusionSand, "Fusion"},
{UiStyle::FusionWaves, "Fusion"},
{UiStyle::FusionCustom, "Fusion"},
{UiStyle::Unknown, "?"}};
static const std::unordered_map<UiStyle, std::string> uiStyleName_ {
@ -22,6 +29,13 @@ static const std::unordered_map<UiStyle, std::string> uiStyleName_ {
{UiStyle::Fusion, "Fusion"},
{UiStyle::FusionLight, "Fusion Light"},
{UiStyle::FusionDark, "Fusion Dark"},
{UiStyle::FusionAiry, "Fusion Airy"},
{UiStyle::FusionDarker, "Fusion Darker"},
{UiStyle::FusionDusk, "Fusion Dusk"},
{UiStyle::FusionIaOra, "Fusion IA Ora"},
{UiStyle::FusionSand, "Fusion Sand"},
{UiStyle::FusionWaves, "Fusion Waves"},
{UiStyle::FusionCustom, "Fusion Custom"},
{UiStyle::Unknown, "?"}};
static const std::unordered_map<UiStyle, Qt::ColorScheme> qtColorSchemeMap_ {
@ -29,8 +43,23 @@ static const std::unordered_map<UiStyle, Qt::ColorScheme> qtColorSchemeMap_ {
{UiStyle::Fusion, Qt::ColorScheme::Unknown},
{UiStyle::FusionLight, Qt::ColorScheme::Light},
{UiStyle::FusionDark, Qt::ColorScheme::Dark},
{UiStyle::FusionAiry, Qt::ColorScheme::Unknown},
{UiStyle::FusionDarker, Qt::ColorScheme::Unknown},
{UiStyle::FusionDusk, Qt::ColorScheme::Unknown},
{UiStyle::FusionIaOra, Qt::ColorScheme::Unknown},
{UiStyle::FusionSand, Qt::ColorScheme::Unknown},
{UiStyle::FusionWaves, Qt::ColorScheme::Unknown},
{UiStyle::FusionCustom, Qt::ColorScheme::Unknown},
{UiStyle::Unknown, Qt::ColorScheme::Unknown}};
static const std::unordered_map<UiStyle, std::string> paletteFile_ {
{UiStyle::FusionAiry, ":res/qt6ct_colors/airy.conf"},
{UiStyle::FusionDarker, ":res/qt6ct_colors/darker.conf"},
{UiStyle::FusionDusk, ":res/qt6ct_colors/dusk.conf"},
{UiStyle::FusionIaOra, ":res/qt6ct_colors/ia_ora.conf"},
{UiStyle::FusionSand, ":res/qt6ct_colors/sand.conf"},
{UiStyle::FusionWaves, ":res/qt6ct_colors/waves.conf"}};
SCWX_GET_ENUM(UiStyle, GetUiStyle, uiStyleName_)
Qt::ColorScheme GetQtColorScheme(UiStyle uiStyle)
@ -43,6 +72,16 @@ std::string GetQtStyleName(UiStyle uiStyle)
return qtStyleName_.at(uiStyle);
}
std::optional<std::string> GetQtPaletteFile(UiStyle uiStyle)
{
if (paletteFile_.contains(uiStyle))
{
return paletteFile_.at(uiStyle);
}
return std::nullopt;
}
std::string GetUiStyleName(UiStyle uiStyle)
{
return uiStyleName_.at(uiStyle);

View file

@ -2,6 +2,7 @@
#include <scwx/util/iterator.hpp>
#include <optional>
#include <string>
#include <Qt>
@ -26,13 +27,22 @@ enum class UiStyle
Fusion,
FusionLight,
FusionDark,
FusionAiry,
FusionDarker,
FusionDusk,
FusionIaOra,
FusionSand,
FusionWaves,
FusionCustom,
Unknown
};
typedef scwx::util::Iterator<UiStyle, UiStyle::Default, UiStyle::FusionDark>
typedef scwx::util::Iterator<UiStyle, UiStyle::Default, UiStyle::FusionCustom>
UiStyleIterator;
Qt::ColorScheme GetQtColorScheme(UiStyle uiStyle);
std::string GetQtStyleName(UiStyle uiStyle);
Qt::ColorScheme GetQtColorScheme(UiStyle uiStyle);
std::string GetQtStyleName(UiStyle uiStyle);
std::optional<std::string> GetQtPaletteFile(UiStyle uiStyle);
UiStyle GetUiStyle(const std::string& name);
std::string GetUiStyleName(UiStyle uiStyle);

View file

@ -121,6 +121,7 @@ public:
&mapboxApiKey_,
&mapTilerApiKey_,
&theme_,
&themeFile_,
&defaultAlertAction_,
&clockFormat_,
&customStyleDrawLayer_,
@ -242,6 +243,7 @@ public:
settings::SettingsInterface<std::int64_t> nmeaBaudRate_ {};
settings::SettingsInterface<std::string> nmeaSource_ {};
settings::SettingsInterface<std::string> theme_ {};
settings::SettingsInterface<std::string> themeFile_ {};
settings::SettingsInterface<std::string> warningsProvider_ {};
settings::SettingsInterface<bool> antiAliasingEnabled_ {};
settings::SettingsInterface<bool> showMapAttribution_ {};
@ -519,6 +521,21 @@ void SettingsDialogImpl::SetupGeneralTab()
settings::GeneralSettings& generalSettings =
settings::GeneralSettings::Instance();
QObject::connect(
self_->ui->themeComboBox,
&QComboBox::currentTextChanged,
self_,
[this](const QString& text)
{
types::UiStyle style = types::GetUiStyle(text.toStdString());
bool themeFileEnabled = style == types::UiStyle::FusionCustom;
self_->ui->themeFileLineEdit->setEnabled(themeFileEnabled);
self_->ui->themeFileSelectButton->setEnabled(themeFileEnabled);
self_->ui->resetThemeFileButton->setEnabled(themeFileEnabled);
});
theme_.SetSettingsVariable(generalSettings.theme());
SCWX_SETTINGS_COMBO_BOX(theme_,
self_->ui->themeComboBox,
@ -526,6 +543,45 @@ void SettingsDialogImpl::SetupGeneralTab()
types::GetUiStyleName);
theme_.SetResetButton(self_->ui->resetThemeButton);
themeFile_.SetSettingsVariable(generalSettings.theme_file());
themeFile_.SetEditWidget(self_->ui->themeFileLineEdit);
themeFile_.SetResetButton(self_->ui->resetThemeFileButton);
themeFile_.EnableTrimming();
QObject::connect(
self_->ui->themeFileSelectButton,
&QAbstractButton::clicked,
self_,
[this]()
{
static const std::string themeFilter = "Qt6Ct Theme File (*.conf)";
static const std::string allFilter = "All Files (*)";
QFileDialog* dialog = new QFileDialog(self_);
dialog->setFileMode(QFileDialog::ExistingFile);
dialog->setNameFilters(
{QObject::tr(themeFilter.c_str()), QObject::tr(allFilter.c_str())});
dialog->setAttribute(Qt::WA_DeleteOnClose);
QObject::connect(
dialog,
&QFileDialog::fileSelected,
self_,
[this](const QString& file)
{
QString path = QDir::toNativeSeparators(file);
logger_->info("Selected theme file: {}", path.toStdString());
self_->ui->themeFileLineEdit->setText(path);
// setText does not emit the textEdited signal
Q_EMIT self_->ui->themeFileLineEdit->textEdited(path);
});
dialog->open();
});
auto radarSites = config::RadarSite::GetAll();
// Sort radar sites by ID

View file

@ -135,9 +135,9 @@
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>513</width>
<height>622</height>
<y>-133</y>
<width>511</width>
<height>676</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
@ -159,15 +159,39 @@
<property name="bottomMargin">
<number>0</number>
</property>
<item row="13" column="0">
<widget class="QLabel" name="label_6">
<item row="3" column="3">
<widget class="QToolButton" name="radarSiteSelectButton">
<property name="text">
<string>MapTiler API Key</string>
<string>...</string>
</property>
</widget>
</item>
<item row="6" column="4">
<widget class="QToolButton" name="resetGridHeightButton">
<item row="12" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Mapbox API Key</string>
</property>
</widget>
</item>
<item row="15" column="0">
<widget class="QLabel" name="label_27">
<property name="text">
<string>Custom Map Layer</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QComboBox" name="radarSiteComboBox"/>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_23">
<property name="text">
<string>GPS Plugin</string>
</property>
</widget>
</item>
<item row="9" column="4">
<widget class="QToolButton" name="resetNmeaSourceButton">
<property name="text">
<string>...</string>
</property>
@ -180,15 +204,18 @@
<item row="11" column="2">
<widget class="QComboBox" name="mapProviderComboBox"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_21">
<item row="14" column="2">
<widget class="QLineEdit" name="customMapUrlLineEdit"/>
</item>
<item row="9" column="3">
<widget class="QToolButton" name="gpsSourceSelectButton">
<property name="text">
<string>Default Time Zone</string>
<string>...</string>
</property>
</widget>
</item>
<item row="12" column="4">
<widget class="QToolButton" name="resetMapboxApiKeyButton">
<item row="15" column="4">
<widget class="QToolButton" name="resetCustomMapLayerButton">
<property name="text">
<string>...</string>
</property>
@ -198,30 +225,34 @@
</property>
</widget>
</item>
<item row="6" column="2">
<widget class="QSpinBox" name="gridHeightSpinBox"/>
</item>
<item row="4" column="4">
<widget class="QToolButton" name="resetDefaultTimeZoneButton">
<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="11" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Map Provider</string>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QComboBox" name="defaultTimeZoneComboBox"/>
</item>
<item row="6" column="2">
<widget class="QSpinBox" name="gridHeightSpinBox"/>
</item>
<item row="11" column="4">
<widget class="QToolButton" name="resetMapProviderButton">
<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="14" column="4">
<widget class="QToolButton" name="resetCustomMapUrlButton">
<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="18" column="4">
<widget class="QToolButton" name="resetThemeButton">
<property name="text">
@ -233,77 +264,9 @@
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QComboBox" name="clockFormatComboBox"/>
</item>
<item row="3" column="2">
<widget class="QComboBox" name="radarSiteComboBox"/>
</item>
<item row="9" column="3">
<widget class="QToolButton" name="gpsSourceSelectButton">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="12" column="2">
<widget class="QLineEdit" name="mapboxApiKeyLineEdit">
<property name="echoMode">
<enum>QLineEdit::EchoMode::Password</enum>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_23">
<property name="text">
<string>GPS Plugin</string>
</property>
</widget>
</item>
<item row="10" column="0">
<widget class="QLabel" name="label_24">
<property name="text">
<string>GPS Baud Rate</string>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QSpinBox" name="gridWidthSpinBox"/>
</item>
<item row="3" column="3">
<widget class="QToolButton" name="radarSiteSelectButton">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="21" column="4">
<widget class="QToolButton" name="resetWarningsProviderButton">
<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="5" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Grid Width</string>
</property>
</widget>
</item>
<item row="9" column="2">
<widget class="QLineEdit" name="nmeaSourceLineEdit"/>
</item>
<item row="18" column="2">
<widget class="QComboBox" name="themeComboBox"/>
</item>
<item row="8" column="2">
<widget class="QComboBox" name="positioningPluginComboBox"/>
</item>
<item row="9" column="0">
<widget class="QLabel" name="label_25">
<property name="text">
@ -311,9 +274,16 @@
</property>
</widget>
</item>
<item row="21" column="2">
<item row="22" column="2">
<widget class="QLineEdit" name="warningsProviderLineEdit"/>
</item>
<item row="22" column="0">
<widget class="QLabel" name="label_22">
<property name="text">
<string>Warnings Provider</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label">
<property name="text">
@ -339,8 +309,8 @@
</property>
</widget>
</item>
<item row="2" column="4">
<widget class="QToolButton" name="resetDefaultAlertActionButton">
<item row="13" column="4">
<widget class="QToolButton" name="resetMapTilerApiKeyButton">
<property name="text">
<string>...</string>
</property>
@ -350,45 +320,66 @@
</property>
</widget>
</item>
<item row="18" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Theme</string>
<item row="10" column="2">
<widget class="QSpinBox" name="nmeaBaudRateSpinBox">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>999999999</number>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QToolButton" name="resetClockFormatButton">
<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="12" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Mapbox API Key</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_20">
<property name="text">
<string>Clock Format</string>
</property>
</widget>
</item>
<item row="13" column="2">
<widget class="QLineEdit" name="mapTilerApiKeyLineEdit">
<item row="12" column="2">
<widget class="QLineEdit" name="mapboxApiKeyLineEdit">
<property name="echoMode">
<enum>QLineEdit::EchoMode::Password</enum>
</property>
</widget>
</item>
<item row="22" column="4">
<widget class="QToolButton" name="resetWarningsProviderButton">
<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="9" column="2">
<widget class="QLineEdit" name="nmeaSourceLineEdit"/>
</item>
<item row="10" column="0">
<widget class="QLabel" name="label_24">
<property name="text">
<string>GPS Baud Rate</string>
</property>
</widget>
</item>
<item row="6" column="4">
<widget class="QToolButton" name="resetGridHeightButton">
<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="12" column="4">
<widget class="QToolButton" name="resetMapboxApiKeyButton">
<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="5" column="4">
<widget class="QToolButton" name="resetGridWidthButton">
<property name="text">
@ -400,8 +391,8 @@
</property>
</widget>
</item>
<item row="13" column="4">
<widget class="QToolButton" name="resetMapTilerApiKeyButton">
<item row="4" column="4">
<widget class="QToolButton" name="resetDefaultTimeZoneButton">
<property name="text">
<string>...</string>
</property>
@ -411,35 +402,56 @@
</property>
</widget>
</item>
<item row="11" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Map Provider</string>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QSpinBox" name="gridWidthSpinBox"/>
</item>
<item row="18" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Theme</string>
</property>
</widget>
</item>
<item row="13" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>MapTiler API Key</string>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QToolButton" name="resetClockFormatButton">
<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="15" column="2">
<widget class="QLineEdit" name="customMapLayerLineEdit"/>
</item>
<item row="14" column="0">
<widget class="QLabel" name="label_26">
<property name="text">
<string>Custom Map URL</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QComboBox" name="defaultAlertActionComboBox"/>
</item>
<item row="21" column="0">
<widget class="QLabel" name="label_22">
<property name="text">
<string>Warnings Provider</string>
</property>
</widget>
</item>
<item row="10" column="2">
<widget class="QSpinBox" name="nmeaBaudRateSpinBox">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>999999999</number>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="defaultAlertActionLabel">
<property name="text">
<string>Default Alert Action</string>
</property>
</widget>
</item>
<item row="11" column="4">
<widget class="QToolButton" name="resetMapProviderButton">
<item row="10" column="4">
<widget class="QToolButton" name="resetNmeaBaudRateButton">
<property name="text">
<string>...</string>
</property>
@ -449,6 +461,38 @@
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_20">
<property name="text">
<string>Clock Format</string>
</property>
</widget>
</item>
<item row="2" 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="5" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Grid Width</string>
</property>
</widget>
</item>
<item row="13" column="2">
<widget class="QLineEdit" name="mapTilerApiKeyLineEdit">
<property name="echoMode">
<enum>QLineEdit::EchoMode::Password</enum>
</property>
</widget>
</item>
<item row="8" column="4">
<widget class="QToolButton" name="resetPositioningPluginButton">
<property name="text">
@ -460,61 +504,45 @@
</property>
</widget>
</item>
<item row="9" column="4">
<widget class="QToolButton" name="resetNmeaSourceButton">
<item row="4" column="0">
<widget class="QLabel" name="label_21">
<property name="text">
<string>Default Time Zone</string>
</property>
</widget>
</item>
<item row="2" 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="positioningPluginComboBox"/>
</item>
<item row="1" column="2">
<widget class="QComboBox" name="clockFormatComboBox"/>
</item>
<item row="19" column="0">
<widget class="QLabel" name="label_30">
<property name="text">
<string>Theme File</string>
</property>
</widget>
</item>
<item row="19" column="2">
<widget class="QLineEdit" name="themeFileLineEdit"/>
</item>
<item row="19" column="3">
<widget class="QToolButton" name="themeFileSelectButton">
<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="10" column="4">
<widget class="QToolButton" name="resetNmeaBaudRateButton">
<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="14" column="2">
<widget class="QLineEdit" name="customMapUrlLineEdit"/>
</item>
<item row="15" column="2">
<widget class="QLineEdit" name="customMapLayerLineEdit"/>
</item>
<item row="14" column="0">
<widget class="QLabel" name="label_26">
<property name="text">
<string>Custom Map URL</string>
</property>
</widget>
</item>
<item row="15" column="0">
<widget class="QLabel" name="label_27">
<property name="text">
<string>Custom Map Layer</string>
</property>
</widget>
</item>
<item row="14" column="4">
<widget class="QToolButton" name="resetCustomMapUrlButton">
<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="15" column="4">
<widget class="QToolButton" name="resetCustomMapLayerButton">
<item row="19" column="4">
<widget class="QToolButton" name="resetThemeFileButton">
<property name="text">
<string>...</string>
</property>
@ -610,8 +638,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>506</width>
<height>383</height>
<width>98</width>
<height>28</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_3">

@ -1 +1 @@
Subproject commit 40a367ca89b5b197353ca58dea547a3e3407c7f3
Subproject commit a642d730bd8d6c9b291b90e61b3a3a389139f2f6