mirror of
https://github.com/ciphervance/supercell-wx.git
synced 2025-10-30 21:30:05 +00:00
Merge branch 'feature/resource-explorer' into develop
This commit is contained in:
commit
b2b413c48d
12 changed files with 708 additions and 6 deletions
|
|
@ -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
|
||||
|
|
@ -73,6 +75,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
|
||||
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
|
||||
|
|
@ -140,6 +148,8 @@ set(PROJECT_SOURCES ${HDR_MAIN}
|
|||
${UI_MAIN}
|
||||
${HDR_MAP}
|
||||
${SRC_MAP}
|
||||
${HDR_MODEL}
|
||||
${SRC_MODEL}
|
||||
${HDR_REQUEST}
|
||||
${SRC_REQUEST}
|
||||
${HDR_SETTINGS}
|
||||
|
|
@ -172,6 +182,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})
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include <scwx/qt/manager/radar_product_manager.hpp>
|
||||
#include <scwx/qt/manager/settings_manager.hpp>
|
||||
#include <scwx/qt/map/map_widget.hpp>
|
||||
#include <scwx/qt/model/radar_product_model.hpp>
|
||||
#include <scwx/qt/ui/flow_layout.hpp>
|
||||
#include <scwx/qt/ui/level2_products_widget.hpp>
|
||||
#include <scwx/qt/ui/level2_settings_widget.hpp>
|
||||
|
|
@ -123,6 +124,24 @@ MainWindow::MainWindow(QWidget* parent) :
|
|||
ui->vcpValueLabel->setVisible(false);
|
||||
ui->vcpDescriptionLabel->setVisible(false);
|
||||
|
||||
// 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);
|
||||
|
||||
ui->resourceTreeView->setModel(new model::RadarProductModel(this));
|
||||
|
||||
// Configure Map
|
||||
p->ConfigureMapLayout();
|
||||
|
||||
// Add Level 2 Products
|
||||
|
|
|
|||
|
|
@ -52,13 +52,21 @@
|
|||
</property>
|
||||
<addaction name="actionAboutSupercellWx"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuView">
|
||||
<property name="title">
|
||||
<string>&View</string>
|
||||
</property>
|
||||
<addaction name="actionRadarToolbox"/>
|
||||
<addaction name="actionResourceExplorer"/>
|
||||
</widget>
|
||||
<addaction name="menuFile"/>
|
||||
<addaction name="menuView"/>
|
||||
<addaction name="menuHelp"/>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar"/>
|
||||
<widget class="QDockWidget" name="radarToolboxDock">
|
||||
<property name="windowTitle">
|
||||
<string>Toolbox</string>
|
||||
<string>Radar Toolbox</string>
|
||||
</property>
|
||||
<attribute name="dockWidgetArea">
|
||||
<number>1</number>
|
||||
|
|
@ -217,6 +225,21 @@
|
|||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QDockWidget" name="resourceExplorerDock">
|
||||
<property name="windowTitle">
|
||||
<string>Resource Explorer</string>
|
||||
</property>
|
||||
<attribute name="dockWidgetArea">
|
||||
<number>2</number>
|
||||
</attribute>
|
||||
<widget class="QWidget" name="dockWidgetContents">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QTreeView" name="resourceTreeView"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<action name="actionExit">
|
||||
<property name="text">
|
||||
<string>E&xit</string>
|
||||
|
|
@ -235,6 +258,16 @@
|
|||
<string>Ctrl+O</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionRadarToolbox">
|
||||
<property name="text">
|
||||
<string>Radar Toolbox</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionResourceExplorer">
|
||||
<property name="text">
|
||||
<string>&Resource Explorer</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include <scwx/qt/manager/radar_product_manager.hpp>
|
||||
#include <scwx/qt/manager/radar_product_manager_notifier.hpp>
|
||||
#include <scwx/common/constants.hpp>
|
||||
#include <scwx/provider/nexrad_data_provider_factory.hpp>
|
||||
#include <scwx/util/logger.hpp>
|
||||
|
|
@ -937,15 +938,29 @@ void RadarProductManager::UpdateAvailableProducts()
|
|||
std::shared_ptr<RadarProductManager>
|
||||
RadarProductManager::Instance(const std::string& radarSite)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(instanceMutex_);
|
||||
std::shared_ptr<RadarProductManager> instance = nullptr;
|
||||
bool instanceCreated = false;
|
||||
|
||||
if (!instanceMap_.contains(radarSite))
|
||||
{
|
||||
instanceMap_[radarSite] =
|
||||
std::make_shared<RadarProductManager>(radarSite);
|
||||
std::lock_guard<std::mutex> guard(instanceMutex_);
|
||||
|
||||
if (!instanceMap_.contains(radarSite))
|
||||
{
|
||||
instanceMap_[radarSite] =
|
||||
std::make_shared<RadarProductManager>(radarSite);
|
||||
instanceCreated = true;
|
||||
}
|
||||
|
||||
instance = instanceMap_[radarSite];
|
||||
}
|
||||
|
||||
return instanceMap_[radarSite];
|
||||
if (instanceCreated)
|
||||
{
|
||||
emit RadarProductManagerNotifier::Instance().RadarProductManagerCreated(
|
||||
radarSite);
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
} // namespace manager
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
#include <scwx/qt/manager/radar_product_manager_notifier.hpp>
|
||||
|
||||
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<RadarProductManagerNotifierImpl>())
|
||||
{
|
||||
}
|
||||
RadarProductManagerNotifier::~RadarProductManagerNotifier() = default;
|
||||
|
||||
RadarProductManagerNotifier& RadarProductManagerNotifier::Instance()
|
||||
{
|
||||
static RadarProductManagerNotifier instance_ {};
|
||||
return instance_;
|
||||
}
|
||||
|
||||
} // namespace manager
|
||||
} // namespace qt
|
||||
} // namespace scwx
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <QObject>
|
||||
|
||||
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<RadarProductManagerNotifierImpl> p;
|
||||
};
|
||||
|
||||
} // namespace manager
|
||||
} // namespace qt
|
||||
} // namespace scwx
|
||||
146
scwx-qt/source/scwx/qt/model/radar_product_model.cpp
Normal file
146
scwx-qt/source/scwx/qt/model/radar_product_model.cpp
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
#include <scwx/qt/model/radar_product_model.hpp>
|
||||
#include <scwx/qt/manager/radar_product_manager.hpp>
|
||||
#include <scwx/qt/manager/radar_product_manager_notifier.hpp>
|
||||
#include <scwx/util/logger.hpp>
|
||||
#include <scwx/util/time.hpp>
|
||||
|
||||
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 QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit RadarProductModelImpl(RadarProductModel* self);
|
||||
~RadarProductModelImpl() = default;
|
||||
|
||||
RadarProductModel* self_;
|
||||
std::shared_ptr<TreeItem> rootItem_;
|
||||
};
|
||||
|
||||
RadarProductModel::RadarProductModel(QObject* parent) :
|
||||
TreeModel(parent), p(std::make_unique<RadarProductModelImpl>(this))
|
||||
{
|
||||
}
|
||||
RadarProductModel::~RadarProductModel() = default;
|
||||
|
||||
const std::shared_ptr<TreeItem> RadarProductModel::root_item() const
|
||||
{
|
||||
return p->rootItem_;
|
||||
}
|
||||
|
||||
RadarProductModelImpl::RadarProductModelImpl(RadarProductModel* self) :
|
||||
self_ {self},
|
||||
rootItem_ {std::make_shared<TreeItem>(
|
||||
std::vector<QVariant> {QObject::tr("Product")})}
|
||||
{
|
||||
connect(
|
||||
&manager::RadarProductManagerNotifier::Instance(),
|
||||
&manager::RadarProductManagerNotifier::RadarProductManagerCreated,
|
||||
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();
|
||||
|
||||
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,
|
||||
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)
|
||||
{
|
||||
// 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;
|
||||
|
||||
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)
|
||||
{
|
||||
// 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);
|
||||
});
|
||||
}
|
||||
|
||||
#include "radar_product_model.moc"
|
||||
|
||||
} // namespace model
|
||||
} // namespace qt
|
||||
} // namespace scwx
|
||||
31
scwx-qt/source/scwx/qt/model/radar_product_model.hpp
Normal file
31
scwx-qt/source/scwx/qt/model/radar_product_model.hpp
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
#pragma once
|
||||
|
||||
#include <scwx/qt/model/tree_model.hpp>
|
||||
|
||||
namespace scwx
|
||||
{
|
||||
namespace qt
|
||||
{
|
||||
namespace model
|
||||
{
|
||||
|
||||
class RadarProductModelImpl;
|
||||
|
||||
class RadarProductModel : public TreeModel
|
||||
{
|
||||
public:
|
||||
explicit RadarProductModel(QObject* parent = nullptr);
|
||||
~RadarProductModel();
|
||||
|
||||
protected:
|
||||
const std::shared_ptr<TreeItem> root_item() const override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<RadarProductModelImpl> p;
|
||||
|
||||
friend class RadarProductModelImpl;
|
||||
};
|
||||
|
||||
} // namespace model
|
||||
} // namespace qt
|
||||
} // namespace scwx
|
||||
138
scwx-qt/source/scwx/qt/model/tree_item.cpp
Normal file
138
scwx-qt/source/scwx/qt/model/tree_item.cpp
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
#include <scwx/qt/model/tree_item.hpp>
|
||||
|
||||
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<QVariant>& data, TreeItem* parent) :
|
||||
childItems_ {}, itemData_ {data}, parentItem_ {parent}
|
||||
{
|
||||
}
|
||||
~Impl() { qDeleteAll(childItems_); }
|
||||
|
||||
std::vector<TreeItem*> childItems_;
|
||||
std::vector<QVariant> itemData_;
|
||||
TreeItem* parentItem_;
|
||||
};
|
||||
|
||||
TreeItem::TreeItem(const std::vector<QVariant>& data, TreeItem* parent) :
|
||||
p {std::make_unique<Impl>(data, parent)}
|
||||
{
|
||||
}
|
||||
|
||||
TreeItem::TreeItem(std::initializer_list<QVariant> data, TreeItem* parent) :
|
||||
TreeItem(std::vector<QVariant> {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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (0 <= row && row < p->childItems_.size())
|
||||
{
|
||||
item = p->childItems_[row];
|
||||
}
|
||||
|
||||
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*> TreeItem::children()
|
||||
{
|
||||
return p->childItems_;
|
||||
}
|
||||
|
||||
int TreeItem::child_count() const
|
||||
{
|
||||
return static_cast<int>(p->childItems_.size());
|
||||
}
|
||||
|
||||
int TreeItem::column_count() const
|
||||
{
|
||||
return static_cast<int>(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
|
||||
49
scwx-qt/source/scwx/qt/model/tree_item.hpp
Normal file
49
scwx-qt/source/scwx/qt/model/tree_item.hpp
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <QVariant>
|
||||
|
||||
namespace scwx
|
||||
{
|
||||
namespace qt
|
||||
{
|
||||
namespace model
|
||||
{
|
||||
|
||||
class TreeItem
|
||||
{
|
||||
public:
|
||||
explicit TreeItem(const std::vector<QVariant>& data,
|
||||
TreeItem* parent = nullptr);
|
||||
explicit TreeItem(std::initializer_list<QVariant> 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);
|
||||
TreeItem* FindChild(int column, const QVariant& data);
|
||||
|
||||
const TreeItem* child(int row) const;
|
||||
TreeItem* child(int row);
|
||||
std::vector<TreeItem*> 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;
|
||||
std::unique_ptr<Impl> p;
|
||||
};
|
||||
|
||||
} // namespace model
|
||||
} // namespace qt
|
||||
} // namespace scwx
|
||||
145
scwx-qt/source/scwx/qt/model/tree_model.cpp
Normal file
145
scwx-qt/source/scwx/qt/model/tree_model.cpp
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
#include <scwx/qt/model/tree_model.hpp>
|
||||
|
||||
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) :
|
||||
QAbstractItemModel(parent), p(std::make_unique<TreeModelImpl>())
|
||||
{
|
||||
}
|
||||
TreeModel::~TreeModel() = default;
|
||||
|
||||
int TreeModel::rowCount(const QModelIndex& parent) const
|
||||
{
|
||||
const TreeItem* parentItem;
|
||||
|
||||
if (parent.isValid())
|
||||
{
|
||||
parentItem = static_cast<const TreeItem*>(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<const TreeItem*>(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<const TreeItem*>(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<const TreeItem*>(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<const TreeItem*>(index.constInternalPointer());
|
||||
const TreeItem* parentItem = childItem->parent_item();
|
||||
|
||||
if (parentItem == root_item().get() || parentItem == nullptr)
|
||||
{
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
return createIndex(parentItem->row(), 0, parentItem);
|
||||
}
|
||||
|
||||
} // namespace model
|
||||
} // namespace qt
|
||||
} // namespace scwx
|
||||
45
scwx-qt/source/scwx/qt/model/tree_model.hpp
Normal file
45
scwx-qt/source/scwx/qt/model/tree_model.hpp
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
#pragma once
|
||||
|
||||
#include <scwx/qt/model/tree_item.hpp>
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
|
||||
namespace scwx
|
||||
{
|
||||
namespace qt
|
||||
{
|
||||
namespace model
|
||||
{
|
||||
|
||||
class TreeModelImpl;
|
||||
|
||||
class TreeModel : public QAbstractItemModel
|
||||
{
|
||||
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<TreeItem> root_item() const = 0;
|
||||
|
||||
private:
|
||||
std::unique_ptr<TreeModelImpl> p;
|
||||
};
|
||||
|
||||
} // namespace model
|
||||
} // namespace qt
|
||||
} // namespace scwx
|
||||
Loading…
Add table
Add a link
Reference in a new issue