aboutsummaryrefslogtreecommitdiffstats
path: root/examples/quickcontrols/spreadsheets/Spreadsheets/spreadformula.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'examples/quickcontrols/spreadsheets/Spreadsheets/spreadformula.cpp')
-rw-r--r--examples/quickcontrols/spreadsheets/Spreadsheets/spreadformula.cpp74
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;
+}