File indexing completed on 2024-04-28 16:21:28

0001 /* This file is part of the KDE project
0002    Copyright 2010 Marijn Kruisselbrink <mkruisselbrink@kde.org>
0003 
0004    This library is free software; you can redistribute it and/or
0005    modify it under the terms of the GNU Library General Public
0006    License as published by the Free Software Foundation; either
0007    version 2 of the License, or (at your option) any later version.
0008 
0009    This library is distributed in the hope that it will be useful,
0010    but WITHOUT ANY WARRANTY; without even the implied warranty of
0011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012    Library General Public License for more details.
0013 
0014    You should have received a copy of the GNU Library General Public License
0015    along with this library; see the file COPYING.LIB.  If not, write to
0016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0017    Boston, MA 02110-1301, USA.
0018 */
0019 #include "RowRepeatStorage.h"
0020 
0021 #include <QList>
0022 #include <QPair>
0023 #include <QDebug>
0024 
0025 #include "calligra_sheets_limits.h"
0026 
0027 using namespace Calligra::Sheets;
0028 
0029 RowRepeatStorage::RowRepeatStorage()
0030 {
0031 }
0032 
0033 void RowRepeatStorage::dump() const
0034 {
0035     for (QMap<int, int>::const_iterator it = m_data.begin(); it != m_data.end(); ++it) {
0036         qDebug() << "[" << (it.key() - it.value() + 1) << it.key() << "] =" << it.value();
0037     }
0038 }
0039 
0040 void RowRepeatStorage::setRowRepeat(int firstRow, int rowRepeat)
0041 {
0042    const int lastRow = firstRow + rowRepeat - 1;
0043    // see if m_data contains a range that includes firstRow
0044    QMap<int, int>::iterator it = m_data.lowerBound(firstRow);
0045    typedef QPair<int, int> intPair;
0046    QList<intPair> newRanges;
0047    // returns first range that ends at or after firstRow
0048    if (it != m_data.end()) {
0049        while (it != m_data.end() && (it.key() - it.value() + 1) <= lastRow) {
0050            if ((it.key() - it.value() + 1) < firstRow) {
0051                // starts before the new range, so we want to change the row repeat value of this range
0052                // but since the key is the end of the range, we can only remove it and re-insert it later
0053                newRanges.append(qMakePair(firstRow - 1, it.value() - (it.key() - firstRow + 1)));
0054                if (it.key() > lastRow) {
0055                    // ends after the new range, so also adjust the end
0056                    it.value() = it.key() - lastRow;
0057                    ++it;
0058                } else {
0059                    it = m_data.erase(it);
0060                }
0061            } else {
0062                // starts inside the new range, ends in or after the new range
0063                if (it.key() <= lastRow) {
0064                    // ends inside the new range, so just remove
0065                    it = m_data.erase(it);
0066                } else {
0067                    // ends after the new range, adjust and go to the next
0068                    it.value() = it.key() - lastRow;
0069                    ++it;
0070                }
0071            }
0072        }
0073    }
0074 
0075    // finally set the new range of row-repeat values
0076    if (rowRepeat != 1)
0077        m_data[lastRow] = rowRepeat;
0078 
0079    foreach (const intPair& p, newRanges) {
0080        if (p.second > 1) m_data[p.first] = p.second;
0081    }
0082 }
0083 
0084 int RowRepeatStorage::rowRepeat(int row) const
0085 {
0086     // first range that ends at or after row
0087     QMap<int, int>::const_iterator it = m_data.lowerBound(row);
0088     // not found? default value = 1
0089     if (it == m_data.end()) return 1;
0090     // otherwise, see if row is actually inside the range
0091     if (it.key() - it.value() + 1 <= row) {
0092         return it.value();
0093     }
0094     return 1;
0095 }
0096 
0097 int RowRepeatStorage::firstIdenticalRow(int row) const
0098 {
0099     // first range that ends at or after row
0100     QMap<int, int>::const_iterator it = m_data.lowerBound(row);
0101     // not found? default value = row
0102     if (it == m_data.end()) return row;
0103     // otherwise, see if row is actually inside the range
0104     if (it.key() - it.value() + 1 <= row) {
0105         return it.key() - it.value() + 1;
0106     }
0107     return row;
0108 }
0109 
0110 void RowRepeatStorage::insertRows(int row, int count)
0111 {
0112     typedef QPair<int, int> intPair;
0113     QList<intPair> newRanges;
0114 
0115     // first range that ends at or after row
0116     QMap<int, int>::iterator it = m_data.lowerBound(row);
0117     while (it != m_data.end()) {
0118         if (it.key() - it.value() + 1 < row) {
0119             // starts before the newly inserted rows, so split it up
0120             newRanges.append(qMakePair(row-1, row - it.key() + it.value() - 1));
0121             newRanges.append(qMakePair(it.key() + count, it.key() - row + 1));
0122         } else {
0123             newRanges.append(qMakePair(it.key() + count, it.value()));
0124         }
0125         it = m_data.erase(it);
0126     }
0127 
0128     m_data[row+count-1] = count;
0129     foreach (const intPair& p, newRanges) {
0130         if (p.second > 1) m_data[p.first] = p.second;
0131     }
0132 }
0133 
0134 void RowRepeatStorage::removeRows(int row, int count)
0135 {
0136     typedef QPair<int, int> intPair;
0137     QList<intPair> newRanges;
0138 
0139     // first range that ends at or after row
0140     QMap<int, int>::iterator it = m_data.lowerBound(row);
0141     while (it != m_data.end()) {
0142         if (it.key() - it.value() + 1 < row) {
0143             // starts before removed rows
0144             newRanges.append(qMakePair(row-1, row - it.key() + it.value() - 1));
0145         }
0146         if (it.key() >= row + count) {
0147             // ends after the removed rows
0148             newRanges.append(qMakePair(it.key() - count, qMin(it.value(), it.key() - row - count + 1)));
0149         }
0150         it = m_data.erase(it);
0151     }
0152 
0153     foreach (const intPair& p, newRanges) {
0154         if (p.second > 1) m_data[p.first] = p.second;
0155     }
0156 }
0157 
0158 void RowRepeatStorage::insertShiftDown(const QRect &rect)
0159 {
0160     RowRepeatStorage s2 = *this;
0161     s2.insertRows(rect.top(), rect.height());
0162 
0163     typedef QPair<int, int> intPair;
0164     QList<intPair> newRanges;
0165 
0166     for (int row = 1; row <= KS_rowMax;) {
0167         int repeat1 = rowRepeat(row);
0168         int repeat2 = s2.rowRepeat(row);
0169         repeat1 -= row - firstIdenticalRow(row);
0170         repeat2 -= row - s2.firstIdenticalRow(row);
0171         int repeat = qMin(repeat1, repeat2);
0172         if (repeat > 1) {
0173             newRanges.append(qMakePair(row + repeat - 1, repeat));
0174         }
0175         row += repeat;
0176     }
0177 
0178     m_data.clear();
0179     foreach (const intPair& p, newRanges) {
0180         if (p.second > 1) m_data[p.first] = p.second;
0181     }
0182 }
0183 
0184 void RowRepeatStorage::removeShiftUp(const QRect &rect)
0185 {
0186     RowRepeatStorage s2 = *this;
0187     s2.removeRows(rect.top(), rect.height());
0188 
0189     typedef QPair<int, int> intPair;
0190     QList<intPair> newRanges;
0191 
0192     for (int row = 1; row <= KS_rowMax;) {
0193         int repeat1 = rowRepeat(row);
0194         int repeat2 = s2.rowRepeat(row);
0195         repeat1 -= row - firstIdenticalRow(row);
0196         repeat2 -= row - s2.firstIdenticalRow(row);
0197         int repeat = qMin(repeat1, repeat2);
0198         if (repeat > 1) {
0199             newRanges.append(qMakePair(row + repeat - 1, repeat));
0200         }
0201         row += repeat;
0202     }
0203 
0204     m_data.clear();
0205     foreach (const intPair& p, newRanges) {
0206         if (p.second > 1) m_data[p.first] = p.second;
0207     }
0208 }
0209 
0210 void RowRepeatStorage::insertShiftRight(const QRect &rect)
0211 {
0212     splitRowRepeat(rect.top());
0213     splitRowRepeat(rect.bottom()+1);
0214 }
0215 
0216 void RowRepeatStorage::removeShiftLeft(const QRect &rect)
0217 {
0218     // identical to insert
0219     insertShiftRight(rect);
0220 }
0221 
0222 void RowRepeatStorage::splitRowRepeat(int row)
0223 {
0224     // first range that ends at or after row
0225     QMap<int, int>::iterator it = m_data.lowerBound(row);
0226     if (it != m_data.end() && (it.key() - it.value() + 1) < row) {
0227         // range starts before row, ends in or after it; split it
0228         int start = it.key() - it.value() + 1;
0229         int count = row - start;
0230         it.value() = it.key() - row + 1;
0231         if (count > 1) m_data[start+count-1] = count;
0232     }
0233 }