Additional layer model row population, properties

This commit is contained in:
Dan Paulat 2023-10-13 13:04:48 -05:00
parent d82a1cc171
commit 14d6912014
4 changed files with 187 additions and 90 deletions

View file

@ -1,5 +1,6 @@
#include <scwx/qt/model/layer_model.hpp> #include <scwx/qt/model/layer_model.hpp>
#include <scwx/qt/manager/placefile_manager.hpp> #include <scwx/qt/manager/placefile_manager.hpp>
#include <scwx/qt/types/map_types.hpp>
#include <scwx/qt/types/qt_types.hpp> #include <scwx/qt/types/qt_types.hpp>
#include <scwx/util/logger.hpp> #include <scwx/util/logger.hpp>
@ -27,35 +28,53 @@ static constexpr int kLastColumn =
static_cast<int>(LayerModel::Column::Description); static_cast<int>(LayerModel::Column::Description);
static constexpr int kNumColumns = kLastColumn - kFirstColumn + 1; static constexpr int kNumColumns = kLastColumn - kFirstColumn + 1;
static const std::unordered_map<LayerModel::LayerType, std::string> static constexpr std::size_t kMapCount_ = 4u;
layerTypeNames_ {{LayerModel::LayerType::Map, "Map"},
{LayerModel::LayerType::Radar, "Radar"},
{LayerModel::LayerType::Alert, "Alert"},
{LayerModel::LayerType::Placefile, "Placefile"}};
typedef std::variant<std::monostate, std::string, awips::Phenomenon> typedef std::
LayerDescription; variant<std::monostate, types::Layer, awips::Phenomenon, std::string>
typedef boost::container::devector< LayerDescription;
std::pair<LayerModel::LayerType, LayerDescription>>
LayerVector;
class LayerModel::Impl class LayerModel::Impl
{ {
public: public:
explicit Impl() struct LayerInfo
{ {
layers_.emplace_back(LayerType::Alert, awips::Phenomenon::Tornado); types::LayerType type_;
layers_.emplace_back(LayerType::Alert, awips::Phenomenon::SnowSquall); LayerDescription description_;
layers_.emplace_back(LayerType::Alert, bool movable_;
awips::Phenomenon::SevereThunderstorm); std::array<bool, kMapCount_> displayed_ {true, true, true, true};
layers_.emplace_back(LayerType::Alert, awips::Phenomenon::FlashFlood); };
layers_.emplace_back(LayerType::Alert, awips::Phenomenon::Marine);
layers_.emplace_back(LayerType::Map, "Map Overlay"); typedef boost::container::devector<LayerInfo> LayerVector;
layers_.emplace_back(LayerType::Radar, std::monostate {});
layers_.emplace_back(LayerType::Map, "Map Underlay"); explicit Impl(LayerModel* self) : self_ {self}
{
layers_.emplace_back(
types::LayerType::Information, types::Layer::MapOverlay, false);
layers_.emplace_back(
types::LayerType::Information, types::Layer::ColorTable, false);
layers_.emplace_back(
types::LayerType::Alert, awips::Phenomenon::Tornado, true);
layers_.emplace_back(
types::LayerType::Alert, awips::Phenomenon::SnowSquall, true);
layers_.emplace_back(
types::LayerType::Alert, awips::Phenomenon::SevereThunderstorm, true);
layers_.emplace_back(
types::LayerType::Alert, awips::Phenomenon::FlashFlood, true);
layers_.emplace_back(
types::LayerType::Alert, awips::Phenomenon::Marine, true);
layers_.emplace_back(
types::LayerType::Map, types::Layer::MapSymbology, false);
layers_.emplace_back(types::LayerType::Radar, std::monostate {}, true);
layers_.emplace_back(
types::LayerType::Map, types::Layer::MapUnderlay, false);
} }
~Impl() = default; ~Impl() = default;
void AddPlacefile(const std::string& name);
LayerModel* self_;
std::shared_ptr<manager::PlacefileManager> placefileManager_ { std::shared_ptr<manager::PlacefileManager> placefileManager_ {
manager::PlacefileManager::Instance()}; manager::PlacefileManager::Instance()};
@ -63,7 +82,7 @@ public:
}; };
LayerModel::LayerModel(QObject* parent) : LayerModel::LayerModel(QObject* parent) :
QAbstractTableModel(parent), p(std::make_unique<Impl>()) QAbstractTableModel(parent), p(std::make_unique<Impl>(this))
{ {
connect(p->placefileManager_.get(), connect(p->placefileManager_.get(),
&manager::PlacefileManager::PlacefileEnabled, &manager::PlacefileManager::PlacefileEnabled,
@ -101,13 +120,25 @@ Qt::ItemFlags LayerModel::flags(const QModelIndex& index) const
{ {
Qt::ItemFlags flags = QAbstractTableModel::flags(index); Qt::ItemFlags flags = QAbstractTableModel::flags(index);
if (!index.isValid() || index.row() < 0 ||
static_cast<std::size_t>(index.row()) >= p->layers_.size())
{
return flags;
}
const auto& layer = p->layers_.at(index.row());
switch (index.column()) switch (index.column())
{ {
case static_cast<int>(Column::DisplayMap1): case static_cast<int>(Column::DisplayMap1):
case static_cast<int>(Column::DisplayMap2): case static_cast<int>(Column::DisplayMap2):
case static_cast<int>(Column::DisplayMap3): case static_cast<int>(Column::DisplayMap3):
case static_cast<int>(Column::DisplayMap4): case static_cast<int>(Column::DisplayMap4):
flags |= Qt::ItemFlag::ItemIsUserCheckable | Qt::ItemFlag::ItemIsEditable; if (layer.type_ != types::LayerType::Map)
{
flags |=
Qt::ItemFlag::ItemIsUserCheckable | Qt::ItemFlag::ItemIsEditable;
}
break; break;
default: default:
@ -131,8 +162,7 @@ QVariant LayerModel::data(const QModelIndex& index, int role) const
return QVariant(); return QVariant();
} }
const auto& layer = p->layers_.at(index.row()); const auto& layer = p->layers_.at(index.row());
bool enabled = true; // TODO
switch (index.column()) switch (index.column())
{ {
@ -147,15 +177,21 @@ QVariant LayerModel::data(const QModelIndex& index, int role) const
case static_cast<int>(Column::DisplayMap2): case static_cast<int>(Column::DisplayMap2):
case static_cast<int>(Column::DisplayMap3): case static_cast<int>(Column::DisplayMap3):
case static_cast<int>(Column::DisplayMap4): case static_cast<int>(Column::DisplayMap4):
// TODO if (layer.type_ != types::LayerType::Map)
if (role == Qt::ItemDataRole::ToolTipRole)
{ {
return enabled ? displayedString : hiddenString; bool displayed =
} layer.displayed_[index.column() -
else if (role == Qt::ItemDataRole::CheckStateRole) static_cast<int>(Column::DisplayMap1)];
{
return static_cast<int>(enabled ? Qt::CheckState::Checked : if (role == Qt::ItemDataRole::ToolTipRole)
Qt::CheckState::Unchecked); {
return displayed ? displayedString : hiddenString;
}
else if (role == Qt::ItemDataRole::CheckStateRole)
{
return static_cast<int>(displayed ? Qt::CheckState::Checked :
Qt::CheckState::Unchecked);
}
} }
break; break;
@ -163,7 +199,7 @@ QVariant LayerModel::data(const QModelIndex& index, int role) const
if (role == Qt::ItemDataRole::DisplayRole || if (role == Qt::ItemDataRole::DisplayRole ||
role == Qt::ItemDataRole::ToolTipRole) role == Qt::ItemDataRole::ToolTipRole)
{ {
return QString::fromStdString(layerTypeNames_.at(layer.first)); return QString::fromStdString(types::GetLayerTypeName(layer.type_));
} }
break; break;
@ -171,17 +207,13 @@ QVariant LayerModel::data(const QModelIndex& index, int role) const
if (role == Qt::ItemDataRole::DisplayRole || if (role == Qt::ItemDataRole::DisplayRole ||
role == Qt::ItemDataRole::ToolTipRole) role == Qt::ItemDataRole::ToolTipRole)
{ {
if (layer.first == LayerType::Placefile) if (layer.type_ == types::LayerType::Placefile)
{ {
return p->placefileManager_->placefile_enabled( return p->placefileManager_->placefile_enabled(
std::get<std::string>(layer.second)) ? std::get<std::string>(layer.description_)) ?
enabledString : enabledString :
disabledString; disabledString;
} }
else
{
return enabledString;
}
} }
break; break;
@ -189,10 +221,11 @@ QVariant LayerModel::data(const QModelIndex& index, int role) const
if (role == Qt::ItemDataRole::DisplayRole || if (role == Qt::ItemDataRole::DisplayRole ||
role == Qt::ItemDataRole::ToolTipRole) role == Qt::ItemDataRole::ToolTipRole)
{ {
if (layer.first == LayerType::Placefile) if (layer.type_ == types::LayerType::Placefile)
{ {
std::string placefileName = std::get<std::string>(layer.second); std::string placefileName =
std::string description = placefileName; std::get<std::string>(layer.description_);
std::string description = placefileName;
std::string title = std::string title =
p->placefileManager_->placefile_title(placefileName); p->placefileManager_->placefile_title(placefileName);
if (!title.empty()) if (!title.empty())
@ -204,15 +237,21 @@ QVariant LayerModel::data(const QModelIndex& index, int role) const
} }
else else
{ {
if (std::holds_alternative<std::string>(layer.second)) if (std::holds_alternative<std::string>(layer.description_))
{ {
return QString::fromStdString( return QString::fromStdString(
std::get<std::string>(layer.second)); std::get<std::string>(layer.description_));
} }
else if (std::holds_alternative<awips::Phenomenon>(layer.second)) else if (std::holds_alternative<types::Layer>(layer.description_))
{
return QString::fromStdString(types::GetLayerName(
std::get<types::Layer>(layer.description_)));
}
else if (std::holds_alternative<awips::Phenomenon>(
layer.description_))
{ {
return QString::fromStdString(awips::GetPhenomenonText( return QString::fromStdString(awips::GetPhenomenonText(
std::get<awips::Phenomenon>(layer.second))); std::get<awips::Phenomenon>(layer.description_)));
} }
} }
} }
@ -321,8 +360,8 @@ bool LayerModel::setData(const QModelIndex& index,
return false; return false;
} }
const auto& layer = p->layers_.at(index.row()); auto& layer = p->layers_.at(index.row());
bool result = false; bool result = false;
switch (index.column()) switch (index.column())
{ {
@ -332,9 +371,10 @@ bool LayerModel::setData(const QModelIndex& index,
case static_cast<int>(Column::DisplayMap4): case static_cast<int>(Column::DisplayMap4):
if (role == Qt::ItemDataRole::CheckStateRole) if (role == Qt::ItemDataRole::CheckStateRole)
{ {
// TODO layer.displayed_[index.column() -
Q_UNUSED(layer); static_cast<int>(Column::DisplayMap1)] =
Q_UNUSED(value); value.toBool();
result = true;
} }
break; break;
@ -352,13 +392,14 @@ bool LayerModel::setData(const QModelIndex& index,
void LayerModel::HandlePlacefileRemoved(const std::string& name) void LayerModel::HandlePlacefileRemoved(const std::string& name)
{ {
auto it = std::find_if(p->layers_.begin(), auto it =
p->layers_.end(), std::find_if(p->layers_.begin(),
[&name](const auto& layer) p->layers_.end(),
{ [&name](const auto& layer)
return layer.first == LayerType::Placefile && {
std::get<std::string>(layer.second) == name; return layer.type_ == types::LayerType::Placefile &&
}); std::get<std::string>(layer.description_) == name;
});
if (it != p->layers_.end()) if (it != p->layers_.end())
{ {
@ -374,14 +415,14 @@ void LayerModel::HandlePlacefileRemoved(const std::string& name)
void LayerModel::HandlePlacefileRenamed(const std::string& oldName, void LayerModel::HandlePlacefileRenamed(const std::string& oldName,
const std::string& newName) const std::string& newName)
{ {
auto it = auto it = std::find_if(
std::find_if(p->layers_.begin(), p->layers_.begin(),
p->layers_.end(), p->layers_.end(),
[&oldName](const auto& layer) [&oldName](const auto& layer)
{ {
return layer.first == LayerType::Placefile && return layer.type_ == types::LayerType::Placefile &&
std::get<std::string>(layer.second) == oldName; std::get<std::string>(layer.description_) == oldName;
}); });
if (it != p->layers_.end()) if (it != p->layers_.end())
{ {
@ -391,28 +432,27 @@ void LayerModel::HandlePlacefileRenamed(const std::string& oldName,
QModelIndex bottomRight = createIndex(row, kLastColumn); QModelIndex bottomRight = createIndex(row, kLastColumn);
// Rename placefile // Rename placefile
it->second = newName; it->description_ = newName;
Q_EMIT dataChanged(topLeft, bottomRight); Q_EMIT dataChanged(topLeft, bottomRight);
} }
else else
{ {
// Placefile is new, prepend row // Placefile doesn't exist, add row
beginInsertRows(QModelIndex(), 0, 0); p->AddPlacefile(newName);
p->layers_.push_front({LayerType::Placefile, newName});
endInsertRows();
} }
} }
void LayerModel::HandlePlacefileUpdate(const std::string& name) void LayerModel::HandlePlacefileUpdate(const std::string& name)
{ {
auto it = std::find_if(p->layers_.begin(), auto it =
p->layers_.end(), std::find_if(p->layers_.begin(),
[&name](const auto& layer) p->layers_.end(),
{ [&name](const auto& layer)
return layer.first == LayerType::Placefile && {
std::get<std::string>(layer.second) == name; return layer.type_ == types::LayerType::Placefile &&
}); std::get<std::string>(layer.description_) == name;
});
if (it != p->layers_.end()) if (it != p->layers_.end())
{ {
@ -425,13 +465,34 @@ void LayerModel::HandlePlacefileUpdate(const std::string& name)
} }
else else
{ {
// Placefile is new, prepend row // Placefile doesn't exist, add row
beginInsertRows(QModelIndex(), 0, 0); p->AddPlacefile(name);
p->layers_.push_front({LayerType::Placefile, name});
endInsertRows();
} }
} }
void LayerModel::Impl::AddPlacefile(const std::string& name)
{
// Insert after color table
auto insertPosition = std::find_if(
layers_.begin(),
layers_.end(),
[](const Impl::LayerInfo& layerInfo)
{
return std::holds_alternative<types::Layer>(layerInfo.description_) &&
std::get<types::Layer>(layerInfo.description_) ==
types::Layer::ColorTable;
});
if (insertPosition != layers_.end())
{
++insertPosition;
}
// Placefile is new, add row
self_->beginInsertRows(QModelIndex(), 0, 0);
layers_.insert(insertPosition, {types::LayerType::Placefile, name});
self_->endInsertRows();
}
} // namespace model } // namespace model
} // namespace qt } // namespace qt
} // namespace scwx } // namespace scwx

View file

@ -17,6 +17,8 @@ namespace model
class LayerModel : public QAbstractTableModel class LayerModel : public QAbstractTableModel
{ {
Q_DISABLE_COPY_MOVE(LayerModel)
public: public:
enum class Column : int enum class Column : int
{ {
@ -32,14 +34,6 @@ public:
typedef scwx::util::Iterator<Column, Column::Order, Column::Description> typedef scwx::util::Iterator<Column, Column::Order, Column::Description>
ColumnIterator; ColumnIterator;
enum class LayerType
{
Map,
Radar,
Alert,
Placefile
};
explicit LayerModel(QObject* parent = nullptr); explicit LayerModel(QObject* parent = nullptr);
~LayerModel(); ~LayerModel();

View file

@ -9,9 +9,32 @@ namespace qt
namespace types namespace types
{ {
static const std::unordered_map<types::LayerType, std::string> layerTypeName_ {
{types::LayerType::Map, "Map"},
{types::LayerType::Radar, "Radar"},
{types::LayerType::Alert, "Alert"},
{types::LayerType::Placefile, "Placefile"},
{types::LayerType::Information, "Information"}};
static const std::unordered_map<types::Layer, std::string> layerName_ {
{types::Layer::MapOverlay, "Map Overlay"},
{types::Layer::ColorTable, "Color Table"},
{types::Layer::MapSymbology, "Map Symbology"},
{types::Layer::MapUnderlay, "Map Underlay"}};
static const std::unordered_map<MapTime, std::string> mapTimeName_ { static const std::unordered_map<MapTime, std::string> mapTimeName_ {
{MapTime::Live, "Live"}, {MapTime::Archive, "Archive"}}; {MapTime::Live, "Live"}, {MapTime::Archive, "Archive"}};
std::string GetLayerTypeName(LayerType layerType)
{
return layerTypeName_.at(layerType);
}
std::string GetLayerName(Layer layer)
{
return layerName_.at(layer);
}
std::string GetMapTimeName(MapTime mapTime) std::string GetMapTimeName(MapTime mapTime)
{ {
return mapTimeName_.at(mapTime); return mapTimeName_.at(mapTime);

View file

@ -9,6 +9,23 @@ namespace qt
namespace types namespace types
{ {
enum class LayerType
{
Map,
Radar,
Alert,
Placefile,
Information
};
enum class Layer
{
MapOverlay,
ColorTable,
MapSymbology,
MapUnderlay
};
enum class AnimationState enum class AnimationState
{ {
Play, Play,
@ -29,6 +46,8 @@ enum class NoUpdateReason
InvalidData InvalidData
}; };
std::string GetLayerTypeName(LayerType layerType);
std::string GetLayerName(Layer layer);
std::string GetMapTimeName(MapTime mapTime); std::string GetMapTimeName(MapTime mapTime);
} // namespace types } // namespace types