TechDraw: Return text fields directly as childs of QGISVGTemplate

As the title says. I've noticed during reproducing of #18921, that
after in `PagePrinter::renderPage` we call `setTemplateMarkers`
twice, which results in deleting `childItems` allocated memory
(in `setTemplateMarkers`->`setMarkers`->`updateView`->`clearClickHandles`),
and then we are calling `setTemplateMarkers` (also in `PagePrinter::renderPage`) second time,
accessing `textFields` in `setMarkers` method, which still contain hanging pointers
from the previous deallocation. This results in segfaults as we iterate through `textFields`.

So, instead of keeping sychronization between childs of QGISVGTemplate
and textFields vector - this patch removes this variable at all and uses
childs directly to return text fields.
This commit is contained in:
tetektoza
2025-04-19 23:45:50 +02:00
committed by Kacper Donat
parent b31a6d8b69
commit bbcdb77003
3 changed files with 23 additions and 10 deletions

View File

@@ -204,17 +204,30 @@ void QGISVGTemplate::updateView(bool update)
draw();
}
std::vector<TemplateTextField*> QGISVGTemplate::getTextFields()
{
constexpr int TemplateTextFieldType {QGraphicsItem::UserType + 160};
std::vector<TemplateTextField*> result;
result.reserve(childItems().size());
QList<QGraphicsItem*> templateChildren = childItems();
for (auto& child : templateChildren) {
if (child->type() == TemplateTextFieldType) {
result.push_back(dynamic_cast<TemplateTextField*>(child));
}
}
return result;
}
void QGISVGTemplate::clearClickHandles()
{
prepareGeometryChange();
constexpr int TemplateTextFieldType{QGraphicsItem::UserType + 160};
auto templateChildren = childItems();
for (auto& child : templateChildren) {
if (child->type() == TemplateTextFieldType) {
child->hide();
scene()->removeItem(child);
delete child;
}
std::vector<TemplateTextField*> textFields = getTextFields();
for (auto& textField : textFields) {
textField->hide();
scene()->removeItem(textField);
delete textField;
}
}
@@ -317,7 +330,6 @@ void QGISVGTemplate::createClickHandles()
item->setZValue(ZVALUE::SVGTEMPLATE + 1);
addToGroup(item);
textFields.push_back(item);
}
}

View File

@@ -60,6 +60,7 @@ public:
void updateView(bool update = false) override;
TechDraw::DrawSVGTemplate* getSVGTemplate();
std::vector<TemplateTextField*> getTextFields() override;
protected:
void openFile(const QFile& file);

View File

@@ -60,7 +60,7 @@ public:
inline qreal getY() { return y() * -1; }
virtual void updateView(bool update = false);
std::vector<TemplateTextField *> getTextFields() { return textFields; };
virtual std::vector<TemplateTextField *> getTextFields() { return textFields; };
virtual void draw() = 0;