File indexing completed on 2024-04-28 16:21:27
0001 /* This file is part of the KDE project 0002 Copyright (C) 1998, 1999 Torben Weis <weis@kde.org> 0003 Copyright (C) 2000 - 2005 The KSpread Team <calligra-devel@kde.org> 0004 0005 This library is free software; you can redistribute it and/or 0006 modify it under the terms of the GNU Library General Public 0007 License as published by the Free Software Foundation; either 0008 version 2 of the License, or (at your option) any later version. 0009 0010 This library is distributed in the hope that it will be useful, 0011 but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0013 Library General Public License for more details. 0014 0015 You should have received a copy of the GNU Library General Public License 0016 along with this library; see the file COPYING.LIB. If not, write to 0017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0018 Boston, MA 02110-1301, USA. 0019 */ 0020 0021 // Local 0022 #include "RowColumnFormat.h" 0023 0024 #include <float.h> 0025 #include <iostream> 0026 #include <stdlib.h> 0027 #include <stdio.h> 0028 0029 #include <KoXmlNS.h> 0030 #include <KoUnit.h> 0031 0032 #include "SheetsDebug.h" 0033 #include "CellStorage.h" 0034 #include "Global.h" 0035 #include "Map.h" 0036 #include "Region.h" 0037 #include "RowFormatStorage.h" 0038 #include "Sheet.h" 0039 #include "SheetPrint.h" 0040 #include "Style.h" 0041 #include "StyleManager.h" 0042 0043 using namespace std; 0044 using namespace Calligra::Sheets; 0045 0046 /***************************************************************************** 0047 * 0048 * RowFormat 0049 * 0050 *****************************************************************************/ 0051 0052 class Q_DECL_HIDDEN RowFormat::Private 0053 { 0054 public: 0055 Sheet* sheet; 0056 RowFormat* next; 0057 RowFormat* prev; 0058 double height; 0059 int row; 0060 bool hide : 1; 0061 bool filtered : 1; 0062 bool pageBreak : 1; // before row 0063 }; 0064 0065 RowFormat::RowFormat() 0066 : d(new Private) 0067 { 0068 d->sheet = 0; 0069 d->row = 0; 0070 d->height = 0.0; 0071 d->hide = false; 0072 d->filtered = false; 0073 d->pageBreak = false; 0074 d->next = 0; 0075 d->prev = 0; 0076 } 0077 0078 RowFormat::RowFormat(const RowFormat& other) 0079 : d(new Private(*other.d)) 0080 { 0081 } 0082 0083 RowFormat::RowFormat(const RowFormatStorage *rows, int row) 0084 : d(new Private) 0085 { 0086 d->sheet = rows->sheet(); 0087 d->row = row; 0088 d->height = rows->rowHeight(row); 0089 d->hide = rows->isHidden(row); 0090 d->filtered = rows->isFiltered(row); 0091 d->pageBreak = rows->hasPageBreak(row); 0092 d->next = d->prev = 0; 0093 } 0094 0095 RowFormat::~RowFormat() 0096 { 0097 if (d->next) 0098 d->next->setPrevious(d->prev); 0099 if (d->prev) 0100 d->prev->setNext(d->next); 0101 delete d; 0102 } 0103 0104 void RowFormat::setSheet(Sheet* sheet) 0105 { 0106 d->sheet = sheet; 0107 } 0108 0109 void RowFormat::setHeight(double height) 0110 { 0111 // avoid unnecessary updates 0112 if (qAbs(height - this->height()) < DBL_EPSILON) 0113 return; 0114 0115 // default RowFormat? 0116 if (!d->sheet) { 0117 d->height = height; 0118 return; 0119 } 0120 0121 // Raise document height by new height and lower it by old height. 0122 if (!isHidden() && !isFiltered()) 0123 d->sheet->adjustDocumentHeight(height - d->height); 0124 0125 d->height = height; 0126 0127 d->sheet->print()->updateVerticalPageParameters(row()); 0128 } 0129 0130 double RowFormat::height() const 0131 { 0132 return d->height; 0133 } 0134 0135 double RowFormat::visibleHeight() const 0136 { 0137 if (d->hide || d->filtered) 0138 return 0.0; 0139 return d->height; 0140 } 0141 0142 QDomElement RowFormat::save(QDomDocument& doc, int yshift) const 0143 { 0144 Q_ASSERT(d->sheet); 0145 QDomElement row = doc.createElement("row"); 0146 row.setAttribute("height", QString::number(d->height)); 0147 row.setAttribute("row", QString::number(d->row - yshift)); 0148 if (d->hide) 0149 row.setAttribute("hide", QString::number((int) d->hide)); 0150 0151 const Style style = d->sheet->cellStorage()->style(QRect(1, d->row, KS_colMax, 1)); 0152 if (!style.isEmpty()) { 0153 debugSheetsODF << "saving cell style of row" << d->row; 0154 QDomElement format; 0155 style.saveXML(doc, format, d->sheet->map()->styleManager()); 0156 row.appendChild(format); 0157 } 0158 0159 return row; 0160 } 0161 0162 bool RowFormat::load(const KoXmlElement & row, int yshift, Paste::Mode mode) 0163 { 0164 Q_ASSERT(d->sheet); 0165 bool ok; 0166 0167 d->row = row.attribute("row").toInt(&ok) + yshift; 0168 if (!ok) 0169 return false; 0170 0171 if (row.hasAttribute("height")) { 0172 if (d->sheet->map()->syntaxVersion() < 1) //compatibility with old format - was in millimeter 0173 d->height = qRound(MM_TO_POINT(row.attribute("height").toDouble(&ok))); 0174 else 0175 d->height = row.attribute("height").toDouble(&ok); 0176 0177 if (!ok) return false; 0178 } 0179 0180 // Validation 0181 if (d->height < 0) { 0182 debugSheets << "Value height=" << d->height << " out of range"; 0183 return false; 0184 } 0185 if (d->row < 1 || d->row > KS_rowMax) { 0186 debugSheets << "Value row=" << d->row << " out of range"; 0187 return false; 0188 } 0189 0190 if (row.hasAttribute("hide")) { 0191 setHidden((int) row.attribute("hide").toInt(&ok)); 0192 if (!ok) 0193 return false; 0194 } 0195 0196 KoXmlElement f(row.namedItem("format").toElement()); 0197 0198 if (!f.isNull() && (mode == Paste::Normal || mode == Paste::Format || mode == Paste::NoBorder)) { 0199 Style style; 0200 if (!style.loadXML(f, mode)) 0201 return false; 0202 d->sheet->cellStorage()->setStyle(Region(QRect(1, d->row, KS_colMax, 1)), style); 0203 return true; 0204 } 0205 0206 return true; 0207 } 0208 0209 int RowFormat::row() const 0210 { 0211 return d->row; 0212 } 0213 0214 void RowFormat::setRow(int row) 0215 { 0216 d->row = row; 0217 } 0218 0219 RowFormat* RowFormat::next() const 0220 { 0221 return d->next; 0222 } 0223 0224 RowFormat* RowFormat::previous() const 0225 { 0226 return d->prev; 0227 } 0228 0229 void RowFormat::setNext(RowFormat* next) 0230 { 0231 d->next = next; 0232 } 0233 0234 void RowFormat::setPrevious(RowFormat* prev) 0235 { 0236 d->prev = prev; 0237 } 0238 0239 void RowFormat::setHidden(bool _hide, bool repaint) 0240 { 0241 Q_UNUSED(repaint); 0242 Q_ASSERT(d->sheet); 0243 if (_hide != d->hide) { // only if we change the status 0244 if (_hide) { 0245 // Lower maximum size by height of row 0246 d->sheet->adjustDocumentHeight(- height()); 0247 d->hide = _hide; //hide must be set after we requested the height 0248 } else { 0249 // Rise maximum size by height of row 0250 d->hide = _hide; //unhide must be set before we request the height 0251 d->sheet->adjustDocumentHeight(height()); 0252 } 0253 } 0254 } 0255 0256 bool RowFormat::isHidden() const 0257 { 0258 return d->hide; 0259 } 0260 0261 void RowFormat::setFiltered(bool filtered) 0262 { 0263 d->filtered = filtered; 0264 } 0265 0266 bool RowFormat::isFiltered() const 0267 { 0268 return d->filtered; 0269 } 0270 0271 bool RowFormat::isHiddenOrFiltered() const 0272 { 0273 return d->hide || d->filtered; 0274 } 0275 0276 bool RowFormat::isDefault() const 0277 { 0278 return !d->sheet; 0279 } 0280 0281 void RowFormat::setPageBreak(bool enable) 0282 { 0283 d->pageBreak = enable; 0284 } 0285 0286 bool RowFormat::hasPageBreak() const 0287 { 0288 return d->pageBreak; 0289 } 0290 0291 bool RowFormat::operator==(const RowFormat& other) const 0292 { 0293 // NOTE Stefan: Don't compare sheet and cell. 0294 if (d->height != other.d->height) 0295 return false; 0296 if (d->hide != other.d->hide) 0297 return false; 0298 if (d->filtered != other.d->filtered) 0299 return false; 0300 if (d->pageBreak != other.d->pageBreak) { 0301 return false; 0302 } 0303 return true; 0304 } 0305 0306 0307 /***************************************************************************** 0308 * 0309 * ColumnFormat 0310 * 0311 *****************************************************************************/ 0312 0313 class Q_DECL_HIDDEN ColumnFormat::Private 0314 { 0315 public: 0316 Sheet* sheet; 0317 ColumnFormat* next; 0318 ColumnFormat* prev; 0319 double width; 0320 int column; 0321 bool hide : 1; 0322 bool filtered : 1; 0323 bool pageBreak : 1; // before column 0324 }; 0325 0326 ColumnFormat::ColumnFormat() 0327 : d(new Private) 0328 { 0329 d->sheet = 0; 0330 d->column = 0; 0331 d->width = 0.0; 0332 d->hide = false; 0333 d->filtered = false; 0334 d->pageBreak = false; 0335 d->next = 0; 0336 d->prev = 0; 0337 } 0338 0339 ColumnFormat::ColumnFormat(const ColumnFormat& other) 0340 : d(new Private(*other.d)) 0341 { 0342 } 0343 0344 ColumnFormat::~ColumnFormat() 0345 { 0346 if (d->next) 0347 d->next->setPrevious(d->prev); 0348 if (d->prev) 0349 d->prev->setNext(d->next); 0350 delete d; 0351 } 0352 0353 void ColumnFormat::setSheet(Sheet* sheet) 0354 { 0355 d->sheet = sheet; 0356 } 0357 0358 void ColumnFormat::setWidth(double width) 0359 { 0360 // avoid unnecessary updates 0361 if (qAbs(width - this->width()) < DBL_EPSILON) 0362 return; 0363 0364 // default ColumnFormat? 0365 if (!d->sheet) { 0366 d->width = width; 0367 return; 0368 } 0369 0370 // Raise document width by new width and lower it by old width. 0371 if (!isHidden() && !isFiltered()) 0372 d->sheet->adjustDocumentWidth(width - d->width); 0373 0374 d->width = width; 0375 0376 d->sheet->print()->updateHorizontalPageParameters(column()); 0377 } 0378 0379 double ColumnFormat::width() const 0380 { 0381 return d->width; 0382 } 0383 0384 double ColumnFormat::visibleWidth() const 0385 { 0386 if (d->hide || d->filtered) 0387 return 0.0; 0388 return d->width; 0389 } 0390 0391 QDomElement ColumnFormat::save(QDomDocument& doc, int xshift) const 0392 { 0393 Q_ASSERT(d->sheet); 0394 QDomElement col(doc.createElement("column")); 0395 col.setAttribute("width", QString::number(d->width)); 0396 col.setAttribute("column", QString::number(d->column - xshift)); 0397 0398 if (d->hide) 0399 col.setAttribute("hide", QString::number((int) d->hide)); 0400 0401 const Style style = d->sheet->cellStorage()->style(QRect(d->column, 1, 1, KS_rowMax)); 0402 if (!style.isEmpty()) { 0403 debugSheetsODF << "saving cell style of column" << d->column; 0404 QDomElement format(doc.createElement("format")); 0405 style.saveXML(doc, format, d->sheet->map()->styleManager()); 0406 col.appendChild(format); 0407 } 0408 0409 return col; 0410 } 0411 0412 bool ColumnFormat::load(const KoXmlElement & col, int xshift, Paste::Mode mode) 0413 { 0414 Q_ASSERT(d->sheet); 0415 bool ok; 0416 if (col.hasAttribute("width")) { 0417 if (d->sheet->map()->syntaxVersion() < 1) //combatibility to old format - was in millimeter 0418 d->width = qRound(MM_TO_POINT(col.attribute("width").toDouble(&ok))); 0419 else 0420 d->width = col.attribute("width").toDouble(&ok); 0421 0422 if (!ok) 0423 return false; 0424 } 0425 0426 d->column = col.attribute("column").toInt(&ok) + xshift; 0427 0428 if (!ok) 0429 return false; 0430 0431 // Validation 0432 if (d->width < 0) { 0433 debugSheets << "Value width=" << d->width << " out of range"; 0434 return false; 0435 } 0436 if (d->column < 1 || d->column > KS_colMax) { 0437 debugSheets << "Value col=" << d->column << " out of range"; 0438 return false; 0439 } 0440 if (col.hasAttribute("hide")) { 0441 setHidden((int) col.attribute("hide").toInt(&ok)); 0442 if (!ok) 0443 return false; 0444 } 0445 0446 KoXmlElement f(col.namedItem("format").toElement()); 0447 0448 if (!f.isNull() && (mode == Paste::Normal || mode == Paste::Format || mode == Paste::NoBorder)) { 0449 Style style; 0450 if (!style.loadXML(f, mode)) 0451 return false; 0452 d->sheet->cellStorage()->setStyle(Region(QRect(d->column, 1, 1, KS_rowMax)), style); 0453 return true; 0454 } 0455 0456 return true; 0457 } 0458 0459 int ColumnFormat::column() const 0460 { 0461 return d->column; 0462 } 0463 0464 void ColumnFormat::setColumn(int column) 0465 { 0466 d->column = column; 0467 } 0468 0469 ColumnFormat* ColumnFormat::next() const 0470 { 0471 return d->next; 0472 } 0473 0474 ColumnFormat* ColumnFormat::previous() const 0475 { 0476 return d->prev; 0477 } 0478 0479 void ColumnFormat::setNext(ColumnFormat* next) 0480 { 0481 d->next = next; 0482 } 0483 0484 void ColumnFormat::setPrevious(ColumnFormat* prev) 0485 { 0486 d->prev = prev; 0487 } 0488 0489 void ColumnFormat::setHidden(bool _hide) 0490 { 0491 Q_ASSERT(d->sheet); 0492 if (_hide != d->hide) { // only if we change the status 0493 if (_hide) { 0494 // Lower maximum size by width of column 0495 d->sheet->adjustDocumentWidth(- width()); 0496 d->hide = _hide; //hide must be set after we requested the width 0497 } else { 0498 // Rise maximum size by width of column 0499 d->hide = _hide; //unhide must be set before we request the width 0500 d->sheet->adjustDocumentWidth(width()); 0501 } 0502 } 0503 } 0504 0505 bool ColumnFormat::isHidden() const 0506 { 0507 return d->hide; 0508 } 0509 0510 void ColumnFormat::setFiltered(bool filtered) 0511 { 0512 d->filtered = filtered; 0513 } 0514 0515 bool ColumnFormat::isFiltered() const 0516 { 0517 return d->filtered; 0518 } 0519 0520 bool ColumnFormat::isHiddenOrFiltered() const 0521 { 0522 return d->hide || d->filtered; 0523 } 0524 0525 bool ColumnFormat::isDefault() const 0526 { 0527 return !d->sheet; 0528 } 0529 0530 void ColumnFormat::setPageBreak(bool enable) 0531 { 0532 d->pageBreak = enable; 0533 } 0534 0535 bool ColumnFormat::hasPageBreak() const 0536 { 0537 return d->pageBreak; 0538 } 0539 0540 bool ColumnFormat::operator==(const ColumnFormat& other) const 0541 { 0542 // NOTE Stefan: Don't compare sheet and cell. 0543 if (d->width != other.d->width) 0544 return false; 0545 if (d->hide != other.d->hide) 0546 return false; 0547 if (d->filtered != other.d->filtered) 0548 return false; 0549 if (d->pageBreak != other.d->pageBreak) { 0550 return false; 0551 } 0552 return true; 0553 }