mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-08-13 10:04:13 +02:00
Merge pull request #693 from ispyisail/fix/color-editor-crash-bug323
Fix crash changing dynamic text color and confirming with Enter (bugtracker #323) Works like charm: - color is updated immediately - no additional errors or warnings - no crash anymore!
This commit is contained in:
@@ -36,6 +36,7 @@
|
||||
#include <QHash>
|
||||
#include <QModelIndex>
|
||||
#include <QStandardItem>
|
||||
#include <QTimer>
|
||||
#include <QUndoCommand>
|
||||
|
||||
static int src_txt_row = 0;
|
||||
@@ -1595,6 +1596,15 @@ DynamicTextItemDelegate::DynamicTextItemDelegate(QObject *parent) :
|
||||
QStyledItemDelegate(parent)
|
||||
{}
|
||||
|
||||
void DynamicTextItemDelegate::commitAndCloseDeferred(QWidget *editor) const
|
||||
{
|
||||
auto *self = const_cast<DynamicTextItemDelegate *>(this);
|
||||
QTimer::singleShot(0, self, [self, editor]() {
|
||||
emit self->commitData(editor);
|
||||
emit self->closeEditor(editor);
|
||||
});
|
||||
}
|
||||
|
||||
QWidget *DynamicTextItemDelegate::createEditor(
|
||||
QWidget *parent,
|
||||
const QStyleOptionViewItem &option,
|
||||
@@ -1682,13 +1692,43 @@ QWidget *DynamicTextItemDelegate::createEditor(
|
||||
w->setProperty("ok", ok);
|
||||
}
|
||||
w->setObjectName("font_dialog");
|
||||
commitAndCloseDeferred(w);
|
||||
return w;
|
||||
}
|
||||
case DynamicElementTextModel::color:
|
||||
{
|
||||
QColorDialog *cd = new QColorDialog(index.data(Qt::EditRole).value<QColor>(), parent);
|
||||
cd->setObjectName("color_dialog");
|
||||
return cd;
|
||||
/* Like the font case above: run the dialog synchronously via
|
||||
* its static convenience function and stash the result on a
|
||||
* plain placeholder widget, rather than handing back the
|
||||
* QColorDialog itself as the item view's "editor".
|
||||
*
|
||||
* The item view's own Enter/Escape handling (the base
|
||||
* QStyledItemDelegate::eventFilter(), since "color_dialog"
|
||||
* isn't one of the objectNames special-cased in this
|
||||
* delegate's own eventFilter() above) treats whatever
|
||||
* createEditor() returned as a small inline editor it
|
||||
* commits and destroys directly on a key press. A QColorDialog
|
||||
* is not that: on Windows it can hand off to the native
|
||||
* color picker, whose own accept/close path then races the
|
||||
* view's -- pressing Enter fired both, one tearing down an
|
||||
* object the other was still using (case #323 on the bug
|
||||
* tracker: "QObject::installEventFilter(): Cannot filter
|
||||
* events for objects in a different thread" immediately
|
||||
* followed by a segfault; clicking the dialog's own OK
|
||||
* button with the mouse didn't reach the view's key
|
||||
* handling, so it didn't crash). Resolving the dialog
|
||||
* before returning removes the second, competing teardown
|
||||
* path entirely. */
|
||||
QColor color = QColorDialog::getColor(index.data(Qt::EditRole).value<QColor>(), parent);
|
||||
QWidget *w = new QWidget(parent);
|
||||
if (color.isValid())
|
||||
{
|
||||
w->setProperty("color", color);
|
||||
w->setProperty("ok", true);
|
||||
}
|
||||
w->setObjectName("color_dialog");
|
||||
commitAndCloseDeferred(w);
|
||||
return w;
|
||||
}
|
||||
case DynamicElementTextModel::pos:
|
||||
{
|
||||
@@ -1788,11 +1828,11 @@ void DynamicTextItemDelegate::setModelData(
|
||||
{
|
||||
if(QStandardItem *qsi = qsim->itemFromIndex(index))
|
||||
{
|
||||
QColorDialog *cd = static_cast<QColorDialog *> (editor);
|
||||
if (cd->result() == QDialog::Accepted)
|
||||
if (editor->property("ok").toBool() == true)
|
||||
{
|
||||
qsi->setData(cd->selectedColor(), Qt::EditRole);
|
||||
qsi->setData(cd->selectedColor(), Qt::ForegroundRole);
|
||||
QColor color = editor->property("color").value<QColor>();
|
||||
qsi->setData(color, Qt::EditRole);
|
||||
qsi->setData(color, Qt::ForegroundRole);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -155,6 +155,21 @@ class DynamicTextItemDelegate : public QStyledItemDelegate
|
||||
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user