File indexing completed on 2024-05-19 16:08:00

0001 /* This file is part of the KDE project
0002    Copyright 2007,2009 Stefan Nikolaus <stefan.nikolaus@kdemail.net>
0003    Copyright 1999-2007 The KSpread Team <calligra-devel@kde.org>
0004    Copyright 1998,1999 Torben Weis <weis@kde.org>
0005 
0006    This library is free software; you can redistribute it and/or
0007    modify it under the terms of the GNU Library General Public
0008    License as published by the Free Software Foundation; either
0009    version 2 of the License, or (at your option) any later version.
0010 
0011    This library is distributed in the hope that it will be useful,
0012    but WITHOUT ANY WARRANTY; without even the implied warranty of
0013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0014    Library General Public License for more details.
0015 
0016    You should have received a copy of the GNU Library General Public License
0017    along with this library; see the file COPYING.LIB.  If not, write to
0018    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0019    Boston, MA 02110-1301, USA.
0020 */
0021 
0022 #include "CopyCommand.h"
0023 
0024 #include "CellStorage.h"
0025 #include "Map.h"
0026 #include "Region.h"
0027 #include "RowColumnFormat.h"
0028 #include "RowFormatStorage.h"
0029 #include "Sheet.h"
0030 
0031 using namespace Calligra::Sheets;
0032 
0033 // era: encode references absolutely
0034 QDomDocument CopyCommand::saveAsXml(const Region& region, bool era)
0035 {
0036     QDomDocument xmlDoc("spreadsheet-snippet");
0037     xmlDoc.appendChild(xmlDoc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\""));
0038     QDomElement root = xmlDoc.createElement("spreadsheet-snippet");
0039     xmlDoc.appendChild(root);
0040 
0041     // find the upper left corner of the selection
0042     const QRect boundingRect = region.boundingRect();
0043     int left = boundingRect.left();
0044     int top = boundingRect.top();
0045 
0046     // for tiling the clipboard content in the selection
0047     root.setAttribute("rows", QString::number(boundingRect.height()));
0048     root.setAttribute("columns", QString::number(boundingRect.width()));
0049 
0050     const Region::ConstIterator end(region.constEnd());
0051     for (Region::ConstIterator it = region.constBegin(); it != end; ++it) {
0052         Sheet *const sheet = (*it)->sheet();
0053         const QRect range = (*it)->rect();
0054         CellStorage *const storage = sheet->cellStorage();
0055 
0056         //
0057         // Entire rows selected?
0058         //
0059         if ((*it)->isRow()) {
0060             QDomElement rows = xmlDoc.createElement("rows");
0061             rows.setAttribute("count", QString::number(range.height()));
0062             rows.setAttribute("row", QString::number(range.top() - top + 1));
0063             root.appendChild(rows);
0064 
0065             // Save all cells.
0066             for (int row = range.top(); row <= range.bottom(); ++row) {
0067                 Cell cell = storage->firstInRow(row);
0068                 for (; !cell.isNull(); cell = storage->nextInRow(cell.column(), cell.row())) {
0069                     if (!cell.isPartOfMerged()) {
0070                         root.appendChild(cell.save(xmlDoc, 0, top - 1, era));
0071                     }
0072                 }
0073             }
0074 
0075             // TODO Stefan: Inefficient, use cluster functionality
0076             // Save the row formats if there are any
0077             //const RowFormat* format;
0078             for (int row = range.top(); row <= range.bottom(); ++row) {
0079                 if (!sheet->rowFormats()->isDefaultRow(row)) {
0080                     QDomElement e = RowFormat(sheet->rowFormats(), row).save(xmlDoc, top - 1);
0081                     if (!e.isNull()) {
0082                         rows.appendChild(e);
0083                     }
0084                 }
0085             }
0086             continue;
0087         }
0088 
0089         //
0090         // Entire columns selected?
0091         //
0092         if ((*it)->isColumn()) {
0093             QDomElement columns = xmlDoc.createElement("columns");
0094             columns.setAttribute("count", QString::number(range.width()));
0095             columns.setAttribute("column", QString::number(range.left() - left + 1));
0096             root.appendChild(columns);
0097 
0098             // Save all cells.
0099             for (int col = range.left(); col <= range.right(); ++col) {
0100                 Cell cell = storage->firstInColumn(col);
0101                 for (; !cell.isNull(); cell = storage->nextInColumn(cell.column(), cell.row())) {
0102                     if (!cell.isPartOfMerged()) {
0103                         root.appendChild(cell.save(xmlDoc, left - 1, 0, era));
0104                     }
0105                 }
0106             }
0107 
0108             // TODO Stefan: Inefficient, use the cluster functionality
0109             // Save the column formats if there are any
0110             const ColumnFormat* format;
0111             for (int col = range.left(); col <= range.right(); ++col) {
0112                 format = sheet->columnFormat(col);
0113                 if (format && !format->isDefault()) {
0114                     QDomElement e = format->save(xmlDoc, left - 1);
0115                     if (!e.isNull()) {
0116                         columns.appendChild(e);
0117                     }
0118                 }
0119             }
0120             continue;
0121         }
0122 
0123         // Save all cells.
0124         Cell cell;
0125         for (int row = range.top(); row <= range.bottom(); ++row) {
0126             if (range.left() == 1) {
0127                 cell = storage->firstInRow(row);
0128             } else {
0129                 cell = storage->nextInRow(range.left() - 1, row);
0130             }
0131             while (!cell.isNull() && cell.column() >= range.left() && cell.column() <= range.right()) {
0132                 if (!cell.isPartOfMerged()) {
0133                     root.appendChild(cell.save(xmlDoc, left - 1, top - 1, era));
0134                 }
0135                 cell = storage->nextInRow(cell.column(), cell.row());
0136             }
0137         }
0138     }
0139     return xmlDoc;
0140 }
0141 
0142 static QString cellAsText(const Cell& cell, bool addTab)
0143 {
0144     QString result;
0145     if (!cell.isDefault()) {
0146         result += cell.displayText();
0147     }
0148     if (addTab) {
0149         result += '\t';
0150     }
0151     return result;
0152 }
0153 
0154 QString CopyCommand::saveAsPlainText(const Region &region)
0155 {
0156     // Only one cell selected? => copy active cell
0157     if (region.isSingular()) {
0158         const Cell cell(region.firstSheet(), region.firstRange().topLeft());
0159         return cell.displayText();
0160     }
0161 
0162     QString result;
0163     Region::ConstIterator end(region.constEnd());
0164     for (Region::ConstIterator it(region.constBegin()); it != end; ++it) {
0165       if (result.length()) result += QLatin1Char('\n');
0166       Region::Element *el = *it;
0167       QRect used = el->sheet()->usedArea (true);
0168       QRect rect = el->rect().intersected (used);
0169       for (int row = rect.top(); row <= rect.bottom(); ++row) {
0170         for (int col = rect.left(); col <= rect.right(); ++col) {
0171           Cell cell (el->sheet(), col, row);
0172           result += cellAsText (cell, col != rect.right());
0173         }
0174         result += QLatin1Char('\n');
0175       }
0176     }
0177     return result;
0178 }
0179 
0180 QDomDocument CopyCommand::saveAsHtml(const Region &region)
0181 {
0182     QDomDocument doc("spreadsheet-html");
0183     QDomElement html = doc.createElement("html");
0184     doc.appendChild(html);
0185     QDomElement body = doc.createElement("body");
0186     html.appendChild(body);
0187     QDomElement table = doc.createElement("table");
0188     body.appendChild(table);
0189 
0190     const Region::ConstIterator end(region.constEnd());
0191     for (Region::ConstIterator it(region.constBegin()); it != end; ++it) {
0192         Sheet *const sheet = (*it)->sheet();
0193         const QRect range = (*it)->rect();
0194 
0195         // TODO
0196         Q_UNUSED(sheet);
0197         Q_UNUSED(range);
0198     }
0199     return doc;
0200 }
0201 
0202 QString CopyCommand::saveAsCSV(const Region &region)
0203 {
0204     // TODO
0205     Q_UNUSED(region);
0206     return QString();
0207 }