From 296cbd848280ef633cc4991ba7a971cf4ffee635 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 13 May 2022 18:23:27 +0200 Subject: [PATCH] Spreadsheet: fix possible crash in SheetModel::setData See also: https://forum.freecadweb.org/viewtopic.php?f=8&t=68529 --- src/Mod/Spreadsheet/Gui/SheetModel.cpp | 54 ++++++++++++++------------ src/Mod/Spreadsheet/Gui/SheetModel.h | 3 ++ 2 files changed, 33 insertions(+), 24 deletions(-) diff --git a/src/Mod/Spreadsheet/Gui/SheetModel.cpp b/src/Mod/Spreadsheet/Gui/SheetModel.cpp index 38fe3bc07a..7caa79948f 100644 --- a/src/Mod/Spreadsheet/Gui/SheetModel.cpp +++ b/src/Mod/Spreadsheet/Gui/SheetModel.cpp @@ -464,6 +464,25 @@ QVariant SheetModel::headerData(int section, Qt::Orientation orientation, int ro return QVariant(); } +void SheetModel::setCellData(QModelIndex index, QString str) +{ + try { + CellAddress address(index.row(), index.column()); + Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Edit cell")); + // Because of possible complication of recursively escaped + // characters, let's take a shortcut and bypass the command + // interface for now. + + sheet->setContent(address, str.toUtf8().constData()); + Gui::Command::commitCommand(); + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()"); + } + catch (const Base::Exception& e) { + e.ReportException(); + Gui::Command::abortCommand(); + } +} + bool SheetModel::setData(const QModelIndex & index, const QVariant & value, int role) { if (role == Qt::DisplayRole) { @@ -472,32 +491,19 @@ bool SheetModel::setData(const QModelIndex & index, const QVariant & value, int else if (role == Qt::EditRole) { CellAddress address(index.row(), index.column()); - try { - QString str = value.toString(); + QString str = value.toString(); - // Check to see if this is already the value in the cell, and skip the update if so - auto cell = sheet->getCell(address); - if (cell) { - std::string oldContent; - cell->getStringContent(oldContent); - if (str == QString::fromStdString(oldContent)) - return true; - } - - Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Edit cell")); - // Because of possible complication of recursively escaped - // characters, let's take a shortcut and bypass the command - // interface for now. - - sheet->setContent(address, str.toUtf8().constData()); - Gui::Command::commitCommand(); - Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()"); - } - catch (const Base::Exception& e) { - e.ReportException(); - Gui::Command::abortCommand(); - return false; + // Check to see if this is already the value in the cell, and skip the update if so + auto cell = sheet->getCell(address); + if (cell) { + std::string oldContent; + cell->getStringContent(oldContent); + if (str == QString::fromStdString(oldContent)) + return true; } + + QMetaObject::invokeMethod(this, "setCellData", Qt::QueuedConnection, + Q_ARG(QModelIndex, index), Q_ARG(QString, str)); } return true; } diff --git a/src/Mod/Spreadsheet/Gui/SheetModel.h b/src/Mod/Spreadsheet/Gui/SheetModel.h index e52f20fa39..f30ab5c8e5 100644 --- a/src/Mod/Spreadsheet/Gui/SheetModel.h +++ b/src/Mod/Spreadsheet/Gui/SheetModel.h @@ -48,6 +48,9 @@ public: bool setData(const QModelIndex &index, const QVariant &value, int role); Qt::ItemFlags flags(const QModelIndex &) const; +private Q_SLOTS: + void setCellData(QModelIndex index, QString str); + private: void cellUpdated(App::CellAddress address); void rangeUpdated(const App::Range &range);