diff --git a/sheets/Cluster.cpp b/sheets/Cluster.cpp index 8d8f91ea2f0..3f383b72cee 100644 --- a/sheets/Cluster.cpp +++ b/sheets/Cluster.cpp @@ -1,1347 +1,341 @@ /* This file is part of the KDE project Copyright (C) 2005 Tomas Mecir Copyright (C) 2000 Torben Weis This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ // Local #include "Cluster.h" #include #include "SheetsDebug.h" #include "Cell.h" #include "RowColumnFormat.h" using namespace Calligra::Sheets; -#if 0 -/**************************************************** - * - * Cluster - * - ****************************************************/ - -/* Generate a matrix LEVEL1 with the size LEVEL1*LEVEL1 */ -Cluster::Cluster() - : m_first(0), m_autoDelete(false), m_biggestX(0), m_biggestY(0) -{ - m_cluster = (Cell***)malloc(CALLIGRA_SHEETS_CLUSTER_LEVEL1 * CALLIGRA_SHEETS_CLUSTER_LEVEL1 * sizeof(Cell**)); - - for (int x = 0; x < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++x) - for (int y = 0; y < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++y) - m_cluster[ y * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + x ] = 0; -} - -/* Delete the matrix LEVEL1 and all existing LEVEL2 matrizes */ -Cluster::~Cluster() -{ -// Can't we use clear(), to remove double code - Philipp? - for (int x = 0; x < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++x) - for (int y = 0; y < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++y) { - Cell** cl = m_cluster[ y * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + x ]; - if (cl) { - free(cl); - m_cluster[ y * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + x ] = 0; - } - } - - if (m_autoDelete) { - Cell* cell = m_first; - while (cell) { - Cell* n = cell->nextCell(); - delete cell; - cell = n; - } - } - - free(m_cluster); -} - -void Cluster::clear() -{ - for (int x = 0; x < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++x) - for (int y = 0; y < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++y) { - Cell** cl = m_cluster[ y * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + x ]; - if (cl) { - free(cl); - m_cluster[ y * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + x ] = 0; - } - } - - if (m_autoDelete) { - Cell* cell = m_first; - while (cell) { - Cell* n = cell->nextCell(); - delete cell; - cell = n; - } - } - - m_first = 0; - m_biggestX = m_biggestY = 0; -} - -Cell* Cluster::lookup(int x, int y) const -{ - if (x >= CALLIGRA_SHEETS_CLUSTER_MAX || x < 0 || y >= CALLIGRA_SHEETS_CLUSTER_MAX || y < 0) { - debugSheets << "Cluster::lookup: invalid column or row value (col:" - << x << " | row: " << y << ")" << endl; - return 0; - } - int cx = x / CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int cy = y / CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int dx = x % CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int dy = y % CALLIGRA_SHEETS_CLUSTER_LEVEL2; - - Cell** cl = m_cluster[ cy * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + cx ]; - if (!cl) - return 0; - - return cl[ dy * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + dx ]; -} - -/* Paste a cell in LEVEL2 (it's more paste than insert) */ -void Cluster::insert(Cell* cell, int x, int y) -{ - if (x >= CALLIGRA_SHEETS_CLUSTER_MAX || x < 0 || y >= CALLIGRA_SHEETS_CLUSTER_MAX || y < 0) { - debugSheets << "Cluster::insert: invalid column or row value (col:" - << x << " | row: " << y << ")" << endl; - return; - } - - int cx = x / CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int cy = y / CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int dx = x % CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int dy = y % CALLIGRA_SHEETS_CLUSTER_LEVEL2; - - Cell** cl = m_cluster[ cy * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + cx ]; - if (!cl) { - cl = (Cell**)malloc(CALLIGRA_SHEETS_CLUSTER_LEVEL2 * CALLIGRA_SHEETS_CLUSTER_LEVEL2 * sizeof(Cell*)); - m_cluster[ cy * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + cx ] = cl; - - for (int a = 0; a < CALLIGRA_SHEETS_CLUSTER_LEVEL2; ++a) - for (int b = 0; b < CALLIGRA_SHEETS_CLUSTER_LEVEL2; ++b) - cl[ b * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + a ] = 0; - } - - if (cl[ dy * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + dx ]) - remove(x, y); - - cl[ dy * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + dx ] = cell; - - if (m_first) { - cell->setNextCell(m_first); - m_first->setPreviousCell(cell); - } - m_first = cell; - - if (x > m_biggestX) m_biggestX = x; - if (y > m_biggestY) m_biggestY = y; -} - -/* Removes the cell of a matrix, the matrix itself keeps unchanged */ -void Cluster::remove(int x, int y) -{ - if (x >= CALLIGRA_SHEETS_CLUSTER_MAX || x < 0 || y >= CALLIGRA_SHEETS_CLUSTER_MAX || y < 0) { - debugSheets << "Cluster::remove: invalid column or row value (col:" - << x << " | row: " << y << ")" << endl; - return; - } - - int cx = x / CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int cy = y / CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int dx = x % CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int dy = y % CALLIGRA_SHEETS_CLUSTER_LEVEL2; - - Cell** cl = m_cluster[ cy * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + cx ]; - if (!cl) - return; - - Cell* c = cl[ dy * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + dx ]; - if (!c) - return; - - cl[ dy * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + dx ] = 0; - - if (m_autoDelete) { - if (m_first == c) - m_first = c->nextCell(); - if (c->doesMergeCells()) { - c->mergeCells(c->column(), c->row(), 0, 0); - } - delete c; - } else { - if (m_first == c) - m_first = c->nextCell(); - if (c->previousCell()) - c->previousCell()->setNextCell(c->nextCell()); - if (c->nextCell()) - c->nextCell()->setPreviousCell(c->previousCell()); - c->setNextCell(0); - c->setPreviousCell(0); - } -} - -bool Cluster::insertShiftRight(const QPoint& marker) -{ - bool dummy; - return insertShiftRight(marker, dummy); -} - -bool Cluster::insertShiftDown(const QPoint& marker) -{ - bool dummy; - return insertShiftDown(marker, dummy); -} - -void Cluster::removeShiftUp(const QPoint& marker) -{ - bool dummy; - removeShiftUp(marker, dummy); -} - -void Cluster::removeShiftLeft(const QPoint& marker) -{ - bool dummy; - removeShiftLeft(marker, dummy); -} - -void Cluster::setAutoDelete(bool b) -{ - m_autoDelete = b; -} - -bool Cluster::autoDelete() const -{ - return m_autoDelete; -} - -Cell* Cluster::firstCell() const -{ - return m_first; -} - -bool Cluster::insertShiftRight(const QPoint& marker, bool& work) -{ - work = false; - - if (marker.x() >= CALLIGRA_SHEETS_CLUSTER_MAX || marker.x() < 0 || - marker.y() >= CALLIGRA_SHEETS_CLUSTER_MAX || marker.y() < 0) { - debugSheets << "Cluster::insertShiftRight: invalid column or row value (col:" - << marker.x() << " | row: " << marker.y() << ")" << endl; - return false; - } - - int cx = marker.x() / CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int cy = marker.y() / CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int dx = marker.x() % CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int dy = marker.y() % CALLIGRA_SHEETS_CLUSTER_LEVEL2; - - // Is there a cell at the bottom most position ? - // In this case the shift is impossible. - Cell** cl = m_cluster[ cy * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + CALLIGRA_SHEETS_CLUSTER_LEVEL1 - 1 ]; - if (cl && cl[ dy * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 1 ]) - return false; - - bool a = autoDelete(); - setAutoDelete(false); - - // Move cells in this row one down. - for (int i = CALLIGRA_SHEETS_CLUSTER_LEVEL1 - 1; i >= cx ; --i) { - Cell** cl = m_cluster[ cy * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + i ]; - if (cl) { - work = true; - int left = 0; - if (i == cx) - left = dx; - int right = CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 1; - if (i == CALLIGRA_SHEETS_CLUSTER_LEVEL1 - 1) - right = CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 2; - for (int k = right; k >= left; --k) { - Cell* c = cl[ dy * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + k ]; - if (c) { - remove(c->column(), c->row()); - c->move(c->column() + 1, c->row()); - insert(c, c->column(), c->row()); - } - } - } - } - - setAutoDelete(a); - - return true; -} - -bool Cluster::insertShiftDown(const QPoint& marker, bool& work) -{ - work = false; - - if (marker.x() >= CALLIGRA_SHEETS_CLUSTER_MAX || marker.x() < 0 || - marker.y() >= CALLIGRA_SHEETS_CLUSTER_MAX || marker.y() < 0) { - debugSheets << "Cluster::insertShiftDown: invalid column or row value (col:" - << marker.x() << " | row: " << marker.y() << ")" << endl; - return false; - } - - int cx = marker.x() / CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int cy = marker.y() / CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int dx = marker.x() % CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int dy = marker.y() % CALLIGRA_SHEETS_CLUSTER_LEVEL2; - - // Is there a cell at the right most position ? - // In this case the shift is impossible. - Cell** cl = m_cluster[ CALLIGRA_SHEETS_CLUSTER_LEVEL1 * (CALLIGRA_SHEETS_CLUSTER_LEVEL1 - 1) + cx ]; - if (cl && cl[ CALLIGRA_SHEETS_CLUSTER_LEVEL2 *(CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 1) + dx ]) - return false; - - bool a = autoDelete(); - setAutoDelete(false); - - // Move cells in this column one right. - for (int i = CALLIGRA_SHEETS_CLUSTER_LEVEL1 - 1; i >= cy ; --i) { - Cell** cl = m_cluster[ i * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + cx ]; - if (cl) { - work = true; - - int top = 0; - if (i == cy) - top = dy; - int bottom = CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 1; - if (i == CALLIGRA_SHEETS_CLUSTER_LEVEL1 - 1) - bottom = CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 2; - for (int k = bottom; k >= top; --k) { - Cell* c = cl[ k * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + dx ]; - if (c) { - remove(c->column(), c->row()); - c->move(c->column(), c->row() + 1); - insert(c, c->column(), c->row()); - } - } - } - } - - setAutoDelete(a); - - return true; -} - -bool Cluster::insertColumn(int col) -{ - if (col >= CALLIGRA_SHEETS_CLUSTER_MAX || col < 0) { - debugSheets << "Cluster::insertColumn: invalid column value (col:" - << col << ")" << endl; - return false; - } - - // Is there a cell at the right most position ? - // In this case the shift is impossible. - for (int t1 = 0; t1 < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++t1) { - Cell** cl = m_cluster[ t1 * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + CALLIGRA_SHEETS_CLUSTER_LEVEL1 - 1 ]; - if (cl) - for (int t2 = 0; t2 < CALLIGRA_SHEETS_CLUSTER_LEVEL2; ++t2) - if (cl[ t2 * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 1 ]) - return false; - } - - for (int t1 = 0; t1 < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++t1) { - bool work = true; - for (int t2 = 0; work && t2 < CALLIGRA_SHEETS_CLUSTER_LEVEL2; ++t2) - insertShiftRight(QPoint(col, t1 * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + t2), work); - } - - return true; -} - -bool Cluster::insertRow(int row) -{ - if (row >= CALLIGRA_SHEETS_CLUSTER_MAX || row < 0) { - debugSheets << "Cluster::insertRow: invalid row value (row:" - << row << ")" << endl; - return false; - } - - // Is there a cell at the bottom most position ? - // In this case the shift is impossible. - for (int t1 = 0; t1 < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++t1) { - Cell** cl = m_cluster[ CALLIGRA_SHEETS_CLUSTER_LEVEL1 * (CALLIGRA_SHEETS_CLUSTER_LEVEL1 - 1) + t1 ]; - if (cl) - for (int t2 = 0; t2 < CALLIGRA_SHEETS_CLUSTER_LEVEL2; ++t2) - if (cl[ CALLIGRA_SHEETS_CLUSTER_LEVEL2 *(CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 1) + t2 ]) - return false; - } - - for (int t1 = 0; t1 < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++t1) { - bool work = true; - for (int t2 = 0; work && t2 < CALLIGRA_SHEETS_CLUSTER_LEVEL2; ++t2) - insertShiftDown(QPoint(t1 * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + t2, row), work); - } - - return true; -} - -void Cluster::removeShiftUp(const QPoint& marker, bool& work) -{ - work = false; - - if (marker.x() >= CALLIGRA_SHEETS_CLUSTER_MAX || marker.x() < 0 || - marker.y() >= CALLIGRA_SHEETS_CLUSTER_MAX || marker.y() < 0) { - debugSheets << "Cluster::removeShiftUp: invalid column or row value (col:" - << marker.x() << " | row: " << marker.y() << ")" << endl; - return; - } - - int cx = marker.x() / CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int cy = marker.y() / CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int dx = marker.x() % CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int dy = marker.y() % CALLIGRA_SHEETS_CLUSTER_LEVEL2; - - bool a = autoDelete(); - setAutoDelete(false); - - // Move cells in this column one column to the left. - for (int i = cy; i < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++i) { - Cell** cl = m_cluster[ i * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + cx ]; - if (cl) { - work = true; - - int top = 0; - if (i == cy) - top = dy + 1; - int bottom = CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 1; - for (int k = top; k <= bottom; ++k) { - Cell* c = cl[ k * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + dx ]; - if (c) { - remove(c->column(), c->row()); - c->move(c->column(), c->row() - 1); - insert(c, c->column(), c->row()); - } - } - } - } - - setAutoDelete(a); -} - -void Cluster::removeShiftLeft(const QPoint& marker, bool& work) -{ - work = false; - - if (marker.x() >= CALLIGRA_SHEETS_CLUSTER_MAX || marker.x() < 0 || - marker.y() >= CALLIGRA_SHEETS_CLUSTER_MAX || marker.y() < 0) { - debugSheets << "Cluster::removeShiftLeft: invalid column or row value (col:" - << marker.x() << " | row: " << marker.y() << ")" << endl; - return; - } - - int cx = marker.x() / CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int cy = marker.y() / CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int dx = marker.x() % CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int dy = marker.y() % CALLIGRA_SHEETS_CLUSTER_LEVEL2; - - bool a = autoDelete(); - setAutoDelete(false); - - // Move cells in this row one row up. - for (int i = cx; i < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++i) { - Cell** cl = m_cluster[ cy * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + i ]; - if (cl) { - work = true; - - int left = 0; - if (i == cx) - left = dx + 1; - int right = CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 1; - for (int k = left; k <= right; ++k) { - Cell* c = cl[ dy * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + k ]; - if (c) { - remove(c->column(), c->row()); - c->move(c->column() - 1, c->row()); - insert(c, c->column(), c->row()); - } - } - } - } - - setAutoDelete(a); -} - -void Cluster::removeColumn(int col) -{ - if (col >= CALLIGRA_SHEETS_CLUSTER_MAX || col < 0) { - debugSheets << "Cluster::removeColumn: invalid column value (col:" - << col << ")" << endl; - return; - } - - int cx = col / CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int dx = col % CALLIGRA_SHEETS_CLUSTER_LEVEL2; - - for (int y1 = 0; y1 < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++y1) { - Cell** cl = m_cluster[ y1 * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + cx ]; - if (cl) - for (int y2 = 0; y2 < CALLIGRA_SHEETS_CLUSTER_LEVEL2; ++y2) - if (cl[ y2 * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + dx ]) - remove(col, y1 * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + y2); - } - - for (int t1 = 0; t1 < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++t1) { - bool work = true; - for (int t2 = 0; work && t2 < CALLIGRA_SHEETS_CLUSTER_LEVEL2; ++t2) - removeShiftLeft(QPoint(col, t1 * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + t2), work); - } -} - -void Cluster::removeRow(int row) -{ - if (row >= CALLIGRA_SHEETS_CLUSTER_MAX || row < 0) { - debugSheets << "Cluster::removeRow: invalid row value (row:" - << row << ")" << endl; - return; - } - - int cy = row / CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int dy = row % CALLIGRA_SHEETS_CLUSTER_LEVEL2; - - for (int x1 = 0; x1 < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++x1) { - Cell** cl = m_cluster[ cy * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + x1 ]; - if (cl) - for (int x2 = 0; x2 < CALLIGRA_SHEETS_CLUSTER_LEVEL2; ++x2) - if (cl[ dy * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + x2 ]) - remove(x1 * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + x2, row); - } - - for (int t1 = 0; t1 < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++t1) { - bool work = true; - for (int t2 = 0; work && t2 < CALLIGRA_SHEETS_CLUSTER_LEVEL2; ++t2) - removeShiftUp(QPoint(t1 * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + t2, row), work); - } -} - -void Cluster::clearColumn(int col) -{ - if (col >= CALLIGRA_SHEETS_CLUSTER_MAX || col < 0) { - debugSheets << "Cluster::clearColumn: invalid column value (col:" - << col << ")" << endl; - return; - } - - int cx = col / CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int dx = col % CALLIGRA_SHEETS_CLUSTER_LEVEL2; - - for (int cy = 0; cy < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++cy) { - Cell** cl = m_cluster[ cy * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + cx ]; - if (cl) - for (int dy = 0; dy < CALLIGRA_SHEETS_CLUSTER_LEVEL2; ++dy) - if (cl[ dy * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + dx ]) { - int row = cy * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + dy ; - remove(col, row); - } - } -} - -void Cluster::clearRow(int row) -{ - if (row >= CALLIGRA_SHEETS_CLUSTER_MAX || row < 0) { - debugSheets << "Cluster::clearRow: invalid row value (row:" - << row << ")" << endl; - return; - } - - int cy = row / CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int dy = row % CALLIGRA_SHEETS_CLUSTER_LEVEL2; - - for (int cx = 0; cx < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++cx) { - Cell** cl = m_cluster[ cy * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + cx ]; - if (cl) - for (int dx = 0; dx < CALLIGRA_SHEETS_CLUSTER_LEVEL2; ++dx) - if (cl[ dy * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + dx ]) { - int column = cx * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + dx ; - remove(column, row); - } - } -} - -Value Cluster::valueRange(int col1, int row1, - int col2, int row2) const -{ - Value empty; - - //swap first/second values if needed - if (col1 > col2) { - int p = col1; col1 = col2; col2 = p; - } - if (row1 > row2) { - int p = row1; row1 = col2; row2 = p; - } - if ((row1 < 0) || (col1 < 0) || (row2 > CALLIGRA_SHEETS_CLUSTER_MAX) || - (col2 > CALLIGRA_SHEETS_CLUSTER_MAX)) - return empty; - - // if we are out of range occupied by cells, we return an empty - // array of the requested size - if ((row1 > m_biggestY) || (col1 > m_biggestX)) - return Value(Value::Array); - - return makeArray(col1, row1, col2, row2); -} - -Value Cluster::makeArray(int col1, int row1, int col2, int row2) const -{ - // this generates an array of values - Value array(Value::Array); - for (int row = row1; row <= row2; ++row) { - for (Cell* cell = getFirstCellRow(row); cell; cell = getNextCellRight(cell->column(), row)) { - if (cell->column() >= col1 && cell->column() <= col2) - array.setElement(cell->column() - col1, row - row1, cell->value()); - } - } - //return the result - return array; -} - -Cell* Cluster::getFirstCellColumn(int col) const -{ - Cell* cell = lookup(col, 1); - - if (cell == 0) { - cell = getNextCellDown(col, 1); - } - return cell; -} - -Cell* Cluster::getLastCellColumn(int col) const -{ - Cell* cell = lookup(col, KS_rowMax); - - if (cell == 0) { - cell = getNextCellUp(col, KS_rowMax); - } - return cell; -} - -Cell* Cluster::getFirstCellRow(int row) const -{ - Cell* cell = lookup(1, row); - - if (cell == 0) { - cell = getNextCellRight(1, row); - } - return cell; -} - -Cell* Cluster::getLastCellRow(int row) const -{ - Cell* cell = lookup(KS_colMax, row); - - if (cell == 0) { - cell = getNextCellLeft(KS_colMax, row); - } - return cell; -} - -Cell* Cluster::getNextCellUp(int col, int row) const -{ - int cx = col / CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int cy = (row - 1) / CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int dx = col % CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int dy = (row - 1) % CALLIGRA_SHEETS_CLUSTER_LEVEL2; - - while (cy >= 0) { - if (m_cluster[ cy * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + cx ] != 0) { - while (dy >= 0) { - - if (m_cluster[ cy*CALLIGRA_SHEETS_CLUSTER_LEVEL1 + cx] - [ dy*CALLIGRA_SHEETS_CLUSTER_LEVEL2 + dx] != 0) { - return m_cluster[ cy*CALLIGRA_SHEETS_CLUSTER_LEVEL1 + cx ] - [ dy*CALLIGRA_SHEETS_CLUSTER_LEVEL2 + dx]; - } - dy--; - } - } - cy--; - dy = CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 1; - } - return 0; -} - -Cell* Cluster::getNextCellDown(int col, int row) const -{ - int cx = col / CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int cy = (row + 1) / CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int dx = col % CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int dy = (row + 1) % CALLIGRA_SHEETS_CLUSTER_LEVEL2; - - while (cy < CALLIGRA_SHEETS_CLUSTER_LEVEL1) { - if (m_cluster[ cy * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + cx ] != 0) { - while (dy < CALLIGRA_SHEETS_CLUSTER_LEVEL2) { - - if (m_cluster[ cy*CALLIGRA_SHEETS_CLUSTER_LEVEL1 + cx] - [ dy*CALLIGRA_SHEETS_CLUSTER_LEVEL2 + dx] != 0) { - return m_cluster[ cy*CALLIGRA_SHEETS_CLUSTER_LEVEL1 + cx ] - [ dy*CALLIGRA_SHEETS_CLUSTER_LEVEL2 + dx]; - } - dy++; - } - } - cy++; - dy = 0; - } - return 0; -} - -Cell* Cluster::getNextCellLeft(int col, int row) const -{ - int cx = (col - 1) / CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int cy = row / CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int dx = (col - 1) % CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int dy = row % CALLIGRA_SHEETS_CLUSTER_LEVEL2; - - while (cx >= 0) { - if (m_cluster[ cy * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + cx ] != 0) { - while (dx >= 0) { - - if (m_cluster[ cy*CALLIGRA_SHEETS_CLUSTER_LEVEL1 + cx] - [ dy*CALLIGRA_SHEETS_CLUSTER_LEVEL2 + dx] != 0) { - return m_cluster[ cy*CALLIGRA_SHEETS_CLUSTER_LEVEL1 + cx ] - [ dy*CALLIGRA_SHEETS_CLUSTER_LEVEL2 + dx]; - } - dx--; - } - } - cx--; - dx = CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 1; - } - return 0; -} - -Cell* Cluster::getNextCellRight(int col, int row) const -{ - int cx = (col + 1) / CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int cy = row / CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int dx = (col + 1) % CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int dy = row % CALLIGRA_SHEETS_CLUSTER_LEVEL2; - - while (cx < CALLIGRA_SHEETS_CLUSTER_LEVEL1) { - if (m_cluster[ cy * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + cx ] != 0) { - while (dx < CALLIGRA_SHEETS_CLUSTER_LEVEL2) { - - if (m_cluster[ cy*CALLIGRA_SHEETS_CLUSTER_LEVEL1 + cx] - [ dy*CALLIGRA_SHEETS_CLUSTER_LEVEL2 + dx] != 0) { - return m_cluster[ cy*CALLIGRA_SHEETS_CLUSTER_LEVEL1 + cx ] - [ dy*CALLIGRA_SHEETS_CLUSTER_LEVEL2 + dx]; - } - dx++; - } - } - cx++; - dx = 0; - } - return 0; -} -#endif - /**************************************************** * * ColumnCluster * ****************************************************/ ColumnCluster::ColumnCluster() : m_first(0), m_autoDelete(false) { m_cluster = (ColumnFormat***)malloc(CALLIGRA_SHEETS_CLUSTER_LEVEL1 * sizeof(ColumnFormat**)); for (int x = 0; x < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++x) m_cluster[ x ] = 0; } ColumnCluster::~ColumnCluster() { for (int x = 0; x < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++x) { ColumnFormat** cl = m_cluster[ x ]; if (cl) { free(cl); m_cluster[ x ] = 0; } } if (m_autoDelete) { ColumnFormat* cell = m_first; while (cell) { ColumnFormat* n = cell->next(); delete cell; cell = n; } } free(m_cluster); } ColumnFormat* ColumnCluster::lookup(int col) { if (col >= CALLIGRA_SHEETS_CLUSTER_MAX || col < 0) { debugSheets << "ColumnCluster::lookup: invalid column value (col:" << col << ")" << endl; return 0; } int cx = col / CALLIGRA_SHEETS_CLUSTER_LEVEL2; int dx = col % CALLIGRA_SHEETS_CLUSTER_LEVEL2; ColumnFormat** cl = m_cluster[ cx ]; if (!cl) return 0; return cl[ dx ]; } const ColumnFormat* ColumnCluster::lookup(int col) const { if (col >= CALLIGRA_SHEETS_CLUSTER_MAX || col < 0) { debugSheets << "ColumnCluster::lookup: invalid column value (col:" << col << ")" << endl; return 0; } int cx = col / CALLIGRA_SHEETS_CLUSTER_LEVEL2; int dx = col % CALLIGRA_SHEETS_CLUSTER_LEVEL2; ColumnFormat** cl = m_cluster[ cx ]; if (!cl) return 0; return cl[ dx ]; } void ColumnCluster::clear() { for (int x = 0; x < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++x) { ColumnFormat** cl = m_cluster[ x ]; if (cl) { free(cl); m_cluster[ x ] = 0; } } if (m_autoDelete) { ColumnFormat* cell = m_first; while (cell) { ColumnFormat* n = cell->next(); delete cell; cell = n; } } m_first = 0; } void ColumnCluster::insertElement(ColumnFormat* lay, int col) { if (col >= CALLIGRA_SHEETS_CLUSTER_MAX || col < 0) { debugSheets << "ColumnCluster::insertElement: invalid column value (col:" << col << ")" << endl; return; } int cx = col / CALLIGRA_SHEETS_CLUSTER_LEVEL2; int dx = col % CALLIGRA_SHEETS_CLUSTER_LEVEL2; ColumnFormat** cl = m_cluster[ cx ]; if (!cl) { cl = (ColumnFormat**)malloc(CALLIGRA_SHEETS_CLUSTER_LEVEL2 * sizeof(ColumnFormat*)); m_cluster[ cx ] = cl; for (int a = 0; a < CALLIGRA_SHEETS_CLUSTER_LEVEL2; ++a) cl[ a ] = 0; } if (cl[ dx ]) removeElement(col); cl[ dx ] = lay; if (m_first) { lay->setNext(m_first); m_first->setPrevious(lay); } m_first = lay; } void ColumnCluster::removeElement(int col) { if (col >= CALLIGRA_SHEETS_CLUSTER_MAX || col < 0) { debugSheets << "ColumnCluster::removeElement: invalid column value (col:" << col << ")" << endl; return; } int cx = col / CALLIGRA_SHEETS_CLUSTER_LEVEL2; int dx = col % CALLIGRA_SHEETS_CLUSTER_LEVEL2; ColumnFormat** cl = m_cluster[ cx ]; if (!cl) return; ColumnFormat* c = cl[ dx ]; if (!c) return; cl[ dx ] = 0; if (m_autoDelete) { if (m_first == c) m_first = c->next(); delete c; } else { if (m_first == c) m_first = c->next(); if (c->previous()) c->previous()->setNext(c->next()); if (c->next()) c->next()->setPrevious(c->previous()); c->setNext(0); c->setPrevious(0); } } bool ColumnCluster::insertColumn(int col) { if (col >= CALLIGRA_SHEETS_CLUSTER_MAX || col < 0) { debugSheets << "ColumnCluster::insertColumn: invalid column value (col:" << col << ")" << endl; return false; } int cx = col / CALLIGRA_SHEETS_CLUSTER_LEVEL2; int dx = col % CALLIGRA_SHEETS_CLUSTER_LEVEL2; // Is there a column layout at the right most position ? // In this case the shift is impossible. ColumnFormat** cl = m_cluster[ CALLIGRA_SHEETS_CLUSTER_LEVEL1 - 1 ]; if (cl && cl[ CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 1 ]) return false; bool a = autoDelete(); setAutoDelete(false); for (int i = CALLIGRA_SHEETS_CLUSTER_LEVEL1 - 1; i >= cx ; --i) { ColumnFormat** cl = m_cluster[ i ]; if (cl) { int left = 0; if (i == cx) left = dx; int right = CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 1; if (i == CALLIGRA_SHEETS_CLUSTER_LEVEL1 - 1) right = CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 2; for (int k = right; k >= left; --k) { ColumnFormat* c = cl[ k ]; if (c) { removeElement(c->column()); c->setColumn(c->column() + 1); insertElement(c, c->column()); } } } } setAutoDelete(a); return true; } bool ColumnCluster::removeColumn(int column) { if (column >= CALLIGRA_SHEETS_CLUSTER_MAX || column < 0) { debugSheets << "ColumnCluster::removeColumn: invalid column value (col:" << column << ")" << endl; return false; } int cx = column / CALLIGRA_SHEETS_CLUSTER_LEVEL2; int dx = column % CALLIGRA_SHEETS_CLUSTER_LEVEL2; removeElement(column); bool a = autoDelete(); setAutoDelete(false); for (int i = cx; i < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++i) { ColumnFormat** cl = m_cluster[ i ]; if (cl) { int left = 0; if (i == cx) left = dx + 1; int right = CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 1; for (int k = left; k <= right; ++k) { ColumnFormat* c = cl[ k ]; if (c) { removeElement(c->column()); c->setColumn(c->column() - 1); insertElement(c, c->column()); } } } } setAutoDelete(a); return true; } void ColumnCluster::setAutoDelete(bool a) { m_autoDelete = a; } bool ColumnCluster::autoDelete() const { return m_autoDelete; } ColumnFormat* ColumnCluster::next(int col) const { if (col >= CALLIGRA_SHEETS_CLUSTER_MAX || col < 0) { debugSheets << "ColumnCluster::next: invalid column value (col:" << col << ")" << endl; return 0; } int cx = (col + 1) / CALLIGRA_SHEETS_CLUSTER_LEVEL2; int dx = (col + 1) % CALLIGRA_SHEETS_CLUSTER_LEVEL2; while (cx < CALLIGRA_SHEETS_CLUSTER_LEVEL1) { if (m_cluster[ cx ]) { while (dx < CALLIGRA_SHEETS_CLUSTER_LEVEL2) { if (m_cluster[ cx ][ dx ]) { return m_cluster[ cx ][ dx ]; } ++dx; } } ++cx; dx = 0; } return 0; } void ColumnCluster::operator=(const ColumnCluster & other) { m_first = 0; m_autoDelete = other.m_autoDelete; // TODO Stefan: Optimize! m_cluster = (ColumnFormat***)malloc(CALLIGRA_SHEETS_CLUSTER_LEVEL1 * sizeof(ColumnFormat**)); for (int i = 0; i < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++i) { if (other.m_cluster[i]) { m_cluster[i] = (ColumnFormat**)malloc(CALLIGRA_SHEETS_CLUSTER_LEVEL2 * sizeof(ColumnFormat*)); for (int j = 0; j < CALLIGRA_SHEETS_CLUSTER_LEVEL2; ++j) { m_cluster[i][j] = 0; if (other.m_cluster[i][j]) { ColumnFormat* columnFormat = new ColumnFormat(*other.m_cluster[i][j]); columnFormat->setNext(0); columnFormat->setPrevious(0); insertElement(columnFormat, columnFormat->column()); } } } else m_cluster[i] = 0; } } -/**************************************************** - * - * RowCluster - * - ****************************************************/ - -RowCluster::RowCluster() - : m_first(0), m_autoDelete(false) -{ - m_cluster = (RowFormat***)malloc(CALLIGRA_SHEETS_CLUSTER_LEVEL1 * sizeof(RowFormat**)); - - for (int x = 0; x < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++x) - m_cluster[ x ] = 0; -} - -RowCluster::~RowCluster() -{ - for (int x = 0; x < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++x) { - RowFormat** cl = m_cluster[ x ]; - if (cl) { - free(cl); - m_cluster[ x ] = 0; - } - } - - if (m_autoDelete) { - RowFormat* cell = m_first; - while (cell) { - RowFormat* n = cell->next(); - delete cell; - cell = n; - } - } - - free(m_cluster); -} - -const RowFormat* RowCluster::lookup(int row) const -{ - if (row >= CALLIGRA_SHEETS_CLUSTER_MAX || row < 0) { - debugSheets << "RowCluster::lookup: invalid row value (row:" - << row << ")" << endl; - return 0; - } - - int cx = row / CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int dx = row % CALLIGRA_SHEETS_CLUSTER_LEVEL2; - - RowFormat** cl = m_cluster[ cx ]; - if (!cl) - return 0; - - return cl[ dx ]; -} - -RowFormat* RowCluster::lookup(int row) -{ - if (row >= CALLIGRA_SHEETS_CLUSTER_MAX || row < 0) { - debugSheets << "RowCluster::lookup: invalid row value (row:" - << row << ")" << endl; - return 0; - } - - int cx = row / CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int dx = row % CALLIGRA_SHEETS_CLUSTER_LEVEL2; - - RowFormat** cl = m_cluster[ cx ]; - if (!cl) - return 0; - - return cl[ dx ]; -} - -void RowCluster::clear() -{ - for (int x = 0; x < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++x) { - RowFormat** cl = m_cluster[ x ]; - if (cl) { - free(cl); - m_cluster[ x ] = 0; - } - } - - if (m_autoDelete) { - RowFormat* cell = m_first; - while (cell) { - RowFormat* n = cell->next(); - delete cell; - cell = n; - } - } - - m_first = 0; -} - -void RowCluster::insertElement(RowFormat* lay, int row) -{ - if (row >= CALLIGRA_SHEETS_CLUSTER_MAX || row < 0) { - debugSheets << "RowCluster::insertElement: invalid row value (row:" - << row << ")" << endl; - return; - } - - int cx = row / CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int dx = row % CALLIGRA_SHEETS_CLUSTER_LEVEL2; - - RowFormat** cl = m_cluster[ cx ]; - if (!cl) { - cl = (RowFormat**)malloc(CALLIGRA_SHEETS_CLUSTER_LEVEL2 * sizeof(RowFormat*)); - m_cluster[ cx ] = cl; - - for (int a = 0; a < CALLIGRA_SHEETS_CLUSTER_LEVEL2; ++a) - cl[ a ] = 0; - } - - if (cl[ dx ]) - removeElement(row); - - cl[ dx ] = lay; - - if (m_first) { - lay->setNext(m_first); - m_first->setPrevious(lay); - } - m_first = lay; -} - -void RowCluster::removeElement(int row) -{ - if (row >= CALLIGRA_SHEETS_CLUSTER_MAX || row < 0) { - debugSheets << "RowCluster::removeElement: invalid row value (row:" - << row << ")" << endl; - return; - } - - int cx = row / CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int dx = row % CALLIGRA_SHEETS_CLUSTER_LEVEL2; - - RowFormat** cl = m_cluster[ cx ]; - if (!cl) - return; - - RowFormat* c = cl[ dx ]; - if (!c) - return; - - cl[ dx ] = 0; - - if (m_autoDelete) { - if (m_first == c) - m_first = c->next(); - delete c; - } else { - if (m_first == c) - m_first = c->next(); - if (c->previous()) - c->previous()->setNext(c->next()); - if (c->next()) - c->next()->setPrevious(c->previous()); - c->setNext(0); - c->setPrevious(0); - } -} - -bool RowCluster::insertRow(int row) -{ - if (row >= CALLIGRA_SHEETS_CLUSTER_MAX || row < 0) { - debugSheets << "RowCluster::insertRow: invalid row value (row:" - << row << ")" << endl; - return false; - } - - int cx = row / CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int dx = row % CALLIGRA_SHEETS_CLUSTER_LEVEL2; - - // Is there a row layout at the bottom most position ? - // In this case the shift is impossible. - RowFormat** cl = m_cluster[ CALLIGRA_SHEETS_CLUSTER_LEVEL1 - 1 ]; - if (cl && cl[ CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 1 ]) - return false; - - bool a = autoDelete(); - setAutoDelete(false); - - for (int i = CALLIGRA_SHEETS_CLUSTER_LEVEL1 - 1; i >= cx ; --i) { - RowFormat** cl = m_cluster[ i ]; - if (cl) { - int left = 0; - if (i == cx) - left = dx; - int right = CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 1; - if (i == CALLIGRA_SHEETS_CLUSTER_LEVEL1 - 1) - right = CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 2; - for (int k = right; k >= left; --k) { - RowFormat* c = cl[ k ]; - if (c) { - removeElement(c->row()); - c->setRow(c->row() + 1); - insertElement(c, c->row()); - } - } - } - } - - setAutoDelete(a); - - return true; -} - -bool RowCluster::removeRow(int row) -{ - if (row >= CALLIGRA_SHEETS_CLUSTER_MAX || row < 0) { - debugSheets << "RowCluster::removeRow: invalid row value (row:" - << row << ")" << endl; - return false; - } - - int cx = row / CALLIGRA_SHEETS_CLUSTER_LEVEL2; - int dx = row % CALLIGRA_SHEETS_CLUSTER_LEVEL2; - - removeElement(row); - - bool a = autoDelete(); - setAutoDelete(false); - - for (int i = cx; i < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++i) { - RowFormat** cl = m_cluster[ i ]; - if (cl) { - int left = 0; - if (i == cx) - left = dx + 1; - int right = CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 1; - for (int k = left; k <= right; ++k) { - RowFormat* c = cl[ k ]; - if (c) { - removeElement(c->row()); - c->setRow(c->row() - 1); - insertElement(c, c->row()); - } - } - } - } - - setAutoDelete(a); - - return true; -} - -void RowCluster::setAutoDelete(bool a) -{ - m_autoDelete = a; -} - -bool RowCluster::autoDelete() const -{ - return m_autoDelete; -} -void RowCluster::operator=(const RowCluster & other) -{ - m_first = 0; - m_autoDelete = other.m_autoDelete; - // TODO Stefan: Optimize! - m_cluster = (RowFormat***)malloc(CALLIGRA_SHEETS_CLUSTER_LEVEL1 * sizeof(RowFormat**)); - for (int i = 0; i < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++i) { - if (other.m_cluster[i]) { - m_cluster[i] = (RowFormat**)malloc(CALLIGRA_SHEETS_CLUSTER_LEVEL2 * sizeof(RowFormat*)); - for (int j = 0; j < CALLIGRA_SHEETS_CLUSTER_LEVEL2; ++j) { - m_cluster[i][j] = 0; - if (other.m_cluster[i][j]) { - RowFormat* rowFormat = new RowFormat(*other.m_cluster[i][j]); - rowFormat->setNext(0); - rowFormat->setPrevious(0); - insertElement(rowFormat, rowFormat->row()); - } - } - } else - m_cluster[i] = 0; - } -} diff --git a/sheets/Cluster.h b/sheets/Cluster.h index 42ee5138b79..b81e65ac3ac 100644 --- a/sheets/Cluster.h +++ b/sheets/Cluster.h @@ -1,350 +1,83 @@ /* This file is part of the KDE project Copyright (C) 2000 Torben Weis This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef CLUSTER_H #define CLUSTER_H #include "Value.h" #define CALLIGRA_SHEETS_CLUSTER_LEVEL1 256 #define CALLIGRA_SHEETS_CLUSTER_LEVEL2 256 #define CALLIGRA_SHEETS_CLUSTER_MAX (256*256) class QPoint; namespace Calligra { namespace Sheets { class Cell; class ColumnFormat; class RowFormat; -/** -\ingroup Storage -This class defines a pointer map to all cells, which makes access to them more performant -and additionally limits memory consumption. - -In detail: The class defines 2 cluster, where the second cluster (LEVEL2) is a matrix for -single cells, while the first cluster (LEVEL1) is a matrix to handle the matrices of LEVEL2. -On initialization, one LEVEL1 matrix is generated only. -Each time, a cell stores something, this class checks if for the given column and row a -matrix of LEVEL2 is already initialized and in case not generates it on the fly. -This helps to reduce the memory usage to only consum one pointer matrix for LEVEL1 and all -matrices of LEVEL2 that are necessary. - -LEVEL1 is defined as 128x128 matrix. -LEVEL2 is defined as 256x256 matrices. -Each direction then can have LEVEL1 * LEVEL2 = 128*256 = 2^15 different cells, which -is in total (2^15)^2 cells. - -It can be changed easily to different sizes, but it should be more senseful to have a small LEVEL1, -as in most cases only one/two entries in LEVEL1 will be used. - -There are 2 additional special classes to store pointers for column and row formats. - -Future enhancements: -To reduce memory consumption, it should be possible to enhance the functionality by -another LEVEL0, which then keeps the LEVEL1 size smaller. - -Maybe the LEVEL1 should only be generated when there is a need for more than 1 LEVEL2. - -LEVEL1 maybe reallocated. - -Another interesting possibility would be to differentiate between x size and y size. Currently both -are equal in both matrizes, but normally it will be the regular case, that you have more need for -a lot of rows than columns. Maybe something like LEVEL1=128/256 and LEVEL2=256/128 (x/y), still keeping -2^15 values/cells in each direction (benefit: you won't loose memory in empty columns). -*/ -class Cluster -{ - friend class ClusterTest; - -public: - Cluster(); - ~Cluster(); - - Cell* lookup(int x, int y) const; - - /** - * Removes all cells from the sheet and frees memory that - * was used for the clusters. - */ - void clear(); - - /** - * Inserts a cell at the requested position. If there is already - * a cell, then @ref #remove is called on it. - */ - void insert(Cell* cell, int x, int y); - /** - * Removes the cell at the given position, if there is any. - */ - void remove(int x, int y); - - void setAutoDelete(bool); - bool autoDelete() const; - - Cell* firstCell() const; - - bool insertShiftRight(const QPoint& marker); - /** - * Moves all cells in the column marker.x() beginning with - * the one at marker.y() one position downwards. - * - * @return false if a cell would drop out of the sheet because of that. - * In this case the shift is not performed. - */ - bool insertShiftDown(const QPoint& marker); - - /** - * Moves all cells in the column marker.x() beginning with - * the one at marker.y() + 1 one position upwards. - */ - void removeShiftUp(const QPoint& marker); - void removeShiftLeft(const QPoint& marker); - - /** - * Moves all columns beginning with @p col one position - * to the right. If that does not work because a cell would - * drop out of the sheet, then false is returned. - * - * @see #removeColumn - */ - bool insertColumn(int col); - bool insertRow(int row); - - /** - * Removes all elements from the column and - * move all columns right of @p col one position - * to the left. - * - * @see #clearColumn - */ - void removeColumn(int col); - void removeRow(int row); - - /** - * Removes all elements from the column. - * - */ - void clearColumn(int col); - void clearRow(int row); - - /** Retrieve a range of values stored in a Value. - The range is two-leveled with similar structure and reasoning as the - storage of cells themselves. - */ - Value valueRange(int col1, int row1, int col2, int row2) const; - - /** - * Retrieve the first used cell in a given column. Can be used in conjunction - * with getNextCellDown to loop through a column. - * - * @param col The column to get the first cell from - * - * @return Returns a pointer to the cell, or 0 if there are no used cells - * in this column - */ - Cell* getFirstCellColumn(int col) const; - - /** - * Retrieve the last used cell in a given column. Can be used in conjunction - * with getNextCellUp to loop through a column. - * - * @param col The column to get the cell from - * - * @return Returns a pointer to the cell, or 0 if there are no used cells - * in this column - */ - Cell* getLastCellColumn(int col) const; - - /** - * Retrieve the first used cell in a given row. Can be used in conjunction - * with getNextCellRight to loop through a row. - * - * @param row The row to get the first cell from - * - * @return Returns a pointer to the cell, or 0 if there are no used cells - * in this row - */ - Cell* getFirstCellRow(int row) const; - - /** - * Retrieve the last used cell in a given row. Can be used in conjunction - * with getNextCellLeft to loop through a row. - * - * @param row The row to get the last cell from - * - * @return Returns a pointer to the cell, or 0 if there are no used cells - * in this row - */ - Cell* getLastCellRow(int row) const; - - /** - * Retrieves the next used cell above the given col/row pair. The given - * col/row pair does not need to reference a used cell. - * - * @param col column to start looking through - * @param row the row above which to start looking. - * - * @return Returns the next used cell above this one, or 0 if there are none - */ - Cell* getNextCellUp(int col, int row) const; - - /** - * Retrieves the next used cell below the given col/row pair. The given - * col/row pair does not need to reference a used cell. - * - * @param col column to start looking through - * @param row the row below which to start looking. - * - * @return Returns the next used cell below this one, or 0 if there are none - */ - Cell* getNextCellDown(int col, int row) const; - - /** - * Retrieves the next used cell to the right of the given col/row pair. - * The given col/row pair does not need to reference a used cell. - * - * @param col the column after which should be searched - * @param row the row to search through - * - * @return Returns the next used cell to the right of this one, or 0 if - * there are none - */ - Cell* getNextCellRight(int col, int row) const; - - /** - * Retrieves the next used cell to the left of the given col/row pair. - * The given col/row pair does not need to reference a used cell. - * - * @param col the column before which should be searched - * @param row the row to search through - * - * @return Returns the next used cell to the left of this one, or 0 if - * there are none - */ - Cell* getNextCellLeft(int col, int row) const; - -private: - /** - * @param work is set to true if the method found some clusters - * which belong to the shifted row. - */ - bool insertShiftRight(const QPoint& marker, bool& work); - bool insertShiftDown(const QPoint& marker, bool& work); - - void removeShiftUp(const QPoint& marker, bool& work); - void removeShiftLeft(const QPoint& marker, bool& work); - - /** helper method used by valueRange */ - Value makeArray(int col1, int row1, int col2, int row2) const; - - Cell*** m_cluster; - Cell* m_first; - bool m_autoDelete; - int m_biggestX, m_biggestY; -}; - /** * \ingroup Storage - * A pointer map to all column formats. + * A pointer map to all column formats. Should probably be converted to something like RowFormatStorage. * \see Cluster */ class ColumnCluster { public: ColumnCluster(); ~ColumnCluster(); const ColumnFormat* lookup(int col) const; ColumnFormat* lookup(int col); void clear(); void insertElement(ColumnFormat*, int col); void removeElement(int col); bool insertColumn(int col); bool removeColumn(int col); void setAutoDelete(bool); bool autoDelete() const; ColumnFormat* first() const { return m_first; } ColumnFormat* next(int col) const; void operator=(const ColumnCluster& other); private: ColumnCluster(const ColumnCluster& other); private: ColumnFormat*** m_cluster; ColumnFormat* m_first; bool m_autoDelete; }; -/** - * \ingroup Storage - * A pointer map to all row formats. - * \see Cluster - */ -class RowCluster -{ -public: - RowCluster(); - ~RowCluster(); - - const RowFormat* lookup(int col) const; - RowFormat* lookup(int col); - - void clear(); - - void insertElement(RowFormat*, int row); - void removeElement(int row); - - bool insertRow(int row); - bool removeRow(int row); - - void setAutoDelete(bool); - bool autoDelete() const; - - RowFormat* first()const { - return m_first; - } - - void operator=(const RowCluster& other); - -private: - RowCluster(const RowCluster& other); - -private: - RowFormat*** m_cluster; - RowFormat* m_first; - bool m_autoDelete; -}; - } // namespace Sheets } // namespace Calligra #endif