From 0abae52ab0575aaadc8cbdf3f47a6e71aa709ceb Mon Sep 17 00:00:00 2001 From: Matthias Kuehlewein Date: Fri, 19 Jul 2024 16:20:43 +0200 Subject: [PATCH 1/6] Add template selection sets Template selection sets allow to easily switch between different sets of visibilities for the map and templates. Template selection sets are saved to and loaded from the map file in a backward compatible way. Closes #2332 (Template selection sets). --- src/core/map_view.cpp | 379 +++++++++++++++++------ src/core/map_view.h | 128 +++++--- src/gui/widgets/template_list_widget.cpp | 97 +++++- src/gui/widgets/template_list_widget.h | 22 +- 4 files changed, 483 insertions(+), 143 deletions(-) diff --git a/src/core/map_view.cpp b/src/core/map_view.cpp index 138526bbff..c5ba8f8164 100644 --- a/src/core/map_view.cpp +++ b/src/core/map_view.cpp @@ -1,6 +1,7 @@ /* * Copyright 2012, 2013 Thomas Schöps * Copyright 2014-2020, 2025 Kai Pastor + * Copyright 2025 Matthias Kühlewein * * This file is part of OpenOrienteering. * @@ -54,6 +55,9 @@ namespace literal static const QLatin1String hidden("hidden"); static const QLatin1String ref("ref"); static const QLatin1String template_string("template"); + static const QLatin1String template_sets("template_sets"); + static const QLatin1String template_set("template_set"); + static const QLatin1String active_template_set("active_template_set"); } @@ -73,14 +77,11 @@ bool TemplateVisibility::hasAlpha() const const double MapView::zoom_in_limit = 512; const double MapView::zoom_out_limit = 1 / 16.0; - MapView::MapView(QObject* parent, Map* map) : QObject { parent } , map { map } , zoom { 1.0 } , rotation { 0.0 } -, map_visibility{ 1.0f, true } -, all_templates_hidden{ false } , grid_visible{ false } , overprinting_simulation_enabled{ false } { @@ -114,21 +115,40 @@ void MapView::save(QXmlStreamWriter& xml, const QLatin1String& element_name, boo mapview_element.writeAttribute(literal::grid, grid_visible); mapview_element.writeAttribute(literal::overprinting_simulation_enabled, overprinting_simulation_enabled); + // maintain legacy format: + saveTemplateSet(xml, template_details, template_visibility_sets.getVisibility(0)); + + if (getNumberOfVisibilitySets() < 2) + return; // don't duplicate first and only set + + XmlElementWriter template_sets_element(xml, literal::template_sets); + template_sets_element.writeAttribute(XmlStreamLiteral::count, getNumberOfVisibilitySets()); + template_sets_element.writeAttribute(literal::active_template_set, getActiveVisibilityIndex()); + + for (int i = 1; i < getNumberOfVisibilitySets(); ++i) + { + XmlElementWriter template_set_element(xml, literal::template_set); + saveTemplateSet(xml, template_details, template_visibility_sets.getVisibility(i)); + } +} + +void MapView::saveTemplateSet(QXmlStreamWriter& xml, bool template_details, const TemplateVisibilitySet& template_set) const +{ { XmlElementWriter map_element(xml, literal::map); - map_element.writeAttribute(literal::opacity, map_visibility.opacity); - map_element.writeAttribute(literal::visible, map_visibility.visible); + map_element.writeAttribute(literal::opacity, template_set.map_visibility.opacity); + map_element.writeAttribute(literal::visible, template_set.map_visibility.visible); } { XmlElementWriter templates_element(xml, literal::templates); - templates_element.writeAttribute(literal::hidden, all_templates_hidden); + templates_element.writeAttribute(literal::hidden, template_set.all_templates_hidden); if (template_details) { - templates_element.writeAttribute(XmlStreamLiteral::count, template_visibilities.size()); - for (auto entry : template_visibilities) + templates_element.writeAttribute(XmlStreamLiteral::count, template_set.template_visibilities.size()); + for (const auto& entry : template_set.template_visibilities) { - auto const index = map->findTemplateIndex(entry.temp); + auto const index = map->findTemplateIndex(entry.templ); if (index < 0) { qWarning("Template visibility found for unknown template"); @@ -167,52 +187,95 @@ void MapView::load(QXmlStreamReader& xml, int version) grid_visible = mapview_element.attribute(literal::grid); overprinting_simulation_enabled = mapview_element.attribute(literal::overprinting_simulation_enabled); + int current_template_set = 0; + int active_visibility_index = 0; + auto& template_set = template_visibility_sets.accessVisibility(0); + while (xml.readNextStartElement()) { - if (xml.name() == literal::map) - { - XmlElementReader map_element(xml); - map_visibility.opacity = map_element.attribute(literal::opacity); - // Some old maps before version 6 lack visible="true". - if (version >= 6) - map_visibility.visible = map_element.attribute(literal::visible); - else - map_visibility.visible = true; - } - else if (xml.name() == literal::templates) + if (xml.name() == literal::template_sets) { - XmlElementReader templates_element(xml); - auto num_template_visibilities = templates_element.attribute(XmlStreamLiteral::count); - template_visibilities.reserve(qBound(20u, num_template_visibilities, 1000u)); - all_templates_hidden = templates_element.attribute(literal::hidden); - + XmlElementReader template_sets_element(xml); + auto visibility_sets_num = template_sets_element.attribute(XmlStreamLiteral::count); + template_visibility_sets.template_visibility_sets.reserve(visibility_sets_num); + active_visibility_index = template_sets_element.attribute(literal::active_template_set); // stored for later usage while (xml.readNextStartElement()) { - if (xml.name() == literal::ref) + if (xml.name() == literal::template_set) { - XmlElementReader ref_element(xml); - int pos = ref_element.attribute(literal::template_string); - if (pos >= 0 && pos < map->getNumTemplates()) + XmlElementReader template_set_element(xml); + template_visibility_sets.template_visibility_sets.push_back(TemplateVisibilitySet()); + auto& template_set = template_visibility_sets.accessVisibility(++current_template_set); + template_visibility_sets.setActiveVisibilityIndex(current_template_set); + while (xml.readNextStartElement()) { - TemplateVisibility vis { - qBound(0.0f, ref_element.attribute(literal::opacity), 1.0f), - ref_element.attribute(literal::visible) - }; - setTemplateVisibilityHelper(map->getTemplate(pos), vis); + loadMapAndTemplates(xml, template_set, version); } } else + { xml.skipCurrentElement(); + } } } else - xml.skipCurrentElement(); // unsupported + { + loadMapAndTemplates(xml, template_set, version); + } } + if (active_visibility_index >= getNumberOfVisibilitySets()) + active_visibility_index = 0; + template_visibility_sets.setActiveVisibilityIndex(active_visibility_index); emit viewChanged(CenterChange | ZoomChange | RotationChange); emit visibilityChanged(MultipleFeatures, true); } +void MapView::loadMapAndTemplates(QXmlStreamReader& xml, TemplateVisibilitySet& template_set, int version) +{ + if (xml.name() == literal::map) + { + XmlElementReader map_element(xml); + TemplateVisibility map_visibility; + map_visibility.opacity = map_element.attribute(literal::opacity); + // Some old maps before version 6 lack visible="true". + if (version >= 6) + map_visibility.visible = map_element.attribute(literal::visible); + else + map_visibility.visible = true; + template_set.map_visibility = map_visibility; + } + else if (xml.name() == literal::templates) + { + XmlElementReader templates_element(xml); + auto num_template_visibilities = templates_element.attribute(XmlStreamLiteral::count); + template_set.template_visibilities.reserve(qBound(20u, num_template_visibilities, 1000u)); + template_set.all_templates_hidden = templates_element.attribute(literal::hidden); + + while (xml.readNextStartElement()) + { + if (xml.name() == literal::ref) + { + XmlElementReader ref_element(xml); + int pos = ref_element.attribute(literal::template_string); + if (pos >= 0 && pos < map->getNumTemplates()) + { + TemplateVisibility vis { + qBound(0.0f, ref_element.attribute(literal::opacity), 1.0f), + ref_element.attribute(literal::visible) + }; + setTemplateVisibilityHelper(map->getTemplate(pos), vis); + } + } + else + xml.skipCurrentElement(); + } + } + else + xml.skipCurrentElement(); // unsupported +} + + void MapView::updateAllMapWidgets(VisibilityFeature change) { emit visibilityChanged(change, true); @@ -360,104 +423,97 @@ void MapView::updateTransform() TemplateVisibility MapView::effectiveMapVisibility() const { - if (all_templates_hidden) + if (template_visibility_sets.getCurrentVisibility().all_templates_hidden) return { 1.0f, true }; - else if (map_visibility.opacity < 0.005) + else if (template_visibility_sets.getCurrentVisibility().map_visibility.opacity < 0.005) return { 0.0f, false }; else - return map_visibility; + return template_visibility_sets.getCurrentVisibility().map_visibility; } void MapView::setMapVisibility(TemplateVisibility vis) { - if (map_visibility != vis) + if (template_visibility_sets.getCurrentVisibility().map_visibility != vis) { - map_visibility = vis; + template_visibility_sets.accessCurrentVisibility().map_visibility = vis; emit visibilityChanged(VisibilityFeature::MapVisible, vis.visible && vis.opacity > 0, nullptr); } } -MapView::TemplateVisibilityVector::const_iterator MapView::findVisibility(const Template* temp) const -{ - return std::find_if(begin(template_visibilities), end(template_visibilities), [temp](const TemplateVisibilityEntry& entry) - { - return entry.temp == temp; - } ); -} - -MapView::TemplateVisibilityVector::iterator MapView::findVisibility(const Template* temp) +bool MapView::isTemplateVisible(const Template* templ) const { - return std::find_if(begin(template_visibilities), end(template_visibilities), [temp](const TemplateVisibilityEntry& entry) + if (template_visibility_sets.existsCurrentTemplateVisibility(templ)) { - return entry.temp == temp; - } ); -} - -bool MapView::isTemplateVisible(const Template* temp) const -{ - auto entry = findVisibility(temp); - return entry != end(template_visibilities) - && entry->visible - && entry->opacity > 0; + auto current_visibility = template_visibility_sets.getCurrentTemplateVisibility(templ); + return current_visibility.visible && current_visibility.opacity > 0; + } + return false; } -TemplateVisibility MapView::getTemplateVisibility(const Template* temp) const +TemplateVisibility MapView::getTemplateVisibility(const Template* templ) const { - auto entry = findVisibility(temp); - if (entry != end(template_visibilities)) - return *entry; + if (template_visibility_sets.existsCurrentTemplateVisibility(templ)) + return template_visibility_sets.getCurrentTemplateVisibility(templ); else return { 1.0f, false }; } -void MapView::setTemplateVisibility(Template* temp, TemplateVisibility vis) +void MapView::setTemplateVisibility(Template* templ, TemplateVisibility vis) { - if (setTemplateVisibilityHelper(temp, vis)) + if (setTemplateVisibilityHelper(templ, vis)) { auto const visible = vis.visible && vis.opacity > 0; - emit visibilityChanged(VisibilityFeature::TemplateVisible, visible, temp); + emit visibilityChanged(VisibilityFeature::TemplateVisible, visible, templ); } } -bool MapView::setTemplateVisibilityHelper(const Template *temp, TemplateVisibility vis) +bool MapView::setTemplateVisibilityHelper(const Template *templ, TemplateVisibility vis) { - auto stored = findVisibility(temp); - if (stored == end(template_visibilities)) + if (!template_visibility_sets.existsCurrentTemplateVisibility(templ)) { - template_visibilities.emplace_back(temp, vis); + template_visibility_sets.addTemplate(templ, vis); return true; } - if (*stored != vis) + if (template_visibility_sets.getCurrentTemplateVisibility(templ) != vis) // can this condition ever be false? { - stored->opacity = vis.opacity; - stored->visible = vis.visible; + template_visibility_sets.setCurrentTemplateVisibility(templ, vis); return true; } return false; } -void MapView::onAboutToAddTemplate(int, Template* temp) +TemplateVisibility MapView::getMapVisibility() const +{ + return template_visibility_sets.getCurrentVisibility().map_visibility; +} + +bool MapView::areAllTemplatesHidden() const { - setTemplateVisibilityHelper(temp, { 1.0f, false }); + return template_visibility_sets.getCurrentVisibility().all_templates_hidden; } -void MapView::onTemplateAdded(int, Template* temp) +void MapView::onAboutToAddTemplate(int, Template* templ) { - setTemplateVisibility(temp, { 1.0f, true }); + setTemplateVisibilityHelper(templ, { 1.0f, false }); } -void MapView::onTemplateDeleted(int, const Template* temp) +void MapView::onTemplateAdded(int, Template* templ) { - template_visibilities.erase(findVisibility(temp)); + setTemplateVisibility(templ, { 1.0f, true }); +} + +void MapView::onTemplateDeleted(int, const Template* templ) +{ + template_visibility_sets.deleteTemplate(templ); } void MapView::setAllTemplatesHidden(bool value) { - if (all_templates_hidden != value) + if (template_visibility_sets.getCurrentVisibility().all_templates_hidden != value) { - all_templates_hidden = value; - emit visibilityChanged(VisibilityFeature::AllTemplatesHidden, value); + template_visibility_sets.accessCurrentVisibility().all_templates_hidden = value; + emit visibilityChanged(VisibilityFeature::AllTemplatesHidden, value); // paramter 'value' is not used for VisibilityFeature::AllTemplatesHidden } } @@ -466,7 +522,7 @@ void MapView::setGridVisible(bool visible) if (grid_visible != visible) { grid_visible = visible; - emit visibilityChanged(VisibilityFeature::GridVisible, visible); + emit visibilityChanged(VisibilityFeature::GridVisible, visible); // paramter 'visible' is not used for VisibilityFeature::GridVisible } } @@ -475,7 +531,7 @@ void MapView::setOverprintingSimulationEnabled(bool enabled) if (overprinting_simulation_enabled != enabled) { overprinting_simulation_enabled = enabled; - emit visibilityChanged(VisibilityFeature::OverprintingEnabled, enabled); + emit visibilityChanged(VisibilityFeature::OverprintingEnabled, enabled); // paramter 'enabled' is not used for VisibilityFeature::OverprintingEnabled } } @@ -492,14 +548,161 @@ bool MapView::hasAlpha() const for (int i = 0; i < map->getNumTemplates(); ++i) { - auto temp = map->getTemplate(i); - auto visibility = getTemplateVisibility(temp); - if (visibility.hasAlpha() || temp->hasAlpha()) + auto templ = map->getTemplate(i); + auto visibility = getTemplateVisibility(templ); + if (visibility.hasAlpha() || templ->hasAlpha()) return true; } return false; } +bool MapView::applyVisibilitySet(int new_visibility_set) +{ + Q_ASSERT(new_visibility_set < getNumberOfVisibilitySets()); + Q_ASSERT(template_visibility_sets.getVisibility(new_visibility_set).template_visibilities.size() == template_visibility_sets.getCurrentVisibility().template_visibilities.size()); + + if (new_visibility_set != getActiveVisibilityIndex()) + { + auto number_of_templates = (int)template_visibility_sets.getVisibility(new_visibility_set).template_visibilities.size(); + for (int i = 0; i < number_of_templates; ++i) + { + auto new_template_visibility = template_visibility_sets.getTemplateVisibility(new_visibility_set, i); + if (new_template_visibility != template_visibility_sets.getTemplateVisibility(getActiveVisibilityIndex(), i)) + { + auto const visible = new_template_visibility.visible && new_template_visibility.opacity > 0; + emit visibilityChanged(VisibilityFeature::TemplateVisible, visible, const_cast(new_template_visibility.templ)); + } + } + + auto new_map_visibility = template_visibility_sets.getVisibility(new_visibility_set).map_visibility; + if (template_visibility_sets.getCurrentVisibility().map_visibility != new_map_visibility) + { + emit visibilityChanged(VisibilityFeature::MapVisible, new_map_visibility.visible && new_map_visibility.opacity > 0, nullptr); // actual visibility is not used for VisibilityFeature::MapVisible + } + + if (template_visibility_sets.getCurrentVisibility().all_templates_hidden != template_visibility_sets.getVisibility(new_visibility_set).all_templates_hidden) + return true; + } + + return false; +} + +void MapView::setVisibilitySet(int new_visibility_set) +{ + auto emit_change = applyVisibilitySet(new_visibility_set); + template_visibility_sets.setActiveVisibilityIndex(new_visibility_set); + if (emit_change) + emit visibilityChanged(VisibilityFeature::AllTemplatesHidden, true); // 'true' is not used for VisibilityFeature::AllTemplatesHidden +} + +void MapView::addVisibilitySet() +{ + template_visibility_sets.duplicateVisibility(); +} + +void MapView::deleteVisibilitySet() +{ + auto new_visibility_set = getActiveVisibilityIndex(); + if (new_visibility_set < getNumberOfVisibilitySets() - 1) + ++new_visibility_set; // deleting not the last set => the following set will be applied + else + --new_visibility_set; // deleting the last set => the previous set will be applied + auto emit_change = applyVisibilitySet(new_visibility_set); + template_visibility_sets.deleteVisibility(); + if (emit_change) + emit visibilityChanged(VisibilityFeature::AllTemplatesHidden, true); // 'true' is not used for VisibilityFeature::AllTemplatesHidden +} + +// ### TemplateVisibilitySet ### + +TemplateVisibilitySet::TemplateVisibilitySet() +{ + map_visibility = {1.0f, true}; +} + +TemplateVisibilitySets::TemplateVisibilitySets() +{ + template_visibility_sets.push_back(TemplateVisibilitySet()); + active_visibility_index = 0; +} + +void TemplateVisibilitySets::duplicateVisibility() +{ + template_visibility_sets.insert(template_visibility_sets.begin() + active_visibility_index + 1, getCurrentVisibility()); +} + +void TemplateVisibilitySets::deleteVisibility() +{ + Q_ASSERT(getNumberOfVisibilitySets() > 1); + Q_ASSERT(active_visibility_index < getNumberOfVisibilitySets()); + + template_visibility_sets.erase(template_visibility_sets.begin() + active_visibility_index); + if (active_visibility_index >= getNumberOfVisibilitySets()) + --active_visibility_index; +} + +void TemplateVisibilitySets::deleteTemplate(const Template* templ) +{ + for (auto& template_set : template_visibility_sets) + { + template_set.template_visibilities.erase(template_set.findVisibility(templ)); + } +} + +void TemplateVisibilitySets::addTemplate(const Template *templ, TemplateVisibility vis) +{ + for (auto& template_set : template_visibility_sets) + { + // another check is needed to differentiate between adding a template during loading vs. adding a template by the user + if (!template_set.existsVisibility(templ)) + template_set.template_visibilities.emplace_back(templ, vis); + } +} + +TemplateVisibilityEntry TemplateVisibilitySets::getCurrentTemplateVisibility(const Template* templ) const +{ + return *(template_visibility_sets.at(active_visibility_index).findVisibility(templ)); +} + +TemplateVisibilityEntry TemplateVisibilitySets::getTemplateVisibility(int template_set, int index) const +{ + return template_visibility_sets.at(template_set).template_visibilities.at(index); +} + +void TemplateVisibilitySets::setCurrentTemplateVisibility(const Template* templ, TemplateVisibility vis) +{ + template_visibility_sets.at(active_visibility_index).findVisibility(templ)->opacity = vis.opacity; + template_visibility_sets.at(active_visibility_index).findVisibility(templ)->visible = vis.visible; +} + +bool TemplateVisibilitySets::existsCurrentTemplateVisibility(const Template* templ) const +{ + return getCurrentVisibility().existsVisibility(templ); +} + +TemplateVisibilitySet::TemplateVisibilityVector::const_iterator TemplateVisibilitySet::findVisibility(const Template* templ) const +{ + return std::find_if(begin(template_visibilities), end(template_visibilities), [templ](const TemplateVisibilityEntry& entry) + { + return entry.templ == templ; + } ); +} + +TemplateVisibilitySet::TemplateVisibilityVector::iterator TemplateVisibilitySet::findVisibility(const Template* templ) +{ + return std::find_if(begin(template_visibilities), end(template_visibilities), [templ](const TemplateVisibilityEntry& entry) + { + return entry.templ == templ; + } ); +} + +bool TemplateVisibilitySet::existsVisibility(const Template* templ) const +{ + return end(template_visibilities) != std::find_if(begin(template_visibilities), end(template_visibilities), [templ](const TemplateVisibilityEntry& entry) + { + return entry.templ == templ; + } ); +} } // namespace OpenOrienteering diff --git a/src/core/map_view.h b/src/core/map_view.h index 0f3c342eb3..daa374ccad 100644 --- a/src/core/map_view.h +++ b/src/core/map_view.h @@ -1,6 +1,7 @@ /* * Copyright 2012, 2013 Thomas Schöps - * Copyright 2014-2020 Kai Pastor + * Copyright 2014-2020, 2025 Kai Pastor + * Copyright 2025 Matthias Kühlewein * * This file is part of OpenOrienteering. * @@ -35,7 +36,6 @@ #include "map_coord.h" class QLatin1String; -class QRectF; class QXmlStreamReader; class QXmlStreamWriter; @@ -65,6 +65,68 @@ bool operator==(TemplateVisibility lhs, TemplateVisibility rhs); bool operator!=(TemplateVisibility lhs, TemplateVisibility rhs); +class TemplateVisibilityEntry : public TemplateVisibility +{ +public: + TemplateVisibilityEntry() = default; + TemplateVisibilityEntry(const TemplateVisibilityEntry&) = default; + TemplateVisibilityEntry(TemplateVisibilityEntry&&) = default; + TemplateVisibilityEntry& operator=(const TemplateVisibilityEntry&) = default; + TemplateVisibilityEntry& operator=(TemplateVisibilityEntry&&) = default; + TemplateVisibilityEntry(const Template* templ, TemplateVisibility vis) + : TemplateVisibility(vis) + , templ(templ) + {} + +public: + const Template* templ; +}; + +class TemplateVisibilitySet +{ +public: + TemplateVisibilitySet(); + + typedef std::vector TemplateVisibilityVector; + + TemplateVisibilityVector::const_iterator findVisibility(const Template* templ) const; + TemplateVisibilityVector::iterator findVisibility(const Template* templ); + bool existsVisibility(const Template* templ) const; + + TemplateVisibility map_visibility; + TemplateVisibilityVector template_visibilities; + bool all_templates_hidden = false; +}; + +class TemplateVisibilitySets +{ + +public: + TemplateVisibilitySets(); + + void setVisibility(int current_visibility, TemplateVisibility visibility); + void duplicateVisibility(); + void deleteVisibility(); + const TemplateVisibilitySet& getCurrentVisibility() const { return template_visibility_sets.at(active_visibility_index); }; + const TemplateVisibilitySet& getVisibility(int index) const { return template_visibility_sets.at(index); }; + TemplateVisibilitySet& accessCurrentVisibility() { return template_visibility_sets.at(active_visibility_index); }; + TemplateVisibilitySet& accessVisibility(int index) { return template_visibility_sets.at(index); }; + TemplateVisibilityEntry getCurrentTemplateVisibility(const Template* templ) const; + TemplateVisibilityEntry getTemplateVisibility(int template_set, int index) const; + void setCurrentTemplateVisibility(const Template* templ, TemplateVisibility vis); + void deleteTemplate(const Template* templ); + void addTemplate(const Template *templ, TemplateVisibility vis); + bool existsCurrentTemplateVisibility(const Template* templ) const; + void setActiveVisibilityIndex(int active_visibility) { active_visibility_index = active_visibility; }; + int getActiveVisibilityIndex() const { return active_visibility_index; }; + int getNumberOfVisibilitySets() const { return template_visibility_sets.size(); }; + +public: + std::vector template_visibility_sets; + +private: + int active_visibility_index; +}; /** * Stores view position, zoom, rotation and grid / template visibilities @@ -78,7 +140,6 @@ class MapView : public QObject { Q_OBJECT Q_FLAGS(ChangeFlags VisibilityFeature) - public: enum ChangeFlag { @@ -278,19 +339,19 @@ class MapView : public QObject * Checks if the template is visible without creating * a template visibility object if none exists */ - bool isTemplateVisible(const Template* temp) const; + bool isTemplateVisible(const Template* templ) const; /** * Returns the template visibility. * * If the template is unknown, returns default settings. */ - TemplateVisibility getTemplateVisibility(const Template* temp) const; + TemplateVisibility getTemplateVisibility(const Template* templ) const; /** * Sets the template visibility, and emits a change signal. */ - void setTemplateVisibility(Template* temp, TemplateVisibility vis); + void setTemplateVisibility(Template* templ, TemplateVisibility vis); /** Enables or disables hiding all templates in this view */ @@ -322,6 +383,12 @@ class MapView : public QObject */ bool hasAlpha() const; + bool applyVisibilitySet(int new_visibility_set); // private + void setVisibilitySet(int new_visibility_set); + void addVisibilitySet(); + void deleteVisibilitySet(); + int getNumberOfVisibilitySets() const { return template_visibility_sets.getNumberOfVisibilitySets(); }; + int getActiveVisibilityIndex() const { return template_visibility_sets.getActiveVisibilityIndex(); }; signals: /** @@ -341,7 +408,7 @@ class MapView : public QObject * * @param feature The map view feature that has changed. * @param active The features current state of activation. - * @param temp If a the feature is a template, a pointer to this template. + * @param temp If the feature is a template, a pointer to this template. */ void visibilityChanged(OpenOrienteering::MapView::VisibilityFeature feature, bool active, OpenOrienteering::Template* temp = nullptr); @@ -358,48 +425,31 @@ class MapView : public QObject /** * Sets the template visibility without emitting signals. */ - bool setTemplateVisibilityHelper(const Template *temp, TemplateVisibility vis); + bool setTemplateVisibilityHelper(const Template *templ, TemplateVisibility vis); /** * Creates a default visibility entry (100% opaque, hidden) before a template is added to the map. */ - void onAboutToAddTemplate(int pos, Template* temp); + void onAboutToAddTemplate(int pos, Template* templ); /** * Changes the visibility entry to 100% visible after a template is added to the map. */ - void onTemplateAdded(int pos, Template* temp); + void onTemplateAdded(int pos, Template* templ); /** * Removes the visibility data when a template is deleted. */ - void onTemplateDeleted(int pos, const Template* temp); + void onTemplateDeleted(int pos, const Template* templ); private: Q_DISABLE_COPY(MapView) - struct TemplateVisibilityEntry : public TemplateVisibility - { - const Template* temp; - TemplateVisibilityEntry() = default; - TemplateVisibilityEntry(const TemplateVisibilityEntry&) = default; - TemplateVisibilityEntry(TemplateVisibilityEntry&&) = default; - TemplateVisibilityEntry& operator=(const TemplateVisibilityEntry&) = default; - TemplateVisibilityEntry& operator=(TemplateVisibilityEntry&&) = default; - TemplateVisibilityEntry(const Template* temp, TemplateVisibility vis) - : TemplateVisibility(vis) - , temp(temp) - {} - }; - typedef std::vector TemplateVisibilityVector; - + void saveTemplateSet(QXmlStreamWriter& xml, bool template_details, const TemplateVisibilitySet& template_set) const; + void loadMapAndTemplates(QXmlStreamReader& xml, TemplateVisibilitySet& template_set, int version); void updateTransform(); // recalculates the x_to_y matrices - TemplateVisibilityVector::const_iterator findVisibility(const Template* temp) const; - - TemplateVisibilityVector::iterator findVisibility(const Template* temp); - Map* map; @@ -411,10 +461,8 @@ class MapView : public QObject QTransform view_to_map; QTransform map_to_view; - TemplateVisibility map_visibility; - TemplateVisibilityVector template_visibilities; + TemplateVisibilitySets template_visibility_sets; - bool all_templates_hidden; bool grid_visible; bool overprinting_simulation_enabled; }; @@ -500,18 +548,6 @@ QPoint MapView::panOffset() const return pan_offset; } -inline -TemplateVisibility MapView::getMapVisibility() const -{ - return map_visibility; -} - -inline -bool MapView::areAllTemplatesHidden() const -{ - return all_templates_hidden; -} - inline bool MapView::isGridVisible() const { @@ -531,4 +567,4 @@ bool MapView::isOverprintingSimulationEnabled() const Q_DECLARE_OPERATORS_FOR_FLAGS(OpenOrienteering::MapView::ChangeFlags) -#endif +#endif // OPENORIENTEERING_MAP_VIEW_H diff --git a/src/gui/widgets/template_list_widget.cpp b/src/gui/widgets/template_list_widget.cpp index 5b562c46bd..ad798686ca 100644 --- a/src/gui/widgets/template_list_widget.cpp +++ b/src/gui/widgets/template_list_widget.cpp @@ -1,6 +1,7 @@ /* * Copyright 2012, 2013 Thomas Schöps - * Copyright 2012-2020 Kai Pastor + * Copyright 2012-2020, 2025 Kai Pastor + * Copyright 2025 Matthias Kühlewein * * This file is part of OpenOrienteering. * @@ -22,7 +23,6 @@ #include "template_list_widget.h" #include -#include #include #include @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -56,6 +57,7 @@ #include #include #include +#include #include #include #include @@ -145,6 +147,7 @@ TemplateListWidget::TemplateListWidget(Map& map, MapView& main_view, MapEditorCo , main_view(main_view) , controller(controller) , mobile_mode(controller.isInMobileMode()) +, max_template_sets(9) { setWhatsThis(Util::makeWhatThis("templates.html#setup")); @@ -314,7 +317,8 @@ TemplateListWidget::TemplateListWidget(Map& map, MapView& main_view, MapEditorCo style()->pixelMetric(QStyle::PM_LayoutLeftMargin, &style_option) / 2, 0, // Covered by the main layout's spacing. style()->pixelMetric(QStyle::PM_LayoutRightMargin, &style_option) / 2, - style()->pixelMetric(QStyle::PM_LayoutBottomMargin, &style_option) / 2 + //style()->pixelMetric(QStyle::PM_LayoutBottomMargin, &style_option) / 2 + 0 ); all_buttons_layout->addWidget(list_buttons_group); all_buttons_layout->addWidget(new QLabel(QString::fromLatin1(" ")), 1); @@ -327,7 +331,50 @@ TemplateListWidget::TemplateListWidget(Map& map, MapView& main_view, MapEditorCo connect(help_button, &QAbstractButton::clicked, this, &TemplateListWidget::showHelp); } - all_templates_layout->addLayout(all_buttons_layout); + + // Template set layout + auto* template_set_layout = new SegmentedButtonLayout(); + + new_template_set_button = createToolButton(QIcon(QString::fromLatin1(":/images/plus.png")), tr("Add")); + template_set_layout->addWidget(new_template_set_button); + delete_template_set_button = createToolButton(QIcon(QString::fromLatin1(":/images/minus.png")), tr("Remove")); + template_set_layout->addWidget(delete_template_set_button); + template_set_layout->addWidget(new QLabel(QString::fromLatin1(" ")), 1); + + auto* group = new QButtonGroup(this); + template_set_buttons.reserve(max_template_sets); + for (int i = 0; i < max_template_sets; ++i) + { + auto* template_set_button = new QPushButton(tr("%1").arg(i+1)); + const auto textSize = template_set_button->fontMetrics().size(Qt::TextShowMnemonic, template_set_button->text()); + QStyleOptionButton opt; + opt.initFrom(template_set_button); + opt.rect.setSize(textSize); + template_set_button->setMinimumSize(template_set_button->style()->sizeFromContents(QStyle::CT_PushButton, &opt, textSize, template_set_button)); + template_set_buttons.push_back(template_set_button); + group->addButton(template_set_button, i); + template_set_layout->addWidget(template_set_button); + } + updateTemplateSetButtons(); + + // The template set buttons row layout + auto* template_set_buttons_layout = new QHBoxLayout(); + //template_set_buttons_layout->setContentsMargins(0,0,0,0); + template_set_buttons_layout->setContentsMargins( + style()->pixelMetric(QStyle::PM_LayoutLeftMargin, &style_option) / 2, + 0, // Covered by the main layout's spacing. + style()->pixelMetric(QStyle::PM_LayoutRightMargin, &style_option) / 2, + style()->pixelMetric(QStyle::PM_LayoutBottomMargin, &style_option) / 2 + ); + template_set_buttons_layout->addLayout(template_set_layout); + template_set_buttons_layout->addStretch(); + + auto* two_rows_layout = new QVBoxLayout(); + two_rows_layout->addLayout(all_buttons_layout); + two_rows_layout->addLayout(template_set_buttons_layout); + + //all_templates_layout->addLayout(all_buttons_layout); + all_templates_layout->addLayout(two_rows_layout); setLayout(all_templates_layout); @@ -361,6 +408,10 @@ TemplateListWidget::TemplateListWidget(Map& map, MapView& main_view, MapEditorCo connect(adjust_button, &QAbstractButton::clicked, this, &TemplateListWidget::adjustClicked); connect(position_action, &QAction::triggered, this, &TemplateListWidget::positionClicked); + connect(new_template_set_button, &QAbstractButton::clicked, this, &TemplateListWidget::addTemplateSet); + connect(delete_template_set_button, &QAbstractButton::clicked, this, &TemplateListWidget::deleteTemplateSet); + connect(group, &QButtonGroup::idClicked, this, &TemplateListWidget::onGroupButtonClicked); + //connect(group_button, SIGNAL(clicked(bool)), this, &TemplateListWidget::groupClicked); //connect(more_button_menu, SIGNAL(triggered(QAction*)), this, SLOT(moreActionClicked(QAction*))); @@ -687,6 +738,43 @@ void TemplateListWidget::newTemplate(QAction* action) } #endif +void TemplateListWidget::updateTemplateSetButtons() +{ + const auto template_sets = main_view.getNumberOfVisibilitySets(); + const auto current_template_set = main_view.getActiveVisibilityIndex(); + delete_template_set_button->setEnabled(template_sets > 1); + new_template_set_button->setEnabled(template_sets < max_template_sets); + for (int i = 0; i < max_template_sets; ++i) + { + template_set_buttons.at(i)->setVisible(template_sets > i); + template_set_buttons.at(i)->setStyleSheet(current_template_set == i ? QLatin1String("background-color:green;") : QLatin1String("background-color:lightGray;")); + } +} + +// slots: +void TemplateListWidget::addTemplateSet() +{ + main_view.addVisibilitySet(); + updateTemplateSetButtons(); +} + +void TemplateListWidget::deleteTemplateSet() +{ + main_view.deleteVisibilitySet(); + updateTemplateSetButtons(); + template_table->viewport()->update(); +} + +void TemplateListWidget::onGroupButtonClicked(int val) +{ + if (main_view.getActiveVisibilityIndex() != val) + { + main_view.setVisibilitySet(val); + updateTemplateSetButtons(); + template_table->viewport()->update(); + } +} + void TemplateListWidget::openTemplate() { auto new_template = showOpenTemplateDialog(window(), controller); @@ -718,7 +806,6 @@ void TemplateListWidget::duplicateTemplate() Q_ASSERT(row >= 0); int pos = posFromRow(row); Q_ASSERT(pos >= 0); - const auto* prototype = map.getTemplate(pos); const auto visibility = main_view.getTemplateVisibility(prototype); diff --git a/src/gui/widgets/template_list_widget.h b/src/gui/widgets/template_list_widget.h index 85505d44d6..beed54f4ce 100644 --- a/src/gui/widgets/template_list_widget.h +++ b/src/gui/widgets/template_list_widget.h @@ -1,6 +1,7 @@ /* * Copyright 2012, 2013 Thomas Schöps - * Copyright 2020 Kai Pastor + * Copyright 2020, 2025 Kai Pastor + * Copyright 2025 Matthias Kühlewein * * This file is part of OpenOrienteering. * @@ -23,11 +24,13 @@ #define OPENORIENTEERING_TEMPLATE_LIST_WIDGET_H #include +#include #include -#include #include #include +#include +#include #include "core/map_view.h" @@ -36,9 +39,9 @@ class QBoxLayout; class QCheckBox; class QEvent; class QModelIndex; +class QPushButton; class QTableView; class QToolButton; -class QVariant; namespace OpenOrienteering { @@ -114,6 +117,8 @@ class TemplateListWidget : public QWidget */ bool eventFilter(QObject* watched, QEvent* event) override; +private: + void updateTemplateSetButtons(); // slots: #if 0 @@ -142,6 +147,10 @@ class TemplateListWidget : public QWidget void showOpacitySlider(int row); + void addTemplateSet(); + void deleteTemplateSet(); + void onGroupButtonClicked(int val); + private: Map& map; MapView& main_view; @@ -151,6 +160,7 @@ class TemplateListWidget : public QWidget Template* last_template = nullptr; int last_row = -1; + const int max_template_sets; QCheckBox* all_hidden_check; QTableView* template_table; @@ -172,6 +182,10 @@ class TemplateListWidget : public QWidget QToolButton* adjust_button; QToolButton* edit_button; + QToolButton* new_template_set_button; + QToolButton* delete_template_set_button; + std::vector template_set_buttons; + //QToolButton* group_button; //QToolButton* more_button; }; @@ -179,4 +193,4 @@ class TemplateListWidget : public QWidget } // namespace OpenOrienteering -#endif +#endif // OPENORIENTEERING_TEMPLATE_LIST_WIDGET_H From 97da53e8fc18cc30af4fa59399ea191a65185750 Mon Sep 17 00:00:00 2001 From: Matthias Kuehlewein Date: Tue, 4 Feb 2025 19:06:50 +0100 Subject: [PATCH 2/6] Adaption for QT version prior to 5.15 --- src/gui/widgets/template_list_widget.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gui/widgets/template_list_widget.cpp b/src/gui/widgets/template_list_widget.cpp index ad798686ca..a5a992374c 100644 --- a/src/gui/widgets/template_list_widget.cpp +++ b/src/gui/widgets/template_list_widget.cpp @@ -410,7 +410,11 @@ TemplateListWidget::TemplateListWidget(Map& map, MapView& main_view, MapEditorCo connect(new_template_set_button, &QAbstractButton::clicked, this, &TemplateListWidget::addTemplateSet); connect(delete_template_set_button, &QAbstractButton::clicked, this, &TemplateListWidget::deleteTemplateSet); +#if QT_VERSION < 0x051500 + connect(group, QOverload::of(&QButtonGroup::buttonClicked), this, &TemplateListWidget::onGroupButtonClicked); +#else connect(group, &QButtonGroup::idClicked, this, &TemplateListWidget::onGroupButtonClicked); +#endif //connect(group_button, SIGNAL(clicked(bool)), this, &TemplateListWidget::groupClicked); //connect(more_button_menu, SIGNAL(triggered(QAction*)), this, SLOT(moreActionClicked(QAction*))); From 261f22e88972b3dc75ed4c38bd982df17972582b Mon Sep 17 00:00:00 2001 From: Matthias Kuehlewein Date: Thu, 6 Feb 2025 23:04:04 +0100 Subject: [PATCH 3/6] Revise push buttons --- src/gui/widgets/template_list_widget.cpp | 26 ++++++++++++++++-------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/gui/widgets/template_list_widget.cpp b/src/gui/widgets/template_list_widget.cpp index a5a992374c..cbe3c762d7 100644 --- a/src/gui/widgets/template_list_widget.cpp +++ b/src/gui/widgets/template_list_widget.cpp @@ -36,11 +36,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -56,6 +58,7 @@ #include #include #include +#include #include #include #include @@ -333,14 +336,13 @@ TemplateListWidget::TemplateListWidget(Map& map, MapView& main_view, MapEditorCo // Template set layout - auto* template_set_layout = new SegmentedButtonLayout(); - + auto* set_change_layout = new SegmentedButtonLayout(); new_template_set_button = createToolButton(QIcon(QString::fromLatin1(":/images/plus.png")), tr("Add")); - template_set_layout->addWidget(new_template_set_button); + set_change_layout->addWidget(new_template_set_button); delete_template_set_button = createToolButton(QIcon(QString::fromLatin1(":/images/minus.png")), tr("Remove")); - template_set_layout->addWidget(delete_template_set_button); - template_set_layout->addWidget(new QLabel(QString::fromLatin1(" ")), 1); + set_change_layout->addWidget(delete_template_set_button); + auto* set_selection_layout = new SegmentedButtonLayout(); auto* group = new QButtonGroup(this); template_set_buttons.reserve(max_template_sets); for (int i = 0; i < max_template_sets; ++i) @@ -351,9 +353,10 @@ TemplateListWidget::TemplateListWidget(Map& map, MapView& main_view, MapEditorCo opt.initFrom(template_set_button); opt.rect.setSize(textSize); template_set_button->setMinimumSize(template_set_button->style()->sizeFromContents(QStyle::CT_PushButton, &opt, textSize, template_set_button)); + template_set_button->setAutoFillBackground(true); template_set_buttons.push_back(template_set_button); group->addButton(template_set_button, i); - template_set_layout->addWidget(template_set_button); + set_selection_layout->addWidget(template_set_button); } updateTemplateSetButtons(); @@ -366,14 +369,14 @@ TemplateListWidget::TemplateListWidget(Map& map, MapView& main_view, MapEditorCo style()->pixelMetric(QStyle::PM_LayoutRightMargin, &style_option) / 2, style()->pixelMetric(QStyle::PM_LayoutBottomMargin, &style_option) / 2 ); - template_set_buttons_layout->addLayout(template_set_layout); + template_set_buttons_layout->addLayout(set_change_layout); + template_set_buttons_layout->addLayout(set_selection_layout); template_set_buttons_layout->addStretch(); auto* two_rows_layout = new QVBoxLayout(); two_rows_layout->addLayout(all_buttons_layout); two_rows_layout->addLayout(template_set_buttons_layout); - //all_templates_layout->addLayout(all_buttons_layout); all_templates_layout->addLayout(two_rows_layout); setLayout(all_templates_layout); @@ -751,7 +754,12 @@ void TemplateListWidget::updateTemplateSetButtons() for (int i = 0; i < max_template_sets; ++i) { template_set_buttons.at(i)->setVisible(template_sets > i); - template_set_buttons.at(i)->setStyleSheet(current_template_set == i ? QLatin1String("background-color:green;") : QLatin1String("background-color:lightGray;")); + if (i < template_sets) + { + auto pal = template_set_buttons.at(i)->palette(); + pal.setColor(QPalette::Button, i == current_template_set ? QColor(Qt::green) : QColor(Qt::lightGray)); + template_set_buttons.at(i)->setPalette(pal); + } } } From 838f7d791de69581519d07c28127e16d9b3e1bfe Mon Sep 17 00:00:00 2001 From: Matthias Kuehlewein Date: Sun, 9 Feb 2025 12:25:36 +0100 Subject: [PATCH 4/6] Add icons for adding/deleting template selection sets --- images/template-set-add.png | Bin 0 -> 614 bytes images/template-set-delete.png | Bin 0 -> 346 bytes resources.qrc | 10 ++++++---- src/gui/widgets/template_list_widget.cpp | 4 ++-- 4 files changed, 8 insertions(+), 6 deletions(-) create mode 100644 images/template-set-add.png create mode 100644 images/template-set-delete.png diff --git a/images/template-set-add.png b/images/template-set-add.png new file mode 100644 index 0000000000000000000000000000000000000000..432c08f673c22aa769d1591837a489c87811f283 GIT binary patch literal 614 zcmV-s0-61ZP)5i$Q4~FQCdovpmVzG;a3LtJnpLS50^&!sYjNqu zwFsi1xbO!AA-c&QxQJvYQYcs`MGM^tV#PLHO)~c$7c*}v(@fHiV?w15X1KgJ@7*)^ zo^#(7l9=W2Fym3lTM&_v^UIyZc|Vl>QER=mb;&y~FVdAlsQn;(e&=QI=iI~h52l}j zo&Gj<`rBul1El~kSotJ8ndA6Pn-YLqof~t$Ru@QC2#cKq&;-iuw>KBYZ2xsC04we0 zG2L+J4L}tLd?UeFuW1T=T>LgNQq(#CIdueH+vCn7cd;yY7U!!&|GSZa0+56UlP)8ymRt#y3MW8I08FD4 zOSm`i8~|4d^$39c3jkh{sv3Y`fAcVK036p9k^8m|AOKJW;GYE0Bo+7x0N>f+-k|2> z*SK&MW(G24dH_I^$1-*y0Lp$rU&jFkRIMa3DH%6Qn5!Ht3O8@`>07*qoM6N<$f?@0m A>Hq)$ literal 0 HcmV?d00001 diff --git a/images/template-set-delete.png b/images/template-set-delete.png new file mode 100644 index 0000000000000000000000000000000000000000..4c186dde8e6b0f8b0784b38c172bdbcb4e8831ae GIT binary patch literal 346 zcmV-g0j2(lP)LK@de>?HH`VW@aWHLP1P~0r3!e850dm^bUFo zVPs>C7esF$CK}01)i>xJ2SkG%kq+#Rnl8HPb^YoplSIxnA@eE#1)ubaDA}z z>kegRj!jyHPmgZyY$X7I!_&*}4FX9J0SXjC?qHzsWOoNeC8@eSKUqBkkes|dJz{3d zxB>-uha&Ceo`Mn3c1Yd_NA65Fx5h~T@c#15>%(HGmH@LQL@$s6>*q-XR4GF!k__v! z@c;lDyL%8R8w!UQUM&gf%US2hl053#Pmoan^NX`T{{>dYaRDd*{~o{?nrgmrynnSl s+QIzzo~CI=-L31o)Ib3!0QvjC2PM~+b}h!1`2YX_07*qoM6N<$g2af1X8-^I literal 0 HcmV?d00001 diff --git a/resources.qrc b/resources.qrc index 83ef2a9fd3..e0cf87008c 100644 --- a/resources.qrc +++ b/resources.qrc @@ -119,17 +119,19 @@ images/mapper-icon/Mapper-128.png images/map-information.png doc/tip-of-the-day/tips_en.txt + images/template-set-add.png + images/template-set-delete.png - + doc/tip-of-the-day/tips_de.txt - + doc/tip-of-the-day/tips_fr.txt - + doc/tip-of-the-day/tips_ru.txt - + doc/tip-of-the-day/tips_uk.txt diff --git a/src/gui/widgets/template_list_widget.cpp b/src/gui/widgets/template_list_widget.cpp index cbe3c762d7..4a22130290 100644 --- a/src/gui/widgets/template_list_widget.cpp +++ b/src/gui/widgets/template_list_widget.cpp @@ -337,9 +337,9 @@ TemplateListWidget::TemplateListWidget(Map& map, MapView& main_view, MapEditorCo // Template set layout auto* set_change_layout = new SegmentedButtonLayout(); - new_template_set_button = createToolButton(QIcon(QString::fromLatin1(":/images/plus.png")), tr("Add")); + new_template_set_button = createToolButton(QIcon(QString::fromLatin1(":/images/template-set-add.png")), tr("Add")); set_change_layout->addWidget(new_template_set_button); - delete_template_set_button = createToolButton(QIcon(QString::fromLatin1(":/images/minus.png")), tr("Remove")); + delete_template_set_button = createToolButton(QIcon(QString::fromLatin1(":/images/template-set-delete.png")), tr("Remove")); set_change_layout->addWidget(delete_template_set_button); auto* set_selection_layout = new SegmentedButtonLayout(); From fd22a4e012625f1ec7fd13e49ddf780533762903 Mon Sep 17 00:00:00 2001 From: Matthias Kuehlewein Date: Wed, 12 Feb 2025 16:25:51 +0100 Subject: [PATCH 5/6] Switch to added template selection set --- src/core/map_view.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/map_view.cpp b/src/core/map_view.cpp index c5ba8f8164..1dd4bbb603 100644 --- a/src/core/map_view.cpp +++ b/src/core/map_view.cpp @@ -630,6 +630,7 @@ TemplateVisibilitySets::TemplateVisibilitySets() void TemplateVisibilitySets::duplicateVisibility() { template_visibility_sets.insert(template_visibility_sets.begin() + active_visibility_index + 1, getCurrentVisibility()); + ++active_visibility_index; } void TemplateVisibilitySets::deleteVisibility() From 3cfbd4362f0cb6515516ba32d952bc3db4c5e018 Mon Sep 17 00:00:00 2001 From: Matthias Kuehlewein Date: Tue, 18 Feb 2025 14:57:18 +0100 Subject: [PATCH 6/6] Use F4 to step through template selection sets Remove F4 for enabling/disabling the overprinting simulation. --- src/gui/map/map_editor.cpp | 7 +++++-- src/gui/widgets/template_list_widget.cpp | 12 ++++++++++-- src/gui/widgets/template_list_widget.h | 3 +++ 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/gui/map/map_editor.cpp b/src/gui/map/map_editor.cpp index dd85f41460..6476aa49be 100644 --- a/src/gui/map/map_editor.cpp +++ b/src/gui/map/map_editor.cpp @@ -1,6 +1,6 @@ /* * Copyright 2012, 2013 Thomas Schöps - * Copyright 2012-2021, 2024 Kai Pastor + * Copyright 2012-2021, 2024, 2025 Kai Pastor * * This file is part of OpenOrienteering. * @@ -77,6 +77,7 @@ #include #include #include +#include #include #include #include @@ -917,7 +918,6 @@ void MapEditorController::assignKeyboardShortcuts() findAction("hatchareasview")->setShortcut(QKeySequence(Qt::Key_F2)); findAction("baselineview")->setShortcut(QKeySequence(Qt::Key_F3)); findAction("hidealltemplates")->setShortcut(QKeySequence(Qt::Key_F10)); - findAction("overprintsimulation")->setShortcut(QKeySequence(Qt::Key_F4)); findAction("fullscreen")->setShortcut(QKeySequence(Qt::Key_F11)); tags_window_act->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_6)); color_window_act->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_7)); @@ -2288,6 +2288,9 @@ void MapEditorController::createTemplateWindow() dock_widget->setVisible(false); template_dock_widget = dock_widget; + + auto* switch_template_shortcut = new QShortcut(QKeySequence(Qt::Key_F4), window); + connect(switch_template_shortcut, &QShortcut::activated, template_list_widget, &TemplateListWidget::switchTemplateSet); } } diff --git a/src/gui/widgets/template_list_widget.cpp b/src/gui/widgets/template_list_widget.cpp index 4a22130290..9935fe48ec 100644 --- a/src/gui/widgets/template_list_widget.cpp +++ b/src/gui/widgets/template_list_widget.cpp @@ -334,8 +334,7 @@ TemplateListWidget::TemplateListWidget(Map& map, MapView& main_view, MapEditorCo connect(help_button, &QAbstractButton::clicked, this, &TemplateListWidget::showHelp); } - - // Template set layout + // Template sets layout auto* set_change_layout = new SegmentedButtonLayout(); new_template_set_button = createToolButton(QIcon(QString::fromLatin1(":/images/template-set-add.png")), tr("Add")); set_change_layout->addWidget(new_template_set_button); @@ -777,6 +776,15 @@ void TemplateListWidget::deleteTemplateSet() template_table->viewport()->update(); } +void TemplateListWidget::switchTemplateSet() +{ + auto template_set = main_view.getActiveVisibilityIndex() + 1; + if (template_set >= main_view.getNumberOfVisibilitySets()) + template_set = 0; + + onGroupButtonClicked(template_set); +} + void TemplateListWidget::onGroupButtonClicked(int val) { if (main_view.getActiveVisibilityIndex() != val) diff --git a/src/gui/widgets/template_list_widget.h b/src/gui/widgets/template_list_widget.h index beed54f4ce..458dec22d5 100644 --- a/src/gui/widgets/template_list_widget.h +++ b/src/gui/widgets/template_list_widget.h @@ -78,6 +78,9 @@ class TemplateListWidget : public QWidget void closePositionDockWidget(); void closeClicked(); +public slots: + void switchTemplateSet(); + protected: TemplateTableModel* model(); const TemplateTableModel* model() const { return static_cast(const_cast(this)->model()); }