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