Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
181 changes: 179 additions & 2 deletions src/gui/symbols/point_symbol_editor_widget.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/*
* Copyright 2012, 2013 Thomas Schöps
* Copyright 2012-2019, 2024, 2025 Kai Pastor
* Copyright 2025 Matthias Kühlewein
*
* This file is part of OpenOrienteering.
*
Expand All @@ -23,6 +24,7 @@

#include <algorithm>
#include <limits>
#include <numeric>
// IWYU pragma: no_include <memory>
// IWYU pragma: no_include <vector>

Expand Down Expand Up @@ -64,6 +66,7 @@
#include "core/map.h"
#include "core/objects/object.h"
#include "core/symbols/area_symbol.h"
#include "core/symbols/combined_symbol.h"
#include "core/symbols/line_symbol.h"
#include "core/symbols/point_symbol.h"
#include "core/symbols/symbol.h"
Expand All @@ -78,12 +81,13 @@

namespace OpenOrienteering {

PointSymbolEditorWidget::PointSymbolEditorWidget(MapEditorController* controller, PointSymbol* symbol, SymbolRole role, qreal offset_y, QWidget* parent)
: QWidget(parent)
PointSymbolEditorWidget::PointSymbolEditorWidget(MapEditorController* controller, PointSymbol* symbol, SymbolRole role, qreal offset_y, Map* source_map)
: QWidget(nullptr)
, symbol(symbol)
, object_origin_coord(0, offset_y)
, offset_y(offset_y)
, map(controller->getMap())
, source_map(source_map)
, controller(controller)
, permanent_preview(role == PrimarySymbol)
{
Expand Down Expand Up @@ -226,6 +230,11 @@ PointSymbolEditorWidget::PointSymbolEditorWidget(MapEditorController* controller
add_coord_button = new QPushButton(QIcon(QString::fromLatin1(":/images/plus.png")), QString{});
delete_coord_button = new QPushButton(QIcon(QString::fromLatin1(":/images/minus.png")), QString{});
center_coords_button = new QPushButton(tr("Center by coordinate average"));
if (source_map)
{
import_objects_button = new QPushButton(tr("Import from selected objects"));
import_objects_button->setEnabled(source_map->getNumSelectedObjects() > 0);
}

// Layout
auto* left_layout = new QVBoxLayout();
Expand All @@ -237,6 +246,8 @@ PointSymbolEditorWidget::PointSymbolEditorWidget(MapEditorController* controller
element_buttons_layout->addWidget(add_element_button, 1, 2);
element_buttons_layout->addWidget(delete_element_button, 1, 3);
element_buttons_layout->addWidget(center_all_elements_button, 2, 1, 1, 4);
if (source_map)
element_buttons_layout->addWidget(import_objects_button, 3, 1, 1, 4);
element_buttons_layout->setColumnStretch(5, 1);
left_layout->addLayout(element_buttons_layout);

Expand Down Expand Up @@ -292,6 +303,8 @@ PointSymbolEditorWidget::PointSymbolEditorWidget(MapEditorController* controller
connect(add_coord_button, &QPushButton::clicked, this, &PointSymbolEditorWidget::addCoordClicked);
connect(delete_coord_button, &QPushButton::clicked, this, &PointSymbolEditorWidget::deleteCoordClicked);
connect(center_coords_button, &QPushButton::clicked, this, &PointSymbolEditorWidget::centerCoordsClicked);
if (source_map)
connect(import_objects_button, &QPushButton::clicked, this, &PointSymbolEditorWidget::importSelectedObjects);
}

PointSymbolEditorWidget::~PointSymbolEditorWidget()
Expand Down Expand Up @@ -1013,6 +1026,170 @@ Symbol* PointSymbolEditorWidget::getCurrentElementSymbol()
}


void PointSymbolEditorWidget::importSelectedObjects()
{
auto selection_center = determineSelectionCenter();
const auto previous_elements_count = element_list->count();
for (const auto object : source_map->selectedObjects())
{
switch (object->getSymbol()->getType())
{
case Symbol::Point:
importPointObject(object, selection_center);
break;
case Symbol::Area:
importAreaObject(object, selection_center);
break;
case Symbol::Line:
importLineObject(object, selection_center);
break;
case Symbol::Combined:
importCombinedObject(object, selection_center);
break;
default:
;
}
}
if (previous_elements_count != element_list->count())
{
map->updateAllObjectsWithSymbol(symbol);
emit symbolEdited();
}
}

MapCoordF PointSymbolEditorWidget::determineSelectionCenter()
{
const auto only_point_objects = std::all_of(source_map->selectedObjectsBegin(), source_map->selectedObjectsEnd(), [](auto const* object) { return object->getType() == Object::Point; });
if (only_point_objects)
{
QPointF sum = std::accumulate(source_map->selectedObjectsBegin(), source_map->selectedObjectsEnd(), QPointF{0.0,0.0}, [](const QPointF& sum, const auto* object) {
return QPointF{sum.x() + object->asPoint()->getCoordF().x(), sum.y() + object->asPoint()->getCoordF().y()};
});
return MapCoordF(sum.x() / source_map->getNumSelectedObjects(), sum.y() / source_map->getNumSelectedObjects());
}

QRectF rect;
source_map->includeSelectionRect(rect);
return MapCoordF(rect.center());
}

void PointSymbolEditorWidget::importPointObject(const Object* object, MapCoordF& selection_center)
{
const auto point_symbol = object->getSymbol()->asPoint();
const auto point_object = object->asPoint();
if (point_symbol->getInnerColor() || point_symbol->getOuterColor())
{
auto* new_symbol = new PointSymbol();
new_symbol->setInnerColor(point_symbol->getInnerColor());
new_symbol->setInnerRadius(point_symbol->getInnerRadius());
new_symbol->setOuterColor(point_symbol->getOuterColor());
new_symbol->setOuterWidth(point_symbol->getOuterWidth());
auto* new_object = new PointObject(new_symbol);
const MapCoordF new_coords = point_object->getCoordF() - selection_center;
new_object->setPosition(new_coords);
addNewSymbol(new_object, new_symbol);
}
for (int i = 0; i < point_symbol->getNumElements(); ++i)
{
auto* element_symbol = point_symbol->getElementSymbol(i);
auto* element_object = point_symbol->getElementObject(i);
switch (element_object->getSymbol()->getType())
{
case Symbol::Point:
{
auto* new_symbol = element_symbol->asPoint()->duplicate();
auto* new_object = element_object->asPoint()->duplicate();
const MapCoordF distance_to_center = point_object->getCoordF() - selection_center;
new_object->move(MapCoord(distance_to_center));
addNewSymbol(new_object, new_symbol);
}
break;
case Symbol::Area:
{
auto* new_symbol = element_symbol->asArea()->duplicate();
auto* new_object = element_object->asPath()->duplicate();
const MapCoordF distance_to_center = point_object->getCoordF() - selection_center;
new_object->move(MapCoord(distance_to_center));
addNewSymbol(new_object, new_symbol);
}
break;
case Symbol::Line:
{
auto* new_symbol = element_symbol->asLine()->duplicate();
auto* new_object = element_object->asPath()->duplicate();
const MapCoordF distance_to_center = point_object->getCoordF() - selection_center;
new_object->move(MapCoord(distance_to_center));
addNewSymbol(new_object, new_symbol);
}
break;
default:
Q_UNREACHABLE();
}
}
}

void PointSymbolEditorWidget::importAreaObject(const Object* object, MapCoordF& selection_center)
{
auto* new_symbol = object->getSymbol()->asArea()->duplicate();
auto* new_object = object->asPath()->duplicate();
new_object->move(MapCoord(-selection_center));
addNewSymbol(new_object, new_symbol);
}

void PointSymbolEditorWidget::importLineObject(const Object* object, MapCoordF& selection_center)
{
auto* new_symbol = object->getSymbol()->asLine()->duplicate();
auto* new_object = object->asPath()->duplicate();
new_object->move(MapCoord(-selection_center));
addNewSymbol(new_object, new_symbol);
}

void PointSymbolEditorWidget::importCombinedObject(const Object* object, MapCoordF& selection_center)
{
const auto combined_symbol = object->getSymbol()->asCombined();

for (int i = 0; i < combined_symbol->getNumParts(); ++i)
{
auto part = combined_symbol->getPart(i);
if (!part)
continue;
switch (part->getType())
{
case Symbol::Area:
{
auto area_object = object->asPath()->duplicate();
area_object->setSymbol(part, false);
importAreaObject(area_object, selection_center);
}
break;
case Symbol::Line:
{
auto line_object = object->asPath()->duplicate();
line_object->setSymbol(part, false);
importLineObject(line_object, selection_center);
}
break;
case Symbol::Combined:
{
auto combined_object = object->asPath()->duplicate();
combined_object->setSymbol(part, false);
importCombinedObject(combined_object, selection_center);
}
break;
default:
;
}
}
}

void PointSymbolEditorWidget::addNewSymbol(Object* new_object, Symbol* new_symbol)
{
int row = (element_list->currentRow() < 0) ? element_list->count() : (element_list->currentRow() + 1);
symbol->addElement(row - 1, new_object, new_symbol);
element_list->insertItem(row, getLabelForSymbol(new_symbol));
element_list->setCurrentRow(row);
}


// ### PointSymbolEditorTool ###

Expand Down
15 changes: 13 additions & 2 deletions src/gui/symbols/point_symbol_editor_widget.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,9 @@ friend class PointSymbolEditorActivity;
* @param symbol The point symbol to be edited
* @param role The role of the symbol to be edited
* @param offset_y The vertical offset of the point symbol preview/editor from the origin
* @param parent Standard QWidget parentship
* @param source_map The source map
*/
PointSymbolEditorWidget(MapEditorController* controller, PointSymbol* symbol, SymbolRole role = PrimarySymbol, qreal offset_y = 0, QWidget* parent = nullptr);
PointSymbolEditorWidget(MapEditorController* controller, PointSymbol* symbol, SymbolRole role = PrimarySymbol, qreal offset_y = 0, Map* source_map = nullptr);

