diff --git a/scwx-qt/res/icons/font-awesome-6/copy-regular.svg b/scwx-qt/res/icons/font-awesome-6/copy-regular.svg
new file mode 100644
index 00000000..72d18b16
--- /dev/null
+++ b/scwx-qt/res/icons/font-awesome-6/copy-regular.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/scwx-qt/scwx-qt.cmake b/scwx-qt/scwx-qt.cmake
index cb48e893..156b622e 100644
--- a/scwx-qt/scwx-qt.cmake
+++ b/scwx-qt/scwx-qt.cmake
@@ -239,6 +239,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/gps_info_dialog.hpp
source/scwx/qt/ui/hotkey_edit.hpp
source/scwx/qt/ui/imgui_debug_dialog.hpp
source/scwx/qt/ui/imgui_debug_widget.hpp
@@ -263,6 +264,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/gps_info_dialog.cpp
source/scwx/qt/ui/hotkey_edit.cpp
source/scwx/qt/ui/imgui_debug_dialog.cpp
source/scwx/qt/ui/imgui_debug_widget.cpp
@@ -285,6 +287,7 @@ set(UI_UI source/scwx/qt/ui/about_dialog.ui
source/scwx/qt/ui/animation_dock_widget.ui
source/scwx/qt/ui/collapsible_group.ui
source/scwx/qt/ui/county_dialog.ui
+ source/scwx/qt/ui/gps_info_dialog.ui
source/scwx/qt/ui/imgui_debug_dialog.ui
source/scwx/qt/ui/layer_dialog.ui
source/scwx/qt/ui/open_url_dialog.ui
diff --git a/scwx-qt/scwx-qt.qrc b/scwx-qt/scwx-qt.qrc
index 6817307a..c9e00337 100644
--- a/scwx-qt/scwx-qt.qrc
+++ b/scwx-qt/scwx-qt.qrc
@@ -32,6 +32,7 @@
res/icons/font-awesome-6/angles-up-solid.svg
res/icons/font-awesome-6/backward-step-solid.svg
res/icons/font-awesome-6/book-solid.svg
+ res/icons/font-awesome-6/copy-regular.svg
res/icons/font-awesome-6/discord.svg
res/icons/font-awesome-6/earth-americas-solid.svg
res/icons/font-awesome-6/font-solid.svg
diff --git a/scwx-qt/source/scwx/qt/main/main_window.cpp b/scwx-qt/source/scwx/qt/main/main_window.cpp
index a74533f2..a0a44fe4 100644
--- a/scwx-qt/source/scwx/qt/main/main_window.cpp
+++ b/scwx-qt/source/scwx/qt/main/main_window.cpp
@@ -23,6 +23,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -85,6 +86,7 @@ public:
alertDockWidget_ {nullptr},
animationDockWidget_ {nullptr},
aboutDialog_ {nullptr},
+ gpsInfoDialog_ {nullptr},
imGuiDebugDialog_ {nullptr},
layerDialog_ {nullptr},
placefileDialog_ {nullptr},
@@ -190,6 +192,7 @@ public:
ui::AlertDockWidget* alertDockWidget_;
ui::AnimationDockWidget* animationDockWidget_;
ui::AboutDialog* aboutDialog_;
+ ui::GpsInfoDialog* gpsInfoDialog_;
ui::ImGuiDebugDialog* imGuiDebugDialog_;
ui::LayerDialog* layerDialog_;
ui::PlacefileDialog* placefileDialog_;
@@ -264,6 +267,9 @@ MainWindow::MainWindow(QWidget* parent) :
p->alertDockWidget_->setVisible(false);
addDockWidget(Qt::BottomDockWidgetArea, p->alertDockWidget_);
+ // GPS Info Dialog
+ p->gpsInfoDialog_ = new ui::GpsInfoDialog(this);
+
// Configure Menu
ui->menuView->insertAction(ui->actionRadarToolbox,
ui->radarToolboxDock->toggleViewAction());
@@ -535,6 +541,11 @@ void MainWindow::on_actionExit_triggered()
close();
}
+void MainWindow::on_actionGpsInfo_triggered()
+{
+ p->gpsInfoDialog_->show();
+}
+
void MainWindow::on_actionColorTable_triggered(bool checked)
{
p->layerModel_->SetLayerDisplayed(types::LayerType::Information,
diff --git a/scwx-qt/source/scwx/qt/main/main_window.hpp b/scwx-qt/source/scwx/qt/main/main_window.hpp
index d0adf225..33043308 100644
--- a/scwx-qt/source/scwx/qt/main/main_window.hpp
+++ b/scwx-qt/source/scwx/qt/main/main_window.hpp
@@ -38,6 +38,7 @@ private slots:
void on_actionOpenTextEvent_triggered();
void on_actionSettings_triggered();
void on_actionExit_triggered();
+ void on_actionGpsInfo_triggered();
void on_actionColorTable_triggered(bool checked);
void on_actionRadarRange_triggered(bool checked);
void on_actionRadarSites_triggered(bool checked);
diff --git a/scwx-qt/source/scwx/qt/main/main_window.ui b/scwx-qt/source/scwx/qt/main/main_window.ui
index aeb4517f..9fab1adf 100644
--- a/scwx-qt/source/scwx/qt/main/main_window.ui
+++ b/scwx-qt/source/scwx/qt/main/main_window.ui
@@ -39,7 +39,7 @@
0
0
1024
- 21
+ 33
+
@@ -135,13 +136,13 @@
-
- QFrame::NoFrame
+ QFrame::Shape::NoFrame
- Qt::ScrollBarAsNeeded
+ Qt::ScrollBarPolicy::ScrollBarAsNeeded
- QAbstractScrollArea::AdjustToContents
+ QAbstractScrollArea::SizeAdjustPolicy::AdjustToContents
true
@@ -151,8 +152,8 @@
0
0
- 193
- 688
+ 190
+ 686
@@ -171,10 +172,10 @@
-
- QFrame::StyledPanel
+ QFrame::Shape::StyledPanel
- QFrame::Raised
+ QFrame::Shadow::Raised
-
@@ -209,10 +210,10 @@
-
- QFrame::NoFrame
+ QFrame::Shape::NoFrame
- QFrame::Raised
+ QFrame::Shadow::Raised
@@ -260,7 +261,7 @@
:/res/icons/font-awesome-6/star-solid.svg:/res/icons/font-awesome-6/star-solid.svg
- QToolButton::InstantPopup
+ QToolButton::ToolButtonPopupMode::InstantPopup
@@ -340,7 +341,7 @@
-
- Qt::Vertical
+ Qt::Orientation::Vertical
@@ -481,6 +482,11 @@
Radar &Sites
+
+
+ &GPS Info
+
+
diff --git a/scwx-qt/source/scwx/qt/ui/gps_info_dialog.cpp b/scwx-qt/source/scwx/qt/ui/gps_info_dialog.cpp
new file mode 100644
index 00000000..05863221
--- /dev/null
+++ b/scwx-qt/source/scwx/qt/ui/gps_info_dialog.cpp
@@ -0,0 +1,201 @@
+#include "gps_info_dialog.hpp"
+#include "ui_gps_info_dialog.h"
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+namespace scwx
+{
+namespace qt
+{
+namespace ui
+{
+
+static const QString kDisabledString_ = "---";
+
+class GpsInfoDialog::Impl
+{
+public:
+ explicit Impl(GpsInfoDialog* self) : self_ {self} {};
+ ~Impl() = default;
+
+ std::shared_ptr positionManager_ {
+ manager::PositionManager::Instance()};
+
+ void Update(const QGeoPositionInfo& info, bool updateTime = true);
+
+ GpsInfoDialog* self_;
+};
+
+GpsInfoDialog::GpsInfoDialog(QWidget* parent) :
+ QDialog(parent), p {std::make_unique(this)}, ui(new Ui::GpsInfoDialog)
+{
+ ui->setupUi(this);
+
+ p->Update({}, false);
+
+ connect(p->positionManager_.get(),
+ &manager::PositionManager::PositionUpdated,
+ this,
+ [this](const QGeoPositionInfo& info) { p->Update(info); });
+
+ connect(ui->copyCoordinateButton,
+ &QAbstractButton::clicked,
+ this,
+ [this]()
+ {
+ QClipboard* clipboard = QGuiApplication::clipboard();
+ clipboard->setText(ui->coordinateLabel->text());
+ });
+}
+
+GpsInfoDialog::~GpsInfoDialog()
+{
+ delete ui;
+}
+
+void GpsInfoDialog::Impl::Update(const QGeoPositionInfo& info, bool updateTime)
+{
+ auto coordinate = info.coordinate();
+
+ if (coordinate.isValid())
+ {
+ const QString latitude = QString::fromStdString(
+ common::GetLatitudeString(coordinate.latitude()));
+ const QString longitude = QString::fromStdString(
+ common::GetLongitudeString(coordinate.longitude()));
+
+ self_->ui->coordinateLabel->setText(
+ QString("%1, %2").arg(latitude).arg(longitude));
+ }
+ else
+ {
+ self_->ui->coordinateLabel->setText(kDisabledString_);
+ }
+
+ if (coordinate.type() == QGeoCoordinate::CoordinateType::Coordinate3D)
+ {
+ units::length::meters altitude {coordinate.altitude()};
+ self_->ui->altitudeLabel->setText(
+ QString::fromStdString(units::to_string(altitude)));
+ }
+ else
+ {
+ self_->ui->altitudeLabel->setText(kDisabledString_);
+ }
+
+ if (info.hasAttribute(QGeoPositionInfo::Attribute::Direction))
+ {
+ units::angle::degrees direction {
+ info.attribute(QGeoPositionInfo::Attribute::Direction)};
+ self_->ui->directionLabel->setText(
+ QString::fromStdString(units::to_string(direction)));
+ }
+ else
+ {
+ self_->ui->directionLabel->setText(kDisabledString_);
+ }
+
+ if (info.hasAttribute(QGeoPositionInfo::Attribute::GroundSpeed))
+ {
+ units::velocity::meters_per_second groundSpeed {
+ info.attribute(QGeoPositionInfo::Attribute::GroundSpeed)};
+ self_->ui->groundSpeedLabel->setText(
+ QString::fromStdString(units::to_string(groundSpeed)));
+ }
+ else
+ {
+ self_->ui->groundSpeedLabel->setText(kDisabledString_);
+ }
+
+ if (info.hasAttribute(QGeoPositionInfo::Attribute::VerticalSpeed))
+ {
+ units::velocity::meters_per_second verticalSpeed {
+ info.attribute(QGeoPositionInfo::Attribute::VerticalSpeed)};
+ self_->ui->verticalSpeedLabel->setText(
+ QString::fromStdString(units::to_string(verticalSpeed)));
+ }
+ else
+ {
+ self_->ui->verticalSpeedLabel->setText(kDisabledString_);
+ }
+
+ if (info.hasAttribute(QGeoPositionInfo::Attribute::MagneticVariation))
+ {
+ units::angle::degrees magneticVariation {
+ info.attribute(QGeoPositionInfo::Attribute::MagneticVariation)};
+ self_->ui->magneticVariationLabel->setText(
+ QString::fromStdString(units::to_string(magneticVariation)));
+ }
+ else
+ {
+ self_->ui->magneticVariationLabel->setText(kDisabledString_);
+ }
+
+ if (info.hasAttribute(QGeoPositionInfo::Attribute::HorizontalAccuracy))
+ {
+ units::length::meters horizontalAccuracy {
+ info.attribute(QGeoPositionInfo::Attribute::HorizontalAccuracy)};
+ if (!std::isnan(horizontalAccuracy.value()))
+ {
+ self_->ui->horizontalAccuracyLabel->setText(
+ QString::fromStdString(units::to_string(horizontalAccuracy)));
+ }
+ else
+ {
+ self_->ui->horizontalAccuracyLabel->setText(kDisabledString_);
+ }
+ }
+ else
+ {
+ self_->ui->horizontalAccuracyLabel->setText(kDisabledString_);
+ }
+
+ if (info.hasAttribute(QGeoPositionInfo::Attribute::VerticalAccuracy))
+ {
+ units::length::meters verticalAccuracy {
+ info.attribute(QGeoPositionInfo::Attribute::VerticalAccuracy)};
+ if (!std::isnan(verticalAccuracy.value()))
+ {
+ self_->ui->verticalAccuracyLabel->setText(
+ QString::fromStdString(units::to_string(verticalAccuracy)));
+ }
+ else
+ {
+ self_->ui->verticalAccuracyLabel->setText(kDisabledString_);
+ }
+ }
+ else
+ {
+ self_->ui->verticalAccuracyLabel->setText(kDisabledString_);
+ }
+
+ if (info.hasAttribute(QGeoPositionInfo::Attribute::DirectionAccuracy))
+ {
+ units::angle::degrees directionAccuracy {
+ info.attribute(QGeoPositionInfo::Attribute::DirectionAccuracy)};
+ self_->ui->directionAccuracyLabel->setText(
+ QString::fromStdString(units::to_string(directionAccuracy)));
+ }
+ else
+ {
+ self_->ui->directionAccuracyLabel->setText(kDisabledString_);
+ }
+
+ if (updateTime)
+ {
+ self_->ui->lastUpdateLabel->setText(
+ info.timestamp().toString(Qt::DateFormat::ISODate));
+ }
+}
+
+} // namespace ui
+} // namespace qt
+} // namespace scwx
diff --git a/scwx-qt/source/scwx/qt/ui/gps_info_dialog.hpp b/scwx-qt/source/scwx/qt/ui/gps_info_dialog.hpp
new file mode 100644
index 00000000..6330c5c4
--- /dev/null
+++ b/scwx-qt/source/scwx/qt/ui/gps_info_dialog.hpp
@@ -0,0 +1,36 @@
+#pragma once
+
+#include
+
+namespace Ui
+{
+class GpsInfoDialog;
+}
+
+namespace scwx
+{
+namespace qt
+{
+namespace ui
+{
+
+class GpsInfoDialog : public QDialog
+{
+ Q_OBJECT
+
+private:
+ Q_DISABLE_COPY(GpsInfoDialog)
+
+public:
+ explicit GpsInfoDialog(QWidget* parent = nullptr);
+ ~GpsInfoDialog();
+
+private:
+ class Impl;
+ std::unique_ptr p;
+ Ui::GpsInfoDialog* ui;
+};
+
+} // namespace ui
+} // namespace qt
+} // namespace scwx
diff --git a/scwx-qt/source/scwx/qt/ui/gps_info_dialog.ui b/scwx-qt/source/scwx/qt/ui/gps_info_dialog.ui
new file mode 100644
index 00000000..61e50b1c
--- /dev/null
+++ b/scwx-qt/source/scwx/qt/ui/gps_info_dialog.ui
@@ -0,0 +1,266 @@
+
+
+ GpsInfoDialog
+
+
+
+ 0
+ 0
+ 313
+ 292
+
+
+
+ GPS Info
+
+
+ -
+
+
+
+ 6
+
+
-
+
+
+ Direction Accuracy
+
+
+
+ -
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+ -
+
+
+ Qt::Orientation::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+ Magnetic Variation
+
+
+
+ -
+
+
+ Direction
+
+
+
+ -
+
+
+ Vertical Speed
+
+
+
+ -
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+ -
+
+
+ Vertical Accuracy
+
+
+
+ -
+
+
+ ...
+
+
+
+ :/res/icons/font-awesome-6/copy-regular.svg:/res/icons/font-awesome-6/copy-regular.svg
+
+
+
+ -
+
+
+ Horizonal Accuracy
+
+
+
+ -
+
+
+
+
+
+
+ -
+
+
+ Ground Speed
+
+
+
+ -
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+
+ -
+
+
+ Coordinate
+
+
+
+ -
+
+
+
+
+
+
+ -
+
+
+ Altitude
+
+
+
+ -
+
+
+ Last Update
+
+
+
+ -
+
+
+ Never
+
+
+
+
+ verticalAccuracyLabel
+ label_11
+ groundSpeedLabel
+ magneticVariationLabel
+ label_2
+ coordinateLabel
+ altitudeLabel
+ directionAccuracyLabel
+ label_5
+ label_15
+ label_13
+ verticalSpeedLabel
+ label_7
+ label
+ horizontalAccuracyLabel
+ label_17
+ directionLabel
+ label_9
+ copyCoordinateButton
+ label_3
+ lastUpdateLabel
+
+
+ -
+
+
+ Qt::Orientation::Horizontal
+
+
+ QDialogButtonBox::StandardButton::Close
+
+
+
+
+
+
+
+
+
+
+ buttonBox
+ accepted()
+ GpsInfoDialog
+ accept()
+
+
+ 248
+ 254
+
+
+ 157
+ 274
+
+
+
+
+ buttonBox
+ rejected()
+ GpsInfoDialog
+ reject()
+
+
+ 316
+ 260
+
+
+ 286
+ 274
+
+
+
+
+