From 7ef2e3c7ecc0595bbb87654c5ec42c70d9ced43a Mon Sep 17 00:00:00 2001 From: Suthiro Date: Sun, 14 Mar 2021 23:38:08 +0700 Subject: [PATCH] Bugfix for SF#131: matrices processing are now fast upon undoing a formula. --- libscidavis/src/Matrix.cpp | 7 +- .../src/future/matrix/future_Matrix.cpp | 66 +++++++++++++++++++ libscidavis/src/future/matrix/future_Matrix.h | 13 ++++ .../src/future/matrix/matrixcommands.cpp | 25 +++++++ .../src/future/matrix/matrixcommands.h | 36 ++++++++++ 5 files changed, 146 insertions(+), 1 deletion(-) diff --git a/libscidavis/src/Matrix.cpp b/libscidavis/src/Matrix.cpp index eed20ede9..0ab974d31 100644 --- a/libscidavis/src/Matrix.cpp +++ b/libscidavis/src/Matrix.cpp @@ -413,6 +413,10 @@ bool Matrix::recalculate() saveCellsToMemory(); double dx = fabs(xEnd() - xStart()) / (double)(numRows() - 1); double dy = fabs(yEnd() - yStart()) / (double)(numCols() - 1); + std::pair invalidValue(std::numeric_limits::quiet_NaN(), false); + std::vector>> calculatedValues( + endRow - startRow + 1, + std::vector>(endCol - startCol + 1, invalidValue)); for (int row = startRow; row <= endRow; row++) for (int col = startCol; col <= endCol; col++) { if (!isCellSelected(row, col)) @@ -431,8 +435,9 @@ bool Matrix::recalculate() QApplication::restoreOverrideCursor(); return false; } - setCell(row, col, ret.toDouble()); + calculatedValues[row - startRow][col - startCol] = std::pair(ret.toDouble(), true); } + d_future_matrix->setCells(startRow, startCol, calculatedValues); forgetSavedCells(); blockSignals(false); diff --git a/libscidavis/src/future/matrix/future_Matrix.cpp b/libscidavis/src/future/matrix/future_Matrix.cpp index f62a614fc..717ffcbce 100644 --- a/libscidavis/src/future/matrix/future_Matrix.cpp +++ b/libscidavis/src/future/matrix/future_Matrix.cpp @@ -1478,6 +1478,30 @@ void Matrix::transpose() RESET_CURSOR; } +std::vector>> +Matrix::getCells(const int startRow, const int endRow, const int startCol, const int endCol) const +{ + return d_matrix_private->getCells(startRow, endRow, startCol, endCol); +} + +void Matrix::setCells( + const int startRow, const int startCol, + const std::vector>> &values) +{ + WAIT_CURSOR; + auto lastRow = startRow + values.size() - 1; + auto lastCol = startCol + + std::max_element(values.cbegin(), values.cend(), + [](const std::vector> &a, + const std::vector> &b) { + return a.size() > b.size(); + }) + ->size() - 1; + exec(new MatrixSetCellsCmd(d_matrix_private, startRow, lastRow, startCol, lastCol, values)); + RESET_CURSOR; + +} + void Matrix::mirrorHorizontally() { WAIT_CURSOR; @@ -1781,4 +1805,46 @@ void Matrix::Private::setFormula(const QString &formula) emit d_owner->formulaChanged(); } +std::vector>> Matrix::Private::getCells(const int startRow, + const int endRow, + const int startCol, + const int endCol) const +{ + if (startRow > endRow || startCol > endCol || startCol < 0 || endCol > columnCount() + || startRow < 0 || endRow > rowCount()) + return std::vector>>(); + + std::pair invalidValue(std::numeric_limits::quiet_NaN(), false); + std::vector>> values( + endRow - startRow + 1, + std::vector>(endCol - startCol + 1, invalidValue)); + for (int row = startRow; row <= endRow; row++) + for (int col = startCol; col <= endCol; col++) + values[row - startRow][col - startCol] = std::pair(cell(row, col), true); + return values; +} + +void Matrix::Private::setCells(const int startRow, const int startCol, + const std::vector>> &values) +{ + blockChangeSignals(true); + for (size_t ii = 0u; values.size() > ii; ++ii) { + const auto &column = values[ii]; + for (size_t jj = 0u; column.size() > jj; ++jj) { + const auto &pair = column[jj]; + if (!pair.second) + continue; + setCell(startRow + ii, startCol + jj, pair.first); + } + } + blockChangeSignals(false); + auto endRow = startRow + values.size() - 1; + auto endCol = startCol + std::max_element( + values.cbegin(), values.cend(), + [](const std::vector> &a, + const std::vector> &b) + { return a.size() > b.size();})->size() - 1; + emit d_owner->dataChanged(startRow, startCol, endRow, endCol); +} + } // namespace diff --git a/libscidavis/src/future/matrix/future_Matrix.h b/libscidavis/src/future/matrix/future_Matrix.h index 1b87b8bec..6a35e56f0 100644 --- a/libscidavis/src/future/matrix/future_Matrix.h +++ b/libscidavis/src/future/matrix/future_Matrix.h @@ -223,6 +223,12 @@ public slots: //! Clear the whole matrix (i.e. set all cells to 0.0) void clear(); void transpose(); + + std::vector>> + getCells(const int startRow, const int endRow, const int startCol, const int endCol) const; + + void setCells(const int startRow, const int startCol, + const std::vector>> &values); void mirrorVertically(); void mirrorHorizontally(); @@ -438,6 +444,13 @@ class Matrix::Private double yEnd() const; QString formula() const; void setFormula(const QString &formula); + + std::vector>> + getCells(const int startRow, const int endRow, const int startCol, const int endCol) const; + + void setCells(const int startRow, const int startCol, + const std::vector>> &values); + void setXStart(double x); void setXEnd(double x); void setYStart(double y); diff --git a/libscidavis/src/future/matrix/matrixcommands.cpp b/libscidavis/src/future/matrix/matrixcommands.cpp index c6f3f6c95..56a41799b 100644 --- a/libscidavis/src/future/matrix/matrixcommands.cpp +++ b/libscidavis/src/future/matrix/matrixcommands.cpp @@ -532,3 +532,28 @@ void MatrixMirrorVerticallyCmd::undo() /////////////////////////////////////////////////////////////////////////// // end of class MatrixMirrorVerticallyCmd /////////////////////////////////////////////////////////////////////////// + +MatrixSetCellsCmd::MatrixSetCellsCmd( + future::Matrix::Private *private_obj, int first_row, int last_row, int first_column, + int last_column, const std::vector>> &values, + QUndoCommand *parent) + : QUndoCommand(parent), d_private_obj{ private_obj }, + d_first_row{ first_row }, + d_last_row{ last_row }, + d_first_column{ first_column }, + d_last_column{ last_column }, + d_values{ values }, + d_old_values{ private_obj->getCells(first_row, last_row, first_column, last_column) } +{ + setText(QObject::tr("%1: set values for multiple cells").arg(d_private_obj->name())); +} + +void MatrixSetCellsCmd::redo() +{ + d_private_obj->setCells(d_first_row, d_first_column, d_values); +} + +void MatrixSetCellsCmd::undo() +{ + d_private_obj->setCells(d_first_row, d_first_column, d_old_values); +} diff --git a/libscidavis/src/future/matrix/matrixcommands.h b/libscidavis/src/future/matrix/matrixcommands.h index 9dd03bd01..d0437f86b 100644 --- a/libscidavis/src/future/matrix/matrixcommands.h +++ b/libscidavis/src/future/matrix/matrixcommands.h @@ -386,6 +386,42 @@ class MatrixSetRowCellsCmd : public QUndoCommand // end of class MatrixSetRowCellsCmd /////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////// +// class MatrixSetCellsCmd +/////////////////////////////////////////////////////////////////////////// +//! Set cell values for multiple cells at once +class MatrixSetCellsCmd : public QUndoCommand +{ +public: + MatrixSetCellsCmd(future::Matrix::Private *private_obj, int first_row, int last_row, + int first_column, int last_column, + const std::vector>> &values, + QUndoCommand *parent = 0); + + void redo() override; + void undo() override; + +private: + //! The private object to modify + future::Matrix::Private * const d_private_obj; + //! The index of the first row + const int d_first_row; + //! The index of the last row + const int d_last_row; + //! The index of the first column + const int d_first_column; + //! The index of the last column + const int d_last_column; + //! New cell values + const std::vector>> d_values; + //! Backup of the changed values + const std::vector>> d_old_values; +}; + +/////////////////////////////////////////////////////////////////////////// +// end of class MatrixSetCellsCmd +/////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// // class MatrixTransposeCmd ///////////////////////////////////////////////////////////////////////////