mirror of
https://github.com/ciphervance/supercell-wx.git
synced 2025-10-30 19:00:04 +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
|
||||
source/scwx/qt/manager/download_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/placefile_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
|
||||
source/scwx/qt/manager/download_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/placefile_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)
|
||||
set(HDR_SETTINGS source/scwx/qt/settings/audio_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/palette_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)
|
||||
set(SRC_SETTINGS source/scwx/qt/settings/audio_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/palette_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/font_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/imgui_font.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)
|
||||
set(SRC_TYPES source/scwx/qt/types/alert_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/imgui_font.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/download_dialog.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_widget.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/download_dialog.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_widget.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/settings_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
|
||||
source/scwx/qt/ui/setup/finish_page.hpp
|
||||
source/scwx/qt/ui/setup/map_layout_page.hpp
|
||||
|
|
@ -387,6 +399,8 @@ set(PROJECT_SOURCES ${HDR_MAIN}
|
|||
${HDR_UI}
|
||||
${SRC_UI}
|
||||
${UI_UI}
|
||||
${HDR_UI_SETTINGS}
|
||||
${SRC_UI_SETTINGS}
|
||||
${HDR_UI_SETUP}
|
||||
${SRC_UI_SETUP}
|
||||
${HDR_UTIL}
|
||||
|
|
@ -400,41 +414,43 @@ set(PROJECT_SOURCES ${HDR_MAIN}
|
|||
${CMAKE_FILES})
|
||||
set(EXECUTABLE_SOURCES ${SRC_EXE_MAIN})
|
||||
|
||||
source_group("Header Files\\main" FILES ${HDR_MAIN})
|
||||
source_group("Source Files\\main" FILES ${SRC_MAIN})
|
||||
source_group("Header Files\\config" FILES ${HDR_CONFIG})
|
||||
source_group("Source Files\\config" FILES ${SRC_CONFIG})
|
||||
source_group("Source Files\\external" FILES ${SRC_EXTERNAL})
|
||||
source_group("Header Files\\gl" FILES ${HDR_GL})
|
||||
source_group("Source Files\\gl" FILES ${SRC_GL})
|
||||
source_group("Header Files\\gl\\draw" FILES ${HDR_GL_DRAW})
|
||||
source_group("Source Files\\gl\\draw" FILES ${SRC_GL_DRAW})
|
||||
source_group("Header Files\\manager" FILES ${HDR_MANAGER})
|
||||
source_group("Source Files\\manager" FILES ${SRC_MANAGER})
|
||||
source_group("UI Files\\main" FILES ${UI_MAIN})
|
||||
source_group("Header Files\\map" FILES ${HDR_MAP})
|
||||
source_group("Source Files\\map" FILES ${SRC_MAP})
|
||||
source_group("Header Files\\model" FILES ${HDR_MODEL})
|
||||
source_group("Source Files\\model" FILES ${SRC_MODEL})
|
||||
source_group("Header Files\\request" FILES ${HDR_REQUEST})
|
||||
source_group("Source Files\\request" FILES ${SRC_REQUEST})
|
||||
source_group("Header Files\\settings" FILES ${HDR_SETTINGS})
|
||||
source_group("Source Files\\settings" FILES ${SRC_SETTINGS})
|
||||
source_group("Header Files\\types" FILES ${HDR_TYPES})
|
||||
source_group("Source Files\\types" FILES ${SRC_TYPES})
|
||||
source_group("Header Files\\ui" FILES ${HDR_UI})
|
||||
source_group("Source Files\\ui" FILES ${SRC_UI})
|
||||
source_group("Header Files\\ui\\setup" FILES ${HDR_UI_SETUP})
|
||||
source_group("Source Files\\ui\\setup" FILES ${SRC_UI_SETUP})
|
||||
source_group("UI Files\\ui" FILES ${UI_UI})
|
||||
source_group("Header Files\\util" FILES ${HDR_UTIL})
|
||||
source_group("Source Files\\util" FILES ${SRC_UTIL})
|
||||
source_group("Header Files\\view" FILES ${HDR_VIEW})
|
||||
source_group("Source Files\\view" FILES ${SRC_VIEW})
|
||||
source_group("OpenGL Shaders" FILES ${SHADER_FILES})
|
||||
source_group("Resources" FILES ${RESOURCE_FILES})
|
||||
source_group("Resources\\json" FILES ${JSON_FILES})
|
||||
source_group("I18N Files" FILES ${TS_FILES})
|
||||
source_group("Header Files\\main" FILES ${HDR_MAIN})
|
||||
source_group("Source Files\\main" FILES ${SRC_MAIN})
|
||||
source_group("Header Files\\config" FILES ${HDR_CONFIG})
|
||||
source_group("Source Files\\config" FILES ${SRC_CONFIG})
|
||||
source_group("Source Files\\external" FILES ${SRC_EXTERNAL})
|
||||
source_group("Header Files\\gl" FILES ${HDR_GL})
|
||||
source_group("Source Files\\gl" FILES ${SRC_GL})
|
||||
source_group("Header Files\\gl\\draw" FILES ${HDR_GL_DRAW})
|
||||
source_group("Source Files\\gl\\draw" FILES ${SRC_GL_DRAW})
|
||||
source_group("Header Files\\manager" FILES ${HDR_MANAGER})
|
||||
source_group("Source Files\\manager" FILES ${SRC_MANAGER})
|
||||
source_group("UI Files\\main" FILES ${UI_MAIN})
|
||||
source_group("Header Files\\map" FILES ${HDR_MAP})
|
||||
source_group("Source Files\\map" FILES ${SRC_MAP})
|
||||
source_group("Header Files\\model" FILES ${HDR_MODEL})
|
||||
source_group("Source Files\\model" FILES ${SRC_MODEL})
|
||||
source_group("Header Files\\request" FILES ${HDR_REQUEST})
|
||||
source_group("Source Files\\request" FILES ${SRC_REQUEST})
|
||||
source_group("Header Files\\settings" FILES ${HDR_SETTINGS})
|
||||
source_group("Source Files\\settings" FILES ${SRC_SETTINGS})
|
||||
source_group("Header Files\\types" FILES ${HDR_TYPES})
|
||||
source_group("Source Files\\types" FILES ${SRC_TYPES})
|
||||
source_group("Header Files\\ui" FILES ${HDR_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("Source Files\\ui\\setup" FILES ${SRC_UI_SETUP})
|
||||
source_group("UI Files\\ui" FILES ${UI_UI})
|
||||
source_group("Header Files\\util" FILES ${HDR_UTIL})
|
||||
source_group("Source Files\\util" FILES ${SRC_UTIL})
|
||||
source_group("Header Files\\view" FILES ${HDR_VIEW})
|
||||
source_group("Source Files\\view" FILES ${SRC_VIEW})
|
||||
source_group("OpenGL Shaders" FILES ${SHADER_FILES})
|
||||
source_group("Resources" FILES ${RESOURCE_FILES})
|
||||
source_group("Resources\\json" FILES ${JSON_FILES})
|
||||
source_group("I18N Files" FILES ${TS_FILES})
|
||||
|
||||
add_library(scwx-qt OBJECT ${PROJECT_SOURCES})
|
||||
set_property(TARGET scwx-qt PROPERTY AUTOMOC ON)
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
<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/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/palette-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/versions.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/position_manager.hpp>
|
||||
#include <scwx/qt/manager/radar_product_manager.hpp>
|
||||
|
|
@ -42,6 +43,7 @@
|
|||
#include <boost/asio/post.hpp>
|
||||
#include <boost/asio/thread_pool.hpp>
|
||||
#include <QDesktopServices>
|
||||
#include <QKeyEvent>
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QSplitter>
|
||||
|
|
@ -197,7 +199,9 @@ public:
|
|||
|
||||
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::PositionManager> positionManager_;
|
||||
std::shared_ptr<manager::TextEventManager> textEventManager_;
|
||||
|
|
@ -398,6 +402,24 @@ MainWindow::~MainWindow()
|
|||
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)
|
||||
{
|
||||
QMainWindow::showEvent(event);
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ public:
|
|||
MainWindow(QWidget* parent = nullptr);
|
||||
~MainWindow();
|
||||
|
||||
void keyPressEvent(QKeyEvent* ev) override final;
|
||||
void keyReleaseEvent(QKeyEvent* ev) override final;
|
||||
void showEvent(QShowEvent* event) override;
|
||||
|
||||
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/settings/audio_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/palette_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::AudioSettings::Instance().WriteJson(settingsJson);
|
||||
settings::HotkeySettings::Instance().WriteJson(settingsJson);
|
||||
settings::MapSettings::Instance().WriteJson(settingsJson);
|
||||
settings::PaletteSettings::Instance().WriteJson(settingsJson);
|
||||
settings::ProductSettings::Instance().WriteJson(settingsJson);
|
||||
|
|
@ -147,6 +149,7 @@ void SettingsManager::Impl::GenerateDefaultSettings()
|
|||
|
||||
settings::GeneralSettings::Instance().SetDefaults();
|
||||
settings::AudioSettings::Instance().SetDefaults();
|
||||
settings::HotkeySettings::Instance().SetDefaults();
|
||||
settings::MapSettings::Instance().SetDefaults();
|
||||
settings::PaletteSettings::Instance().SetDefaults();
|
||||
settings::ProductSettings::Instance().SetDefaults();
|
||||
|
|
@ -163,6 +166,7 @@ bool SettingsManager::Impl::LoadSettings(
|
|||
|
||||
jsonDirty |= !settings::GeneralSettings::Instance().ReadJson(settingsJson);
|
||||
jsonDirty |= !settings::AudioSettings::Instance().ReadJson(settingsJson);
|
||||
jsonDirty |= !settings::HotkeySettings::Instance().ReadJson(settingsJson);
|
||||
jsonDirty |= !settings::MapSettings::Instance().ReadJson(settingsJson);
|
||||
jsonDirty |= !settings::PaletteSettings::Instance().ReadJson(settingsJson);
|
||||
jsonDirty |= !settings::ProductSettings::Instance().ReadJson(settingsJson);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include <scwx/qt/map/map_widget.hpp>
|
||||
#include <scwx/qt/gl/gl.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/radar_product_manager.hpp>
|
||||
#include <scwx/qt/map/alert_layer.hpp>
|
||||
|
|
@ -39,6 +40,7 @@
|
|||
#include <imgui.h>
|
||||
#include <re2/re2.h>
|
||||
#include <QApplication>
|
||||
#include <QClipboard>
|
||||
#include <QColor>
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
|
|
@ -147,6 +149,9 @@ public:
|
|||
const std::string& before);
|
||||
void ConnectMapSignals();
|
||||
void ConnectSignals();
|
||||
void HandleHotkeyPressed(types::Hotkey hotkey, bool isAutoRepeat);
|
||||
void HandleHotkeyReleased(types::Hotkey hotkey);
|
||||
void HandleHotkeyUpdates();
|
||||
void ImGuiCheckFonts();
|
||||
void InitializeNewRadarProductView(const std::string& colorPalette);
|
||||
void RadarProductManagerConnect();
|
||||
|
|
@ -190,6 +195,8 @@ public:
|
|||
std::shared_ptr<model::LayerModel> layerModel_ {
|
||||
model::LayerModel::Instance()};
|
||||
|
||||
std::shared_ptr<manager::HotkeyManager> hotkeyManager_ {
|
||||
manager::HotkeyManager::Instance()};
|
||||
std::shared_ptr<manager::PlacefileManager> placefileManager_ {
|
||||
manager::PlacefileManager::Instance()};
|
||||
std::shared_ptr<manager::RadarProductManager> radarProductManager_;
|
||||
|
|
@ -227,6 +234,9 @@ public:
|
|||
double prevBearing_;
|
||||
double prevPitch_;
|
||||
|
||||
std::set<types::Hotkey> activeHotkeys_ {};
|
||||
std::chrono::system_clock::time_point prevHotkeyTime_ {};
|
||||
|
||||
public slots:
|
||||
void Update();
|
||||
};
|
||||
|
|
@ -331,6 +341,160 @@ void MapWidgetImpl::ConnectSignals()
|
|||
[this](const QModelIndex& /* parent */, //
|
||||
int /* first */,
|
||||
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()
|
||||
|
|
@ -1061,16 +1225,18 @@ void MapWidget::leaveEvent(QEvent* /* ev */)
|
|||
|
||||
void MapWidget::keyPressEvent(QKeyEvent* ev)
|
||||
{
|
||||
switch (ev->key())
|
||||
if (p->hotkeyManager_->HandleKeyPress(ev))
|
||||
{
|
||||
case Qt::Key_S:
|
||||
changeStyle();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
ev->accept();
|
||||
}
|
||||
}
|
||||
|
||||
ev->accept();
|
||||
void MapWidget::keyReleaseEvent(QKeyEvent* ev)
|
||||
{
|
||||
if (p->hotkeyManager_->HandleKeyRelease(ev))
|
||||
{
|
||||
ev->accept();
|
||||
}
|
||||
}
|
||||
|
||||
void MapWidget::mousePressEvent(QMouseEvent* ev)
|
||||
|
|
@ -1197,6 +1363,9 @@ void MapWidget::paintGL()
|
|||
|
||||
p->frameDraws_++;
|
||||
|
||||
// Handle hotkey updates
|
||||
p->HandleHotkeyUpdates();
|
||||
|
||||
// Setup ImGui Frame
|
||||
ImGui::SetCurrentContext(p->imGuiContext_);
|
||||
|
||||
|
|
|
|||
|
|
@ -125,6 +125,7 @@ private:
|
|||
bool event(QEvent* e) override;
|
||||
void enterEvent(QEnterEvent* ev) override final;
|
||||
void keyPressEvent(QKeyEvent* ev) override final;
|
||||
void keyReleaseEvent(QKeyEvent* ev) override final;
|
||||
void leaveEvent(QEvent* ev) override final;
|
||||
void mousePressEvent(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_variable.hpp>
|
||||
#include <scwx/qt/ui/hotkey_edit.hpp>
|
||||
|
||||
#include <boost/tokenizer.hpp>
|
||||
#include <fmt/ranges.h>
|
||||
|
|
@ -155,7 +156,27 @@ void SettingsInterface<T>::SetEditWidget(QWidget* widget)
|
|||
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>)
|
||||
{
|
||||
|
|
@ -487,7 +508,16 @@ void SettingsInterface<T>::Impl::UpdateEditWidget()
|
|||
const T value = variable_->GetValue();
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
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 "ui_animation_dock_widget.h"
|
||||
|
||||
#include <scwx/qt/manager/hotkey_manager.hpp>
|
||||
#include <scwx/qt/settings/general_settings.hpp>
|
||||
#include <scwx/qt/util/time.hpp>
|
||||
#include <scwx/util/logger.hpp>
|
||||
|
|
@ -39,6 +40,9 @@ public:
|
|||
|
||||
AnimationDockWidget* self_;
|
||||
|
||||
std::shared_ptr<manager::HotkeyManager> hotkeyManager_ {
|
||||
manager::HotkeyManager::Instance()};
|
||||
|
||||
types::AnimationState animationState_ {types::AnimationState::Pause};
|
||||
types::MapTime viewType_ {types::MapTime::Live};
|
||||
bool isLive_ {true};
|
||||
|
|
@ -220,6 +224,39 @@ void AnimationDockWidgetImpl::ConnectSignals()
|
|||
&QAbstractButton::clicked,
|
||||
self_,
|
||||
[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)
|
||||
|
|
|
|||
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/flow_layout.hpp>
|
||||
#include <scwx/qt/manager/hotkey_manager.hpp>
|
||||
#include <scwx/common/characters.hpp>
|
||||
#include <scwx/util/logger.hpp>
|
||||
|
||||
#include <execution>
|
||||
|
||||
|
|
@ -16,6 +18,9 @@ namespace qt
|
|||
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
|
||||
{
|
||||
Q_OBJECT
|
||||
|
|
@ -46,9 +51,15 @@ public:
|
|||
settingsLayout->addWidget(declutterCheckBox_);
|
||||
|
||||
settingsGroupBox_->setVisible(false);
|
||||
|
||||
QObject::connect(hotkeyManager_.get(),
|
||||
&manager::HotkeyManager::HotkeyPressed,
|
||||
this,
|
||||
&Level2SettingsWidgetImpl::HandleHotkeyPressed);
|
||||
}
|
||||
~Level2SettingsWidgetImpl() = default;
|
||||
|
||||
void HandleHotkeyPressed(types::Hotkey hotkey, bool isAutoRepeat);
|
||||
void NormalizeElevationButtons();
|
||||
void SelectElevation(float elevation);
|
||||
|
||||
|
|
@ -63,6 +74,12 @@ public:
|
|||
|
||||
QGroupBox* settingsGroupBox_;
|
||||
QCheckBox* declutterCheckBox_;
|
||||
|
||||
float currentElevation_ {};
|
||||
QToolButton* currentElevationButton_ {nullptr};
|
||||
|
||||
std::shared_ptr<manager::HotkeyManager> hotkeyManager_ {
|
||||
manager::HotkeyManager::Instance()};
|
||||
};
|
||||
|
||||
Level2SettingsWidget::Level2SettingsWidget(QWidget* parent) :
|
||||
|
|
@ -96,6 +113,71 @@ void Level2SettingsWidget::showEvent(QShowEvent* event)
|
|||
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()
|
||||
{
|
||||
// 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) +
|
||||
common::Characters::DEGREE};
|
||||
|
||||
QToolButton* newElevationButton = nullptr;
|
||||
|
||||
std::for_each(p->elevationButtons_.cbegin(),
|
||||
p->elevationButtons_.cend(),
|
||||
[&](auto& toolButton)
|
||||
{
|
||||
if (toolButton->text() == buttonText)
|
||||
{
|
||||
newElevationButton = toolButton;
|
||||
toolButton->setCheckable(true);
|
||||
toolButton->setChecked(true);
|
||||
}
|
||||
|
|
@ -150,6 +235,9 @@ void Level2SettingsWidget::UpdateElevationSelection(float elevation)
|
|||
toolButton->setCheckable(false);
|
||||
}
|
||||
});
|
||||
|
||||
p->currentElevation_ = elevation;
|
||||
p->currentElevationButton_ = newElevationButton;
|
||||
}
|
||||
|
||||
void Level2SettingsWidget::UpdateSettings(map::MapWidget* activeMap)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include <scwx/qt/ui/level3_products_widget.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/settings_interface.hpp>
|
||||
#include <scwx/util/logger.hpp>
|
||||
|
|
@ -127,9 +128,15 @@ public:
|
|||
|
||||
stiPastEnabled_.SetEditWidget(stiPastEnableCheckBox);
|
||||
stiForecastEnabled_.SetEditWidget(stiForecastEnableCheckBox);
|
||||
|
||||
QObject::connect(hotkeyManager_.get(),
|
||||
&manager::HotkeyManager::HotkeyPressed,
|
||||
this,
|
||||
&Level3ProductsWidgetImpl::HandleHotkeyPressed);
|
||||
}
|
||||
~Level3ProductsWidgetImpl() = default;
|
||||
|
||||
void HandleHotkeyPressed(types::Hotkey hotkey, bool isAutoRepeat);
|
||||
void NormalizeProductButtons();
|
||||
void SelectProductCategory(common::Level3ProductCategory category);
|
||||
void UpdateCategorySelection(common::Level3ProductCategory category);
|
||||
|
|
@ -144,11 +151,17 @@ public:
|
|||
std::unordered_map<std::string, QMenu*>>
|
||||
categoryMenuMap_;
|
||||
|
||||
std::shared_ptr<manager::HotkeyManager> hotkeyManager_ {
|
||||
manager::HotkeyManager::Instance()};
|
||||
|
||||
std::unordered_map<std::string, std::vector<QAction*>> productTiltMap_;
|
||||
|
||||
std::unordered_map<QAction*, std::string> awipsProductMap_;
|
||||
std::shared_mutex awipsProductMutex_;
|
||||
|
||||
std::string currentAwipsId_ {};
|
||||
QAction* currentProductTiltAction_ {nullptr};
|
||||
|
||||
settings::SettingsInterface<bool> stiPastEnabled_ {};
|
||||
settings::SettingsInterface<bool> stiForecastEnabled_ {};
|
||||
};
|
||||
|
|
@ -167,6 +180,84 @@ void Level3ProductsWidget::showEvent(QShowEvent* event)
|
|||
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()
|
||||
{
|
||||
int level3MaxWidth = 0;
|
||||
|
|
@ -283,6 +374,8 @@ void Level3ProductsWidget::UpdateProductSelection(
|
|||
else
|
||||
{
|
||||
p->UpdateCategorySelection(common::Level3ProductCategory::Unknown);
|
||||
p->currentAwipsId_.erase();
|
||||
p->currentProductTiltAction_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -293,7 +386,7 @@ void Level3ProductsWidgetImpl::UpdateCategorySelection(
|
|||
|
||||
std::for_each(categoryButtons_.cbegin(),
|
||||
categoryButtons_.cend(),
|
||||
[&](auto& toolButton)
|
||||
[&, this](auto& toolButton)
|
||||
{
|
||||
if (toolButton->text().toStdString() == categoryName)
|
||||
{
|
||||
|
|
@ -313,10 +406,25 @@ void Level3ProductsWidgetImpl::UpdateProductSelection(
|
|||
{
|
||||
std::shared_lock lock {awipsProductMutex_};
|
||||
|
||||
QAction* newProductTilt = nullptr;
|
||||
|
||||
std::for_each(awipsProductMap_.cbegin(),
|
||||
awipsProductMap_.cend(),
|
||||
[=](const auto& pair)
|
||||
{ pair.first->setChecked(pair.second == awipsId); });
|
||||
[&, this](const auto& pair)
|
||||
{
|
||||
if (pair.second == awipsId)
|
||||
{
|
||||
newProductTilt = pair.first;
|
||||
pair.first->setChecked(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
pair.first->setChecked(false);
|
||||
}
|
||||
});
|
||||
|
||||
currentAwipsId_ = awipsId;
|
||||
currentProductTiltAction_ = newProductTilt;
|
||||
}
|
||||
|
||||
} // 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/ui/county_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/file.hpp>
|
||||
#include <scwx/util/logger.hpp>
|
||||
|
|
@ -177,6 +178,7 @@ public:
|
|||
void SetupPalettesAlertsTab();
|
||||
void SetupAudioTab();
|
||||
void SetupTextTab();
|
||||
void SetupHotkeysTab();
|
||||
|
||||
void ShowColorDialog(QLineEdit* lineEdit, QFrame* frame = nullptr);
|
||||
void UpdateRadarDialogLocation(const std::string& id);
|
||||
|
|
@ -216,6 +218,9 @@ public:
|
|||
std::shared_ptr<manager::PositionManager> positionManager_ {
|
||||
manager::PositionManager::Instance()};
|
||||
|
||||
std::vector<SettingsPageWidget*> settingsPages_ {};
|
||||
HotkeySettingsWidget* hotkeySettingsWidget_ {};
|
||||
|
||||
settings::SettingsInterface<std::string> defaultRadarSite_ {};
|
||||
settings::SettingsInterface<std::int64_t> gridWidth_ {};
|
||||
settings::SettingsInterface<std::int64_t> gridHeight_ {};
|
||||
|
|
@ -289,6 +294,9 @@ SettingsDialog::SettingsDialog(QWidget* parent) :
|
|||
// Text
|
||||
p->SetupTextTab();
|
||||
|
||||
// Hotkeys
|
||||
p->SetupHotkeysTab();
|
||||
|
||||
p->ConnectSignals();
|
||||
}
|
||||
|
||||
|
|
@ -1171,6 +1179,16 @@ void SettingsDialogImpl::SetupTextTab()
|
|||
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(
|
||||
std::shared_ptr<common::ColorTable> colorTable,
|
||||
std::uint16_t min,
|
||||
|
|
@ -1343,6 +1361,11 @@ void SettingsDialogImpl::ApplyChanges()
|
|||
committed |= setting->Commit();
|
||||
}
|
||||
|
||||
for (auto& page : settingsPages_)
|
||||
{
|
||||
committed |= page->CommitChanges();
|
||||
}
|
||||
|
||||
if (committed)
|
||||
{
|
||||
manager::SettingsManager::Instance().SaveSettings();
|
||||
|
|
@ -1357,6 +1380,11 @@ void SettingsDialogImpl::DiscardChanges()
|
|||
{
|
||||
setting->Reset();
|
||||
}
|
||||
|
||||
for (auto& page : settingsPages_)
|
||||
{
|
||||
page->DiscardChanges();
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsDialogImpl::ResetToDefault()
|
||||
|
|
@ -1367,6 +1395,11 @@ void SettingsDialogImpl::ResetToDefault()
|
|||
{
|
||||
setting->StageDefault();
|
||||
}
|
||||
|
||||
for (auto& page : settingsPages_)
|
||||
{
|
||||
page->ResetToDefault();
|
||||
}
|
||||
}
|
||||
|
||||
std::string SettingsDialogImpl::RadarSiteLabel(
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@
|
|||
<property name="windowTitle">
|
||||
<string>Settings</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_11">
|
||||
<item row="0" column="0">
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="frameShape">
|
||||
<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>
|
||||
</property>
|
||||
</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 class="QStackedWidget" name="stackedWidget">
|
||||
<property name="sizePolicy">
|
||||
|
|
@ -209,6 +218,9 @@
|
|||
<item row="5" column="2">
|
||||
<widget class="QComboBox" name="mapProviderComboBox"/>
|
||||
</item>
|
||||
<item row="10" column="2">
|
||||
<widget class="QComboBox" name="defaultTimeZoneComboBox"/>
|
||||
</item>
|
||||
<item row="7" column="4">
|
||||
<widget class="QToolButton" name="resetMapTilerApiKeyButton">
|
||||
<property name="text">
|
||||
|
|
@ -249,6 +261,17 @@
|
|||
</property>
|
||||
</widget>
|
||||
</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">
|
||||
<widget class="QSpinBox" name="gridWidthSpinBox"/>
|
||||
</item>
|
||||
|
|
@ -329,20 +352,6 @@
|
|||
<item row="3" column="2">
|
||||
<widget class="QSpinBox" name="gridHeightSpinBox"/>
|
||||
</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">
|
||||
<widget class="QToolButton" name="resetDefaultTimeZoneButton">
|
||||
<property name="text">
|
||||
|
|
@ -429,8 +438,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>63</width>
|
||||
<height>18</height>
|
||||
<width>498</width>
|
||||
<height>383</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
|
|
@ -1007,13 +1016,14 @@
|
|||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="hotkeys"/>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 2ba8740516bbdc58c848bf71755b2f285aa47938
|
||||
Subproject commit 260b340030487b01ce9aa37135d949008c972f27
|
||||
Loading…
Add table
Add a link
Reference in a new issue