mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-31 13:20:06 +00:00 
			
		
		
		
	
						commit
						83e3291db2
					
				
					 27 changed files with 1466 additions and 68 deletions
				
			
		
							
								
								
									
										1
									
								
								scwx-qt/res/icons/font-awesome-6/keyboard-regular.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								scwx-qt/res/icons/font-awesome-6/keyboard-regular.svg
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1 @@ | ||||||
|  | <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--!Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M64 112c-8.8 0-16 7.2-16 16V384c0 8.8 7.2 16 16 16H512c8.8 0 16-7.2 16-16V128c0-8.8-7.2-16-16-16H64zM0 128C0 92.7 28.7 64 64 64H512c35.3 0 64 28.7 64 64V384c0 35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V128zM176 320H400c8.8 0 16 7.2 16 16v16c0 8.8-7.2 16-16 16H176c-8.8 0-16-7.2-16-16V336c0-8.8 7.2-16 16-16zm-72-72c0-8.8 7.2-16 16-16h16c8.8 0 16 7.2 16 16v16c0 8.8-7.2 16-16 16H120c-8.8 0-16-7.2-16-16V248zm16-96h16c8.8 0 16 7.2 16 16v16c0 8.8-7.2 16-16 16H120c-8.8 0-16-7.2-16-16V168c0-8.8 7.2-16 16-16zm64 96c0-8.8 7.2-16 16-16h16c8.8 0 16 7.2 16 16v16c0 8.8-7.2 16-16 16H200c-8.8 0-16-7.2-16-16V248zm16-96h16c8.8 0 16 7.2 16 16v16c0 8.8-7.2 16-16 16H200c-8.8 0-16-7.2-16-16V168c0-8.8 7.2-16 16-16zm64 96c0-8.8 7.2-16 16-16h16c8.8 0 16 7.2 16 16v16c0 8.8-7.2 16-16 16H280c-8.8 0-16-7.2-16-16V248zm16-96h16c8.8 0 16 7.2 16 16v16c0 8.8-7.2 16-16 16H280c-8.8 0-16-7.2-16-16V168c0-8.8 7.2-16 16-16zm64 96c0-8.8 7.2-16 16-16h16c8.8 0 16 7.2 16 16v16c0 8.8-7.2 16-16 16H360c-8.8 0-16-7.2-16-16V248zm16-96h16c8.8 0 16 7.2 16 16v16c0 8.8-7.2 16-16 16H360c-8.8 0-16-7.2-16-16V168c0-8.8 7.2-16 16-16zm64 96c0-8.8 7.2-16 16-16h16c8.8 0 16 7.2 16 16v16c0 8.8-7.2 16-16 16H440c-8.8 0-16-7.2-16-16V248zm16-96h16c8.8 0 16 7.2 16 16v16c0 8.8-7.2 16-16 16H440c-8.8 0-16-7.2-16-16V168c0-8.8 7.2-16 16-16z"/></svg> | ||||||
| After Width: | Height: | Size: 1.5 KiB | 
|  | @ -88,6 +88,7 @@ set(SRC_GL_DRAW source/scwx/qt/gl/draw/draw_item.cpp | ||||||
| set(HDR_MANAGER source/scwx/qt/manager/alert_manager.hpp | set(HDR_MANAGER source/scwx/qt/manager/alert_manager.hpp | ||||||
|                 source/scwx/qt/manager/download_manager.hpp |                 source/scwx/qt/manager/download_manager.hpp | ||||||
|                 source/scwx/qt/manager/font_manager.hpp |                 source/scwx/qt/manager/font_manager.hpp | ||||||
|  |                 source/scwx/qt/manager/hotkey_manager.hpp | ||||||
|                 source/scwx/qt/manager/media_manager.hpp |                 source/scwx/qt/manager/media_manager.hpp | ||||||
|                 source/scwx/qt/manager/placefile_manager.hpp |                 source/scwx/qt/manager/placefile_manager.hpp | ||||||
|                 source/scwx/qt/manager/position_manager.hpp |                 source/scwx/qt/manager/position_manager.hpp | ||||||
|  | @ -101,6 +102,7 @@ set(HDR_MANAGER source/scwx/qt/manager/alert_manager.hpp | ||||||
| set(SRC_MANAGER source/scwx/qt/manager/alert_manager.cpp | set(SRC_MANAGER source/scwx/qt/manager/alert_manager.cpp | ||||||
|                 source/scwx/qt/manager/download_manager.cpp |                 source/scwx/qt/manager/download_manager.cpp | ||||||
|                 source/scwx/qt/manager/font_manager.cpp |                 source/scwx/qt/manager/font_manager.cpp | ||||||
|  |                 source/scwx/qt/manager/hotkey_manager.cpp | ||||||
|                 source/scwx/qt/manager/media_manager.cpp |                 source/scwx/qt/manager/media_manager.cpp | ||||||
|                 source/scwx/qt/manager/placefile_manager.cpp |                 source/scwx/qt/manager/placefile_manager.cpp | ||||||
|                 source/scwx/qt/manager/position_manager.cpp |                 source/scwx/qt/manager/position_manager.cpp | ||||||
|  | @ -162,6 +164,7 @@ set(SRC_REQUEST source/scwx/qt/request/download_request.cpp | ||||||
|                 source/scwx/qt/request/nexrad_file_request.cpp) |                 source/scwx/qt/request/nexrad_file_request.cpp) | ||||||
| set(HDR_SETTINGS source/scwx/qt/settings/audio_settings.hpp | set(HDR_SETTINGS source/scwx/qt/settings/audio_settings.hpp | ||||||
|                  source/scwx/qt/settings/general_settings.hpp |                  source/scwx/qt/settings/general_settings.hpp | ||||||
|  |                  source/scwx/qt/settings/hotkey_settings.hpp | ||||||
|                  source/scwx/qt/settings/map_settings.hpp |                  source/scwx/qt/settings/map_settings.hpp | ||||||
|                  source/scwx/qt/settings/palette_settings.hpp |                  source/scwx/qt/settings/palette_settings.hpp | ||||||
|                  source/scwx/qt/settings/product_settings.hpp |                  source/scwx/qt/settings/product_settings.hpp | ||||||
|  | @ -176,6 +179,7 @@ set(HDR_SETTINGS source/scwx/qt/settings/audio_settings.hpp | ||||||
|                  source/scwx/qt/settings/ui_settings.hpp) |                  source/scwx/qt/settings/ui_settings.hpp) | ||||||
| set(SRC_SETTINGS source/scwx/qt/settings/audio_settings.cpp | set(SRC_SETTINGS source/scwx/qt/settings/audio_settings.cpp | ||||||
|                  source/scwx/qt/settings/general_settings.cpp |                  source/scwx/qt/settings/general_settings.cpp | ||||||
|  |                  source/scwx/qt/settings/hotkey_settings.cpp | ||||||
|                  source/scwx/qt/settings/map_settings.cpp |                  source/scwx/qt/settings/map_settings.cpp | ||||||
|                  source/scwx/qt/settings/palette_settings.cpp |                  source/scwx/qt/settings/palette_settings.cpp | ||||||
|                  source/scwx/qt/settings/product_settings.cpp |                  source/scwx/qt/settings/product_settings.cpp | ||||||
|  | @ -191,6 +195,7 @@ set(HDR_TYPES source/scwx/qt/types/alert_types.hpp | ||||||
|               source/scwx/qt/types/event_types.hpp |               source/scwx/qt/types/event_types.hpp | ||||||
|               source/scwx/qt/types/font_types.hpp |               source/scwx/qt/types/font_types.hpp | ||||||
|               source/scwx/qt/types/github_types.hpp |               source/scwx/qt/types/github_types.hpp | ||||||
|  |               source/scwx/qt/types/hotkey_types.hpp | ||||||
|               source/scwx/qt/types/icon_types.hpp |               source/scwx/qt/types/icon_types.hpp | ||||||
|               source/scwx/qt/types/imgui_font.hpp |               source/scwx/qt/types/imgui_font.hpp | ||||||
|               source/scwx/qt/types/layer_types.hpp |               source/scwx/qt/types/layer_types.hpp | ||||||
|  | @ -205,6 +210,7 @@ set(HDR_TYPES source/scwx/qt/types/alert_types.hpp | ||||||
|               source/scwx/qt/types/time_types.hpp) |               source/scwx/qt/types/time_types.hpp) | ||||||
| set(SRC_TYPES source/scwx/qt/types/alert_types.cpp | set(SRC_TYPES source/scwx/qt/types/alert_types.cpp | ||||||
|               source/scwx/qt/types/github_types.cpp |               source/scwx/qt/types/github_types.cpp | ||||||
|  |               source/scwx/qt/types/hotkey_types.cpp | ||||||
|               source/scwx/qt/types/icon_types.cpp |               source/scwx/qt/types/icon_types.cpp | ||||||
|               source/scwx/qt/types/imgui_font.cpp |               source/scwx/qt/types/imgui_font.cpp | ||||||
|               source/scwx/qt/types/layer_types.cpp |               source/scwx/qt/types/layer_types.cpp | ||||||
|  | @ -225,6 +231,7 @@ set(HDR_UI source/scwx/qt/ui/about_dialog.hpp | ||||||
|            source/scwx/qt/ui/county_dialog.hpp |            source/scwx/qt/ui/county_dialog.hpp | ||||||
|            source/scwx/qt/ui/download_dialog.hpp |            source/scwx/qt/ui/download_dialog.hpp | ||||||
|            source/scwx/qt/ui/flow_layout.hpp |            source/scwx/qt/ui/flow_layout.hpp | ||||||
|  |            source/scwx/qt/ui/hotkey_edit.hpp | ||||||
|            source/scwx/qt/ui/imgui_debug_dialog.hpp |            source/scwx/qt/ui/imgui_debug_dialog.hpp | ||||||
|            source/scwx/qt/ui/imgui_debug_widget.hpp |            source/scwx/qt/ui/imgui_debug_widget.hpp | ||||||
|            source/scwx/qt/ui/layer_dialog.hpp |            source/scwx/qt/ui/layer_dialog.hpp | ||||||
|  | @ -247,6 +254,7 @@ set(SRC_UI source/scwx/qt/ui/about_dialog.cpp | ||||||
|            source/scwx/qt/ui/county_dialog.cpp |            source/scwx/qt/ui/county_dialog.cpp | ||||||
|            source/scwx/qt/ui/download_dialog.cpp |            source/scwx/qt/ui/download_dialog.cpp | ||||||
|            source/scwx/qt/ui/flow_layout.cpp |            source/scwx/qt/ui/flow_layout.cpp | ||||||
|  |            source/scwx/qt/ui/hotkey_edit.cpp | ||||||
|            source/scwx/qt/ui/imgui_debug_dialog.cpp |            source/scwx/qt/ui/imgui_debug_dialog.cpp | ||||||
|            source/scwx/qt/ui/imgui_debug_widget.cpp |            source/scwx/qt/ui/imgui_debug_widget.cpp | ||||||
|            source/scwx/qt/ui/layer_dialog.cpp |            source/scwx/qt/ui/layer_dialog.cpp | ||||||
|  | @ -276,6 +284,10 @@ set(UI_UI  source/scwx/qt/ui/about_dialog.ui | ||||||
|            source/scwx/qt/ui/radar_site_dialog.ui |            source/scwx/qt/ui/radar_site_dialog.ui | ||||||
|            source/scwx/qt/ui/settings_dialog.ui |            source/scwx/qt/ui/settings_dialog.ui | ||||||
|            source/scwx/qt/ui/update_dialog.ui) |            source/scwx/qt/ui/update_dialog.ui) | ||||||
|  | set(HDR_UI_SETTINGS source/scwx/qt/ui/settings/hotkey_settings_widget.hpp | ||||||
|  |                     source/scwx/qt/ui/settings/settings_page_widget.hpp) | ||||||
|  | set(SRC_UI_SETTINGS source/scwx/qt/ui/settings/hotkey_settings_widget.cpp | ||||||
|  |                     source/scwx/qt/ui/settings/settings_page_widget.cpp) | ||||||
| set(HDR_UI_SETUP source/scwx/qt/ui/setup/audio_codec_page.hpp | set(HDR_UI_SETUP source/scwx/qt/ui/setup/audio_codec_page.hpp | ||||||
|                  source/scwx/qt/ui/setup/finish_page.hpp |                  source/scwx/qt/ui/setup/finish_page.hpp | ||||||
|                  source/scwx/qt/ui/setup/map_layout_page.hpp |                  source/scwx/qt/ui/setup/map_layout_page.hpp | ||||||
|  | @ -387,6 +399,8 @@ set(PROJECT_SOURCES ${HDR_MAIN} | ||||||
|                     ${HDR_UI} |                     ${HDR_UI} | ||||||
|                     ${SRC_UI} |                     ${SRC_UI} | ||||||
|                     ${UI_UI} |                     ${UI_UI} | ||||||
|  |                     ${HDR_UI_SETTINGS} | ||||||
|  |                     ${SRC_UI_SETTINGS} | ||||||
|                     ${HDR_UI_SETUP} |                     ${HDR_UI_SETUP} | ||||||
|                     ${SRC_UI_SETUP} |                     ${SRC_UI_SETUP} | ||||||
|                     ${HDR_UTIL} |                     ${HDR_UTIL} | ||||||
|  | @ -424,6 +438,8 @@ source_group("Header Files\\types"     FILES ${HDR_TYPES}) | ||||||
| source_group("Source Files\\types"        FILES ${SRC_TYPES}) | source_group("Source Files\\types"        FILES ${SRC_TYPES}) | ||||||
| source_group("Header Files\\ui"           FILES ${HDR_UI}) | source_group("Header Files\\ui"           FILES ${HDR_UI}) | ||||||
| source_group("Source Files\\ui"           FILES ${SRC_UI}) | source_group("Source Files\\ui"           FILES ${SRC_UI}) | ||||||
|  | source_group("Header Files\\ui\\settings" FILES ${HDR_UI_SETTINGS}) | ||||||
|  | source_group("Source Files\\ui\\settings" FILES ${SRC_UI_SETTINGS}) | ||||||
| source_group("Header Files\\ui\\setup"    FILES ${HDR_UI_SETUP}) | source_group("Header Files\\ui\\setup"    FILES ${HDR_UI_SETUP}) | ||||||
| source_group("Source Files\\ui\\setup"    FILES ${SRC_UI_SETUP}) | source_group("Source Files\\ui\\setup"    FILES ${SRC_UI_SETUP}) | ||||||
| source_group("UI Files\\ui"               FILES ${UI_UI}) | source_group("UI Files\\ui"               FILES ${UI_UI}) | ||||||
|  |  | ||||||
|  | @ -39,6 +39,7 @@ | ||||||
|         <file>res/icons/font-awesome-6/gears-solid.svg</file> |         <file>res/icons/font-awesome-6/gears-solid.svg</file> | ||||||
|         <file>res/icons/font-awesome-6/github.svg</file> |         <file>res/icons/font-awesome-6/github.svg</file> | ||||||
|         <file>res/icons/font-awesome-6/house-solid.svg</file> |         <file>res/icons/font-awesome-6/house-solid.svg</file> | ||||||
|  |         <file>res/icons/font-awesome-6/keyboard-regular.svg</file> | ||||||
|         <file>res/icons/font-awesome-6/layer-group-solid.svg</file> |         <file>res/icons/font-awesome-6/layer-group-solid.svg</file> | ||||||
|         <file>res/icons/font-awesome-6/palette-solid.svg</file> |         <file>res/icons/font-awesome-6/palette-solid.svg</file> | ||||||
|         <file>res/icons/font-awesome-6/pause-solid.svg</file> |         <file>res/icons/font-awesome-6/pause-solid.svg</file> | ||||||
|  |  | ||||||
|  | @ -4,6 +4,7 @@ | ||||||
| #include <scwx/qt/main/application.hpp> | #include <scwx/qt/main/application.hpp> | ||||||
| #include <scwx/qt/main/versions.hpp> | #include <scwx/qt/main/versions.hpp> | ||||||
| #include <scwx/qt/manager/alert_manager.hpp> | #include <scwx/qt/manager/alert_manager.hpp> | ||||||
|  | #include <scwx/qt/manager/hotkey_manager.hpp> | ||||||
| #include <scwx/qt/manager/placefile_manager.hpp> | #include <scwx/qt/manager/placefile_manager.hpp> | ||||||
| #include <scwx/qt/manager/position_manager.hpp> | #include <scwx/qt/manager/position_manager.hpp> | ||||||
| #include <scwx/qt/manager/radar_product_manager.hpp> | #include <scwx/qt/manager/radar_product_manager.hpp> | ||||||
|  | @ -42,6 +43,7 @@ | ||||||
| #include <boost/asio/post.hpp> | #include <boost/asio/post.hpp> | ||||||
| #include <boost/asio/thread_pool.hpp> | #include <boost/asio/thread_pool.hpp> | ||||||
| #include <QDesktopServices> | #include <QDesktopServices> | ||||||
|  | #include <QKeyEvent> | ||||||
| #include <QFileDialog> | #include <QFileDialog> | ||||||
| #include <QMessageBox> | #include <QMessageBox> | ||||||
| #include <QSplitter> | #include <QSplitter> | ||||||
|  | @ -198,6 +200,8 @@ public: | ||||||
|    QTimer clockTimer_ {}; |    QTimer clockTimer_ {}; | ||||||
| 
 | 
 | ||||||
|    std::shared_ptr<manager::AlertManager>  alertManager_; |    std::shared_ptr<manager::AlertManager>  alertManager_; | ||||||
|  |    std::shared_ptr<manager::HotkeyManager> hotkeyManager_ { | ||||||
|  |       manager::HotkeyManager::Instance()}; | ||||||
|    std::shared_ptr<manager::PlacefileManager> placefileManager_; |    std::shared_ptr<manager::PlacefileManager> placefileManager_; | ||||||
|    std::shared_ptr<manager::PositionManager>  positionManager_; |    std::shared_ptr<manager::PositionManager>  positionManager_; | ||||||
|    std::shared_ptr<manager::TextEventManager> textEventManager_; |    std::shared_ptr<manager::TextEventManager> textEventManager_; | ||||||
|  | @ -398,6 +402,24 @@ MainWindow::~MainWindow() | ||||||
|    delete ui; |    delete ui; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void MainWindow::keyPressEvent(QKeyEvent* ev) | ||||||
|  | { | ||||||
|  |    if (p->hotkeyManager_->HandleKeyPress(ev)) | ||||||
|  |    { | ||||||
|  |       p->activeMap_->update(); | ||||||
|  |       ev->accept(); | ||||||
|  |    } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void MainWindow::keyReleaseEvent(QKeyEvent* ev) | ||||||
|  | { | ||||||
|  |    if (p->hotkeyManager_->HandleKeyRelease(ev)) | ||||||
|  |    { | ||||||
|  |       p->activeMap_->update(); | ||||||
|  |       ev->accept(); | ||||||
|  |    } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void MainWindow::showEvent(QShowEvent* event) | void MainWindow::showEvent(QShowEvent* event) | ||||||
| { | { | ||||||
|    QMainWindow::showEvent(event); |    QMainWindow::showEvent(event); | ||||||
|  |  | ||||||
|  | @ -26,6 +26,8 @@ public: | ||||||
|    MainWindow(QWidget* parent = nullptr); |    MainWindow(QWidget* parent = nullptr); | ||||||
|    ~MainWindow(); |    ~MainWindow(); | ||||||
| 
 | 
 | ||||||
|  |    void keyPressEvent(QKeyEvent* ev) override final; | ||||||
|  |    void keyReleaseEvent(QKeyEvent* ev) override final; | ||||||
|    void showEvent(QShowEvent* event) override; |    void showEvent(QShowEvent* event) override; | ||||||
| 
 | 
 | ||||||
| signals: | signals: | ||||||
|  |  | ||||||
							
								
								
									
										128
									
								
								scwx-qt/source/scwx/qt/manager/hotkey_manager.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								scwx-qt/source/scwx/qt/manager/hotkey_manager.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,128 @@ | ||||||
|  | #include <scwx/qt/manager/hotkey_manager.hpp> | ||||||
|  | #include <scwx/qt/settings/hotkey_settings.hpp> | ||||||
|  | #include <scwx/util/logger.hpp> | ||||||
|  | 
 | ||||||
|  | #include <vector> | ||||||
|  | 
 | ||||||
|  | #include <boost/container/flat_map.hpp> | ||||||
|  | #include <QKeyEvent> | ||||||
|  | #include <QKeySequence> | ||||||
|  | 
 | ||||||
|  | namespace scwx | ||||||
|  | { | ||||||
|  | namespace qt | ||||||
|  | { | ||||||
|  | namespace manager | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | static const std::string logPrefix_ = "scwx::qt::manager::hotkey_manager"; | ||||||
|  | static const auto        logger_    = scwx::util::Logger::Create(logPrefix_); | ||||||
|  | 
 | ||||||
|  | class HotkeyManager::Impl | ||||||
|  | { | ||||||
|  | public: | ||||||
|  |    explicit Impl() | ||||||
|  |    { | ||||||
|  |       auto& hotkeySettings = settings::HotkeySettings::Instance(); | ||||||
|  | 
 | ||||||
|  |       for (auto hotkey : types::HotkeyIterator()) | ||||||
|  |       { | ||||||
|  |          auto& hotkeyVariable = hotkeySettings.hotkey(hotkey); | ||||||
|  | 
 | ||||||
|  |          UpdateHotkey(hotkey, hotkeyVariable.GetValue()); | ||||||
|  | 
 | ||||||
|  |          callbacks_.emplace_back(hotkeyVariable, | ||||||
|  |                                  hotkeyVariable.RegisterValueChangedCallback( | ||||||
|  |                                     [this, hotkey](const std::string& value) | ||||||
|  |                                     { UpdateHotkey(hotkey, value); })); | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    ~Impl() | ||||||
|  |    { | ||||||
|  |       for (auto& callback : callbacks_) | ||||||
|  |       { | ||||||
|  |          callback.first.UnregisterValueChangedCallback(callback.second); | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    void UpdateHotkey(types::Hotkey hotkey, const std::string& value); | ||||||
|  | 
 | ||||||
|  |    std::vector< | ||||||
|  |       std::pair<settings::SettingsVariable<std::string>&, boost::uuids::uuid>> | ||||||
|  |                                                            callbacks_ {}; | ||||||
|  |    boost::container::flat_map<types::Hotkey, QKeySequence> hotkeys_ {}; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | HotkeyManager::HotkeyManager() : p(std::make_unique<Impl>()) {} | ||||||
|  | HotkeyManager::~HotkeyManager() = default; | ||||||
|  | 
 | ||||||
|  | void HotkeyManager::Impl::UpdateHotkey(types::Hotkey      hotkey, | ||||||
|  |                                        const std::string& value) | ||||||
|  | { | ||||||
|  |    hotkeys_.insert_or_assign(hotkey, | ||||||
|  |                              QKeySequence {QString::fromStdString(value)}); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool HotkeyManager::HandleKeyPress(QKeyEvent* ev) | ||||||
|  | { | ||||||
|  |    logger_->trace("HandleKeyPress: {}, {}", | ||||||
|  |                   ev->keyCombination().toCombined(), | ||||||
|  |                   ev->isAutoRepeat()); | ||||||
|  | 
 | ||||||
|  |    bool hotkeyPressed = false; | ||||||
|  | 
 | ||||||
|  |    for (auto& hotkey : p->hotkeys_) | ||||||
|  |    { | ||||||
|  |       if (hotkey.second.count() == 1 && | ||||||
|  |           hotkey.second[0] == ev->keyCombination()) | ||||||
|  |       { | ||||||
|  |          hotkeyPressed = true; | ||||||
|  |          Q_EMIT HotkeyPressed(hotkey.first, ev->isAutoRepeat()); | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    return hotkeyPressed; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool HotkeyManager::HandleKeyRelease(QKeyEvent* ev) | ||||||
|  | { | ||||||
|  |    logger_->trace("HandleKeyRelease: {}", ev->keyCombination().toCombined()); | ||||||
|  | 
 | ||||||
|  |    bool hotkeyReleased = false; | ||||||
|  | 
 | ||||||
|  |    for (auto& hotkey : p->hotkeys_) | ||||||
|  |    { | ||||||
|  |       if (hotkey.second.count() == 1 && | ||||||
|  |           hotkey.second[0] == ev->keyCombination()) | ||||||
|  |       { | ||||||
|  |          hotkeyReleased = true; | ||||||
|  |          Q_EMIT HotkeyReleased(hotkey.first); | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    return hotkeyReleased; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | std::shared_ptr<HotkeyManager> HotkeyManager::Instance() | ||||||
|  | { | ||||||
|  |    static std::weak_ptr<HotkeyManager> hotkeyManagerReference_ {}; | ||||||
|  |    static std::mutex                   instanceMutex_ {}; | ||||||
|  | 
 | ||||||
|  |    std::unique_lock lock(instanceMutex_); | ||||||
|  | 
 | ||||||
|  |    std::shared_ptr<HotkeyManager> hotkeyManager = | ||||||
|  |       hotkeyManagerReference_.lock(); | ||||||
|  | 
 | ||||||
|  |    if (hotkeyManager == nullptr) | ||||||
|  |    { | ||||||
|  |       hotkeyManager           = std::make_shared<HotkeyManager>(); | ||||||
|  |       hotkeyManagerReference_ = hotkeyManager; | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    return hotkeyManager; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } // namespace manager
 | ||||||
|  | } // namespace qt
 | ||||||
|  | } // namespace scwx
 | ||||||
							
								
								
									
										43
									
								
								scwx-qt/source/scwx/qt/manager/hotkey_manager.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								scwx-qt/source/scwx/qt/manager/hotkey_manager.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,43 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <scwx/qt/types/hotkey_types.hpp> | ||||||
|  | 
 | ||||||
|  | #include <memory> | ||||||
|  | 
 | ||||||
|  | #include <QObject> | ||||||
|  | 
 | ||||||
|  | class QKeyEvent; | ||||||
|  | 
 | ||||||
|  | namespace scwx | ||||||
|  | { | ||||||
|  | namespace qt | ||||||
|  | { | ||||||
|  | namespace manager | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | class HotkeyManager : public QObject | ||||||
|  | { | ||||||
|  |    Q_OBJECT | ||||||
|  |    Q_DISABLE_COPY_MOVE(HotkeyManager) | ||||||
|  | 
 | ||||||
|  | public: | ||||||
|  |    explicit HotkeyManager(); | ||||||
|  |    ~HotkeyManager(); | ||||||
|  | 
 | ||||||
|  |    bool HandleKeyPress(QKeyEvent* event); | ||||||
|  |    bool HandleKeyRelease(QKeyEvent* event); | ||||||
|  | 
 | ||||||
|  |    static std::shared_ptr<HotkeyManager> Instance(); | ||||||
|  | 
 | ||||||
|  | signals: | ||||||
|  |    void HotkeyPressed(scwx::qt::types::Hotkey hotkey, bool isAutoRepeat); | ||||||
|  |    void HotkeyReleased(scwx::qt::types::Hotkey hotkey); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |    class Impl; | ||||||
|  |    std::unique_ptr<Impl> p; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } // namespace manager
 | ||||||
|  | } // namespace qt
 | ||||||
|  | } // namespace scwx
 | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
| #include <scwx/qt/map/map_provider.hpp> | #include <scwx/qt/map/map_provider.hpp> | ||||||
| #include <scwx/qt/settings/audio_settings.hpp> | #include <scwx/qt/settings/audio_settings.hpp> | ||||||
| #include <scwx/qt/settings/general_settings.hpp> | #include <scwx/qt/settings/general_settings.hpp> | ||||||
|  | #include <scwx/qt/settings/hotkey_settings.hpp> | ||||||
| #include <scwx/qt/settings/map_settings.hpp> | #include <scwx/qt/settings/map_settings.hpp> | ||||||
| #include <scwx/qt/settings/palette_settings.hpp> | #include <scwx/qt/settings/palette_settings.hpp> | ||||||
| #include <scwx/qt/settings/product_settings.hpp> | #include <scwx/qt/settings/product_settings.hpp> | ||||||
|  | @ -132,6 +133,7 @@ boost::json::value SettingsManager::Impl::ConvertSettingsToJson() | ||||||
| 
 | 
 | ||||||
|    settings::GeneralSettings::Instance().WriteJson(settingsJson); |    settings::GeneralSettings::Instance().WriteJson(settingsJson); | ||||||
|    settings::AudioSettings::Instance().WriteJson(settingsJson); |    settings::AudioSettings::Instance().WriteJson(settingsJson); | ||||||
|  |    settings::HotkeySettings::Instance().WriteJson(settingsJson); | ||||||
|    settings::MapSettings::Instance().WriteJson(settingsJson); |    settings::MapSettings::Instance().WriteJson(settingsJson); | ||||||
|    settings::PaletteSettings::Instance().WriteJson(settingsJson); |    settings::PaletteSettings::Instance().WriteJson(settingsJson); | ||||||
|    settings::ProductSettings::Instance().WriteJson(settingsJson); |    settings::ProductSettings::Instance().WriteJson(settingsJson); | ||||||
|  | @ -147,6 +149,7 @@ void SettingsManager::Impl::GenerateDefaultSettings() | ||||||
| 
 | 
 | ||||||
|    settings::GeneralSettings::Instance().SetDefaults(); |    settings::GeneralSettings::Instance().SetDefaults(); | ||||||
|    settings::AudioSettings::Instance().SetDefaults(); |    settings::AudioSettings::Instance().SetDefaults(); | ||||||
|  |    settings::HotkeySettings::Instance().SetDefaults(); | ||||||
|    settings::MapSettings::Instance().SetDefaults(); |    settings::MapSettings::Instance().SetDefaults(); | ||||||
|    settings::PaletteSettings::Instance().SetDefaults(); |    settings::PaletteSettings::Instance().SetDefaults(); | ||||||
|    settings::ProductSettings::Instance().SetDefaults(); |    settings::ProductSettings::Instance().SetDefaults(); | ||||||
|  | @ -163,6 +166,7 @@ bool SettingsManager::Impl::LoadSettings( | ||||||
| 
 | 
 | ||||||
|    jsonDirty |= !settings::GeneralSettings::Instance().ReadJson(settingsJson); |    jsonDirty |= !settings::GeneralSettings::Instance().ReadJson(settingsJson); | ||||||
|    jsonDirty |= !settings::AudioSettings::Instance().ReadJson(settingsJson); |    jsonDirty |= !settings::AudioSettings::Instance().ReadJson(settingsJson); | ||||||
|  |    jsonDirty |= !settings::HotkeySettings::Instance().ReadJson(settingsJson); | ||||||
|    jsonDirty |= !settings::MapSettings::Instance().ReadJson(settingsJson); |    jsonDirty |= !settings::MapSettings::Instance().ReadJson(settingsJson); | ||||||
|    jsonDirty |= !settings::PaletteSettings::Instance().ReadJson(settingsJson); |    jsonDirty |= !settings::PaletteSettings::Instance().ReadJson(settingsJson); | ||||||
|    jsonDirty |= !settings::ProductSettings::Instance().ReadJson(settingsJson); |    jsonDirty |= !settings::ProductSettings::Instance().ReadJson(settingsJson); | ||||||
|  |  | ||||||
|  | @ -1,6 +1,7 @@ | ||||||
| #include <scwx/qt/map/map_widget.hpp> | #include <scwx/qt/map/map_widget.hpp> | ||||||
| #include <scwx/qt/gl/gl.hpp> | #include <scwx/qt/gl/gl.hpp> | ||||||
| #include <scwx/qt/manager/font_manager.hpp> | #include <scwx/qt/manager/font_manager.hpp> | ||||||
|  | #include <scwx/qt/manager/hotkey_manager.hpp> | ||||||
| #include <scwx/qt/manager/placefile_manager.hpp> | #include <scwx/qt/manager/placefile_manager.hpp> | ||||||
| #include <scwx/qt/manager/radar_product_manager.hpp> | #include <scwx/qt/manager/radar_product_manager.hpp> | ||||||
| #include <scwx/qt/map/alert_layer.hpp> | #include <scwx/qt/map/alert_layer.hpp> | ||||||
|  | @ -39,6 +40,7 @@ | ||||||
| #include <imgui.h> | #include <imgui.h> | ||||||
| #include <re2/re2.h> | #include <re2/re2.h> | ||||||
| #include <QApplication> | #include <QApplication> | ||||||
|  | #include <QClipboard> | ||||||
| #include <QColor> | #include <QColor> | ||||||
| #include <QDebug> | #include <QDebug> | ||||||
| #include <QFile> | #include <QFile> | ||||||
|  | @ -147,6 +149,9 @@ public: | ||||||
|                           const std::string& before); |                           const std::string& before); | ||||||
|    void ConnectMapSignals(); |    void ConnectMapSignals(); | ||||||
|    void ConnectSignals(); |    void ConnectSignals(); | ||||||
|  |    void HandleHotkeyPressed(types::Hotkey hotkey, bool isAutoRepeat); | ||||||
|  |    void HandleHotkeyReleased(types::Hotkey hotkey); | ||||||
|  |    void HandleHotkeyUpdates(); | ||||||
|    void ImGuiCheckFonts(); |    void ImGuiCheckFonts(); | ||||||
|    void InitializeNewRadarProductView(const std::string& colorPalette); |    void InitializeNewRadarProductView(const std::string& colorPalette); | ||||||
|    void RadarProductManagerConnect(); |    void RadarProductManagerConnect(); | ||||||
|  | @ -190,6 +195,8 @@ public: | ||||||
|    std::shared_ptr<model::LayerModel> layerModel_ { |    std::shared_ptr<model::LayerModel> layerModel_ { | ||||||
|       model::LayerModel::Instance()}; |       model::LayerModel::Instance()}; | ||||||
| 
 | 
 | ||||||
|  |    std::shared_ptr<manager::HotkeyManager> hotkeyManager_ { | ||||||
|  |       manager::HotkeyManager::Instance()}; | ||||||
|    std::shared_ptr<manager::PlacefileManager> placefileManager_ { |    std::shared_ptr<manager::PlacefileManager> placefileManager_ { | ||||||
|       manager::PlacefileManager::Instance()}; |       manager::PlacefileManager::Instance()}; | ||||||
|    std::shared_ptr<manager::RadarProductManager> radarProductManager_; |    std::shared_ptr<manager::RadarProductManager> radarProductManager_; | ||||||
|  | @ -227,6 +234,9 @@ public: | ||||||
|    double prevBearing_; |    double prevBearing_; | ||||||
|    double prevPitch_; |    double prevPitch_; | ||||||
| 
 | 
 | ||||||
|  |    std::set<types::Hotkey>               activeHotkeys_ {}; | ||||||
|  |    std::chrono::system_clock::time_point prevHotkeyTime_ {}; | ||||||
|  | 
 | ||||||
| public slots: | public slots: | ||||||
|    void Update(); |    void Update(); | ||||||
| }; | }; | ||||||
|  | @ -331,6 +341,160 @@ void MapWidgetImpl::ConnectSignals() | ||||||
|            [this](const QModelIndex& /* parent */, //
 |            [this](const QModelIndex& /* parent */, //
 | ||||||
|                   int /* first */, |                   int /* first */, | ||||||
|                   int /* last */) { AddLayers(); }); |                   int /* last */) { AddLayers(); }); | ||||||
|  | 
 | ||||||
|  |    connect(hotkeyManager_.get(), | ||||||
|  |            &manager::HotkeyManager::HotkeyPressed, | ||||||
|  |            this, | ||||||
|  |            &MapWidgetImpl::HandleHotkeyPressed); | ||||||
|  |    connect(hotkeyManager_.get(), | ||||||
|  |            &manager::HotkeyManager::HotkeyReleased, | ||||||
|  |            this, | ||||||
|  |            &MapWidgetImpl::HandleHotkeyReleased); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void MapWidgetImpl::HandleHotkeyPressed(types::Hotkey hotkey, bool isAutoRepeat) | ||||||
|  | { | ||||||
|  |    Q_UNUSED(isAutoRepeat); | ||||||
|  | 
 | ||||||
|  |    switch (hotkey) | ||||||
|  |    { | ||||||
|  |    case types::Hotkey::ChangeMapStyle: | ||||||
|  |       if (context_->settings().isActive_) | ||||||
|  |       { | ||||||
|  |          widget_->changeStyle(); | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|  | 
 | ||||||
|  |    case types::Hotkey::CopyCursorCoordinates: | ||||||
|  |       if (hasMouse_) | ||||||
|  |       { | ||||||
|  |          QClipboard* clipboard  = QGuiApplication::clipboard(); | ||||||
|  |          auto        coordinate = map_->coordinateForPixel(lastPos_); | ||||||
|  |          std::string text = | ||||||
|  |             fmt::format("{}, {}", coordinate.first, coordinate.second); | ||||||
|  |          clipboard->setText(QString::fromStdString(text)); | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|  | 
 | ||||||
|  |    case types::Hotkey::CopyMapCoordinates: | ||||||
|  |       if (context_->settings().isActive_) | ||||||
|  |       { | ||||||
|  |          QClipboard* clipboard  = QGuiApplication::clipboard(); | ||||||
|  |          auto        coordinate = map_->coordinate(); | ||||||
|  |          std::string text = | ||||||
|  |             fmt::format("{}, {}", coordinate.first, coordinate.second); | ||||||
|  |          clipboard->setText(QString::fromStdString(text)); | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|  | 
 | ||||||
|  |    default: | ||||||
|  |       break; | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    activeHotkeys_.insert(hotkey); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void MapWidgetImpl::HandleHotkeyReleased(types::Hotkey hotkey) | ||||||
|  | { | ||||||
|  |    // Erase the hotkey from the active set regardless of whether this is the
 | ||||||
|  |    // active map
 | ||||||
|  |    activeHotkeys_.erase(hotkey); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void MapWidgetImpl::HandleHotkeyUpdates() | ||||||
|  | { | ||||||
|  |    using namespace std::chrono_literals; | ||||||
|  | 
 | ||||||
|  |    static constexpr float  kMapPanFactor    = 0.2f; | ||||||
|  |    static constexpr float  kMapRotateFactor = 0.2f; | ||||||
|  |    static constexpr double kMapScaleFactor  = 1000.0; | ||||||
|  | 
 | ||||||
|  |    std::chrono::system_clock::time_point hotkeyTime = | ||||||
|  |       std::chrono::system_clock::now(); | ||||||
|  |    std::chrono::milliseconds hotkeyElapsed = | ||||||
|  |       std::min(std::chrono::duration_cast<std::chrono::milliseconds>( | ||||||
|  |                   hotkeyTime - prevHotkeyTime_), | ||||||
|  |                100ms); | ||||||
|  | 
 | ||||||
|  |    prevHotkeyTime_ = hotkeyTime; | ||||||
|  | 
 | ||||||
|  |    if (!context_->settings().isActive_) | ||||||
|  |    { | ||||||
|  |       // Don't attempt to handle a hotkey if this is not the active map
 | ||||||
|  |       return; | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    for (auto& hotkey : activeHotkeys_) | ||||||
|  |    { | ||||||
|  |       switch (hotkey) | ||||||
|  |       { | ||||||
|  |       case types::Hotkey::MapPanUp: | ||||||
|  |       { | ||||||
|  |          QPointF delta {0.0f, kMapPanFactor * hotkeyElapsed.count()}; | ||||||
|  |          map_->moveBy(delta); | ||||||
|  |          break; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       case types::Hotkey::MapPanDown: | ||||||
|  |       { | ||||||
|  |          QPointF delta {0.0f, -kMapPanFactor * hotkeyElapsed.count()}; | ||||||
|  |          map_->moveBy(delta); | ||||||
|  |          break; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       case types::Hotkey::MapPanLeft: | ||||||
|  |       { | ||||||
|  |          QPointF delta {kMapPanFactor * hotkeyElapsed.count(), 0.0f}; | ||||||
|  |          map_->moveBy(delta); | ||||||
|  |          break; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       case types::Hotkey::MapPanRight: | ||||||
|  |       { | ||||||
|  |          QPointF delta {-kMapPanFactor * hotkeyElapsed.count(), 0.0f}; | ||||||
|  |          map_->moveBy(delta); | ||||||
|  |          break; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       case types::Hotkey::MapRotateClockwise: | ||||||
|  |       { | ||||||
|  |          QPointF delta {-kMapRotateFactor * hotkeyElapsed.count(), 0.0f}; | ||||||
|  |          map_->rotateBy({}, delta); | ||||||
|  |          break; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       case types::Hotkey::MapRotateCounterclockwise: | ||||||
|  |       { | ||||||
|  |          QPointF delta {kMapRotateFactor * hotkeyElapsed.count(), 0.0f}; | ||||||
|  |          map_->rotateBy({}, delta); | ||||||
|  |          break; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       case types::Hotkey::MapZoomIn: | ||||||
|  |       { | ||||||
|  |          auto    widgetSize = widget_->size(); | ||||||
|  |          QPointF center     = {widgetSize.width() * 0.5f, | ||||||
|  |                                widgetSize.height() * 0.5f}; | ||||||
|  |          double  scale = std::pow(2.0, hotkeyElapsed.count() / kMapScaleFactor); | ||||||
|  |          map_->scaleBy(scale, center); | ||||||
|  |          break; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       case types::Hotkey::MapZoomOut: | ||||||
|  |       { | ||||||
|  |          auto    widgetSize = widget_->size(); | ||||||
|  |          QPointF center     = {widgetSize.width() * 0.5f, | ||||||
|  |                                widgetSize.height() * 0.5f}; | ||||||
|  |          double  scale = | ||||||
|  |             1.0 / std::pow(2.0, hotkeyElapsed.count() / kMapScaleFactor); | ||||||
|  |          map_->scaleBy(scale, center); | ||||||
|  |          break; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       default: | ||||||
|  |          break; | ||||||
|  |       } | ||||||
|  |    } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| common::Level3ProductCategoryMap MapWidget::GetAvailableLevel3Categories() | common::Level3ProductCategoryMap MapWidget::GetAvailableLevel3Categories() | ||||||
|  | @ -1061,17 +1225,19 @@ void MapWidget::leaveEvent(QEvent* /* ev */) | ||||||
| 
 | 
 | ||||||
| void MapWidget::keyPressEvent(QKeyEvent* ev) | void MapWidget::keyPressEvent(QKeyEvent* ev) | ||||||
| { | { | ||||||
|    switch (ev->key()) |    if (p->hotkeyManager_->HandleKeyPress(ev)) | ||||||
|    { |    { | ||||||
|    case Qt::Key_S: |       ev->accept(); | ||||||
|       changeStyle(); |    } | ||||||
|       break; |  | ||||||
|    default: |  | ||||||
|       break; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void MapWidget::keyReleaseEvent(QKeyEvent* ev) | ||||||
|  | { | ||||||
|  |    if (p->hotkeyManager_->HandleKeyRelease(ev)) | ||||||
|  |    { | ||||||
|       ev->accept(); |       ev->accept(); | ||||||
|    } |    } | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| void MapWidget::mousePressEvent(QMouseEvent* ev) | void MapWidget::mousePressEvent(QMouseEvent* ev) | ||||||
| { | { | ||||||
|  | @ -1197,6 +1363,9 @@ void MapWidget::paintGL() | ||||||
| 
 | 
 | ||||||
|    p->frameDraws_++; |    p->frameDraws_++; | ||||||
| 
 | 
 | ||||||
|  |    // Handle hotkey updates
 | ||||||
|  |    p->HandleHotkeyUpdates(); | ||||||
|  | 
 | ||||||
|    // Setup ImGui Frame
 |    // Setup ImGui Frame
 | ||||||
|    ImGui::SetCurrentContext(p->imGuiContext_); |    ImGui::SetCurrentContext(p->imGuiContext_); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -125,6 +125,7 @@ private: | ||||||
|    bool event(QEvent* e) override; |    bool event(QEvent* e) override; | ||||||
|    void enterEvent(QEnterEvent* ev) override final; |    void enterEvent(QEnterEvent* ev) override final; | ||||||
|    void keyPressEvent(QKeyEvent* ev) override final; |    void keyPressEvent(QKeyEvent* ev) override final; | ||||||
|  |    void keyReleaseEvent(QKeyEvent* ev) override final; | ||||||
|    void leaveEvent(QEvent* ev) override final; |    void leaveEvent(QEvent* ev) override final; | ||||||
|    void mousePressEvent(QMouseEvent* ev) override final; |    void mousePressEvent(QMouseEvent* ev) override final; | ||||||
|    void mouseMoveEvent(QMouseEvent* ev) override final; |    void mouseMoveEvent(QMouseEvent* ev) override final; | ||||||
|  |  | ||||||
							
								
								
									
										126
									
								
								scwx-qt/source/scwx/qt/settings/hotkey_settings.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								scwx-qt/source/scwx/qt/settings/hotkey_settings.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,126 @@ | ||||||
|  | #include <scwx/qt/settings/hotkey_settings.hpp> | ||||||
|  | 
 | ||||||
|  | #include <QKeySequence> | ||||||
|  | 
 | ||||||
|  | namespace scwx | ||||||
|  | { | ||||||
|  | namespace qt | ||||||
|  | { | ||||||
|  | namespace settings | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | static const std::string logPrefix_ = "scwx::qt::settings::hotkey_settings"; | ||||||
|  | 
 | ||||||
|  | static const std::unordered_map<types::Hotkey, QKeySequence> kDefaultHotkeys_ { | ||||||
|  |    {types::Hotkey::ChangeMapStyle, QKeySequence {Qt::Key::Key_Z}}, | ||||||
|  |    {types::Hotkey::CopyCursorCoordinates, | ||||||
|  |     QKeySequence {QKeyCombination {Qt::KeyboardModifier::ControlModifier, | ||||||
|  |                                    Qt::Key::Key_C}}}, | ||||||
|  |    {types::Hotkey::CopyMapCoordinates, | ||||||
|  |     QKeySequence {QKeyCombination {Qt::KeyboardModifier::ControlModifier | | ||||||
|  |                                       Qt::KeyboardModifier::ShiftModifier, | ||||||
|  |                                    Qt::Key::Key_C}}}, | ||||||
|  |    {types::Hotkey::MapPanUp, QKeySequence {Qt::Key::Key_W}}, | ||||||
|  |    {types::Hotkey::MapPanDown, QKeySequence {Qt::Key::Key_S}}, | ||||||
|  |    {types::Hotkey::MapPanLeft, QKeySequence {Qt::Key::Key_A}}, | ||||||
|  |    {types::Hotkey::MapPanRight, QKeySequence {Qt::Key::Key_D}}, | ||||||
|  |    {types::Hotkey::MapRotateClockwise, QKeySequence {Qt::Key::Key_E}}, | ||||||
|  |    {types::Hotkey::MapRotateCounterclockwise, QKeySequence {Qt::Key::Key_Q}}, | ||||||
|  |    {types::Hotkey::MapZoomIn, QKeySequence {Qt::Key::Key_Equal}}, | ||||||
|  |    {types::Hotkey::MapZoomOut, QKeySequence {Qt::Key::Key_Minus}}, | ||||||
|  |    {types::Hotkey::ProductTiltDecrease, | ||||||
|  |     QKeySequence {Qt::Key::Key_BracketLeft}}, | ||||||
|  |    {types::Hotkey::ProductTiltIncrease, | ||||||
|  |     QKeySequence {Qt::Key::Key_BracketRight}}, | ||||||
|  |    {types::Hotkey::TimelineStepBegin, | ||||||
|  |     QKeySequence {QKeyCombination {Qt::KeyboardModifier::ControlModifier, | ||||||
|  |                                    Qt::Key::Key_Left}}}, | ||||||
|  |    {types::Hotkey::TimelineStepBack, QKeySequence {Qt::Key::Key_Left}}, | ||||||
|  |    {types::Hotkey::TimelinePlay, QKeySequence {Qt::Key::Key_Space}}, | ||||||
|  |    {types::Hotkey::TimelineStepNext, QKeySequence {Qt::Key::Key_Right}}, | ||||||
|  |    {types::Hotkey::TimelineStepEnd, | ||||||
|  |     QKeySequence {QKeyCombination {Qt::KeyboardModifier::ControlModifier, | ||||||
|  |                                    Qt::Key::Key_Right}}}, | ||||||
|  |    {types::Hotkey::Unknown, QKeySequence {}}}; | ||||||
|  | 
 | ||||||
|  | static bool IsHotkeyValid(const std::string& value); | ||||||
|  | 
 | ||||||
|  | class HotkeySettings::Impl | ||||||
|  | { | ||||||
|  | public: | ||||||
|  |    explicit Impl() | ||||||
|  |    { | ||||||
|  |       for (const auto& hotkey : types::HotkeyIterator()) | ||||||
|  |       { | ||||||
|  |          const std::string& name = types::GetHotkeyShortName(hotkey); | ||||||
|  |          const std::string  defaultValue = | ||||||
|  |             kDefaultHotkeys_.at(hotkey).toString().toStdString(); | ||||||
|  | 
 | ||||||
|  |          auto result = | ||||||
|  |             hotkey_.emplace(hotkey, SettingsVariable<std::string> {name}); | ||||||
|  | 
 | ||||||
|  |          SettingsVariable<std::string>& settingsVariable = result.first->second; | ||||||
|  | 
 | ||||||
|  |          settingsVariable.SetDefault(defaultValue); | ||||||
|  |          settingsVariable.SetValidator(&IsHotkeyValid); | ||||||
|  | 
 | ||||||
|  |          variables_.push_back(&settingsVariable); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       // Add an empty hotkey (not part of registered variables) for error
 | ||||||
|  |       // handling
 | ||||||
|  |       hotkey_.emplace(types::Hotkey::Unknown, | ||||||
|  |                       SettingsVariable<std::string> {"?"}); | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    ~Impl() {} | ||||||
|  | 
 | ||||||
|  |    std::unordered_map<types::Hotkey, SettingsVariable<std::string>> hotkey_ {}; | ||||||
|  |    std::vector<SettingsVariableBase*> variables_ {}; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | HotkeySettings::HotkeySettings() : | ||||||
|  |     SettingsCategory("hotkeys"), p(std::make_unique<Impl>()) | ||||||
|  | { | ||||||
|  |    RegisterVariables(p->variables_); | ||||||
|  |    SetDefaults(); | ||||||
|  | 
 | ||||||
|  |    p->variables_.clear(); | ||||||
|  | } | ||||||
|  | HotkeySettings::~HotkeySettings() = default; | ||||||
|  | 
 | ||||||
|  | HotkeySettings::HotkeySettings(HotkeySettings&&) noexcept            = default; | ||||||
|  | HotkeySettings& HotkeySettings::operator=(HotkeySettings&&) noexcept = default; | ||||||
|  | 
 | ||||||
|  | SettingsVariable<std::string>& | ||||||
|  | HotkeySettings::hotkey(scwx::qt::types::Hotkey hotkey) const | ||||||
|  | { | ||||||
|  |    auto hotkeyVariable = p->hotkey_.find(hotkey); | ||||||
|  |    if (hotkeyVariable == p->hotkey_.cend()) | ||||||
|  |    { | ||||||
|  |       hotkeyVariable = p->hotkey_.find(types::Hotkey::Unknown); | ||||||
|  |    } | ||||||
|  |    return hotkeyVariable->second; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | HotkeySettings& HotkeySettings::Instance() | ||||||
|  | { | ||||||
|  |    static HotkeySettings hotkeySettings_; | ||||||
|  |    return hotkeySettings_; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool operator==(const HotkeySettings& lhs, const HotkeySettings& rhs) | ||||||
|  | { | ||||||
|  |    return (lhs.p->hotkey_ == rhs.p->hotkey_); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static bool IsHotkeyValid(const std::string& value) | ||||||
|  | { | ||||||
|  |    return QKeySequence::fromString(QString::fromStdString(value)) | ||||||
|  |              .toString() | ||||||
|  |              .toStdString() == value; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } // namespace settings
 | ||||||
|  | } // namespace qt
 | ||||||
|  | } // namespace scwx
 | ||||||
							
								
								
									
										42
									
								
								scwx-qt/source/scwx/qt/settings/hotkey_settings.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								scwx-qt/source/scwx/qt/settings/hotkey_settings.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,42 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <scwx/qt/settings/settings_category.hpp> | ||||||
|  | #include <scwx/qt/settings/settings_variable.hpp> | ||||||
|  | #include <scwx/qt/types/hotkey_types.hpp> | ||||||
|  | 
 | ||||||
|  | #include <memory> | ||||||
|  | #include <string> | ||||||
|  | 
 | ||||||
|  | namespace scwx | ||||||
|  | { | ||||||
|  | namespace qt | ||||||
|  | { | ||||||
|  | namespace settings | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | class HotkeySettings : public SettingsCategory | ||||||
|  | { | ||||||
|  | public: | ||||||
|  |    explicit HotkeySettings(); | ||||||
|  |    ~HotkeySettings(); | ||||||
|  | 
 | ||||||
|  |    HotkeySettings(const HotkeySettings&)            = delete; | ||||||
|  |    HotkeySettings& operator=(const HotkeySettings&) = delete; | ||||||
|  | 
 | ||||||
|  |    HotkeySettings(HotkeySettings&&) noexcept; | ||||||
|  |    HotkeySettings& operator=(HotkeySettings&&) noexcept; | ||||||
|  | 
 | ||||||
|  |    SettingsVariable<std::string>& hotkey(scwx::qt::types::Hotkey hotkey) const; | ||||||
|  | 
 | ||||||
|  |    static HotkeySettings& Instance(); | ||||||
|  | 
 | ||||||
|  |    friend bool operator==(const HotkeySettings& lhs, const HotkeySettings& rhs); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |    class Impl; | ||||||
|  |    std::unique_ptr<Impl> p; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } // namespace settings
 | ||||||
|  | } // namespace qt
 | ||||||
|  | } // namespace scwx
 | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
| 
 | 
 | ||||||
| #include <scwx/qt/settings/settings_interface.hpp> | #include <scwx/qt/settings/settings_interface.hpp> | ||||||
| #include <scwx/qt/settings/settings_variable.hpp> | #include <scwx/qt/settings/settings_variable.hpp> | ||||||
|  | #include <scwx/qt/ui/hotkey_edit.hpp> | ||||||
| 
 | 
 | ||||||
| #include <boost/tokenizer.hpp> | #include <boost/tokenizer.hpp> | ||||||
| #include <fmt/ranges.h> | #include <fmt/ranges.h> | ||||||
|  | @ -155,7 +156,27 @@ void SettingsInterface<T>::SetEditWidget(QWidget* widget) | ||||||
|       return; |       return; | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|    if (QLineEdit* lineEdit = dynamic_cast<QLineEdit*>(widget)) |    if (ui::HotkeyEdit* hotkeyEdit = dynamic_cast<ui::HotkeyEdit*>(widget)) | ||||||
|  |    { | ||||||
|  |       if constexpr (std::is_same_v<T, std::string>) | ||||||
|  |       { | ||||||
|  |          QObject::connect(hotkeyEdit, | ||||||
|  |                           &ui::HotkeyEdit::KeySequenceChanged, | ||||||
|  |                           p->context_.get(), | ||||||
|  |                           [this](const QKeySequence& sequence) | ||||||
|  |                           { | ||||||
|  |                              std::string value { | ||||||
|  |                                 sequence.toString().toStdString()}; | ||||||
|  | 
 | ||||||
|  |                              // Attempt to stage the value
 | ||||||
|  |                              p->stagedValid_ = p->variable_->StageValue(value); | ||||||
|  |                              p->UpdateResetButton(); | ||||||
|  | 
 | ||||||
|  |                              // TODO: Display invalid status
 | ||||||
|  |                           }); | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  |    else if (QLineEdit* lineEdit = dynamic_cast<QLineEdit*>(widget)) | ||||||
|    { |    { | ||||||
|       if constexpr (std::is_same_v<T, std::string>) |       if constexpr (std::is_same_v<T, std::string>) | ||||||
|       { |       { | ||||||
|  | @ -487,7 +508,16 @@ void SettingsInterface<T>::Impl::UpdateEditWidget() | ||||||
|    const T                value        = variable_->GetValue(); |    const T                value        = variable_->GetValue(); | ||||||
|    const T&               currentValue = staged.has_value() ? *staged : value; |    const T&               currentValue = staged.has_value() ? *staged : value; | ||||||
| 
 | 
 | ||||||
|    if (QLineEdit* lineEdit = dynamic_cast<QLineEdit*>(editWidget_)) |    if (ui::HotkeyEdit* hotkeyEdit = dynamic_cast<ui::HotkeyEdit*>(editWidget_)) | ||||||
|  |    { | ||||||
|  |       if constexpr (std::is_same_v<T, std::string>) | ||||||
|  |       { | ||||||
|  |          QKeySequence keySequence = | ||||||
|  |             QKeySequence::fromString(QString::fromStdString(currentValue)); | ||||||
|  |          hotkeyEdit->set_key_sequence(keySequence); | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  |    else if (QLineEdit* lineEdit = dynamic_cast<QLineEdit*>(editWidget_)) | ||||||
|    { |    { | ||||||
|       SetWidgetText(lineEdit, currentValue); |       SetWidgetText(lineEdit, currentValue); | ||||||
|    } |    } | ||||||
|  |  | ||||||
							
								
								
									
										72
									
								
								scwx-qt/source/scwx/qt/types/hotkey_types.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								scwx-qt/source/scwx/qt/types/hotkey_types.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,72 @@ | ||||||
|  | #include <scwx/qt/types/hotkey_types.hpp> | ||||||
|  | #include <scwx/util/enum.hpp> | ||||||
|  | 
 | ||||||
|  | #include <unordered_map> | ||||||
|  | 
 | ||||||
|  | #include <boost/algorithm/string.hpp> | ||||||
|  | 
 | ||||||
|  | namespace scwx | ||||||
|  | { | ||||||
|  | namespace qt | ||||||
|  | { | ||||||
|  | namespace types | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | static const std::unordered_map<Hotkey, std::string> hotkeyShortName_ { | ||||||
|  |    {Hotkey::ChangeMapStyle, "change_map_style"}, | ||||||
|  |    {Hotkey::CopyCursorCoordinates, "copy_cursor_coordinates"}, | ||||||
|  |    {Hotkey::CopyMapCoordinates, "copy_map_coordinates"}, | ||||||
|  |    {Hotkey::MapPanUp, "map_pan_up"}, | ||||||
|  |    {Hotkey::MapPanDown, "map_pan_down"}, | ||||||
|  |    {Hotkey::MapPanLeft, "map_pan_left"}, | ||||||
|  |    {Hotkey::MapPanRight, "map_pan_right"}, | ||||||
|  |    {Hotkey::MapRotateClockwise, "map_rotate_clockwise"}, | ||||||
|  |    {Hotkey::MapRotateCounterclockwise, "map_rotate_counterclockwise"}, | ||||||
|  |    {Hotkey::MapZoomIn, "map_zoom_in"}, | ||||||
|  |    {Hotkey::MapZoomOut, "map_zoom_out"}, | ||||||
|  |    {Hotkey::ProductTiltDecrease, "product_tilt_decrease"}, | ||||||
|  |    {Hotkey::ProductTiltIncrease, "product_tilt_increase"}, | ||||||
|  |    {Hotkey::TimelineStepBegin, "timeline_step_begin"}, | ||||||
|  |    {Hotkey::TimelineStepBack, "timeline_step_back"}, | ||||||
|  |    {Hotkey::TimelinePlay, "timeline_play"}, | ||||||
|  |    {Hotkey::TimelineStepNext, "timeline_step_next"}, | ||||||
|  |    {Hotkey::TimelineStepEnd, "timeline_step_end"}, | ||||||
|  |    {Hotkey::Unknown, "?"}}; | ||||||
|  | 
 | ||||||
|  | static const std::unordered_map<Hotkey, std::string> hotkeyLongName_ { | ||||||
|  |    {Hotkey::ChangeMapStyle, "Change Map Style"}, | ||||||
|  |    {Hotkey::CopyCursorCoordinates, "Copy Cursor Coordinates"}, | ||||||
|  |    {Hotkey::CopyMapCoordinates, "Copy Map Coordinates"}, | ||||||
|  |    {Hotkey::MapPanUp, "Map Pan Up"}, | ||||||
|  |    {Hotkey::MapPanDown, "Map Pan Down"}, | ||||||
|  |    {Hotkey::MapPanLeft, "Map Pan Left"}, | ||||||
|  |    {Hotkey::MapPanRight, "Map Pan Right"}, | ||||||
|  |    {Hotkey::MapRotateClockwise, "Map Rotate Clockwise"}, | ||||||
|  |    {Hotkey::MapRotateCounterclockwise, "Map Rotate Counterclockwise"}, | ||||||
|  |    {Hotkey::MapZoomIn, "Map Zoom In"}, | ||||||
|  |    {Hotkey::MapZoomOut, "Map Zoom Out"}, | ||||||
|  |    {Hotkey::ProductTiltDecrease, "Product Tilt Decrease"}, | ||||||
|  |    {Hotkey::ProductTiltIncrease, "Product Tilt Increase"}, | ||||||
|  |    {Hotkey::TimelineStepBegin, "Timeline Step Begin"}, | ||||||
|  |    {Hotkey::TimelineStepBack, "Timeline Step Back"}, | ||||||
|  |    {Hotkey::TimelinePlay, "Timeline Play/Pause"}, | ||||||
|  |    {Hotkey::TimelineStepNext, "Timeline Step Next"}, | ||||||
|  |    {Hotkey::TimelineStepEnd, "Timeline Step End"}, | ||||||
|  |    {Hotkey::Unknown, "?"}}; | ||||||
|  | 
 | ||||||
|  | SCWX_GET_ENUM(Hotkey, GetHotkeyFromShortName, hotkeyShortName_) | ||||||
|  | SCWX_GET_ENUM(Hotkey, GetHotkeyFromLongName, hotkeyLongName_) | ||||||
|  | 
 | ||||||
|  | const std::string& GetHotkeyShortName(Hotkey hotkey) | ||||||
|  | { | ||||||
|  |    return hotkeyShortName_.at(hotkey); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const std::string& GetHotkeyLongName(Hotkey hotkey) | ||||||
|  | { | ||||||
|  |    return hotkeyLongName_.at(hotkey); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } // namespace types
 | ||||||
|  | } // namespace qt
 | ||||||
|  | } // namespace scwx
 | ||||||
							
								
								
									
										47
									
								
								scwx-qt/source/scwx/qt/types/hotkey_types.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								scwx-qt/source/scwx/qt/types/hotkey_types.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,47 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <scwx/util/iterator.hpp> | ||||||
|  | 
 | ||||||
|  | #include <string> | ||||||
|  | 
 | ||||||
|  | namespace scwx | ||||||
|  | { | ||||||
|  | namespace qt | ||||||
|  | { | ||||||
|  | namespace types | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | enum class Hotkey | ||||||
|  | { | ||||||
|  |    ChangeMapStyle, | ||||||
|  |    CopyCursorCoordinates, | ||||||
|  |    CopyMapCoordinates, | ||||||
|  |    MapPanUp, | ||||||
|  |    MapPanDown, | ||||||
|  |    MapPanLeft, | ||||||
|  |    MapPanRight, | ||||||
|  |    MapRotateClockwise, | ||||||
|  |    MapRotateCounterclockwise, | ||||||
|  |    MapZoomIn, | ||||||
|  |    MapZoomOut, | ||||||
|  |    ProductTiltDecrease, | ||||||
|  |    ProductTiltIncrease, | ||||||
|  |    TimelineStepBegin, | ||||||
|  |    TimelineStepBack, | ||||||
|  |    TimelinePlay, | ||||||
|  |    TimelineStepNext, | ||||||
|  |    TimelineStepEnd, | ||||||
|  |    Unknown | ||||||
|  | }; | ||||||
|  | typedef scwx::util:: | ||||||
|  |    Iterator<Hotkey, Hotkey::ChangeMapStyle, Hotkey::TimelineStepEnd> | ||||||
|  |       HotkeyIterator; | ||||||
|  | 
 | ||||||
|  | Hotkey             GetHotkeyFromShortName(const std::string& name); | ||||||
|  | Hotkey             GetHotkeyFromLongName(const std::string& name); | ||||||
|  | const std::string& GetHotkeyShortName(Hotkey hotkey); | ||||||
|  | const std::string& GetHotkeyLongName(Hotkey hotkey); | ||||||
|  | 
 | ||||||
|  | } // namespace types
 | ||||||
|  | } // namespace qt
 | ||||||
|  | } // namespace scwx
 | ||||||
|  | @ -1,6 +1,7 @@ | ||||||
| #include "animation_dock_widget.hpp" | #include "animation_dock_widget.hpp" | ||||||
| #include "ui_animation_dock_widget.h" | #include "ui_animation_dock_widget.h" | ||||||
| 
 | 
 | ||||||
|  | #include <scwx/qt/manager/hotkey_manager.hpp> | ||||||
| #include <scwx/qt/settings/general_settings.hpp> | #include <scwx/qt/settings/general_settings.hpp> | ||||||
| #include <scwx/qt/util/time.hpp> | #include <scwx/qt/util/time.hpp> | ||||||
| #include <scwx/util/logger.hpp> | #include <scwx/util/logger.hpp> | ||||||
|  | @ -39,6 +40,9 @@ public: | ||||||
| 
 | 
 | ||||||
|    AnimationDockWidget* self_; |    AnimationDockWidget* self_; | ||||||
| 
 | 
 | ||||||
|  |    std::shared_ptr<manager::HotkeyManager> hotkeyManager_ { | ||||||
|  |       manager::HotkeyManager::Instance()}; | ||||||
|  | 
 | ||||||
|    types::AnimationState animationState_ {types::AnimationState::Pause}; |    types::AnimationState animationState_ {types::AnimationState::Pause}; | ||||||
|    types::MapTime        viewType_ {types::MapTime::Live}; |    types::MapTime        viewType_ {types::MapTime::Live}; | ||||||
|    bool                  isLive_ {true}; |    bool                  isLive_ {true}; | ||||||
|  | @ -220,6 +224,39 @@ void AnimationDockWidgetImpl::ConnectSignals() | ||||||
|                     &QAbstractButton::clicked, |                     &QAbstractButton::clicked, | ||||||
|                     self_, |                     self_, | ||||||
|                     [this]() { Q_EMIT self_->AnimationStepEndSelected(); }); |                     [this]() { Q_EMIT self_->AnimationStepEndSelected(); }); | ||||||
|  | 
 | ||||||
|  |    // Shortcuts
 | ||||||
|  |    QObject::connect(hotkeyManager_.get(), | ||||||
|  |                     &manager::HotkeyManager::HotkeyPressed, | ||||||
|  |                     self_, | ||||||
|  |                     [this](types::Hotkey hotkey, bool /* isAutoRepeat */) | ||||||
|  |                     { | ||||||
|  |                        switch (hotkey) | ||||||
|  |                        { | ||||||
|  |                        case types::Hotkey::TimelineStepBegin: | ||||||
|  |                           Q_EMIT self_->AnimationStepBeginSelected(); | ||||||
|  |                           break; | ||||||
|  | 
 | ||||||
|  |                        case types::Hotkey::TimelineStepBack: | ||||||
|  |                           Q_EMIT self_->AnimationStepBackSelected(); | ||||||
|  |                           break; | ||||||
|  | 
 | ||||||
|  |                        case types::Hotkey::TimelinePlay: | ||||||
|  |                           Q_EMIT self_->AnimationPlaySelected(); | ||||||
|  |                           break; | ||||||
|  | 
 | ||||||
|  |                        case types::Hotkey::TimelineStepNext: | ||||||
|  |                           Q_EMIT self_->AnimationStepNextSelected(); | ||||||
|  |                           break; | ||||||
|  | 
 | ||||||
|  |                        case types::Hotkey::TimelineStepEnd: | ||||||
|  |                           Q_EMIT self_->AnimationStepEndSelected(); | ||||||
|  |                           break; | ||||||
|  | 
 | ||||||
|  |                        default: | ||||||
|  |                           break; | ||||||
|  |                        } | ||||||
|  |                     }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void AnimationDockWidget::UpdateAnimationState(types::AnimationState state) | void AnimationDockWidget::UpdateAnimationState(types::AnimationState state) | ||||||
|  |  | ||||||
							
								
								
									
										137
									
								
								scwx-qt/source/scwx/qt/ui/hotkey_edit.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										137
									
								
								scwx-qt/source/scwx/qt/ui/hotkey_edit.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,137 @@ | ||||||
|  | #include <scwx/qt/ui/hotkey_edit.hpp> | ||||||
|  | #include <scwx/util/logger.hpp> | ||||||
|  | 
 | ||||||
|  | #include <qevent.h> | ||||||
|  | 
 | ||||||
|  | namespace scwx | ||||||
|  | { | ||||||
|  | namespace qt | ||||||
|  | { | ||||||
|  | namespace ui | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | static const std::string logPrefix_ = "scwx::qt::ui::hotkey_edit"; | ||||||
|  | static const auto        logger_    = scwx::util::Logger::Create(logPrefix_); | ||||||
|  | 
 | ||||||
|  | class HotkeyEdit::Impl | ||||||
|  | { | ||||||
|  | public: | ||||||
|  |    explicit Impl() {}; | ||||||
|  |    ~Impl() = default; | ||||||
|  | 
 | ||||||
|  |    QKeySequence sequence_ {}; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | HotkeyEdit::HotkeyEdit(QWidget* parent) : | ||||||
|  |     QLineEdit(parent), p {std::make_unique<Impl>()} | ||||||
|  | { | ||||||
|  |    setReadOnly(true); | ||||||
|  |    setClearButtonEnabled(true); | ||||||
|  | 
 | ||||||
|  |    QAction* clearAction = findChild<QAction*>(); | ||||||
|  |    if (clearAction != nullptr) | ||||||
|  |    { | ||||||
|  |       clearAction->setEnabled(true); | ||||||
|  | 
 | ||||||
|  |       connect(clearAction, | ||||||
|  |               &QAction::triggered, | ||||||
|  |               this, | ||||||
|  |               [this](bool /* checked */) | ||||||
|  |               { | ||||||
|  |                  logger_->trace("clearAction"); | ||||||
|  | 
 | ||||||
|  |                  if (!p->sequence_.isEmpty()) | ||||||
|  |                  { | ||||||
|  |                     // Clear saved sequence
 | ||||||
|  |                     p->sequence_ = QKeySequence {}; | ||||||
|  |                     setText(p->sequence_.toString()); | ||||||
|  |                     Q_EMIT KeySequenceChanged({}); | ||||||
|  |                  } | ||||||
|  |               }); | ||||||
|  |    } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | HotkeyEdit::~HotkeyEdit() {} | ||||||
|  | 
 | ||||||
|  | QKeySequence HotkeyEdit::key_sequence() const | ||||||
|  | { | ||||||
|  |    return p->sequence_; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void HotkeyEdit::set_key_sequence(const QKeySequence& sequence) | ||||||
|  | { | ||||||
|  |    if (sequence != p->sequence_) | ||||||
|  |    { | ||||||
|  |       p->sequence_ = sequence; | ||||||
|  |       setText(sequence.toString()); | ||||||
|  |       Q_EMIT KeySequenceChanged(sequence); | ||||||
|  |    } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void HotkeyEdit::focusInEvent(QFocusEvent* e) | ||||||
|  | { | ||||||
|  |    logger_->trace("focusInEvent"); | ||||||
|  | 
 | ||||||
|  |    // Replace text with placeholder prompting for input
 | ||||||
|  |    setPlaceholderText("Press any key"); | ||||||
|  |    setText({}); | ||||||
|  | 
 | ||||||
|  |    QLineEdit::focusInEvent(e); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void HotkeyEdit::focusOutEvent(QFocusEvent* e) | ||||||
|  | { | ||||||
|  |    logger_->trace("focusOutEvent"); | ||||||
|  | 
 | ||||||
|  |    // Replace text with saved sequence
 | ||||||
|  |    setPlaceholderText({}); | ||||||
|  |    setText(p->sequence_.toString()); | ||||||
|  | 
 | ||||||
|  |    QLineEdit::focusOutEvent(e); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void HotkeyEdit::keyPressEvent(QKeyEvent* e) | ||||||
|  | { | ||||||
|  |    logger_->trace("keyPressEvent"); | ||||||
|  | 
 | ||||||
|  |    QKeySequence sequence {}; | ||||||
|  | 
 | ||||||
|  |    switch (e->key()) | ||||||
|  |    { | ||||||
|  |    case Qt::Key::Key_Shift: | ||||||
|  |    case Qt::Key::Key_Control: | ||||||
|  |    case Qt::Key::Key_Alt: | ||||||
|  |    case Qt::Key::Key_Meta: | ||||||
|  |    case Qt::Key::Key_Mode_switch: | ||||||
|  |       // Record modifiers only in sequence
 | ||||||
|  |       sequence = e->modifiers().toInt(); | ||||||
|  |       break; | ||||||
|  | 
 | ||||||
|  |    default: | ||||||
|  |       // Record modifiers and keys in sequence, and save sequence
 | ||||||
|  |       sequence = e->modifiers().toInt() | e->key(); | ||||||
|  | 
 | ||||||
|  |       if (sequence != p->sequence_) | ||||||
|  |       { | ||||||
|  |          p->sequence_ = sequence; | ||||||
|  |          Q_EMIT KeySequenceChanged(sequence); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       clearFocus(); | ||||||
|  |       break; | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    setText(sequence.toString()); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void HotkeyEdit::keyReleaseEvent(QKeyEvent*) | ||||||
|  | { | ||||||
|  |    logger_->trace("keyReleaseEvent"); | ||||||
|  | 
 | ||||||
|  |    // Modifiers were released prior to pressing a non-modifier key
 | ||||||
|  |    setText({}); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } // namespace ui
 | ||||||
|  | } // namespace qt
 | ||||||
|  | } // namespace scwx
 | ||||||
							
								
								
									
										41
									
								
								scwx-qt/source/scwx/qt/ui/hotkey_edit.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								scwx-qt/source/scwx/qt/ui/hotkey_edit.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,41 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <QLineEdit> | ||||||
|  | 
 | ||||||
|  | namespace scwx | ||||||
|  | { | ||||||
|  | namespace qt | ||||||
|  | { | ||||||
|  | namespace ui | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | class HotkeyEdit : public QLineEdit | ||||||
|  | { | ||||||
|  |    Q_OBJECT | ||||||
|  |    Q_DISABLE_COPY_MOVE(HotkeyEdit) | ||||||
|  | 
 | ||||||
|  | public: | ||||||
|  |    explicit HotkeyEdit(QWidget* parent = nullptr); | ||||||
|  |    ~HotkeyEdit(); | ||||||
|  | 
 | ||||||
|  |    QKeySequence key_sequence() const; | ||||||
|  | 
 | ||||||
|  |    void set_key_sequence(const QKeySequence& sequence); | ||||||
|  | 
 | ||||||
|  | protected: | ||||||
|  |    void focusInEvent(QFocusEvent* e) override; | ||||||
|  |    void focusOutEvent(QFocusEvent* e) override; | ||||||
|  |    void keyPressEvent(QKeyEvent* e) override; | ||||||
|  |    void keyReleaseEvent(QKeyEvent* e) override; | ||||||
|  | 
 | ||||||
|  | signals: | ||||||
|  |    void KeySequenceChanged(const QKeySequence& sequence); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |    class Impl; | ||||||
|  |    std::unique_ptr<Impl> p; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } // namespace ui
 | ||||||
|  | } // namespace qt
 | ||||||
|  | } // namespace scwx
 | ||||||
|  | @ -1,6 +1,8 @@ | ||||||
| #include <scwx/qt/ui/level2_settings_widget.hpp> | #include <scwx/qt/ui/level2_settings_widget.hpp> | ||||||
| #include <scwx/qt/ui/flow_layout.hpp> | #include <scwx/qt/ui/flow_layout.hpp> | ||||||
|  | #include <scwx/qt/manager/hotkey_manager.hpp> | ||||||
| #include <scwx/common/characters.hpp> | #include <scwx/common/characters.hpp> | ||||||
|  | #include <scwx/util/logger.hpp> | ||||||
| 
 | 
 | ||||||
| #include <execution> | #include <execution> | ||||||
| 
 | 
 | ||||||
|  | @ -16,6 +18,9 @@ namespace qt | ||||||
| namespace ui | namespace ui | ||||||
| { | { | ||||||
| 
 | 
 | ||||||
|  | static const std::string logPrefix_ = "scwx::qt::ui::level2_settings_widget"; | ||||||
|  | static const auto        logger_    = util::Logger::Create(logPrefix_); | ||||||
|  | 
 | ||||||
| class Level2SettingsWidgetImpl : public QObject | class Level2SettingsWidgetImpl : public QObject | ||||||
| { | { | ||||||
|    Q_OBJECT |    Q_OBJECT | ||||||
|  | @ -46,9 +51,15 @@ public: | ||||||
|       settingsLayout->addWidget(declutterCheckBox_); |       settingsLayout->addWidget(declutterCheckBox_); | ||||||
| 
 | 
 | ||||||
|       settingsGroupBox_->setVisible(false); |       settingsGroupBox_->setVisible(false); | ||||||
|  | 
 | ||||||
|  |       QObject::connect(hotkeyManager_.get(), | ||||||
|  |                        &manager::HotkeyManager::HotkeyPressed, | ||||||
|  |                        this, | ||||||
|  |                        &Level2SettingsWidgetImpl::HandleHotkeyPressed); | ||||||
|    } |    } | ||||||
|    ~Level2SettingsWidgetImpl() = default; |    ~Level2SettingsWidgetImpl() = default; | ||||||
| 
 | 
 | ||||||
|  |    void HandleHotkeyPressed(types::Hotkey hotkey, bool isAutoRepeat); | ||||||
|    void NormalizeElevationButtons(); |    void NormalizeElevationButtons(); | ||||||
|    void SelectElevation(float elevation); |    void SelectElevation(float elevation); | ||||||
| 
 | 
 | ||||||
|  | @ -63,6 +74,12 @@ public: | ||||||
| 
 | 
 | ||||||
|    QGroupBox* settingsGroupBox_; |    QGroupBox* settingsGroupBox_; | ||||||
|    QCheckBox* declutterCheckBox_; |    QCheckBox* declutterCheckBox_; | ||||||
|  | 
 | ||||||
|  |    float        currentElevation_ {}; | ||||||
|  |    QToolButton* currentElevationButton_ {nullptr}; | ||||||
|  | 
 | ||||||
|  |    std::shared_ptr<manager::HotkeyManager> hotkeyManager_ { | ||||||
|  |       manager::HotkeyManager::Instance()}; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| Level2SettingsWidget::Level2SettingsWidget(QWidget* parent) : | Level2SettingsWidget::Level2SettingsWidget(QWidget* parent) : | ||||||
|  | @ -96,6 +113,71 @@ void Level2SettingsWidget::showEvent(QShowEvent* event) | ||||||
|    p->NormalizeElevationButtons(); |    p->NormalizeElevationButtons(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void Level2SettingsWidgetImpl::HandleHotkeyPressed(types::Hotkey hotkey, | ||||||
|  |                                                    bool          isAutoRepeat) | ||||||
|  | { | ||||||
|  |    if (hotkey != types::Hotkey::ProductTiltDecrease && | ||||||
|  |        hotkey != types::Hotkey::ProductTiltIncrease) | ||||||
|  |    { | ||||||
|  |       // Not handling this hotkey
 | ||||||
|  |       return; | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    logger_->trace("Handling hotkey: {}, repeat: {}", | ||||||
|  |                   types::GetHotkeyShortName(hotkey), | ||||||
|  |                   isAutoRepeat); | ||||||
|  | 
 | ||||||
|  |    if (!self_->isVisible() || currentElevationButton_ == nullptr) | ||||||
|  |    { | ||||||
|  |       // Level 2 product is not selected
 | ||||||
|  |       return; | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    // Find the current elevation tilt
 | ||||||
|  |    auto tiltIt = std::find(elevationButtons_.cbegin(), | ||||||
|  |                            elevationButtons_.cend(), | ||||||
|  |                            currentElevationButton_); | ||||||
|  | 
 | ||||||
|  |    if (tiltIt == elevationButtons_.cend()) | ||||||
|  |    { | ||||||
|  |       logger_->error("Could not locate level 2 tilt: {}", currentElevation_); | ||||||
|  |       return; | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    if (hotkey == types::Hotkey::ProductTiltDecrease) | ||||||
|  |    { | ||||||
|  |       // Validate the current elevation tilt
 | ||||||
|  |       if (tiltIt != elevationButtons_.cbegin()) | ||||||
|  |       { | ||||||
|  |          // Get the previous elevation tilt
 | ||||||
|  |          --tiltIt; | ||||||
|  | 
 | ||||||
|  |          // Select the new elevation tilt
 | ||||||
|  |          (*tiltIt)->click(); | ||||||
|  |       } | ||||||
|  |       else | ||||||
|  |       { | ||||||
|  |          logger_->info("Level 2 tilt at lower limit"); | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  |    else if (hotkey == types::Hotkey::ProductTiltIncrease) | ||||||
|  |    { | ||||||
|  |       // Get the next elevation tilt
 | ||||||
|  |       ++tiltIt; | ||||||
|  | 
 | ||||||
|  |       // Validate the next elevation tilt
 | ||||||
|  |       if (tiltIt != elevationButtons_.cend()) | ||||||
|  |       { | ||||||
|  |          // Select the new elevation tilt
 | ||||||
|  |          (*tiltIt)->click(); | ||||||
|  |       } | ||||||
|  |       else | ||||||
|  |       { | ||||||
|  |          logger_->info("Level 2 tilt at upper limit"); | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void Level2SettingsWidgetImpl::NormalizeElevationButtons() | void Level2SettingsWidgetImpl::NormalizeElevationButtons() | ||||||
| { | { | ||||||
|    // Set each elevation cut's tool button to the same size
 |    // Set each elevation cut's tool button to the same size
 | ||||||
|  | @ -135,12 +217,15 @@ void Level2SettingsWidget::UpdateElevationSelection(float elevation) | ||||||
|    QString buttonText {QString::number(elevation, 'f', 1) + |    QString buttonText {QString::number(elevation, 'f', 1) + | ||||||
|                        common::Characters::DEGREE}; |                        common::Characters::DEGREE}; | ||||||
| 
 | 
 | ||||||
|  |    QToolButton* newElevationButton = nullptr; | ||||||
|  | 
 | ||||||
|    std::for_each(p->elevationButtons_.cbegin(), |    std::for_each(p->elevationButtons_.cbegin(), | ||||||
|                  p->elevationButtons_.cend(), |                  p->elevationButtons_.cend(), | ||||||
|                  [&](auto& toolButton) |                  [&](auto& toolButton) | ||||||
|                  { |                  { | ||||||
|                     if (toolButton->text() == buttonText) |                     if (toolButton->text() == buttonText) | ||||||
|                     { |                     { | ||||||
|  |                        newElevationButton = toolButton; | ||||||
|                        toolButton->setCheckable(true); |                        toolButton->setCheckable(true); | ||||||
|                        toolButton->setChecked(true); |                        toolButton->setChecked(true); | ||||||
|                     } |                     } | ||||||
|  | @ -150,6 +235,9 @@ void Level2SettingsWidget::UpdateElevationSelection(float elevation) | ||||||
|                        toolButton->setCheckable(false); |                        toolButton->setCheckable(false); | ||||||
|                     } |                     } | ||||||
|                  }); |                  }); | ||||||
|  | 
 | ||||||
|  |    p->currentElevation_       = elevation; | ||||||
|  |    p->currentElevationButton_ = newElevationButton; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Level2SettingsWidget::UpdateSettings(map::MapWidget* activeMap) | void Level2SettingsWidget::UpdateSettings(map::MapWidget* activeMap) | ||||||
|  |  | ||||||
|  | @ -1,5 +1,6 @@ | ||||||
| #include <scwx/qt/ui/level3_products_widget.hpp> | #include <scwx/qt/ui/level3_products_widget.hpp> | ||||||
| #include <scwx/qt/ui/flow_layout.hpp> | #include <scwx/qt/ui/flow_layout.hpp> | ||||||
|  | #include <scwx/qt/manager/hotkey_manager.hpp> | ||||||
| #include <scwx/qt/settings/product_settings.hpp> | #include <scwx/qt/settings/product_settings.hpp> | ||||||
| #include <scwx/qt/settings/settings_interface.hpp> | #include <scwx/qt/settings/settings_interface.hpp> | ||||||
| #include <scwx/util/logger.hpp> | #include <scwx/util/logger.hpp> | ||||||
|  | @ -127,9 +128,15 @@ public: | ||||||
| 
 | 
 | ||||||
|       stiPastEnabled_.SetEditWidget(stiPastEnableCheckBox); |       stiPastEnabled_.SetEditWidget(stiPastEnableCheckBox); | ||||||
|       stiForecastEnabled_.SetEditWidget(stiForecastEnableCheckBox); |       stiForecastEnabled_.SetEditWidget(stiForecastEnableCheckBox); | ||||||
|  | 
 | ||||||
|  |       QObject::connect(hotkeyManager_.get(), | ||||||
|  |                        &manager::HotkeyManager::HotkeyPressed, | ||||||
|  |                        this, | ||||||
|  |                        &Level3ProductsWidgetImpl::HandleHotkeyPressed); | ||||||
|    } |    } | ||||||
|    ~Level3ProductsWidgetImpl() = default; |    ~Level3ProductsWidgetImpl() = default; | ||||||
| 
 | 
 | ||||||
|  |    void HandleHotkeyPressed(types::Hotkey hotkey, bool isAutoRepeat); | ||||||
|    void NormalizeProductButtons(); |    void NormalizeProductButtons(); | ||||||
|    void SelectProductCategory(common::Level3ProductCategory category); |    void SelectProductCategory(common::Level3ProductCategory category); | ||||||
|    void UpdateCategorySelection(common::Level3ProductCategory category); |    void UpdateCategorySelection(common::Level3ProductCategory category); | ||||||
|  | @ -144,11 +151,17 @@ public: | ||||||
|                       std::unordered_map<std::string, QMenu*>> |                       std::unordered_map<std::string, QMenu*>> | ||||||
|       categoryMenuMap_; |       categoryMenuMap_; | ||||||
| 
 | 
 | ||||||
|  |    std::shared_ptr<manager::HotkeyManager> hotkeyManager_ { | ||||||
|  |       manager::HotkeyManager::Instance()}; | ||||||
|  | 
 | ||||||
|    std::unordered_map<std::string, std::vector<QAction*>> productTiltMap_; |    std::unordered_map<std::string, std::vector<QAction*>> productTiltMap_; | ||||||
| 
 | 
 | ||||||
|    std::unordered_map<QAction*, std::string> awipsProductMap_; |    std::unordered_map<QAction*, std::string> awipsProductMap_; | ||||||
|    std::shared_mutex                         awipsProductMutex_; |    std::shared_mutex                         awipsProductMutex_; | ||||||
| 
 | 
 | ||||||
|  |    std::string currentAwipsId_ {}; | ||||||
|  |    QAction*    currentProductTiltAction_ {nullptr}; | ||||||
|  | 
 | ||||||
|    settings::SettingsInterface<bool> stiPastEnabled_ {}; |    settings::SettingsInterface<bool> stiPastEnabled_ {}; | ||||||
|    settings::SettingsInterface<bool> stiForecastEnabled_ {}; |    settings::SettingsInterface<bool> stiForecastEnabled_ {}; | ||||||
| }; | }; | ||||||
|  | @ -167,6 +180,84 @@ void Level3ProductsWidget::showEvent(QShowEvent* event) | ||||||
|    p->NormalizeProductButtons(); |    p->NormalizeProductButtons(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void Level3ProductsWidgetImpl::HandleHotkeyPressed(types::Hotkey hotkey, | ||||||
|  |                                                    bool          isAutoRepeat) | ||||||
|  | { | ||||||
|  |    if (hotkey != types::Hotkey::ProductTiltDecrease && | ||||||
|  |        hotkey != types::Hotkey::ProductTiltIncrease) | ||||||
|  |    { | ||||||
|  |       // Not handling this hotkey
 | ||||||
|  |       return; | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    logger_->trace("Handling hotkey: {}, repeat: {}", | ||||||
|  |                   types::GetHotkeyShortName(hotkey), | ||||||
|  |                   isAutoRepeat); | ||||||
|  | 
 | ||||||
|  |    std::string currentAwipsId           = currentAwipsId_; | ||||||
|  |    QAction*    currentProductTiltAction = currentProductTiltAction_; | ||||||
|  | 
 | ||||||
|  |    if (currentProductTiltAction == nullptr || currentAwipsId.empty() || | ||||||
|  |        currentAwipsId == "?") | ||||||
|  |    { | ||||||
|  |       // Level 3 product is not selected
 | ||||||
|  |       return; | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    // Get product
 | ||||||
|  |    std::string product = common::GetLevel3ProductByAwipsId(currentAwipsId); | ||||||
|  |    if (product == "?") | ||||||
|  |    { | ||||||
|  |       logger_->error("Invalid AWIPS ID: {}", currentAwipsId); | ||||||
|  |       return; | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    std::shared_lock lock {awipsProductMutex_}; | ||||||
|  | 
 | ||||||
|  |    // Find the current product tilt
 | ||||||
|  |    auto productTiltsIt = productTiltMap_.find(product); | ||||||
|  |    if (productTiltsIt == productTiltMap_.cend()) | ||||||
|  |    { | ||||||
|  |       logger_->error("Could not find product tilt map: {}", | ||||||
|  |                      common::GetLevel3ProductDescription(product)); | ||||||
|  |       return; | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    auto& productTilts  = productTiltsIt->second; | ||||||
|  |    auto  productTiltIt = std::find( | ||||||
|  |       productTilts.cbegin(), productTilts.cend(), currentProductTiltAction); | ||||||
|  |    if (productTiltIt == productTilts.cend()) | ||||||
|  |    { | ||||||
|  |       logger_->error("Could not locate product tilt: {}", currentAwipsId); | ||||||
|  |       return; | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    std::ptrdiff_t productTiltIndex = | ||||||
|  |       std::distance(productTilts.cbegin(), productTiltIt); | ||||||
|  | 
 | ||||||
|  |    // Determine the new product tilt index
 | ||||||
|  |    std::ptrdiff_t newProductTiltIndex = | ||||||
|  |       (hotkey == types::Hotkey::ProductTiltDecrease) ? productTiltIndex - 1 : | ||||||
|  |                                                        productTiltIndex + 1; | ||||||
|  | 
 | ||||||
|  |    // Validate the new product tilt index
 | ||||||
|  |    if (newProductTiltIndex < 0 || | ||||||
|  |        newProductTiltIndex >= | ||||||
|  |           static_cast<std::ptrdiff_t>(productTilts.size()) || | ||||||
|  |        !productTilts.at(newProductTiltIndex)->isVisible()) | ||||||
|  |    { | ||||||
|  |       const std::string direction = | ||||||
|  |          (hotkey == types::Hotkey::ProductTiltDecrease) ? "lower" : "upper"; | ||||||
|  | 
 | ||||||
|  |       logger_->info("Product tilt at {} limit", direction); | ||||||
|  | 
 | ||||||
|  |       return; | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    // Select the new tilt
 | ||||||
|  |    productTilts.at(newProductTiltIndex)->trigger(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void Level3ProductsWidgetImpl::NormalizeProductButtons() | void Level3ProductsWidgetImpl::NormalizeProductButtons() | ||||||
| { | { | ||||||
|    int level3MaxWidth = 0; |    int level3MaxWidth = 0; | ||||||
|  | @ -283,6 +374,8 @@ void Level3ProductsWidget::UpdateProductSelection( | ||||||
|    else |    else | ||||||
|    { |    { | ||||||
|       p->UpdateCategorySelection(common::Level3ProductCategory::Unknown); |       p->UpdateCategorySelection(common::Level3ProductCategory::Unknown); | ||||||
|  |       p->currentAwipsId_.erase(); | ||||||
|  |       p->currentProductTiltAction_ = nullptr; | ||||||
|    } |    } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -293,7 +386,7 @@ void Level3ProductsWidgetImpl::UpdateCategorySelection( | ||||||
| 
 | 
 | ||||||
|    std::for_each(categoryButtons_.cbegin(), |    std::for_each(categoryButtons_.cbegin(), | ||||||
|                  categoryButtons_.cend(), |                  categoryButtons_.cend(), | ||||||
|                  [&](auto& toolButton) |                  [&, this](auto& toolButton) | ||||||
|                  { |                  { | ||||||
|                     if (toolButton->text().toStdString() == categoryName) |                     if (toolButton->text().toStdString() == categoryName) | ||||||
|                     { |                     { | ||||||
|  | @ -313,10 +406,25 @@ void Level3ProductsWidgetImpl::UpdateProductSelection( | ||||||
| { | { | ||||||
|    std::shared_lock lock {awipsProductMutex_}; |    std::shared_lock lock {awipsProductMutex_}; | ||||||
| 
 | 
 | ||||||
|  |    QAction* newProductTilt = nullptr; | ||||||
|  | 
 | ||||||
|    std::for_each(awipsProductMap_.cbegin(), |    std::for_each(awipsProductMap_.cbegin(), | ||||||
|                  awipsProductMap_.cend(), |                  awipsProductMap_.cend(), | ||||||
|                  [=](const auto& pair) |                  [&, this](const auto& pair) | ||||||
|                  { pair.first->setChecked(pair.second == awipsId); }); |                  { | ||||||
|  |                     if (pair.second == awipsId) | ||||||
|  |                     { | ||||||
|  |                        newProductTilt = pair.first; | ||||||
|  |                        pair.first->setChecked(true); | ||||||
|  |                     } | ||||||
|  |                     else | ||||||
|  |                     { | ||||||
|  |                        pair.first->setChecked(false); | ||||||
|  |                     } | ||||||
|  |                  }); | ||||||
|  | 
 | ||||||
|  |    currentAwipsId_           = awipsId; | ||||||
|  |    currentProductTiltAction_ = newProductTilt; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace ui
 | } // namespace ui
 | ||||||
|  |  | ||||||
							
								
								
									
										107
									
								
								scwx-qt/source/scwx/qt/ui/settings/hotkey_settings_widget.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								scwx-qt/source/scwx/qt/ui/settings/hotkey_settings_widget.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,107 @@ | ||||||
|  | #include <scwx/qt/ui/settings/hotkey_settings_widget.hpp> | ||||||
|  | #include <scwx/qt/ui/hotkey_edit.hpp> | ||||||
|  | #include <scwx/qt/settings/hotkey_settings.hpp> | ||||||
|  | #include <scwx/qt/settings/settings_interface.hpp> | ||||||
|  | #include <scwx/qt/types/hotkey_types.hpp> | ||||||
|  | 
 | ||||||
|  | #include <boost/unordered/unordered_flat_map.hpp> | ||||||
|  | #include <QGridLayout> | ||||||
|  | #include <QLabel> | ||||||
|  | #include <QScrollArea> | ||||||
|  | #include <QToolButton> | ||||||
|  | #include <QVBoxLayout> | ||||||
|  | 
 | ||||||
|  | namespace scwx | ||||||
|  | { | ||||||
|  | namespace qt | ||||||
|  | { | ||||||
|  | namespace ui | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | static const std::string logPrefix_ = | ||||||
|  |    "scwx::qt::ui::settings::hotkey_settings_widget"; | ||||||
|  | 
 | ||||||
|  | class HotkeySettingsWidget::Impl | ||||||
|  | { | ||||||
|  | public: | ||||||
|  |    explicit Impl(HotkeySettingsWidget* self) | ||||||
|  |    { | ||||||
|  |       auto& hotkeySettings = settings::HotkeySettings::Instance(); | ||||||
|  | 
 | ||||||
|  |       gridLayout_ = new QGridLayout(self); | ||||||
|  |       contents_   = new QWidget(self); | ||||||
|  |       contents_->setLayout(gridLayout_); | ||||||
|  | 
 | ||||||
|  |       scrollArea_ = new QScrollArea(self); | ||||||
|  |       scrollArea_->setHorizontalScrollBarPolicy( | ||||||
|  |          Qt::ScrollBarPolicy::ScrollBarAlwaysOff); | ||||||
|  |       scrollArea_->setWidgetResizable(true); | ||||||
|  |       scrollArea_->setWidget(contents_); | ||||||
|  | 
 | ||||||
|  |       layout_ = new QVBoxLayout(self); | ||||||
|  |       layout_->setContentsMargins(0, 0, 0, 0); | ||||||
|  |       layout_->addWidget(scrollArea_); | ||||||
|  | 
 | ||||||
|  |       self->setLayout(layout_); | ||||||
|  | 
 | ||||||
|  |       int row = 0; | ||||||
|  | 
 | ||||||
|  |       for (types::Hotkey hotkey : types::HotkeyIterator()) | ||||||
|  |       { | ||||||
|  |          const std::string& labelText = types::GetHotkeyLongName(hotkey); | ||||||
|  | 
 | ||||||
|  |          QLabel*      label = new QLabel(QObject::tr(labelText.c_str()), self); | ||||||
|  |          HotkeyEdit*  hotkeyEdit  = new HotkeyEdit(self); | ||||||
|  |          QToolButton* resetButton = new QToolButton(self); | ||||||
|  | 
 | ||||||
|  |          resetButton->setIcon( | ||||||
|  |             QIcon {":/res/icons/font-awesome-6/rotate-left-solid.svg"}); | ||||||
|  |          resetButton->setVisible(false); | ||||||
|  | 
 | ||||||
|  |          gridLayout_->addWidget(label, row, 0); | ||||||
|  |          gridLayout_->addWidget(hotkeyEdit, row, 1); | ||||||
|  |          gridLayout_->addWidget(resetButton, row, 2); | ||||||
|  | 
 | ||||||
|  |          // Create settings interface
 | ||||||
|  |          auto result = hotkeys_.emplace( | ||||||
|  |             hotkey, settings::SettingsInterface<std::string> {}); | ||||||
|  |          auto& pair      = *result.first; | ||||||
|  |          auto& interface = pair.second; | ||||||
|  | 
 | ||||||
|  |          // Add to settings list
 | ||||||
|  |          self->AddSettingsInterface(&interface); | ||||||
|  | 
 | ||||||
|  |          auto& hotkeyVariable = hotkeySettings.hotkey(hotkey); | ||||||
|  |          interface.SetSettingsVariable(hotkeyVariable); | ||||||
|  |          interface.SetEditWidget(hotkeyEdit); | ||||||
|  |          interface.SetResetButton(resetButton); | ||||||
|  | 
 | ||||||
|  |          ++row; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       QSpacerItem* spacer = | ||||||
|  |          new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding); | ||||||
|  |       gridLayout_->addItem(spacer, row, 0); | ||||||
|  |    } | ||||||
|  |    ~Impl() = default; | ||||||
|  | 
 | ||||||
|  |    QWidget*     contents_; | ||||||
|  |    QLayout*     layout_; | ||||||
|  |    QScrollArea* scrollArea_ {}; | ||||||
|  |    QGridLayout* gridLayout_ {}; | ||||||
|  | 
 | ||||||
|  |    boost::unordered_flat_map<types::Hotkey, | ||||||
|  |                              settings::SettingsInterface<std::string>> | ||||||
|  |       hotkeys_ {}; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | HotkeySettingsWidget::HotkeySettingsWidget(QWidget* parent) : | ||||||
|  |     SettingsPageWidget(parent), p {std::make_shared<Impl>(this)} | ||||||
|  | { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | HotkeySettingsWidget::~HotkeySettingsWidget() = default; | ||||||
|  | 
 | ||||||
|  | } // namespace ui
 | ||||||
|  | } // namespace qt
 | ||||||
|  | } // namespace scwx
 | ||||||
|  | @ -0,0 +1,29 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <scwx/qt/ui/settings/settings_page_widget.hpp> | ||||||
|  | 
 | ||||||
|  | #include <QWidget> | ||||||
|  | 
 | ||||||
|  | namespace scwx | ||||||
|  | { | ||||||
|  | namespace qt | ||||||
|  | { | ||||||
|  | namespace ui | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | class HotkeySettingsWidget : public SettingsPageWidget | ||||||
|  | { | ||||||
|  |    Q_OBJECT | ||||||
|  | 
 | ||||||
|  | public: | ||||||
|  |    explicit HotkeySettingsWidget(QWidget* parent = nullptr); | ||||||
|  |    ~HotkeySettingsWidget(); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |    class Impl; | ||||||
|  |    std::shared_ptr<Impl> p; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } // namespace ui
 | ||||||
|  | } // namespace qt
 | ||||||
|  | } // namespace scwx
 | ||||||
							
								
								
									
										68
									
								
								scwx-qt/source/scwx/qt/ui/settings/settings_page_widget.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								scwx-qt/source/scwx/qt/ui/settings/settings_page_widget.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,68 @@ | ||||||
|  | #include <scwx/qt/ui/settings/settings_page_widget.hpp> | ||||||
|  | #include <scwx/qt/settings/settings_interface_base.hpp> | ||||||
|  | 
 | ||||||
|  | #include <vector> | ||||||
|  | 
 | ||||||
|  | namespace scwx | ||||||
|  | { | ||||||
|  | namespace qt | ||||||
|  | { | ||||||
|  | namespace ui | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | static const std::string logPrefix_ = | ||||||
|  |    "scwx::qt::ui::settings::settings_page_widget"; | ||||||
|  | 
 | ||||||
|  | class SettingsPageWidget::Impl | ||||||
|  | { | ||||||
|  | public: | ||||||
|  |    explicit Impl() {} | ||||||
|  |    ~Impl() = default; | ||||||
|  | 
 | ||||||
|  |    std::vector<settings::SettingsInterfaceBase*> settings_; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | SettingsPageWidget::SettingsPageWidget(QWidget* parent) : | ||||||
|  |     QWidget(parent), p {std::make_shared<Impl>()} | ||||||
|  | { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SettingsPageWidget::~SettingsPageWidget() = default; | ||||||
|  | 
 | ||||||
|  | void SettingsPageWidget::AddSettingsInterface( | ||||||
|  |    settings::SettingsInterfaceBase* setting) | ||||||
|  | { | ||||||
|  |    p->settings_.push_back(setting); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool SettingsPageWidget::CommitChanges() | ||||||
|  | { | ||||||
|  |    bool committed = false; | ||||||
|  | 
 | ||||||
|  |    for (auto& setting : p->settings_) | ||||||
|  |    { | ||||||
|  |       committed |= setting->Commit(); | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    return committed; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void SettingsPageWidget::DiscardChanges() | ||||||
|  | { | ||||||
|  |    for (auto& setting : p->settings_) | ||||||
|  |    { | ||||||
|  |       setting->Reset(); | ||||||
|  |    } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void SettingsPageWidget::ResetToDefault() | ||||||
|  | { | ||||||
|  |    for (auto& setting : p->settings_) | ||||||
|  |    { | ||||||
|  |       setting->StageDefault(); | ||||||
|  |    } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } // namespace ui
 | ||||||
|  | } // namespace qt
 | ||||||
|  | } // namespace scwx
 | ||||||
							
								
								
									
										36
									
								
								scwx-qt/source/scwx/qt/ui/settings/settings_page_widget.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								scwx-qt/source/scwx/qt/ui/settings/settings_page_widget.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,36 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <scwx/qt/settings/settings_interface_base.hpp> | ||||||
|  | 
 | ||||||
|  | #include <QWidget> | ||||||
|  | 
 | ||||||
|  | namespace scwx | ||||||
|  | { | ||||||
|  | namespace qt | ||||||
|  | { | ||||||
|  | namespace ui | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | class SettingsPageWidget : public QWidget | ||||||
|  | { | ||||||
|  |    Q_OBJECT | ||||||
|  | 
 | ||||||
|  | public: | ||||||
|  |    explicit SettingsPageWidget(QWidget* parent = nullptr); | ||||||
|  |    ~SettingsPageWidget(); | ||||||
|  | 
 | ||||||
|  |    bool CommitChanges(); | ||||||
|  |    void DiscardChanges(); | ||||||
|  |    void ResetToDefault(); | ||||||
|  | 
 | ||||||
|  | protected: | ||||||
|  |    void AddSettingsInterface(settings::SettingsInterfaceBase* setting); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |    class Impl; | ||||||
|  |    std::shared_ptr<Impl> p; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } // namespace ui
 | ||||||
|  | } // namespace qt
 | ||||||
|  | } // namespace scwx
 | ||||||
|  | @ -22,6 +22,7 @@ | ||||||
| #include <scwx/qt/types/time_types.hpp> | #include <scwx/qt/types/time_types.hpp> | ||||||
| #include <scwx/qt/ui/county_dialog.hpp> | #include <scwx/qt/ui/county_dialog.hpp> | ||||||
| #include <scwx/qt/ui/radar_site_dialog.hpp> | #include <scwx/qt/ui/radar_site_dialog.hpp> | ||||||
|  | #include <scwx/qt/ui/settings/hotkey_settings_widget.hpp> | ||||||
| #include <scwx/qt/util/color.hpp> | #include <scwx/qt/util/color.hpp> | ||||||
| #include <scwx/qt/util/file.hpp> | #include <scwx/qt/util/file.hpp> | ||||||
| #include <scwx/util/logger.hpp> | #include <scwx/util/logger.hpp> | ||||||
|  | @ -177,6 +178,7 @@ public: | ||||||
|    void SetupPalettesAlertsTab(); |    void SetupPalettesAlertsTab(); | ||||||
|    void SetupAudioTab(); |    void SetupAudioTab(); | ||||||
|    void SetupTextTab(); |    void SetupTextTab(); | ||||||
|  |    void SetupHotkeysTab(); | ||||||
| 
 | 
 | ||||||
|    void ShowColorDialog(QLineEdit* lineEdit, QFrame* frame = nullptr); |    void ShowColorDialog(QLineEdit* lineEdit, QFrame* frame = nullptr); | ||||||
|    void UpdateRadarDialogLocation(const std::string& id); |    void UpdateRadarDialogLocation(const std::string& id); | ||||||
|  | @ -216,6 +218,9 @@ public: | ||||||
|    std::shared_ptr<manager::PositionManager> positionManager_ { |    std::shared_ptr<manager::PositionManager> positionManager_ { | ||||||
|       manager::PositionManager::Instance()}; |       manager::PositionManager::Instance()}; | ||||||
| 
 | 
 | ||||||
|  |    std::vector<SettingsPageWidget*> settingsPages_ {}; | ||||||
|  |    HotkeySettingsWidget*            hotkeySettingsWidget_ {}; | ||||||
|  | 
 | ||||||
|    settings::SettingsInterface<std::string>  defaultRadarSite_ {}; |    settings::SettingsInterface<std::string>  defaultRadarSite_ {}; | ||||||
|    settings::SettingsInterface<std::int64_t> gridWidth_ {}; |    settings::SettingsInterface<std::int64_t> gridWidth_ {}; | ||||||
|    settings::SettingsInterface<std::int64_t> gridHeight_ {}; |    settings::SettingsInterface<std::int64_t> gridHeight_ {}; | ||||||
|  | @ -289,6 +294,9 @@ SettingsDialog::SettingsDialog(QWidget* parent) : | ||||||
|    // Text
 |    // Text
 | ||||||
|    p->SetupTextTab(); |    p->SetupTextTab(); | ||||||
| 
 | 
 | ||||||
|  |    // Hotkeys
 | ||||||
|  |    p->SetupHotkeysTab(); | ||||||
|  | 
 | ||||||
|    p->ConnectSignals(); |    p->ConnectSignals(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1171,6 +1179,16 @@ void SettingsDialogImpl::SetupTextTab() | ||||||
|       self_->ui->radarSiteHoverTextCheckBox); |       self_->ui->radarSiteHoverTextCheckBox); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void SettingsDialogImpl::SetupHotkeysTab() | ||||||
|  | { | ||||||
|  |    QVBoxLayout* layout = new QVBoxLayout(self_->ui->hotkeys); | ||||||
|  | 
 | ||||||
|  |    hotkeySettingsWidget_ = new HotkeySettingsWidget(self_->ui->hotkeys); | ||||||
|  |    layout->addWidget(hotkeySettingsWidget_); | ||||||
|  | 
 | ||||||
|  |    settingsPages_.push_back(hotkeySettingsWidget_); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| QImage SettingsDialogImpl::GenerateColorTableImage( | QImage SettingsDialogImpl::GenerateColorTableImage( | ||||||
|    std::shared_ptr<common::ColorTable> colorTable, |    std::shared_ptr<common::ColorTable> colorTable, | ||||||
|    std::uint16_t                       min, |    std::uint16_t                       min, | ||||||
|  | @ -1343,6 +1361,11 @@ void SettingsDialogImpl::ApplyChanges() | ||||||
|       committed |= setting->Commit(); |       committed |= setting->Commit(); | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|  |    for (auto& page : settingsPages_) | ||||||
|  |    { | ||||||
|  |       committed |= page->CommitChanges(); | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|    if (committed) |    if (committed) | ||||||
|    { |    { | ||||||
|       manager::SettingsManager::Instance().SaveSettings(); |       manager::SettingsManager::Instance().SaveSettings(); | ||||||
|  | @ -1357,6 +1380,11 @@ void SettingsDialogImpl::DiscardChanges() | ||||||
|    { |    { | ||||||
|       setting->Reset(); |       setting->Reset(); | ||||||
|    } |    } | ||||||
|  | 
 | ||||||
|  |    for (auto& page : settingsPages_) | ||||||
|  |    { | ||||||
|  |       page->DiscardChanges(); | ||||||
|  |    } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void SettingsDialogImpl::ResetToDefault() | void SettingsDialogImpl::ResetToDefault() | ||||||
|  | @ -1367,6 +1395,11 @@ void SettingsDialogImpl::ResetToDefault() | ||||||
|    { |    { | ||||||
|       setting->StageDefault(); |       setting->StageDefault(); | ||||||
|    } |    } | ||||||
|  | 
 | ||||||
|  |    for (auto& page : settingsPages_) | ||||||
|  |    { | ||||||
|  |       page->ResetToDefault(); | ||||||
|  |    } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::string SettingsDialogImpl::RadarSiteLabel( | std::string SettingsDialogImpl::RadarSiteLabel( | ||||||
|  |  | ||||||
|  | @ -13,8 +13,8 @@ | ||||||
|   <property name="windowTitle"> |   <property name="windowTitle"> | ||||||
|    <string>Settings</string> |    <string>Settings</string> | ||||||
|   </property> |   </property> | ||||||
|   <layout class="QVBoxLayout" name="verticalLayout"> |   <layout class="QGridLayout" name="gridLayout_11"> | ||||||
|    <item> |    <item row="0" column="0"> | ||||||
|     <widget class="QFrame" name="frame"> |     <widget class="QFrame" name="frame"> | ||||||
|      <property name="frameShape"> |      <property name="frameShape"> | ||||||
|       <enum>QFrame::StyledPanel</enum> |       <enum>QFrame::StyledPanel</enum> | ||||||
|  | @ -95,6 +95,15 @@ | ||||||
|             <normaloff>:/res/icons/font-awesome-6/font-solid.svg</normaloff>:/res/icons/font-awesome-6/font-solid.svg</iconset> |             <normaloff>:/res/icons/font-awesome-6/font-solid.svg</normaloff>:/res/icons/font-awesome-6/font-solid.svg</iconset> | ||||||
|           </property> |           </property> | ||||||
|          </item> |          </item> | ||||||
|  |          <item> | ||||||
|  |           <property name="text"> | ||||||
|  |            <string>Hotkeys</string> | ||||||
|  |           </property> | ||||||
|  |           <property name="icon"> | ||||||
|  |            <iconset resource="../../../../scwx-qt.qrc"> | ||||||
|  |             <normaloff>:/res/icons/font-awesome-6/keyboard-regular.svg</normaloff>:/res/icons/font-awesome-6/keyboard-regular.svg</iconset> | ||||||
|  |           </property> | ||||||
|  |          </item> | ||||||
|         </widget> |         </widget> | ||||||
|         <widget class="QStackedWidget" name="stackedWidget"> |         <widget class="QStackedWidget" name="stackedWidget"> | ||||||
|          <property name="sizePolicy"> |          <property name="sizePolicy"> | ||||||
|  | @ -209,6 +218,9 @@ | ||||||
|               <item row="5" column="2"> |               <item row="5" column="2"> | ||||||
|                <widget class="QComboBox" name="mapProviderComboBox"/> |                <widget class="QComboBox" name="mapProviderComboBox"/> | ||||||
|               </item> |               </item> | ||||||
|  |               <item row="10" column="2"> | ||||||
|  |                <widget class="QComboBox" name="defaultTimeZoneComboBox"/> | ||||||
|  |               </item> | ||||||
|               <item row="7" column="4"> |               <item row="7" column="4"> | ||||||
|                <widget class="QToolButton" name="resetMapTilerApiKeyButton"> |                <widget class="QToolButton" name="resetMapTilerApiKeyButton"> | ||||||
|                 <property name="text"> |                 <property name="text"> | ||||||
|  | @ -249,6 +261,17 @@ | ||||||
|                 </property> |                 </property> | ||||||
|                </widget> |                </widget> | ||||||
|               </item> |               </item> | ||||||
|  |               <item row="9" 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="2" column="2"> |               <item row="2" column="2"> | ||||||
|                <widget class="QSpinBox" name="gridWidthSpinBox"/> |                <widget class="QSpinBox" name="gridWidthSpinBox"/> | ||||||
|               </item> |               </item> | ||||||
|  | @ -329,20 +352,6 @@ | ||||||
|               <item row="3" column="2"> |               <item row="3" column="2"> | ||||||
|                <widget class="QSpinBox" name="gridHeightSpinBox"/> |                <widget class="QSpinBox" name="gridHeightSpinBox"/> | ||||||
|               </item> |               </item> | ||||||
|               <item row="10" column="2"> |  | ||||||
|                <widget class="QComboBox" name="defaultTimeZoneComboBox"/> |  | ||||||
|               </item> |  | ||||||
|               <item row="9" 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="10" column="4"> |               <item row="10" column="4"> | ||||||
|                <widget class="QToolButton" name="resetDefaultTimeZoneButton"> |                <widget class="QToolButton" name="resetDefaultTimeZoneButton"> | ||||||
|                 <property name="text"> |                 <property name="text"> | ||||||
|  | @ -429,8 +438,8 @@ | ||||||
|                    <rect> |                    <rect> | ||||||
|                     <x>0</x> |                     <x>0</x> | ||||||
|                     <y>0</y> |                     <y>0</y> | ||||||
|                     <width>63</width> |                     <width>498</width> | ||||||
|                     <height>18</height> |                     <height>383</height> | ||||||
|                    </rect> |                    </rect> | ||||||
|                   </property> |                   </property> | ||||||
|                   <layout class="QGridLayout" name="gridLayout_3"> |                   <layout class="QGridLayout" name="gridLayout_3"> | ||||||
|  | @ -1007,13 +1016,14 @@ | ||||||
|            </item> |            </item> | ||||||
|           </layout> |           </layout> | ||||||
|          </widget> |          </widget> | ||||||
|  |          <widget class="QWidget" name="hotkeys"/> | ||||||
|         </widget> |         </widget> | ||||||
|        </widget> |        </widget> | ||||||
|       </item> |       </item> | ||||||
|      </layout> |      </layout> | ||||||
|     </widget> |     </widget> | ||||||
|    </item> |    </item> | ||||||
|    <item> |    <item row="1" column="0"> | ||||||
|     <widget class="QDialogButtonBox" name="buttonBox"> |     <widget class="QDialogButtonBox" name="buttonBox"> | ||||||
|      <property name="orientation"> |      <property name="orientation"> | ||||||
|       <enum>Qt::Horizontal</enum> |       <enum>Qt::Horizontal</enum> | ||||||
|  |  | ||||||
|  | @ -1 +1 @@ | ||||||
| Subproject commit 2ba8740516bbdc58c848bf71755b2f285aa47938 | Subproject commit 260b340030487b01ce9aa37135d949008c972f27 | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dan Paulat
						Dan Paulat