From 7af56c6972bb6b788e83f14582e99116d7460a09 Mon Sep 17 00:00:00 2001 From: Matthias Kuehlewein Date: Wed, 2 Jul 2025 17:29:18 +0200 Subject: [PATCH 1/2] Templates: Add custom names Add the possibility to enter a custom name for a template that is shown instead of the filename. Allow to select whether the filename or custom name is shown. Save and load custom file names and selection preferences. Closes GH-1060 (Templates should be able to be named independently of file name). --- src/gui/widgets/template_list_widget.cpp | 44 +++++++++++++++++++++++- src/gui/widgets/template_list_widget.h | 7 ++-- src/templates/template.cpp | 10 ++++++ src/templates/template.h | 16 +++++++-- src/templates/template_table_model.cpp | 6 ++-- 5 files changed, 75 insertions(+), 8 deletions(-) diff --git a/src/gui/widgets/template_list_widget.cpp b/src/gui/widgets/template_list_widget.cpp index 5b562c46bd..c17764f5e9 100644 --- a/src/gui/widgets/template_list_widget.cpp +++ b/src/gui/widgets/template_list_widget.cpp @@ -1,6 +1,6 @@ /* * Copyright 2012, 2013 Thomas Schöps - * Copyright 2012-2020 Kai Pastor + * Copyright 2012-2020, 2025 Kai Pastor * * This file is part of OpenOrienteering. * @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -56,6 +57,7 @@ #include #include #include +#include #include #include #include @@ -227,6 +229,9 @@ TemplateListWidget::TemplateListWidget(Map& map, MapView& main_view, MapEditorCo auto header_check_size = geometry.size(); if (header_check_size.isValid()) template_model->setCheckBoxDecorator(makeCheckBoxDecorator(style(), header_check_size)); + + template_table->setContextMenuPolicy(Qt::CustomContextMenu); + connect(template_table, &QTableView::customContextMenuRequested, this, &TemplateListWidget::showContextMenu); } all_templates_layout = new QVBoxLayout(); @@ -1042,5 +1047,42 @@ void TemplateListWidget::showOpacitySlider(int row) dialog.exec(); } +void TemplateListWidget::showContextMenu(const QPoint& clicked_pos) +{ + const auto index = template_table->indexAt(clicked_pos); + const auto row = index.row(); + const auto pos = posFromRow(qMax(0, row)); + if (row >= 0 && pos >= 0 && index.column() == TemplateTableModel::nameColumn()) + { + auto* templ = map.getTemplate(pos); + if (!templ) + return; + auto* enter_customname_action = new QAction(tr("Enter custom name"), template_table); + connect(enter_customname_action, &QAction::triggered, this, [this, templ]() { + bool ok; + const auto previous_customname = templ->getTemplateCustomname(); + const auto text = QInputDialog::getText(this, tr("Enter custom name"), tr("Custom name:"), QLineEdit::Normal, previous_customname, &ok); + if (ok) + { + templ->setTemplateCustomname(text); + templ->setCustomnamePreference(!text.isEmpty()); + if (previous_customname != text) + map.setTemplatesDirty(); // only mark as dirty if custom name has changed + } + }); + QMenu context_menu(this); + context_menu.addAction(enter_customname_action); + if (!templ->getTemplateCustomname().isEmpty()) + { + auto* toggle_show_name_action = new QAction(templ->getCustomnamePreference() ? tr("Show filename") : tr("Show custom name"), template_table); + connect(toggle_show_name_action, &QAction::triggered, this, [templ]() { + templ->setCustomnamePreference(!templ->getCustomnamePreference()); // don't mark as dirty + }); + context_menu.addAction(toggle_show_name_action); + } + context_menu.exec(mapToGlobal(clicked_pos)); + } +} + } // namespace OpenOrienteering diff --git a/src/gui/widgets/template_list_widget.h b/src/gui/widgets/template_list_widget.h index 85505d44d6..6501995cc9 100644 --- a/src/gui/widgets/template_list_widget.h +++ b/src/gui/widgets/template_list_widget.h @@ -1,6 +1,6 @@ /* * Copyright 2012, 2013 Thomas Schöps - * Copyright 2020 Kai Pastor + * Copyright 2020, 2025 Kai Pastor * * This file is part of OpenOrienteering. * @@ -36,6 +36,7 @@ class QBoxLayout; class QCheckBox; class QEvent; class QModelIndex; +class QPoint; class QTableView; class QToolButton; class QVariant; @@ -142,6 +143,8 @@ class TemplateListWidget : public QWidget void showOpacitySlider(int row); + void showContextMenu(const QPoint &pos); + private: Map& map; MapView& main_view; @@ -179,4 +182,4 @@ class TemplateListWidget : public QWidget } // namespace OpenOrienteering -#endif +#endif // OPENORIENTEERING_TEMPLATE_LIST_WIDGET_H diff --git a/src/templates/template.cpp b/src/templates/template.cpp index cbb74f7766..69d910fc70 100644 --- a/src/templates/template.cpp +++ b/src/templates/template.cpp @@ -290,6 +290,11 @@ void Template::saveTemplateConfiguration(QXmlStreamWriter& xml, bool open, const primary_path = relative_path; xml.writeAttribute(QString::fromLatin1("path"), primary_path); xml.writeAttribute(QString::fromLatin1("relpath"), relative_path); + if (!template_custom_name.isEmpty()) + { + xml.writeAttribute(QString::fromLatin1("customname"), getTemplateCustomname()); + xml.writeAttribute(QString::fromLatin1("custompref"), QString::fromLatin1(getCustomnamePreference() ? "true" : "false")); + } if (template_group) { @@ -349,6 +354,11 @@ std::unique_ptr