Switch to using new edit_marker_dialog for marker adding and editting

This commit is contained in:
AdenKoperczak 2024-11-28 12:33:14 -05:00
parent 1a32748b8e
commit d0d9adfd1a
8 changed files with 514 additions and 110 deletions

View file

@ -256,6 +256,7 @@ set(HDR_UI source/scwx/qt/ui/about_dialog.hpp
source/scwx/qt/ui/county_dialog.hpp source/scwx/qt/ui/county_dialog.hpp
source/scwx/qt/ui/download_dialog.hpp source/scwx/qt/ui/download_dialog.hpp
source/scwx/qt/ui/edit_line_dialog.hpp source/scwx/qt/ui/edit_line_dialog.hpp
source/scwx/qt/ui/edit_marker_dialog.hpp
source/scwx/qt/ui/flow_layout.hpp source/scwx/qt/ui/flow_layout.hpp
source/scwx/qt/ui/gps_info_dialog.hpp source/scwx/qt/ui/gps_info_dialog.hpp
source/scwx/qt/ui/hotkey_edit.hpp source/scwx/qt/ui/hotkey_edit.hpp
@ -286,6 +287,7 @@ set(SRC_UI source/scwx/qt/ui/about_dialog.cpp
source/scwx/qt/ui/county_dialog.cpp source/scwx/qt/ui/county_dialog.cpp
source/scwx/qt/ui/download_dialog.cpp source/scwx/qt/ui/download_dialog.cpp
source/scwx/qt/ui/edit_line_dialog.cpp source/scwx/qt/ui/edit_line_dialog.cpp
source/scwx/qt/ui/edit_marker_dialog.cpp
source/scwx/qt/ui/flow_layout.cpp source/scwx/qt/ui/flow_layout.cpp
source/scwx/qt/ui/gps_info_dialog.cpp source/scwx/qt/ui/gps_info_dialog.cpp
source/scwx/qt/ui/hotkey_edit.cpp source/scwx/qt/ui/hotkey_edit.cpp
@ -315,6 +317,7 @@ set(UI_UI source/scwx/qt/ui/about_dialog.ui
source/scwx/qt/ui/collapsible_group.ui source/scwx/qt/ui/collapsible_group.ui
source/scwx/qt/ui/county_dialog.ui source/scwx/qt/ui/county_dialog.ui
source/scwx/qt/ui/edit_line_dialog.ui source/scwx/qt/ui/edit_line_dialog.ui
source/scwx/qt/ui/edit_marker_dialog.ui
source/scwx/qt/ui/gps_info_dialog.ui source/scwx/qt/ui/gps_info_dialog.ui
source/scwx/qt/ui/imgui_debug_dialog.ui source/scwx/qt/ui/imgui_debug_dialog.ui
source/scwx/qt/ui/layer_dialog.ui source/scwx/qt/ui/layer_dialog.ui

View file

@ -313,7 +313,7 @@ void MarkerManager::set_marker(types::MarkerId id, const types::MarkerInfo& mark
Q_EMIT MarkersUpdated(); Q_EMIT MarkersUpdated();
} }
void MarkerManager::add_marker(const types::MarkerInfo& marker) types::MarkerId MarkerManager::add_marker(const types::MarkerInfo& marker)
{ {
types::MarkerId id; types::MarkerId id;
{ {
@ -326,6 +326,7 @@ void MarkerManager::add_marker(const types::MarkerInfo& marker)
} }
Q_EMIT MarkerAdded(id); Q_EMIT MarkerAdded(id);
Q_EMIT MarkersUpdated(); Q_EMIT MarkersUpdated();
return id;
} }
void MarkerManager::remove_marker(types::MarkerId id) void MarkerManager::remove_marker(types::MarkerId id)

View file

@ -25,7 +25,7 @@ public:
std::optional<types::MarkerInfo> get_marker(types::MarkerId id); std::optional<types::MarkerInfo> get_marker(types::MarkerId id);
std::optional<size_t> get_index(types::MarkerId id); std::optional<size_t> get_index(types::MarkerId id);
void set_marker(types::MarkerId id, const types::MarkerInfo& marker); void set_marker(types::MarkerId id, const types::MarkerInfo& marker);
void add_marker(const types::MarkerInfo& marker); types::MarkerId add_marker(const types::MarkerInfo& marker);
void remove_marker(types::MarkerId id); void remove_marker(types::MarkerId id);
void move_marker(size_t from, size_t to); void move_marker(size_t from, size_t to);

View file

@ -78,26 +78,11 @@ Qt::ItemFlags MarkerModel::flags(const QModelIndex& index) const
{ {
Qt::ItemFlags flags = QAbstractTableModel::flags(index); Qt::ItemFlags flags = QAbstractTableModel::flags(index);
switch (index.column())
{
case static_cast<int>(Column::Name):
case static_cast<int>(Column::Latitude):
case static_cast<int>(Column::Longitude):
flags |= Qt::ItemFlag::ItemIsEditable;
break;
default:
break;
}
return flags; return flags;
} }
QVariant MarkerModel::data(const QModelIndex& index, int role) const QVariant MarkerModel::data(const QModelIndex& index, int role) const
{ {
static const char COORDINATE_FORMAT = 'g';
static const int COORDINATE_PRECISION = 10;
if (!index.isValid() || index.row() < 0 || if (!index.isValid() || index.row() < 0 ||
static_cast<size_t>(index.row()) >= p->markerIds_.size()) static_cast<size_t>(index.row()) >= p->markerIds_.size())
{ {
@ -118,8 +103,7 @@ QVariant MarkerModel::data(const QModelIndex& index, int role) const
{ {
case static_cast<int>(Column::Name): case static_cast<int>(Column::Name):
if (role == Qt::ItemDataRole::DisplayRole || if (role == Qt::ItemDataRole::DisplayRole ||
role == Qt::ItemDataRole::ToolTipRole || role == Qt::ItemDataRole::ToolTipRole)
role == Qt::ItemDataRole::EditRole)
{ {
return QString::fromStdString(markerInfo->name); return QString::fromStdString(markerInfo->name);
} }
@ -132,11 +116,6 @@ QVariant MarkerModel::data(const QModelIndex& index, int role) const
return QString::fromStdString( return QString::fromStdString(
common::GetLatitudeString(markerInfo->latitude)); common::GetLatitudeString(markerInfo->latitude));
} }
else if (role == Qt::ItemDataRole::EditRole)
{
return QString::number(
markerInfo->latitude, COORDINATE_FORMAT, COORDINATE_PRECISION);
}
break; break;
case static_cast<int>(Column::Longitude): case static_cast<int>(Column::Longitude):
@ -146,11 +125,6 @@ QVariant MarkerModel::data(const QModelIndex& index, int role) const
return QString::fromStdString( return QString::fromStdString(
common::GetLongitudeString(markerInfo->longitude)); common::GetLongitudeString(markerInfo->longitude));
} }
else if (role == Qt::ItemDataRole::EditRole)
{
return QString::number(
markerInfo->longitude, COORDINATE_FORMAT, COORDINATE_PRECISION);
}
break; break;
break; break;
@ -199,78 +173,9 @@ QVariant MarkerModel::headerData(int section,
return QVariant(); return QVariant();
} }
bool MarkerModel::setData(const QModelIndex& index, bool MarkerModel::setData(const QModelIndex&, const QVariant&, int)
const QVariant& value,
int role)
{ {
return false;
if (!index.isValid() || index.row() < 0 ||
static_cast<size_t>(index.row()) >= p->markerIds_.size())
{
return false;
}
types::MarkerId id = p->markerIds_[index.row()];
std::optional<types::MarkerInfo> markerInfo =
p->markerManager_->get_marker(id);
if (!markerInfo)
{
return false;
}
bool result = false;
switch(index.column())
{
case static_cast<int>(Column::Name):
if (role == Qt::ItemDataRole::EditRole)
{
QString str = value.toString();
markerInfo->name = str.toStdString();
p->markerManager_->set_marker(id, *markerInfo);
result = true;
}
break;
case static_cast<int>(Column::Latitude):
if (role == Qt::ItemDataRole::EditRole)
{
QString str = value.toString();
bool ok;
double latitude = str.toDouble(&ok);
if (!str.isEmpty() && ok && -90 <= latitude && latitude <= 90)
{
markerInfo->latitude = latitude;
p->markerManager_->set_marker(id, *markerInfo);
result = true;
}
}
break;
case static_cast<int>(Column::Longitude):
if (role == Qt::ItemDataRole::EditRole)
{
QString str = value.toString();
bool ok;
double longitude = str.toDouble(&ok);
if (!str.isEmpty() && ok && -180 <= longitude && longitude <= 180)
{
markerInfo->longitude = longitude;
p->markerManager_->set_marker(id, *markerInfo);
result = true;
}
}
break;
default:
break;
}
if (result)
{
Q_EMIT dataChanged(index, index);
}
return result;
} }
void MarkerModel::HandleMarkersInitialized(size_t count) void MarkerModel::HandleMarkersInitialized(size_t count)

View file

@ -0,0 +1,249 @@
#include "edit_marker_dialog.hpp"
#include "ui_edit_marker_dialog.h"
#include <scwx/qt/manager/marker_manager.hpp>
#include <scwx/qt/types/marker_types.hpp>
#include <scwx/qt/util/color.hpp>
#include <scwx/qt/util/q_color_modulate.hpp>
#include <scwx/util/logger.hpp>
#include <string>
#include <vector>
#include <QObject>
#include <QString>
#include <QIcon>
#include <QPixmap>
#include <QColorDialog>
#include <QPushButton>
namespace scwx
{
namespace qt
{
namespace ui
{
static const std::string logPrefix_ = "scwx::qt::ui::edit_marker_dialog";
static const auto logger_ = scwx::util::Logger::Create(logPrefix_);
class EditMarkerDialog::Impl
{
public:
explicit Impl(EditMarkerDialog* self) :
self_{self}
{
}
void show_color_dialog();
void set_icon_color(const std::string& color);
void connect_signals();
void handle_accepted();
void handle_rejected();
EditMarkerDialog* self_;
QPushButton* deleteButton_;
QIcon get_colored_icon(size_t index, const std::string& color);
std::shared_ptr<manager::MarkerManager> markerManager_ =
manager::MarkerManager::Instance();
const std::vector<types::MarkerIconInfo>* icons_;
types::MarkerId editId_;
bool adding_;
};
QIcon EditMarkerDialog::Impl::get_colored_icon(size_t index,
const std::string& color)
{
if (index >= icons_->size())
{
return QIcon();
}
return util::modulateColors((*icons_)[index].qIcon,
self_->ui->iconComboBox->iconSize(),
QColor(QString::fromStdString(color)));
}
EditMarkerDialog::EditMarkerDialog(QWidget* parent) :
QDialog(parent),
p {std::make_unique<Impl>(this)},
ui(new Ui::EditMarkerDialog)
{
ui->setupUi(this);
p->icons_ = &types::getMarkerIcons();
for (auto& markerIcon : (*p->icons_))
{
ui->iconComboBox->addItem(markerIcon.qIcon,
QString(""),
QString::fromStdString(markerIcon.name));
}
p->deleteButton_ =
ui->buttonBox->addButton("Delete", QDialogButtonBox::DestructiveRole);
p->connect_signals();
}
EditMarkerDialog::~EditMarkerDialog()
{
delete ui;
}
void EditMarkerDialog::setup()
{
setup(0, 0);
}
void EditMarkerDialog::setup(double latitude, double longitude)
{
ui->iconComboBox->setCurrentIndex(0);
// By default use foreground color as marker color, mainly so the icons
// are vissable in the dropdown menu.
QColor color = QWidget::palette().color(QWidget::foregroundRole());
p->editId_ = p->markerManager_->add_marker(types::MarkerInfo(
"",
latitude,
longitude,
ui->iconComboBox->currentData().toString().toStdString(),
boost::gil::rgba8_pixel_t {static_cast<uint8_t>(color.red()),
static_cast<uint8_t>(color.green()),
static_cast<uint8_t>(color.blue()),
static_cast<uint8_t>(color.alpha())}));
setup(p->editId_);
p->adding_ = true;
}
void EditMarkerDialog::setup(types::MarkerId id)
{
std::optional<types::MarkerInfo> marker =
p->markerManager_->get_marker(id);
if (!marker)
{
return;
}
p->editId_ = id;
p->adding_ = false;
int iconIndex =
ui->iconComboBox->findData(QString::fromStdString(marker->iconName));
if (iconIndex < 0 || marker->iconName == "")
{
iconIndex = 0;
}
std::string iconColorStr = util::color::ToArgbString(marker->iconColor);
ui->nameLineEdit->setText(QString::fromStdString(marker->name));
ui->iconComboBox->setCurrentIndex(iconIndex);
ui->latitudeDoubleSpinBox->setValue(marker->latitude);
ui->longitudeDoubleSpinBox->setValue(marker->longitude);
ui->iconColorLineEdit->setText(QString::fromStdString(iconColorStr));
p->set_icon_color(iconColorStr);
}
types::MarkerInfo EditMarkerDialog::get_marker_info() const
{
QString colorName = ui->iconColorLineEdit->text();
boost::gil::rgba8_pixel_t color =
util::color::ToRgba8PixelT(colorName.toStdString());
return types::MarkerInfo(
ui->nameLineEdit->text().toStdString(),
ui->latitudeDoubleSpinBox->value(),
ui->longitudeDoubleSpinBox->value(),
ui->iconComboBox->currentData().toString().toStdString(),
color);
}
void EditMarkerDialog::Impl::show_color_dialog()
{
QColorDialog* dialog = new QColorDialog(self_);
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->setOption(QColorDialog::ColorDialogOption::ShowAlphaChannel);
QColor initialColor(self_->ui->iconColorLineEdit->text());
if (initialColor.isValid())
{
dialog->setCurrentColor(initialColor);
}
QObject::connect(dialog,
&QColorDialog::colorSelected,
self_,
[this](const QColor& qColor)
{
QString colorName =
qColor.name(QColor::NameFormat::HexArgb);
self_->ui->iconColorLineEdit->setText(colorName);
});
dialog->open();
}
void EditMarkerDialog::Impl::connect_signals()
{
connect(self_,
&EditMarkerDialog::accepted,
self_,
[this]() { handle_accepted(); });
connect(self_,
&EditMarkerDialog::rejected,
self_,
[this]() { handle_rejected(); });
connect(deleteButton_,
&QPushButton::clicked,
self_,
[this]()
{
markerManager_->remove_marker(editId_);
self_->done(0);
});
connect(self_->ui->iconColorLineEdit,
&QLineEdit::textEdited,
self_,
[=, this](const QString& text)
{ set_icon_color(text.toStdString()); });
connect(self_->ui->iconColorButton,
&QAbstractButton::clicked,
self_,
[=, this]() { self_->p->show_color_dialog(); });
}
void EditMarkerDialog::Impl::set_icon_color(const std::string& color)
{
self_->ui->iconColorFrame->setStyleSheet(
QString::fromStdString(fmt::format("background-color: {}", color)));
for (size_t i = 0; i < icons_->size(); i++)
{
self_->ui->iconComboBox->setItemIcon(static_cast<int>(i),
get_colored_icon(i, color));
}
}
void EditMarkerDialog::Impl::handle_accepted()
{
markerManager_->set_marker(editId_, self_->get_marker_info());
}
void EditMarkerDialog::Impl::handle_rejected()
{
if (adding_)
{
markerManager_->remove_marker(editId_);
}
}
} // namespace ui
} // namespace qt
} // namespace scwx

View file

@ -0,0 +1,41 @@
#pragma once
#include <scwx/qt/types/marker_types.hpp>
#include <QDialog>
namespace Ui
{
class EditMarkerDialog;
}
namespace scwx
{
namespace qt
{
namespace ui
{
class EditMarkerDialog : public QDialog
{
Q_OBJECT
Q_DISABLE_COPY_MOVE(EditMarkerDialog)
public:
explicit EditMarkerDialog(QWidget* parent = nullptr);
~EditMarkerDialog();
void setup();
void setup(double latitude, double longitude);
void setup(types::MarkerId id);
types::MarkerInfo get_marker_info() const;
private:
class Impl;
std::unique_ptr<Impl> p;
Ui::EditMarkerDialog* ui;
};
} // namespace ui
} // namespace qt
} // namespace scwx

View file

@ -0,0 +1,188 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>EditMarkerDialog</class>
<widget class="QDialog" name="EditMarkerDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>211</height>
</rect>
</property>
<property name="windowTitle">
<string>Edit Location Marker</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="2" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Icon</string>
</property>
</widget>
</item>
<item row="6" column="0" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok</set>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="iconComboBox">
<property name="autoFillBackground">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Latitude</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QDoubleSpinBox" name="longitudeDoubleSpinBox">
<property name="decimals">
<number>4</number>
</property>
<property name="minimum">
<double>-180.000000000000000</double>
</property>
<property name="maximum">
<double>180.000000000000000</double>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLineEdit" name="nameLineEdit"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Name</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QDoubleSpinBox" name="latitudeDoubleSpinBox">
<property name="decimals">
<number>4</number>
</property>
<property name="minimum">
<double>-90.000000000000000</double>
</property>
<property name="maximum">
<double>90.000000000000000</double>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Longitude</string>
</property>
</widget>
</item>
<item row="5" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Icon Color</string>
</property>
</widget>
</item>
<item row="3" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QFrame" name="iconColorFrame">
<property name="minimumSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::Shape::Box</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Shadow::Plain</enum>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="iconColorLineEdit">
<property name="text">
<string>#ffffffff</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="iconColorButton">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../../scwx-qt.qrc">
<normaloff>:/res/icons/font-awesome-6/palette-solid.svg</normaloff>:/res/icons/font-awesome-6/palette-solid.svg</iconset>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources>
<include location="../../../../scwx-qt.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>EditMarkerDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>EditMarkerDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View file

@ -4,11 +4,9 @@
#include <scwx/qt/manager/marker_manager.hpp> #include <scwx/qt/manager/marker_manager.hpp>
#include <scwx/qt/model/marker_model.hpp> #include <scwx/qt/model/marker_model.hpp>
#include <scwx/qt/types/qt_types.hpp> #include <scwx/qt/types/qt_types.hpp>
#include <scwx/qt/ui/open_url_dialog.hpp> #include <scwx/qt/ui/edit_marker_dialog.hpp>
#include <scwx/util/logger.hpp> #include <scwx/util/logger.hpp>
#include <scwx/qt/util/color.hpp>
#include <QSortFilterProxyModel> #include <QSortFilterProxyModel>
namespace scwx namespace scwx
@ -36,6 +34,7 @@ public:
model::MarkerModel* markerModel_; model::MarkerModel* markerModel_;
std::shared_ptr<manager::MarkerManager> markerManager_ { std::shared_ptr<manager::MarkerManager> markerManager_ {
manager::MarkerManager::Instance()}; manager::MarkerManager::Instance()};
std::shared_ptr<ui::EditMarkerDialog> editMarkerDialog_ {nullptr};
}; };
@ -47,9 +46,10 @@ MarkerSettingsWidget::MarkerSettingsWidget(QWidget* parent) :
ui->setupUi(this); ui->setupUi(this);
ui->removeButton->setEnabled(false); ui->removeButton->setEnabled(false);
ui->markerView->setModel(p->markerModel_); ui->markerView->setModel(p->markerModel_);
p->editMarkerDialog_ = std::make_shared<ui::EditMarkerDialog>(this);
p->ConnectSignals(); p->ConnectSignals();
} }
@ -65,12 +65,8 @@ void MarkerSettingsWidgetImpl::ConnectSignals()
self_, self_,
[this]() [this]()
{ {
markerManager_->add_marker(types::MarkerInfo( editMarkerDialog_->setup();
"", editMarkerDialog_->show();
0,
0,
types::getMarkerIcons()[0].name,
util::color::ToRgba8PixelT("#ffff0000")));
}); });
QObject::connect( QObject::connect(
self_->ui->removeButton, self_->ui->removeButton,
@ -109,6 +105,27 @@ void MarkerSettingsWidgetImpl::ConnectSignals()
bool itemSelected = selected.size() > 0; bool itemSelected = selected.size() > 0;
self_->ui->removeButton->setEnabled(itemSelected); self_->ui->removeButton->setEnabled(itemSelected);
}); });
QObject::connect(self_->ui->markerView,
&QAbstractItemView::doubleClicked,
self_,
[this](const QModelIndex& index)
{
int row = index.row();
if (row < 0)
{
return;
}
std::optional<types::MarkerId> id =
markerModel_->getId(row);
if (!id)
{
return;
}
editMarkerDialog_->setup(*id);
editMarkerDialog_->show();
});
} }
} // namespace ui } // namespace ui