diff options
Diffstat (limited to 'examples/quickcontrols/spreadsheets/Spreadsheets/spreadformula.cpp')
-rw-r--r-- | examples/quickcontrols/spreadsheets/Spreadsheets/spreadformula.cpp | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/examples/quickcontrols/spreadsheets/Spreadsheets/spreadformula.cpp b/examples/quickcontrols/spreadsheets/Spreadsheets/spreadformula.cpp new file mode 100644 index 0000000000..87a961f40c --- /dev/null +++ b/examples/quickcontrols/spreadsheets/Spreadsheets/spreadformula.cpp @@ -0,0 +1,74 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "spreadformula.h" +#include "datamodel.h" +#include "spreadkey.h" +#include "spreadrole.h" +#include "spreadmodel.h" + +bool Formula::includesLoop(SpreadModel *model, const DataModel *dataModel, QSet<int> *history) const +{ + if (m_operator == Operator::Invalid) + return false; + + if (history == nullptr) { + QSet<int> history; + return includesLoop(model, dataModel, &history); + } + + if (m_operator == Operator::Sum) { + SpreadKey top_left = dataModel->getKey(m_cellIds.first); + SpreadKey bottom_right = dataModel->getKey(m_cellIds.second); + if (bottom_right.first < top_left.first) + std::swap(top_left.first, bottom_right.first); + if (bottom_right.second < top_left.second) + std::swap(top_left.second, bottom_right.second); + for (int row = top_left.first; row <= bottom_right.first; ++row) { + for (int column = top_left.second; column <= bottom_right.second; ++column) { + const int id = dataModel->getId(SpreadKey{row, column}); + if (history->find(id) != history->end()) + return true; + const QString edit_text = dataModel->getData(id, spread::Role::Edit).toString(); + const Formula formula = model->parseFormulaString(edit_text); + if (!formula.isValid()) + continue; + auto it = history->insert(id); + if (formula.includesLoop(model, dataModel, history)) + return true; + auto cit = spread::make_const(*history, it); + history->erase(cit); + } + } + } else { + const int id_1 = m_cellIds.first; + if (history->find(id_1) != history->end()) + return true; + const QString edit_text = dataModel->getData(id_1, spread::Role::Edit).toString(); + const Formula formula = model->parseFormulaString(edit_text); + if (!formula.isValid()) + return false; + auto it = history->insert(id_1); + if (formula.includesLoop(model, dataModel, history)) + return true; + auto cit = spread::make_const(*history, it); + history->erase(cit); + + if (m_operator != Operator::Assign) { + const int id_2 = m_cellIds.second; + if (history->find(id_2) != history->end()) + return true; + const QString edit_text = dataModel->getData(id_2, spread::Role::Edit).toString(); + const Formula formula = model->parseFormulaString(edit_text); + if (!formula.isValid()) + return false; + auto it = history->insert(id_2); + if (formula.includesLoop(model, dataModel, history)) + return true; + auto cit = spread::make_const(*history, it); + history->erase(cit); + } + } + + return false; +} |