~PointSymbolEditorWidget() override;

Expand Down Expand Up @@ -130,6 +130,8 @@ private slots:
void deleteCoordClicked();
void centerCoordsClicked();

void importSelectedObjects();

private:
void initElementList();
void updateCoordsTable();
Expand All @@ -142,6 +144,13 @@ private slots:
Symbol* getCurrentElementSymbol();
Object* getCurrentElementObject();

void importPointObject(const Object* object, MapCoordF& selection_center);
void importAreaObject(const Object* object, MapCoordF& selection_center);
void importLineObject(const Object* object, MapCoordF& selection_center);
void importCombinedObject(const Object* object, MapCoordF& selection_center);
MapCoordF determineSelectionCenter();
void addNewSymbol(Object* new_object, Symbol* new_symbol);

PointSymbol* const symbol;
PointObject* midpoint_object = nullptr;
const MapCoordF object_origin_coord;
Expand All @@ -151,6 +160,7 @@ private slots:
QListWidget* element_list;
QPushButton* delete_element_button;
QPushButton* center_all_elements_button;
QPushButton* import_objects_button;

QStackedWidget* element_properties_widget;

Expand Down Expand Up @@ -179,6 +189,7 @@ private slots:
const qreal offset_y;
PointSymbolEditorActivity* activity;
Map* map;
Map* source_map;
MapEditorController* controller;
const bool permanent_preview;
};
Expand Down
4 changes: 2 additions & 2 deletions src/gui/symbols/point_symbol_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ PointSymbolSettings::PointSymbolSettings(PointSymbol* symbol, SymbolSettingDialo
: SymbolPropertiesWidget(symbol, dialog),
symbol(symbol)
{
symbol_editor = new PointSymbolEditorWidget(dialog->getPreviewController(), symbol);
symbol_editor = new PointSymbolEditorWidget(dialog->getPreviewController(), symbol, PointSymbolEditorWidget::PrimarySymbol, 0, dialog->getSourceMap());
connect(symbol_editor, &PointSymbolEditorWidget::symbolEdited, this, &SymbolPropertiesWidget::propertiesModified );

layout = new QVBoxLayout();
Expand Down Expand Up @@ -81,7 +81,7 @@ void PointSymbolSettings::reset(Symbol* symbol)
layout->removeWidget(symbol_editor);
delete(symbol_editor);

symbol_editor = new PointSymbolEditorWidget(dialog->getPreviewController(), this->symbol);
symbol_editor = new PointSymbolEditorWidget(dialog->getPreviewController(), this->symbol, PointSymbolEditorWidget::PrimarySymbol, 0, dialog->getSourceMap());
connect(symbol_editor, &PointSymbolEditorWidget::symbolEdited, this, &SymbolPropertiesWidget::propertiesModified );
layout->addWidget(symbol_editor);
}
Expand Down