mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-08-13 18:14:13 +02:00
b0b5345e15
plc-user on PR #693: the crash is fixed, but the color/font field and
the on-diagram text no longer update until you leave the properties
list and click in the diagram -- previously it updated as soon as you
clicked OK.
That's a side effect of the crash fix itself. The old, crashing code
returned a *live* QColorDialog as the item view's editor; clicking its
OK button called accept()/hide() on it, and hiding the active editor
happens to trip the base delegate's own focus-lost commit path -- so
the value applied immediately, racily, as a side effect of the same
mechanism that crashed on Enter. The fix (commit 4bd9b6b21) replaced
that with running the dialog synchronously inside createEditor() and
returning an inert placeholder with the result stashed in a property.
Correct for the crash, but it also removed that accidental commit
trigger: the placeholder never had focus to lose, so nothing tells
the view to read the value back until some unrelated interaction
(clicking away) incidentally triggers it.
Fix: explicitly emit commitData()/closeEditor() for the resolved
editor, deferred via QTimer::singleShot(0, ...) since the view only
registers createEditor()'s return value as "the active editor" after
createEditor() itself returns -- emitting synchronously, before
returning, would target a widget the view doesn't know about yet.
Applied to both font and color, since both share the exact same
"resolve synchronously in createEditor(), return an inert
placeholder" shape and thus the exact same gap; font just hadn't been
reported.
Verified with the same standalone harness from the crash fix (real
QTreeView + DynamicTextItemDelegate + QAbstractItemView::edit()),
this time deliberately *not* sending the synthetic Enter keypress the
crash-fix verification needed: clicks the dialog's real OK button,
lets the event loop run, and confirms the picked color lands in the
model on its own. Also reconfirmed the crash fix itself still holds
(clean exit, no synthetic-Enter needed either way now) and did a full
Release build (504/504) with no new warnings.
176 lines
5.5 KiB
C++
176 lines
5.5 KiB
C++
/*
|
|
Copyright 2006-2026 The QElectroTech Team
|
|
This file is part of QElectroTech.
|
|
|
|
QElectroTech is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
QElectroTech is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
#ifndef DYNAMICELEMENTTEXTMODEL_H
|
|
#define DYNAMICELEMENTTEXTMODEL_H
|
|
|
|
#include "../qetgraphicsitem/dynamicelementtextitem.h"
|
|
|
|
#include <QHash>
|
|
#include <QStandardItemModel>
|
|
#include <qstyleditemdelegate.h>
|
|
|
|
class QUndoCommand;
|
|
class ElementTextItemGroup;
|
|
class Element;
|
|
|
|
/**
|
|
@brief The DynamicElementTextModel class
|
|
A model to use with QtView.
|
|
This model display and can edit the value of dynamic text of an element.
|
|
Set the delegate DynamicTextItemDelegate as delegate of this model.
|
|
*/
|
|
class DynamicElementTextModel : public QStandardItemModel
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
enum ValueType {
|
|
textFrom =1,
|
|
userText,
|
|
infoText,
|
|
compositeText,
|
|
txtAlignment,
|
|
size,
|
|
font,
|
|
color,
|
|
pos,
|
|
frame,
|
|
rotation,
|
|
keepVisualRotation,
|
|
textWidth,
|
|
grpAlignment,
|
|
grpPos,
|
|
grpRotation,
|
|
grpVAdjust,
|
|
grpName,
|
|
grpHoldBottom,
|
|
grpFrame
|
|
};
|
|
|
|
DynamicElementTextModel(Element *element, QObject *parent = nullptr);
|
|
~DynamicElementTextModel() override;
|
|
|
|
bool indexIsInGroup(const QModelIndex &index) const;
|
|
DynamicElementTextItem *textFromIndex(const QModelIndex &index) const;
|
|
DynamicElementTextItem *textFromItem(QStandardItem *item) const;
|
|
QModelIndex indexFromText(DynamicElementTextItem *text) const;
|
|
QUndoCommand *undoForEditedText(
|
|
DynamicElementTextItem *deti,
|
|
QUndoCommand *parent_undo = nullptr) const;
|
|
QUndoCommand *undoForEditedGroup(
|
|
ElementTextItemGroup *group,
|
|
QUndoCommand *parent_undo = nullptr) const;
|
|
|
|
ElementTextItemGroup *groupFromIndex(const QModelIndex &index) const;
|
|
ElementTextItemGroup *groupFromItem(QStandardItem *item) const;
|
|
QModelIndex indexFromGroup(ElementTextItemGroup *group) const;
|
|
bool indexIsText(const QModelIndex &index) const;
|
|
bool indexIsGroup(const QModelIndex &index) const;
|
|
|
|
bool canDropMimeData(
|
|
const QMimeData *data,
|
|
Qt::DropAction action,
|
|
int row,
|
|
int column,
|
|
const QModelIndex &parent) const override;
|
|
bool dropMimeData(
|
|
const QMimeData *data,
|
|
Qt::DropAction action,
|
|
int row,
|
|
int column,
|
|
const QModelIndex &parent) override;
|
|
QMimeData *mimeData(const QModelIndexList &indexes) const override;
|
|
QStringList mimeTypes() const override;
|
|
|
|
signals:
|
|
void dataChanged();
|
|
|
|
private:
|
|
QList<QStandardItem *> itemsForText(DynamicElementTextItem *deti);
|
|
void addText(DynamicElementTextItem *deti);
|
|
void removeText(DynamicElementTextItem *deti);
|
|
void addGroup(ElementTextItemGroup *group);
|
|
void removeGroup(ElementTextItemGroup *group);
|
|
void addTextToGroup(
|
|
DynamicElementTextItem *deti,
|
|
ElementTextItemGroup *group);
|
|
void removeTextFromGroup(DynamicElementTextItem *deti,
|
|
ElementTextItemGroup *group);
|
|
void enableSourceText(
|
|
DynamicElementTextItem *deti,
|
|
DynamicElementTextItem::TextFrom tf );
|
|
void enableGroupRotationAndPos(ElementTextItemGroup *group);
|
|
void itemDataChanged(QStandardItem *qsi);
|
|
void setConnection(DynamicElementTextItem *deti, bool set);
|
|
void setConnection(ElementTextItemGroup *group, bool set);
|
|
void updateDataFromText(DynamicElementTextItem *deti,
|
|
DynamicElementTextModel::ValueType type);
|
|
void updateDataFromGroup(ElementTextItemGroup *group,
|
|
DynamicElementTextModel::ValueType type);
|
|
|
|
private:
|
|
QPointer<Element> m_element;
|
|
QHash <DynamicElementTextItem *, QStandardItem *> m_texts_list;
|
|
QHash <ElementTextItemGroup *, QStandardItem *> m_groups_list;
|
|
QHash <DynamicElementTextItem *,
|
|
QList<QMetaObject::Connection>> m_hash_text_connect;
|
|
QHash <ElementTextItemGroup *,
|
|
QList<QMetaObject::Connection>> m_hash_group_connect;
|
|
bool m_block_dataChanged = false;
|
|
};
|
|
|
|
class DynamicTextItemDelegate : public QStyledItemDelegate
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
DynamicTextItemDelegate(QObject *parent = Q_NULLPTR);
|
|
|
|
QWidget *createEditor(
|
|
QWidget *parent,
|
|
const QStyleOptionViewItem &option,
|
|
const QModelIndex &index) const override;
|
|
void setModelData(
|
|
QWidget *editor,
|
|
QAbstractItemModel *model,
|
|
const QModelIndex &index) const override;
|
|
|
|
protected:
|
|
bool eventFilter(QObject *object, QEvent *event) override;
|
|
|
|
private:
|
|
QStringList availableInfo(DynamicElementTextItem *deti) const;
|
|
/**
|
|
@brief commitAndCloseDeferred
|
|
Schedule commitData()/closeEditor() for @a editor on the next
|
|
event loop iteration. For editors resolved synchronously inside
|
|
createEditor() (font/color, both run their picker dialog before
|
|
returning) there is no user interaction left to drive the base
|
|
QStyledItemDelegate::eventFilter()'s usual Enter/focus-out commit
|
|
path, so without this the value sits picked-but-uncommitted
|
|
until something unrelated (e.g. clicking elsewhere) happens to
|
|
trigger it. Deferred rather than called immediately: the view
|
|
only registers the widget createEditor() returns as "the active
|
|
editor" *after* createEditor() itself returns, so emitting here
|
|
would target an editor the view doesn't know about yet.
|
|
*/
|
|
void commitAndCloseDeferred(QWidget *editor) const;
|
|
};
|
|
|
|
#endif // DYNAMICELEMENTTEXTMODEL_H
|