From 8a450a76bb39aafbc5cf78b47e2adce1136cd13e Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Tue, 13 Sep 2022 23:24:46 -0500 Subject: [PATCH 01/11] Add Resource Explorer dock and menu --- scwx-qt/source/scwx/qt/main/main_window.cpp | 15 +++++++++++ scwx-qt/source/scwx/qt/main/main_window.ui | 29 ++++++++++++++++++++- 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/scwx-qt/source/scwx/qt/main/main_window.cpp b/scwx-qt/source/scwx/qt/main/main_window.cpp index ececc023..3462beaf 100644 --- a/scwx-qt/source/scwx/qt/main/main_window.cpp +++ b/scwx-qt/source/scwx/qt/main/main_window.cpp @@ -125,6 +125,21 @@ MainWindow::MainWindow(QWidget* parent) : p->ConfigureMapLayout(); + // Configure Menu + ui->menuView->insertAction(ui->actionRadarToolbox, + ui->radarToolboxDock->toggleViewAction()); + ui->radarToolboxDock->toggleViewAction()->setText(tr("Radar &Toolbox")); + ui->actionRadarToolbox->setVisible(false); + + ui->menuView->insertAction(ui->actionResourceExplorer, + ui->resourceExplorerDock->toggleViewAction()); + ui->resourceExplorerDock->toggleViewAction()->setText( + tr("&Resource Explorer")); + ui->actionResourceExplorer->setVisible(false); + + // Configure Docks + ui->resourceExplorerDock->setVisible(false); + // Add Level 2 Products p->level2ProductsWidget_ = new ui::Level2ProductsWidget(this); ui->radarProductGroupBox->layout()->replaceWidget(ui->level2ProductFrame, diff --git a/scwx-qt/source/scwx/qt/main/main_window.ui b/scwx-qt/source/scwx/qt/main/main_window.ui index 56ee6e30..70547a05 100644 --- a/scwx-qt/source/scwx/qt/main/main_window.ui +++ b/scwx-qt/source/scwx/qt/main/main_window.ui @@ -52,13 +52,21 @@ + + + &View + + + + + - Toolbox + Radar Toolbox 1 @@ -217,6 +225,15 @@ + + + Resource Explorer + + + 8 + + + E&xit @@ -235,6 +252,16 @@ Ctrl+O + + + Radar Toolbox + + + + + &Resource Explorer + + From 8abee4cda1bc2badc6508124f883d44cbce656d9 Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Wed, 14 Sep 2022 23:17:31 -0500 Subject: [PATCH 02/11] Creating Radar Product Model --- scwx-qt/scwx-qt.cmake | 6 ++++ .../scwx/qt/model/radar_product_model.cpp | 30 +++++++++++++++++++ .../scwx/qt/model/radar_product_model.hpp | 28 +++++++++++++++++ 3 files changed, 64 insertions(+) create mode 100644 scwx-qt/source/scwx/qt/model/radar_product_model.cpp create mode 100644 scwx-qt/source/scwx/qt/model/radar_product_model.hpp diff --git a/scwx-qt/scwx-qt.cmake b/scwx-qt/scwx-qt.cmake index 482aaad5..7ad527eb 100644 --- a/scwx-qt/scwx-qt.cmake +++ b/scwx-qt/scwx-qt.cmake @@ -73,6 +73,8 @@ set(SRC_MAP source/scwx/qt/map/color_table_layer.cpp source/scwx/qt/map/overlay_layer.cpp source/scwx/qt/map/radar_product_layer.cpp source/scwx/qt/map/radar_range_layer.cpp) +set(HDR_MODEL source/scwx/qt/model/radar_product_model.hpp) +set(SRC_MODEL source/scwx/qt/model/radar_product_model.cpp) set(HDR_REQUEST source/scwx/qt/request/nexrad_file_request.hpp) set(SRC_REQUEST source/scwx/qt/request/nexrad_file_request.cpp) set(HDR_SETTINGS source/scwx/qt/settings/general_settings.hpp @@ -140,6 +142,8 @@ set(PROJECT_SOURCES ${HDR_MAIN} ${UI_MAIN} ${HDR_MAP} ${SRC_MAP} + ${HDR_MODEL} + ${SRC_MODEL} ${HDR_REQUEST} ${SRC_REQUEST} ${HDR_SETTINGS} @@ -172,6 +176,8 @@ 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}) diff --git a/scwx-qt/source/scwx/qt/model/radar_product_model.cpp b/scwx-qt/source/scwx/qt/model/radar_product_model.cpp new file mode 100644 index 00000000..cd0ff8c5 --- /dev/null +++ b/scwx-qt/source/scwx/qt/model/radar_product_model.cpp @@ -0,0 +1,30 @@ +#include +#include + +namespace scwx +{ +namespace qt +{ +namespace model +{ + +static const std::string logPrefix_ = "scwx::qt::model::radar_product_model"; +static const auto logger_ = scwx::util::Logger::Create(logPrefix_); + +class RadarProductModelImpl +{ +public: + explicit RadarProductModelImpl() {} + + ~RadarProductModelImpl() {} +}; + +RadarProductModel::RadarProductModel(QObject* parent) : + QAbstractTableModel(parent), p(std::make_unique()) +{ +} +RadarProductModel::~RadarProductModel() = default; + +} // namespace model +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/model/radar_product_model.hpp b/scwx-qt/source/scwx/qt/model/radar_product_model.hpp new file mode 100644 index 00000000..25980534 --- /dev/null +++ b/scwx-qt/source/scwx/qt/model/radar_product_model.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include + +#include + +namespace scwx +{ +namespace qt +{ +namespace model +{ + +class RadarProductModelImpl; + +class RadarProductModel : QAbstractTableModel +{ +public: + explicit RadarProductModel(QObject* parent = nullptr); + ~RadarProductModel(); + +private: + std::unique_ptr p; +}; + +} // namespace model +} // namespace qt +} // namespace scwx From b917e1a8181bcdf7ecf511c3742818d81070420d Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Sat, 17 Sep 2022 00:31:22 -0500 Subject: [PATCH 03/11] Implementing default Radar Product Model methods --- scwx-qt/source/scwx/qt/main/main_window.cpp | 3 +++ scwx-qt/source/scwx/qt/main/main_window.ui | 8 +++++++- .../scwx/qt/model/radar_product_model.cpp | 19 +++++++++++++++++-- .../scwx/qt/model/radar_product_model.hpp | 7 ++++++- 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/scwx-qt/source/scwx/qt/main/main_window.cpp b/scwx-qt/source/scwx/qt/main/main_window.cpp index 3462beaf..1f8287fe 100644 --- a/scwx-qt/source/scwx/qt/main/main_window.cpp +++ b/scwx-qt/source/scwx/qt/main/main_window.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -140,6 +141,8 @@ MainWindow::MainWindow(QWidget* parent) : // Configure Docks ui->resourceExplorerDock->setVisible(false); + ui->resourceTreeView->setModel(new model::RadarProductModel()); + // Add Level 2 Products p->level2ProductsWidget_ = new ui::Level2ProductsWidget(this); ui->radarProductGroupBox->layout()->replaceWidget(ui->level2ProductFrame, diff --git a/scwx-qt/source/scwx/qt/main/main_window.ui b/scwx-qt/source/scwx/qt/main/main_window.ui index 70547a05..a0ac0a3a 100644 --- a/scwx-qt/source/scwx/qt/main/main_window.ui +++ b/scwx-qt/source/scwx/qt/main/main_window.ui @@ -232,7 +232,13 @@ 8 - + + + + + + + diff --git a/scwx-qt/source/scwx/qt/model/radar_product_model.cpp b/scwx-qt/source/scwx/qt/model/radar_product_model.cpp index cd0ff8c5..12b5a14c 100644 --- a/scwx-qt/source/scwx/qt/model/radar_product_model.cpp +++ b/scwx-qt/source/scwx/qt/model/radar_product_model.cpp @@ -15,8 +15,7 @@ class RadarProductModelImpl { public: explicit RadarProductModelImpl() {} - - ~RadarProductModelImpl() {} + ~RadarProductModelImpl() = default; }; RadarProductModel::RadarProductModel(QObject* parent) : @@ -25,6 +24,22 @@ RadarProductModel::RadarProductModel(QObject* parent) : } RadarProductModel::~RadarProductModel() = default; +int RadarProductModel::rowCount(const QModelIndex& /*parent*/) const +{ + return 0; +} + +int RadarProductModel::columnCount(const QModelIndex& /*parent*/) const +{ + return 0; +} + +QVariant RadarProductModel::data(const QModelIndex& /*index*/, + int /*role*/) const +{ + return QVariant(); +} + } // namespace model } // namespace qt } // namespace scwx diff --git a/scwx-qt/source/scwx/qt/model/radar_product_model.hpp b/scwx-qt/source/scwx/qt/model/radar_product_model.hpp index 25980534..b3f0014b 100644 --- a/scwx-qt/source/scwx/qt/model/radar_product_model.hpp +++ b/scwx-qt/source/scwx/qt/model/radar_product_model.hpp @@ -13,12 +13,17 @@ namespace model class RadarProductModelImpl; -class RadarProductModel : QAbstractTableModel +class RadarProductModel : public QAbstractTableModel { public: explicit RadarProductModel(QObject* parent = nullptr); ~RadarProductModel(); + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + int columnCount(const QModelIndex& parent = QModelIndex()) const override; + QVariant data(const QModelIndex& index, + int role = Qt::DisplayRole) const override; + private: std::unique_ptr p; }; From a47c13ca993cae61d929401274125b3af8275dd0 Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Sat, 17 Sep 2022 00:38:40 -0500 Subject: [PATCH 04/11] Radar Product Model Item class --- .../scwx/qt/model/radar_product_model.cpp | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/scwx-qt/source/scwx/qt/model/radar_product_model.cpp b/scwx-qt/source/scwx/qt/model/radar_product_model.cpp index 12b5a14c..13029fad 100644 --- a/scwx-qt/source/scwx/qt/model/radar_product_model.cpp +++ b/scwx-qt/source/scwx/qt/model/radar_product_model.cpp @@ -11,6 +11,27 @@ namespace model static const std::string logPrefix_ = "scwx::qt::model::radar_product_model"; static const auto logger_ = scwx::util::Logger::Create(logPrefix_); +class RadarProductModelItem +{ +public: + explicit RadarProductModelItem(RadarProductModelItem* parent = nullptr); + ~RadarProductModelItem(); + + void AppendChild(RadarProductModelItem* child); + + RadarProductModelItem* child(int row); + int child_count() const; + int column_count() const; + QVariant data(int column) const; + int row() const; + RadarProductModelItem* parent_item(); + +private: + std::vector childItems_; + std::vector itemData_; + RadarProductModelItem* parentItem_; +}; + class RadarProductModelImpl { public: @@ -40,6 +61,75 @@ QVariant RadarProductModel::data(const QModelIndex& /*index*/, return QVariant(); } +RadarProductModelItem::RadarProductModelItem(RadarProductModelItem* parent) : + childItems_ {}, itemData_ {}, parentItem_ {parent} +{ +} + +RadarProductModelItem::~RadarProductModelItem() +{ + qDeleteAll(childItems_); +} + +void RadarProductModelItem::AppendChild(RadarProductModelItem* item) +{ + childItems_.push_back(item); +} + +RadarProductModelItem* RadarProductModelItem::child(int row) +{ + RadarProductModelItem* item = nullptr; + + if (0 <= row && row < childItems_.size()) + { + item = childItems_[row]; + } + + return item; +} + +int RadarProductModelItem::child_count() const +{ + return static_cast(childItems_.size()); +} + +int RadarProductModelItem::column_count() const +{ + return static_cast(itemData_.size()); +} + +QVariant RadarProductModelItem::data(int column) const +{ + if (0 <= column && column < itemData_.size()) + { + return itemData_[column]; + } + else + { + return QVariant(); + } +} + +int RadarProductModelItem::row() const +{ + int row = 0; + + if (parentItem_ != nullptr) + { + const auto& childItems = parentItem_->childItems_; + row = + std::distance(childItems.cbegin(), + std::find(childItems.cbegin(), childItems.cend(), this)); + } + + return row; +} + +RadarProductModelItem* RadarProductModelItem::parent_item() +{ + return parentItem_; +} + } // namespace model } // namespace qt } // namespace scwx From 1ba60f0da1f6d2d7e87559e9611574b616398088 Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Mon, 19 Sep 2022 22:48:35 -0500 Subject: [PATCH 05/11] Radar Product Model functional stub --- .../scwx/qt/model/radar_product_model.cpp | 158 +++++++++++++++--- .../scwx/qt/model/radar_product_model.hpp | 13 +- 2 files changed, 149 insertions(+), 22 deletions(-) diff --git a/scwx-qt/source/scwx/qt/model/radar_product_model.cpp b/scwx-qt/source/scwx/qt/model/radar_product_model.cpp index 13029fad..d4576b11 100644 --- a/scwx-qt/source/scwx/qt/model/radar_product_model.cpp +++ b/scwx-qt/source/scwx/qt/model/radar_product_model.cpp @@ -14,17 +14,18 @@ static const auto logger_ = scwx::util::Logger::Create(logPrefix_); class RadarProductModelItem { public: - explicit RadarProductModelItem(RadarProductModelItem* parent = nullptr); + explicit RadarProductModelItem(const std::vector& data, + RadarProductModelItem* parent = nullptr); ~RadarProductModelItem(); void AppendChild(RadarProductModelItem* child); - RadarProductModelItem* child(int row); - int child_count() const; - int column_count() const; - QVariant data(int column) const; - int row() const; - RadarProductModelItem* parent_item(); + const RadarProductModelItem* child(int row) const; + int child_count() const; + int column_count() const; + QVariant data(int column) const; + int row() const; + const RadarProductModelItem* parent_item() const; private: std::vector childItems_; @@ -35,8 +36,16 @@ private: class RadarProductModelImpl { public: - explicit RadarProductModelImpl() {} + explicit RadarProductModelImpl() : + rootItem_ {std::make_shared( + std::vector {QObject::tr("Name"), QObject::tr("Info")})} + { + rootItem_->AppendChild(new RadarProductModelItem( + std::vector {QObject::tr("MyItem"), QObject::tr("Data")})); + } ~RadarProductModelImpl() = default; + + std::shared_ptr rootItem_; }; RadarProductModel::RadarProductModel(QObject* parent) : @@ -45,24 +54,132 @@ RadarProductModel::RadarProductModel(QObject* parent) : } RadarProductModel::~RadarProductModel() = default; -int RadarProductModel::rowCount(const QModelIndex& /*parent*/) const +int RadarProductModel::rowCount(const QModelIndex& parent) const { - return 0; + const RadarProductModelItem* parentItem; + + if (parent.isValid()) + { + parentItem = static_cast( + parent.constInternalPointer()); + } + else + { + parentItem = p->rootItem_.get(); + } + + return parentItem->child_count(); } -int RadarProductModel::columnCount(const QModelIndex& /*parent*/) const +int RadarProductModel::columnCount(const QModelIndex& parent) const { - return 0; + const RadarProductModelItem* parentItem; + + if (parent.isValid()) + { + parentItem = static_cast( + parent.constInternalPointer()); + } + else + { + parentItem = p->rootItem_.get(); + } + + return parentItem->column_count(); } -QVariant RadarProductModel::data(const QModelIndex& /*index*/, - int /*role*/) const +QVariant RadarProductModel::data(const QModelIndex& index, int role) const { + if (!index.isValid() || role != Qt::DisplayRole) + { + return QVariant(); + } + + const RadarProductModelItem* item = + static_cast(index.internalPointer()); + + return item->data(index.column()); +} + +Qt::ItemFlags RadarProductModel::flags(const QModelIndex& index) const +{ + Qt::ItemFlags flags; + + if (!index.isValid()) + { + flags = Qt::NoItemFlags; + } + else + { + flags = QAbstractItemModel::flags(index); + } + + return flags; +} + +QVariant RadarProductModel::headerData(int section, + Qt::Orientation orientation, + int role) const +{ + if (orientation == Qt::Horizontal && role == Qt::DisplayRole) + { + return p->rootItem_->data(section); + } + return QVariant(); } -RadarProductModelItem::RadarProductModelItem(RadarProductModelItem* parent) : - childItems_ {}, itemData_ {}, parentItem_ {parent} +QModelIndex +RadarProductModel::index(int row, int column, const QModelIndex& parent) const +{ + if (!hasIndex(row, column, parent)) + { + return QModelIndex(); + } + + const RadarProductModelItem* parentItem; + + if (!parent.isValid()) + { + parentItem = p->rootItem_.get(); + } + else + { + parentItem = static_cast( + parent.constInternalPointer()); + } + + const RadarProductModelItem* childItem = parentItem->child(row); + if (childItem) + { + return createIndex(row, column, childItem); + } + + return QModelIndex(); +} + +QModelIndex RadarProductModel::parent(const QModelIndex& index) const +{ + if (!index.isValid()) + { + return QModelIndex(); + } + + const RadarProductModelItem* childItem = + static_cast(index.constInternalPointer()); + const RadarProductModelItem* parentItem = childItem->parent_item(); + + if (parentItem == p->rootItem_.get()) + { + return QModelIndex(); + } + + return createIndex(parentItem->row(), 0, parentItem); +} + +RadarProductModelItem::RadarProductModelItem(const std::vector& data, + RadarProductModelItem* parent) : + childItems_ {}, itemData_ {data}, parentItem_ {parent} { } @@ -73,12 +190,13 @@ RadarProductModelItem::~RadarProductModelItem() void RadarProductModelItem::AppendChild(RadarProductModelItem* item) { + item->parentItem_ = this; childItems_.push_back(item); } -RadarProductModelItem* RadarProductModelItem::child(int row) +const RadarProductModelItem* RadarProductModelItem::child(int row) const { - RadarProductModelItem* item = nullptr; + const RadarProductModelItem* item = nullptr; if (0 <= row && row < childItems_.size()) { @@ -106,7 +224,7 @@ QVariant RadarProductModelItem::data(int column) const } else { - return QVariant(); + return QVariant("Hello world"); } } @@ -125,7 +243,7 @@ int RadarProductModelItem::row() const return row; } -RadarProductModelItem* RadarProductModelItem::parent_item() +const RadarProductModelItem* RadarProductModelItem::parent_item() const { return parentItem_; } diff --git a/scwx-qt/source/scwx/qt/model/radar_product_model.hpp b/scwx-qt/source/scwx/qt/model/radar_product_model.hpp index b3f0014b..8b1fdfa6 100644 --- a/scwx-qt/source/scwx/qt/model/radar_product_model.hpp +++ b/scwx-qt/source/scwx/qt/model/radar_product_model.hpp @@ -21,8 +21,17 @@ public: int rowCount(const QModelIndex& parent = QModelIndex()) const override; int columnCount(const QModelIndex& parent = QModelIndex()) const override; - QVariant data(const QModelIndex& index, - int role = Qt::DisplayRole) const override; + + QVariant data(const QModelIndex& index, + int role = Qt::DisplayRole) const override; + Qt::ItemFlags flags(const QModelIndex& index) const override; + QVariant headerData(int section, + Qt::Orientation orientation, + int role = Qt::DisplayRole) const override; + QModelIndex index(int row, + int column, + const QModelIndex& parent = QModelIndex()) const override; + QModelIndex parent(const QModelIndex& index) const override; private: std::unique_ptr p; From 98f8bab79a7439b74c83f25feb8b9314874f8924 Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Mon, 19 Sep 2022 23:12:46 -0500 Subject: [PATCH 06/11] Refactoring generic tree model behavior --- scwx-qt/scwx-qt.cmake | 8 +- .../scwx/qt/model/radar_product_model.cpp | 223 +----------------- .../scwx/qt/model/radar_product_model.hpp | 21 +- scwx-qt/source/scwx/qt/model/tree_item.cpp | 98 ++++++++ scwx-qt/source/scwx/qt/model/tree_item.hpp | 44 ++++ scwx-qt/source/scwx/qt/model/tree_model.cpp | 145 ++++++++++++ scwx-qt/source/scwx/qt/model/tree_model.hpp | 45 ++++ 7 files changed, 348 insertions(+), 236 deletions(-) create mode 100644 scwx-qt/source/scwx/qt/model/tree_item.cpp create mode 100644 scwx-qt/source/scwx/qt/model/tree_item.hpp create mode 100644 scwx-qt/source/scwx/qt/model/tree_model.cpp create mode 100644 scwx-qt/source/scwx/qt/model/tree_model.hpp diff --git a/scwx-qt/scwx-qt.cmake b/scwx-qt/scwx-qt.cmake index 7ad527eb..ce097ef8 100644 --- a/scwx-qt/scwx-qt.cmake +++ b/scwx-qt/scwx-qt.cmake @@ -73,8 +73,12 @@ set(SRC_MAP source/scwx/qt/map/color_table_layer.cpp source/scwx/qt/map/overlay_layer.cpp source/scwx/qt/map/radar_product_layer.cpp source/scwx/qt/map/radar_range_layer.cpp) -set(HDR_MODEL source/scwx/qt/model/radar_product_model.hpp) -set(SRC_MODEL source/scwx/qt/model/radar_product_model.cpp) +set(HDR_MODEL source/scwx/qt/model/radar_product_model.hpp + source/scwx/qt/model/tree_item.hpp + source/scwx/qt/model/tree_model.hpp) +set(SRC_MODEL source/scwx/qt/model/radar_product_model.cpp + source/scwx/qt/model/tree_item.cpp + source/scwx/qt/model/tree_model.cpp) set(HDR_REQUEST source/scwx/qt/request/nexrad_file_request.hpp) set(SRC_REQUEST source/scwx/qt/request/nexrad_file_request.cpp) set(HDR_SETTINGS source/scwx/qt/settings/general_settings.hpp diff --git a/scwx-qt/source/scwx/qt/model/radar_product_model.cpp b/scwx-qt/source/scwx/qt/model/radar_product_model.cpp index d4576b11..49453572 100644 --- a/scwx-qt/source/scwx/qt/model/radar_product_model.cpp +++ b/scwx-qt/source/scwx/qt/model/radar_product_model.cpp @@ -11,241 +11,30 @@ namespace model static const std::string logPrefix_ = "scwx::qt::model::radar_product_model"; static const auto logger_ = scwx::util::Logger::Create(logPrefix_); -class RadarProductModelItem -{ -public: - explicit RadarProductModelItem(const std::vector& data, - RadarProductModelItem* parent = nullptr); - ~RadarProductModelItem(); - - void AppendChild(RadarProductModelItem* child); - - const RadarProductModelItem* child(int row) const; - int child_count() const; - int column_count() const; - QVariant data(int column) const; - int row() const; - const RadarProductModelItem* parent_item() const; - -private: - std::vector childItems_; - std::vector itemData_; - RadarProductModelItem* parentItem_; -}; - class RadarProductModelImpl { public: explicit RadarProductModelImpl() : - rootItem_ {std::make_shared( + rootItem_ {std::make_shared( std::vector {QObject::tr("Name"), QObject::tr("Info")})} { - rootItem_->AppendChild(new RadarProductModelItem( + rootItem_->AppendChild(new TreeItem( std::vector {QObject::tr("MyItem"), QObject::tr("Data")})); } ~RadarProductModelImpl() = default; - std::shared_ptr rootItem_; + std::shared_ptr rootItem_; }; RadarProductModel::RadarProductModel(QObject* parent) : - QAbstractTableModel(parent), p(std::make_unique()) + TreeModel(parent), p(std::make_unique()) { } RadarProductModel::~RadarProductModel() = default; -int RadarProductModel::rowCount(const QModelIndex& parent) const +const std::shared_ptr RadarProductModel::root_item() const { - const RadarProductModelItem* parentItem; - - if (parent.isValid()) - { - parentItem = static_cast( - parent.constInternalPointer()); - } - else - { - parentItem = p->rootItem_.get(); - } - - return parentItem->child_count(); -} - -int RadarProductModel::columnCount(const QModelIndex& parent) const -{ - const RadarProductModelItem* parentItem; - - if (parent.isValid()) - { - parentItem = static_cast( - parent.constInternalPointer()); - } - else - { - parentItem = p->rootItem_.get(); - } - - return parentItem->column_count(); -} - -QVariant RadarProductModel::data(const QModelIndex& index, int role) const -{ - if (!index.isValid() || role != Qt::DisplayRole) - { - return QVariant(); - } - - const RadarProductModelItem* item = - static_cast(index.internalPointer()); - - return item->data(index.column()); -} - -Qt::ItemFlags RadarProductModel::flags(const QModelIndex& index) const -{ - Qt::ItemFlags flags; - - if (!index.isValid()) - { - flags = Qt::NoItemFlags; - } - else - { - flags = QAbstractItemModel::flags(index); - } - - return flags; -} - -QVariant RadarProductModel::headerData(int section, - Qt::Orientation orientation, - int role) const -{ - if (orientation == Qt::Horizontal && role == Qt::DisplayRole) - { - return p->rootItem_->data(section); - } - - return QVariant(); -} - -QModelIndex -RadarProductModel::index(int row, int column, const QModelIndex& parent) const -{ - if (!hasIndex(row, column, parent)) - { - return QModelIndex(); - } - - const RadarProductModelItem* parentItem; - - if (!parent.isValid()) - { - parentItem = p->rootItem_.get(); - } - else - { - parentItem = static_cast( - parent.constInternalPointer()); - } - - const RadarProductModelItem* childItem = parentItem->child(row); - if (childItem) - { - return createIndex(row, column, childItem); - } - - return QModelIndex(); -} - -QModelIndex RadarProductModel::parent(const QModelIndex& index) const -{ - if (!index.isValid()) - { - return QModelIndex(); - } - - const RadarProductModelItem* childItem = - static_cast(index.constInternalPointer()); - const RadarProductModelItem* parentItem = childItem->parent_item(); - - if (parentItem == p->rootItem_.get()) - { - return QModelIndex(); - } - - return createIndex(parentItem->row(), 0, parentItem); -} - -RadarProductModelItem::RadarProductModelItem(const std::vector& data, - RadarProductModelItem* parent) : - childItems_ {}, itemData_ {data}, parentItem_ {parent} -{ -} - -RadarProductModelItem::~RadarProductModelItem() -{ - qDeleteAll(childItems_); -} - -void RadarProductModelItem::AppendChild(RadarProductModelItem* item) -{ - item->parentItem_ = this; - childItems_.push_back(item); -} - -const RadarProductModelItem* RadarProductModelItem::child(int row) const -{ - const RadarProductModelItem* item = nullptr; - - if (0 <= row && row < childItems_.size()) - { - item = childItems_[row]; - } - - return item; -} - -int RadarProductModelItem::child_count() const -{ - return static_cast(childItems_.size()); -} - -int RadarProductModelItem::column_count() const -{ - return static_cast(itemData_.size()); -} - -QVariant RadarProductModelItem::data(int column) const -{ - if (0 <= column && column < itemData_.size()) - { - return itemData_[column]; - } - else - { - return QVariant("Hello world"); - } -} - -int RadarProductModelItem::row() const -{ - int row = 0; - - if (parentItem_ != nullptr) - { - const auto& childItems = parentItem_->childItems_; - row = - std::distance(childItems.cbegin(), - std::find(childItems.cbegin(), childItems.cend(), this)); - } - - return row; -} - -const RadarProductModelItem* RadarProductModelItem::parent_item() const -{ - return parentItem_; + return p->rootItem_; } } // namespace model diff --git a/scwx-qt/source/scwx/qt/model/radar_product_model.hpp b/scwx-qt/source/scwx/qt/model/radar_product_model.hpp index 8b1fdfa6..2d3f69d3 100644 --- a/scwx-qt/source/scwx/qt/model/radar_product_model.hpp +++ b/scwx-qt/source/scwx/qt/model/radar_product_model.hpp @@ -1,8 +1,6 @@ #pragma once -#include - -#include +#include namespace scwx { @@ -13,25 +11,14 @@ namespace model class RadarProductModelImpl; -class RadarProductModel : public QAbstractTableModel +class RadarProductModel : public TreeModel { public: explicit RadarProductModel(QObject* parent = nullptr); ~RadarProductModel(); - int rowCount(const QModelIndex& parent = QModelIndex()) const override; - int columnCount(const QModelIndex& parent = QModelIndex()) const override; - - QVariant data(const QModelIndex& index, - int role = Qt::DisplayRole) const override; - Qt::ItemFlags flags(const QModelIndex& index) const override; - QVariant headerData(int section, - Qt::Orientation orientation, - int role = Qt::DisplayRole) const override; - QModelIndex index(int row, - int column, - const QModelIndex& parent = QModelIndex()) const override; - QModelIndex parent(const QModelIndex& index) const override; +protected: + const std::shared_ptr root_item() const override; private: std::unique_ptr p; diff --git a/scwx-qt/source/scwx/qt/model/tree_item.cpp b/scwx-qt/source/scwx/qt/model/tree_item.cpp new file mode 100644 index 00000000..4780dd3d --- /dev/null +++ b/scwx-qt/source/scwx/qt/model/tree_item.cpp @@ -0,0 +1,98 @@ +#include + +namespace scwx +{ +namespace qt +{ +namespace model +{ + +static const std::string logPrefix_ = "scwx::qt::model::tree_item"; + +class TreeItem::Impl +{ +public: + explicit Impl(const std::vector& data, TreeItem* parent) : + childItems_ {}, itemData_ {data}, parentItem_ {parent} + { + } + ~Impl() { qDeleteAll(childItems_); } + + std::vector childItems_; + std::vector itemData_; + TreeItem* parentItem_; +}; + +TreeItem::TreeItem(const std::vector& data, TreeItem* parent) : + p {std::make_unique(data, parent)} +{ +} + +TreeItem::~TreeItem() {} + +TreeItem::TreeItem(TreeItem&&) noexcept = default; +TreeItem& TreeItem::operator=(TreeItem&&) noexcept = default; + +void TreeItem::AppendChild(TreeItem* item) +{ + item->p->parentItem_ = this; + p->childItems_.push_back(item); +} + +const TreeItem* TreeItem::child(int row) const +{ + const TreeItem* item = nullptr; + + if (0 <= row && row < p->childItems_.size()) + { + item = p->childItems_[row]; + } + + return item; +} + +int TreeItem::child_count() const +{ + return static_cast(p->childItems_.size()); +} + +int TreeItem::column_count() const +{ + return static_cast(p->itemData_.size()); +} + +QVariant TreeItem::data(int column) const +{ + if (0 <= column && column < p->itemData_.size()) + { + return p->itemData_[column]; + } + else + { + return QVariant(); + } +} + +int TreeItem::row() const +{ + int row = 0; + + if (p->parentItem_ != nullptr) + { + const auto& childItems = p->parentItem_->p->childItems_; + row = + std::distance(childItems.cbegin(), + std::find(childItems.cbegin(), childItems.cend(), this)); + } + + return row; +} + +const TreeItem* TreeItem::parent_item() const +{ + return p->parentItem_; +} + +} // namespace model +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/model/tree_item.hpp b/scwx-qt/source/scwx/qt/model/tree_item.hpp new file mode 100644 index 00000000..37e3bd6f --- /dev/null +++ b/scwx-qt/source/scwx/qt/model/tree_item.hpp @@ -0,0 +1,44 @@ +#pragma once + +#include +#include + +#include + +namespace scwx +{ +namespace qt +{ +namespace model +{ + +class TreeItem +{ +public: + explicit TreeItem(const std::vector& data, + TreeItem* parent = nullptr); + virtual ~TreeItem(); + + TreeItem(const TreeItem&) = delete; + TreeItem& operator=(const TreeItem&) = delete; + + TreeItem(TreeItem&&) noexcept; + TreeItem& operator=(TreeItem&&) noexcept; + + void AppendChild(TreeItem* child); + + const TreeItem* child(int row) const; + int child_count() const; + int column_count() const; + QVariant data(int column) const; + int row() const; + const TreeItem* parent_item() const; + +private: + class Impl; + std::unique_ptr p; +}; + +} // namespace model +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/model/tree_model.cpp b/scwx-qt/source/scwx/qt/model/tree_model.cpp new file mode 100644 index 00000000..6ee59366 --- /dev/null +++ b/scwx-qt/source/scwx/qt/model/tree_model.cpp @@ -0,0 +1,145 @@ +#include + +namespace scwx +{ +namespace qt +{ +namespace model +{ + +static const std::string logPrefix_ = "scwx::qt::model::tree_model"; + +class TreeModelImpl +{ +public: + explicit TreeModelImpl() = default; + ~TreeModelImpl() = default; +}; + +TreeModel::TreeModel(QObject* parent) : + QAbstractTableModel(parent), p(std::make_unique()) +{ +} +TreeModel::~TreeModel() = default; + +int TreeModel::rowCount(const QModelIndex& parent) const +{ + const TreeItem* parentItem; + + if (parent.isValid()) + { + parentItem = static_cast(parent.constInternalPointer()); + } + else + { + parentItem = root_item().get(); + } + + return parentItem->child_count(); +} + +int TreeModel::columnCount(const QModelIndex& parent) const +{ + const TreeItem* parentItem; + + if (parent.isValid()) + { + parentItem = static_cast(parent.constInternalPointer()); + } + else + { + parentItem = root_item().get(); + } + + return parentItem->column_count(); +} + +QVariant TreeModel::data(const QModelIndex& index, int role) const +{ + if (!index.isValid() || role != Qt::DisplayRole) + { + return QVariant(); + } + + const TreeItem* item = static_cast(index.internalPointer()); + + return item->data(index.column()); +} + +Qt::ItemFlags TreeModel::flags(const QModelIndex& index) const +{ + Qt::ItemFlags flags; + + if (!index.isValid()) + { + flags = Qt::NoItemFlags; + } + else + { + flags = QAbstractItemModel::flags(index); + } + + return flags; +} + +QVariant +TreeModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (orientation == Qt::Horizontal && role == Qt::DisplayRole) + { + return root_item()->data(section); + } + + return QVariant(); +} + +QModelIndex +TreeModel::index(int row, int column, const QModelIndex& parent) const +{ + if (!hasIndex(row, column, parent)) + { + return QModelIndex(); + } + + const TreeItem* parentItem; + + if (!parent.isValid()) + { + parentItem = root_item().get(); + } + else + { + parentItem = static_cast(parent.constInternalPointer()); + } + + const TreeItem* childItem = parentItem->child(row); + if (childItem) + { + return createIndex(row, column, childItem); + } + + return QModelIndex(); +} + +QModelIndex TreeModel::parent(const QModelIndex& index) const +{ + if (!index.isValid()) + { + return QModelIndex(); + } + + const TreeItem* childItem = + static_cast(index.constInternalPointer()); + const TreeItem* parentItem = childItem->parent_item(); + + if (parentItem == root_item().get()) + { + return QModelIndex(); + } + + return createIndex(parentItem->row(), 0, parentItem); +} + +} // namespace model +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/model/tree_model.hpp b/scwx-qt/source/scwx/qt/model/tree_model.hpp new file mode 100644 index 00000000..41bd527c --- /dev/null +++ b/scwx-qt/source/scwx/qt/model/tree_model.hpp @@ -0,0 +1,45 @@ +#pragma once + +#include + +#include + +namespace scwx +{ +namespace qt +{ +namespace model +{ + +class TreeModelImpl; + +class TreeModel : public QAbstractTableModel +{ +public: + explicit TreeModel(QObject* parent = nullptr); + virtual ~TreeModel(); + + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + int columnCount(const QModelIndex& parent = QModelIndex()) const override; + + QVariant data(const QModelIndex& index, + int role = Qt::DisplayRole) const override; + Qt::ItemFlags flags(const QModelIndex& index) const override; + QVariant headerData(int section, + Qt::Orientation orientation, + int role = Qt::DisplayRole) const override; + QModelIndex index(int row, + int column, + const QModelIndex& parent = QModelIndex()) const override; + QModelIndex parent(const QModelIndex& index) const override; + +protected: + virtual const std::shared_ptr root_item() const = 0; + +private: + std::unique_ptr p; +}; + +} // namespace model +} // namespace qt +} // namespace scwx From 4c4c93cad1cc17b7a4b7729c45c70f17a5f5f3ef Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Mon, 19 Sep 2022 23:46:15 -0500 Subject: [PATCH 07/11] Connecting Radar Product Manager creation to Radar Product Model --- scwx-qt/scwx-qt.cmake | 2 ++ scwx-qt/source/scwx/qt/main/main_window.cpp | 5 +-- .../scwx/qt/manager/radar_product_manager.cpp | 3 ++ .../radar_product_manager_notifier.cpp | 34 ++++++++++++++++++ .../radar_product_manager_notifier.hpp | 35 +++++++++++++++++++ .../scwx/qt/model/radar_product_model.cpp | 29 ++++++++++----- 6 files changed, 98 insertions(+), 10 deletions(-) create mode 100644 scwx-qt/source/scwx/qt/manager/radar_product_manager_notifier.cpp create mode 100644 scwx-qt/source/scwx/qt/manager/radar_product_manager_notifier.hpp diff --git a/scwx-qt/scwx-qt.cmake b/scwx-qt/scwx-qt.cmake index ce097ef8..00abbaf4 100644 --- a/scwx-qt/scwx-qt.cmake +++ b/scwx-qt/scwx-qt.cmake @@ -50,9 +50,11 @@ set(HDR_GL_DRAW source/scwx/qt/gl/draw/draw_item.hpp set(SRC_GL_DRAW source/scwx/qt/gl/draw/draw_item.cpp source/scwx/qt/gl/draw/rectangle.cpp) set(HDR_MANAGER source/scwx/qt/manager/radar_product_manager.hpp + source/scwx/qt/manager/radar_product_manager_notifier.hpp source/scwx/qt/manager/resource_manager.hpp source/scwx/qt/manager/settings_manager.hpp) set(SRC_MANAGER source/scwx/qt/manager/radar_product_manager.cpp + source/scwx/qt/manager/radar_product_manager_notifier.cpp source/scwx/qt/manager/resource_manager.cpp source/scwx/qt/manager/settings_manager.cpp) set(HDR_MAP source/scwx/qt/map/color_table_layer.hpp diff --git a/scwx-qt/source/scwx/qt/main/main_window.cpp b/scwx-qt/source/scwx/qt/main/main_window.cpp index 1f8287fe..ce5db8a9 100644 --- a/scwx-qt/source/scwx/qt/main/main_window.cpp +++ b/scwx-qt/source/scwx/qt/main/main_window.cpp @@ -124,8 +124,6 @@ MainWindow::MainWindow(QWidget* parent) : ui->vcpValueLabel->setVisible(false); ui->vcpDescriptionLabel->setVisible(false); - p->ConfigureMapLayout(); - // Configure Menu ui->menuView->insertAction(ui->actionRadarToolbox, ui->radarToolboxDock->toggleViewAction()); @@ -143,6 +141,9 @@ MainWindow::MainWindow(QWidget* parent) : ui->resourceTreeView->setModel(new model::RadarProductModel()); + // Configure Map + p->ConfigureMapLayout(); + // Add Level 2 Products p->level2ProductsWidget_ = new ui::Level2ProductsWidget(this); ui->radarProductGroupBox->layout()->replaceWidget(ui->level2ProductFrame, diff --git a/scwx-qt/source/scwx/qt/manager/radar_product_manager.cpp b/scwx-qt/source/scwx/qt/manager/radar_product_manager.cpp index 8a626476..7c60e933 100644 --- a/scwx-qt/source/scwx/qt/manager/radar_product_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/radar_product_manager.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -943,6 +944,8 @@ RadarProductManager::Instance(const std::string& radarSite) { instanceMap_[radarSite] = std::make_shared(radarSite); + emit RadarProductManagerNotifier::Instance().RadarProductManagerCreated( + radarSite); } return instanceMap_[radarSite]; diff --git a/scwx-qt/source/scwx/qt/manager/radar_product_manager_notifier.cpp b/scwx-qt/source/scwx/qt/manager/radar_product_manager_notifier.cpp new file mode 100644 index 00000000..b5c0a89b --- /dev/null +++ b/scwx-qt/source/scwx/qt/manager/radar_product_manager_notifier.cpp @@ -0,0 +1,34 @@ +#include + +namespace scwx +{ +namespace qt +{ +namespace manager +{ + +static const std::string logPrefix_ = + "scwx::qt::manager::radar_product_manager_notifier"; + +class RadarProductManagerNotifierImpl +{ +public: + explicit RadarProductManagerNotifierImpl() {} + ~RadarProductManagerNotifierImpl() {} +}; + +RadarProductManagerNotifier::RadarProductManagerNotifier() : + p(std::make_unique()) +{ +} +RadarProductManagerNotifier::~RadarProductManagerNotifier() = default; + +RadarProductManagerNotifier& RadarProductManagerNotifier::Instance() +{ + static RadarProductManagerNotifier instance_ {}; + return instance_; +} + +} // namespace manager +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/manager/radar_product_manager_notifier.hpp b/scwx-qt/source/scwx/qt/manager/radar_product_manager_notifier.hpp new file mode 100644 index 00000000..163ba29f --- /dev/null +++ b/scwx-qt/source/scwx/qt/manager/radar_product_manager_notifier.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include + +#include + +namespace scwx +{ +namespace qt +{ +namespace manager +{ + +class RadarProductManagerNotifierImpl; + +class RadarProductManagerNotifier : public QObject +{ + Q_OBJECT + +public: + explicit RadarProductManagerNotifier(); + ~RadarProductManagerNotifier(); + + static RadarProductManagerNotifier& Instance(); + +signals: + void RadarProductManagerCreated(const std::string& radarSite); + +private: + std::unique_ptr p; +}; + +} // namespace manager +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/model/radar_product_model.cpp b/scwx-qt/source/scwx/qt/model/radar_product_model.cpp index 49453572..b5c33400 100644 --- a/scwx-qt/source/scwx/qt/model/radar_product_model.cpp +++ b/scwx-qt/source/scwx/qt/model/radar_product_model.cpp @@ -1,4 +1,5 @@ #include +#include #include namespace scwx @@ -11,16 +12,12 @@ namespace model static const std::string logPrefix_ = "scwx::qt::model::radar_product_model"; static const auto logger_ = scwx::util::Logger::Create(logPrefix_); -class RadarProductModelImpl +class RadarProductModelImpl : public QObject { + Q_OBJECT + public: - explicit RadarProductModelImpl() : - rootItem_ {std::make_shared( - std::vector {QObject::tr("Name"), QObject::tr("Info")})} - { - rootItem_->AppendChild(new TreeItem( - std::vector {QObject::tr("MyItem"), QObject::tr("Data")})); - } + explicit RadarProductModelImpl(); ~RadarProductModelImpl() = default; std::shared_ptr rootItem_; @@ -37,6 +34,22 @@ const std::shared_ptr RadarProductModel::root_item() const return p->rootItem_; } +RadarProductModelImpl::RadarProductModelImpl() : + rootItem_ {std::make_shared( + std::vector {QObject::tr("Name"), QObject::tr("Info")})} +{ + connect(&manager::RadarProductManagerNotifier::Instance(), + &manager::RadarProductManagerNotifier::RadarProductManagerCreated, + this, + [=](const std::string& radarSite) + { + rootItem_->AppendChild(new TreeItem( + std::vector {QString::fromStdString(radarSite)})); + }); +} + +#include "radar_product_model.moc" + } // namespace model } // namespace qt } // namespace scwx From efc6dc14132e3da2109153d6b608b69c5f876f64 Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Wed, 21 Sep 2022 22:28:24 -0500 Subject: [PATCH 08/11] Radar Product Model population --- .../scwx/qt/model/radar_product_model.cpp | 76 ++++++++++++++++--- scwx-qt/source/scwx/qt/model/tree_item.cpp | 40 ++++++++++ scwx-qt/source/scwx/qt/model/tree_item.hpp | 19 +++-- scwx-qt/source/scwx/qt/model/tree_model.cpp | 2 +- scwx-qt/source/scwx/qt/model/tree_model.hpp | 4 +- 5 files changed, 120 insertions(+), 21 deletions(-) diff --git a/scwx-qt/source/scwx/qt/model/radar_product_model.cpp b/scwx-qt/source/scwx/qt/model/radar_product_model.cpp index b5c33400..0e12f55f 100644 --- a/scwx-qt/source/scwx/qt/model/radar_product_model.cpp +++ b/scwx-qt/source/scwx/qt/model/radar_product_model.cpp @@ -1,6 +1,8 @@ #include +#include #include #include +#include namespace scwx { @@ -17,14 +19,15 @@ class RadarProductModelImpl : public QObject Q_OBJECT public: - explicit RadarProductModelImpl(); + explicit RadarProductModelImpl(RadarProductModel* self); ~RadarProductModelImpl() = default; + RadarProductModel* self_; std::shared_ptr rootItem_; }; RadarProductModel::RadarProductModel(QObject* parent) : - TreeModel(parent), p(std::make_unique()) + TreeModel(parent), p(std::make_unique(this)) { } RadarProductModel::~RadarProductModel() = default; @@ -34,18 +37,69 @@ const std::shared_ptr RadarProductModel::root_item() const return p->rootItem_; } -RadarProductModelImpl::RadarProductModelImpl() : +RadarProductModelImpl::RadarProductModelImpl(RadarProductModel* self) : + self_ {self}, rootItem_ {std::make_shared( std::vector {QObject::tr("Name"), QObject::tr("Info")})} { - connect(&manager::RadarProductManagerNotifier::Instance(), - &manager::RadarProductManagerNotifier::RadarProductManagerCreated, - this, - [=](const std::string& radarSite) - { - rootItem_->AppendChild(new TreeItem( - std::vector {QString::fromStdString(radarSite)})); - }); + connect( + &manager::RadarProductManagerNotifier::Instance(), + &manager::RadarProductManagerNotifier::RadarProductManagerCreated, + this, + [=](const std::string& radarSite) + { + TreeItem* radarSiteItem = + new TreeItem({QString::fromStdString(radarSite)}); + + rootItem_->AppendChild(radarSiteItem); + + connect( + manager::RadarProductManager::Instance(radarSite).get(), + &manager::RadarProductManager::NewDataAvailable, + this, + [=](common::RadarProductGroup group, + const std::string& product, + std::chrono::system_clock::time_point latestTime) + { + const QString groupName {QString::fromStdString( + common::GetRadarProductGroupName(group))}; + + // Find existing group item (e.g., Level 2, Level 3) + TreeItem* groupItem = radarSiteItem->FindChild(0, groupName); + + if (groupItem == nullptr) + { + groupItem = new TreeItem({groupName}); + radarSiteItem->AppendChild(groupItem); + } + + TreeItem* productItem = nullptr; + + if (group == common::RadarProductGroup::Level2) + { + // Level 2 items are not separated by product + productItem = groupItem; + } + else + { + // Find existing product item (e.g., N0B, N0Q) + const QString productName {QString::fromStdString(product)}; + productItem = groupItem->FindChild(0, productName); + + if (productItem == nullptr) + { + productItem = new TreeItem({productName}); + groupItem->AppendChild(productItem); + } + } + + // Create leaf item for product time + productItem->AppendChild(new TreeItem { + QString::fromStdString(util::TimeString(latestTime))}); + }, + Qt::QueuedConnection); + }, + Qt::QueuedConnection); } #include "radar_product_model.moc" diff --git a/scwx-qt/source/scwx/qt/model/tree_item.cpp b/scwx-qt/source/scwx/qt/model/tree_item.cpp index 4780dd3d..e43ef4c2 100644 --- a/scwx-qt/source/scwx/qt/model/tree_item.cpp +++ b/scwx-qt/source/scwx/qt/model/tree_item.cpp @@ -28,6 +28,11 @@ TreeItem::TreeItem(const std::vector& data, TreeItem* parent) : { } +TreeItem::TreeItem(std::initializer_list data, TreeItem* parent) : + TreeItem(std::vector {data}, parent) +{ +} + TreeItem::~TreeItem() {} TreeItem::TreeItem(TreeItem&&) noexcept = default; @@ -39,6 +44,24 @@ void TreeItem::AppendChild(TreeItem* item) p->childItems_.push_back(item); } +TreeItem* TreeItem::FindChild(int column, const QVariant& data) +{ + auto it = std::find_if(p->childItems_.begin(), + p->childItems_.end(), + [&](auto& item) { + return (column < item->column_count() && + item->data(column) == data); + }); + + TreeItem* item = nullptr; + if (it != p->childItems_.end()) + { + item = *it; + } + + return item; +} + const TreeItem* TreeItem::child(int row) const { const TreeItem* item = nullptr; @@ -51,6 +74,23 @@ const TreeItem* TreeItem::child(int row) const return item; } +TreeItem* TreeItem::child(int row) +{ + TreeItem* item = nullptr; + + if (0 <= row && row < p->childItems_.size()) + { + item = p->childItems_[row]; + } + + return item; +} + +std::vector TreeItem::children() +{ + return p->childItems_; +} + int TreeItem::child_count() const { return static_cast(p->childItems_.size()); diff --git a/scwx-qt/source/scwx/qt/model/tree_item.hpp b/scwx-qt/source/scwx/qt/model/tree_item.hpp index 37e3bd6f..de3eb54e 100644 --- a/scwx-qt/source/scwx/qt/model/tree_item.hpp +++ b/scwx-qt/source/scwx/qt/model/tree_item.hpp @@ -17,6 +17,8 @@ class TreeItem public: explicit TreeItem(const std::vector& data, TreeItem* parent = nullptr); + explicit TreeItem(std::initializer_list data, + TreeItem* parent = nullptr); virtual ~TreeItem(); TreeItem(const TreeItem&) = delete; @@ -25,14 +27,17 @@ public: TreeItem(TreeItem&&) noexcept; TreeItem& operator=(TreeItem&&) noexcept; - void AppendChild(TreeItem* child); + void AppendChild(TreeItem* child); + TreeItem* FindChild(int column, const QVariant& data); - const TreeItem* child(int row) const; - int child_count() const; - int column_count() const; - QVariant data(int column) const; - int row() const; - const TreeItem* parent_item() const; + const TreeItem* child(int row) const; + TreeItem* child(int row); + std::vector children(); + int child_count() const; + int column_count() const; + QVariant data(int column) const; + int row() const; + const TreeItem* parent_item() const; private: class Impl; diff --git a/scwx-qt/source/scwx/qt/model/tree_model.cpp b/scwx-qt/source/scwx/qt/model/tree_model.cpp index 6ee59366..fc2c823f 100644 --- a/scwx-qt/source/scwx/qt/model/tree_model.cpp +++ b/scwx-qt/source/scwx/qt/model/tree_model.cpp @@ -17,7 +17,7 @@ public: }; TreeModel::TreeModel(QObject* parent) : - QAbstractTableModel(parent), p(std::make_unique()) + QAbstractItemModel(parent), p(std::make_unique()) { } TreeModel::~TreeModel() = default; diff --git a/scwx-qt/source/scwx/qt/model/tree_model.hpp b/scwx-qt/source/scwx/qt/model/tree_model.hpp index 41bd527c..6c85c299 100644 --- a/scwx-qt/source/scwx/qt/model/tree_model.hpp +++ b/scwx-qt/source/scwx/qt/model/tree_model.hpp @@ -2,7 +2,7 @@ #include -#include +#include namespace scwx { @@ -13,7 +13,7 @@ namespace model class TreeModelImpl; -class TreeModel : public QAbstractTableModel +class TreeModel : public QAbstractItemModel { public: explicit TreeModel(QObject* parent = nullptr); From 1e58cc29e5f40a330500ca54c23121752ec8cf63 Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Wed, 21 Sep 2022 23:07:06 -0500 Subject: [PATCH 09/11] Add begin/endInsertRows calls to notify view of changes --- .../scwx/qt/model/radar_product_model.cpp | 38 ++++++++++++++++++- .../scwx/qt/model/radar_product_model.hpp | 2 + 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/scwx-qt/source/scwx/qt/model/radar_product_model.cpp b/scwx-qt/source/scwx/qt/model/radar_product_model.cpp index 0e12f55f..d965a23d 100644 --- a/scwx-qt/source/scwx/qt/model/radar_product_model.cpp +++ b/scwx-qt/source/scwx/qt/model/radar_product_model.cpp @@ -48,11 +48,18 @@ RadarProductModelImpl::RadarProductModelImpl(RadarProductModel* self) : this, [=](const std::string& radarSite) { + const QModelIndex rootIndex = + self_->createIndex(rootItem_->row(), 0, rootItem_.get()); + const int rootChildren = rootItem_->child_count(); + + self_->beginInsertRows(rootIndex, rootChildren, rootChildren); + TreeItem* radarSiteItem = new TreeItem({QString::fromStdString(radarSite)}); - rootItem_->AppendChild(radarSiteItem); + self_->endInsertRows(); + connect( manager::RadarProductManager::Instance(radarSite).get(), &manager::RadarProductManager::NewDataAvailable, @@ -69,8 +76,18 @@ RadarProductModelImpl::RadarProductModelImpl(RadarProductModel* self) : if (groupItem == nullptr) { + // Existing group item was not found, create it + const QModelIndex radarSiteIndex = + self_->createIndex(radarSiteItem->row(), 0, radarSiteItem); + const int radarSiteChildren = radarSiteItem->child_count(); + + self_->beginInsertRows( + radarSiteIndex, radarSiteChildren, radarSiteChildren); + groupItem = new TreeItem({groupName}); radarSiteItem->AppendChild(groupItem); + + self_->endInsertRows(); } TreeItem* productItem = nullptr; @@ -88,14 +105,33 @@ RadarProductModelImpl::RadarProductModelImpl(RadarProductModel* self) : if (productItem == nullptr) { + // Existing product item was not found, create it + const QModelIndex groupItemIndex = + self_->createIndex(groupItem->row(), 0, groupItem); + const int groupItemChildren = groupItem->child_count(); + + self_->beginInsertRows( + groupItemIndex, groupItemChildren, groupItemChildren); + productItem = new TreeItem({productName}); groupItem->AppendChild(productItem); + + self_->endInsertRows(); } } // Create leaf item for product time + const QModelIndex productItemIndex = + self_->createIndex(productItem->row(), 0, productItem); + const int productItemChildren = productItem->child_count(); + + self_->beginInsertRows( + productItemIndex, productItemChildren, productItemChildren); + productItem->AppendChild(new TreeItem { QString::fromStdString(util::TimeString(latestTime))}); + + self_->endInsertRows(); }, Qt::QueuedConnection); }, diff --git a/scwx-qt/source/scwx/qt/model/radar_product_model.hpp b/scwx-qt/source/scwx/qt/model/radar_product_model.hpp index 2d3f69d3..9fb45aa2 100644 --- a/scwx-qt/source/scwx/qt/model/radar_product_model.hpp +++ b/scwx-qt/source/scwx/qt/model/radar_product_model.hpp @@ -22,6 +22,8 @@ protected: private: std::unique_ptr p; + + friend class RadarProductModelImpl; }; } // namespace model From 06e33001f75f0fb4b2e84d767f929c393851c583 Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Wed, 21 Sep 2022 23:10:43 -0500 Subject: [PATCH 10/11] Radar Product Model missing initial signals from manager --- .../scwx/qt/manager/radar_product_manager.cpp | 22 ++++++++++++++----- .../scwx/qt/model/radar_product_model.cpp | 5 +++-- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/scwx-qt/source/scwx/qt/manager/radar_product_manager.cpp b/scwx-qt/source/scwx/qt/manager/radar_product_manager.cpp index 7c60e933..117d681d 100644 --- a/scwx-qt/source/scwx/qt/manager/radar_product_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/radar_product_manager.cpp @@ -938,17 +938,29 @@ void RadarProductManager::UpdateAvailableProducts() std::shared_ptr RadarProductManager::Instance(const std::string& radarSite) { - std::lock_guard guard(instanceMutex_); + std::shared_ptr instance = nullptr; + bool instanceCreated = false; - if (!instanceMap_.contains(radarSite)) { - instanceMap_[radarSite] = - std::make_shared(radarSite); + std::lock_guard guard(instanceMutex_); + + if (!instanceMap_.contains(radarSite)) + { + instanceMap_[radarSite] = + std::make_shared(radarSite); + instanceCreated = true; + } + + instance = instanceMap_[radarSite]; + } + + if (instanceCreated) + { emit RadarProductManagerNotifier::Instance().RadarProductManagerCreated( radarSite); } - return instanceMap_[radarSite]; + return instance; } } // namespace manager diff --git a/scwx-qt/source/scwx/qt/model/radar_product_model.cpp b/scwx-qt/source/scwx/qt/model/radar_product_model.cpp index d965a23d..e29e9e72 100644 --- a/scwx-qt/source/scwx/qt/model/radar_product_model.cpp +++ b/scwx-qt/source/scwx/qt/model/radar_product_model.cpp @@ -48,6 +48,8 @@ RadarProductModelImpl::RadarProductModelImpl(RadarProductModel* self) : this, [=](const std::string& radarSite) { + logger_->debug("Adding radar site: {}", radarSite); + const QModelIndex rootIndex = self_->createIndex(rootItem_->row(), 0, rootItem_.get()); const int rootChildren = rootItem_->child_count(); @@ -134,8 +136,7 @@ RadarProductModelImpl::RadarProductModelImpl(RadarProductModel* self) : self_->endInsertRows(); }, Qt::QueuedConnection); - }, - Qt::QueuedConnection); + }); } #include "radar_product_model.moc" From f47fab196ec177eb0b3b744c5fc00acfae75a5e3 Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Thu, 22 Sep 2022 00:09:23 -0500 Subject: [PATCH 11/11] Resource Explorer view and model cleanup --- scwx-qt/source/scwx/qt/main/main_window.cpp | 2 +- scwx-qt/source/scwx/qt/main/main_window.ui | 2 +- scwx-qt/source/scwx/qt/model/radar_product_model.cpp | 2 +- scwx-qt/source/scwx/qt/model/tree_model.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scwx-qt/source/scwx/qt/main/main_window.cpp b/scwx-qt/source/scwx/qt/main/main_window.cpp index ce5db8a9..f28a9688 100644 --- a/scwx-qt/source/scwx/qt/main/main_window.cpp +++ b/scwx-qt/source/scwx/qt/main/main_window.cpp @@ -139,7 +139,7 @@ MainWindow::MainWindow(QWidget* parent) : // Configure Docks ui->resourceExplorerDock->setVisible(false); - ui->resourceTreeView->setModel(new model::RadarProductModel()); + ui->resourceTreeView->setModel(new model::RadarProductModel(this)); // Configure Map p->ConfigureMapLayout(); diff --git a/scwx-qt/source/scwx/qt/main/main_window.ui b/scwx-qt/source/scwx/qt/main/main_window.ui index a0ac0a3a..f5f1c23e 100644 --- a/scwx-qt/source/scwx/qt/main/main_window.ui +++ b/scwx-qt/source/scwx/qt/main/main_window.ui @@ -230,7 +230,7 @@ Resource Explorer - 8 + 2 diff --git a/scwx-qt/source/scwx/qt/model/radar_product_model.cpp b/scwx-qt/source/scwx/qt/model/radar_product_model.cpp index e29e9e72..bb4ecebd 100644 --- a/scwx-qt/source/scwx/qt/model/radar_product_model.cpp +++ b/scwx-qt/source/scwx/qt/model/radar_product_model.cpp @@ -40,7 +40,7 @@ const std::shared_ptr RadarProductModel::root_item() const RadarProductModelImpl::RadarProductModelImpl(RadarProductModel* self) : self_ {self}, rootItem_ {std::make_shared( - std::vector {QObject::tr("Name"), QObject::tr("Info")})} + std::vector {QObject::tr("Product")})} { connect( &manager::RadarProductManagerNotifier::Instance(), diff --git a/scwx-qt/source/scwx/qt/model/tree_model.cpp b/scwx-qt/source/scwx/qt/model/tree_model.cpp index fc2c823f..e2be6382 100644 --- a/scwx-qt/source/scwx/qt/model/tree_model.cpp +++ b/scwx-qt/source/scwx/qt/model/tree_model.cpp @@ -132,7 +132,7 @@ QModelIndex TreeModel::parent(const QModelIndex& index) const static_cast(index.constInternalPointer()); const TreeItem* parentItem = childItem->parent_item(); - if (parentItem == root_item().get()) + if (parentItem == root_item().get() || parentItem == nullptr) { return QModelIndex(); }