1 /* This file is part of the KDE project
2    Copyright 2007,2009 Stefan Nikolaus <stefan.nikolaus@kdemail.net>
3    Copyright 1999-2007 The KSpread Team <calligra-devel@kde.org>
4    Copyright 1998,1999 Torben Weis <weis@kde.org>
5 
6    This library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Library General Public
8    License as published by the Free Software Foundation; either
9    version 2 of the License, or (at your option) any later version.
10 
11    This library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Library General Public License for more details.
15 
16    You should have received a copy of the GNU Library General Public License
17    along with this library; see the file COPYING.LIB.  If not, write to
18    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19    Boston, MA 02110-1301, USA.
20 */
21 
22 #include "CopyCommand.h"
23 
24 #include "CellStorage.h"
25 #include "Map.h"
26 #include "Region.h"
27 #include "RowColumnFormat.h"
28 #include "RowFormatStorage.h"
29 #include "Sheet.h"
30 
31 using namespace Calligra::Sheets;
32 
33 // era: encode references absolutely
saveAsXml(const Region & region,bool era)34 QDomDocument CopyCommand::saveAsXml(const Region& region, bool era)
35 {
36     QDomDocument xmlDoc("spreadsheet-snippet");
37     xmlDoc.appendChild(xmlDoc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\""));
38     QDomElement root = xmlDoc.createElement("spreadsheet-snippet");
39     xmlDoc.appendChild(root);
40 
41     // find the upper left corner of the selection
42     const QRect boundingRect = region.boundingRect();
43     int left = boundingRect.left();
44     int top = boundingRect.top();
45 
46     // for tiling the clipboard content in the selection
47     root.setAttribute("rows", QString::number(boundingRect.height()));
48     root.setAttribute("columns", QString::number(boundingRect.width()));
49 
50     const Region::ConstIterator end(region.constEnd());
51     for (Region::ConstIterator it = region.constBegin(); it != end; ++it) {
52         Sheet *const sheet = (*it)->sheet();
53         const QRect range = (*it)->rect();
54         CellStorage *const storage = sheet->cellStorage();
55 
56         //
57         // Entire rows selected?
58         //
59         if ((*it)->isRow()) {
60             QDomElement rows = xmlDoc.createElement("rows");
61             rows.setAttribute("count", QString::number(range.height()));
62             rows.setAttribute("row", QString::number(range.top() - top + 1));
63             root.appendChild(rows);
64 
65             // Save all cells.
66             for (int row = range.top(); row <= range.bottom(); ++row) {
67                 Cell cell = storage->firstInRow(row);
68                 for (; !cell.isNull(); cell = storage->nextInRow(cell.column(), cell.row())) {
69                     if (!cell.isPartOfMerged()) {
70                         root.appendChild(cell.save(xmlDoc, 0, top - 1, era));
71                     }
72                 }
73             }
74 
75             // TODO Stefan: Inefficient, use cluster functionality
76             // Save the row formats if there are any
77             //const RowFormat* format;
78             for (int row = range.top(); row <= range.bottom(); ++row) {
79                 if (!sheet->rowFormats()->isDefaultRow(row)) {
80                     QDomElement e = RowFormat(sheet->rowFormats(), row).save(xmlDoc, top - 1);
81                     if (!e.isNull()) {
82                         rows.appendChild(e);
83                     }
84                 }
85             }
86             continue;
87         }
88 
89         //
90         // Entire columns selected?
91         //
92         if ((*it)->isColumn()) {
93             QDomElement columns = xmlDoc.createElement("columns");
94             columns.setAttribute("count", QString::number(range.width()));
95             columns.setAttribute("column", QString::number(range.left() - left + 1));
96             root.appendChild(columns);
97 
98             // Save all cells.
99             for (int col = range.left(); col <= range.right(); ++col) {
100                 Cell cell = storage->firstInColumn(col);
101                 for (; !cell.isNull(); cell = storage->nextInColumn(cell.column(), cell.row())) {
102                     if (!cell.isPartOfMerged()) {
103                         root.appendChild(cell.save(xmlDoc, left - 1, 0, era));
104                     }
105                 }
106             }
107 
108             // TODO Stefan: Inefficient, use the cluster functionality
109             // Save the column formats if there are any
110             const ColumnFormat* format;
111             for (int col = range.left(); col <= range.right(); ++col) {
112                 format = sheet->columnFormat(col);
113                 if (format && !format->isDefault()) {
114                     QDomElement e = format->save(xmlDoc, left - 1);
115                     if (!e.isNull()) {
116                         columns.appendChild(e);
117                     }
118                 }
119             }
120             continue;
121         }
122 
123         // Save all cells.
124         Cell cell;
125         for (int row = range.top(); row <= range.bottom(); ++row) {
126             if (range.left() == 1) {
127                 cell = storage->firstInRow(row);
128             } else {
129                 cell = storage->nextInRow(range.left() - 1, row);
130             }
131             while (!cell.isNull() && cell.column() >= range.left() && cell.column() <= range.right()) {
132                 if (!cell.isPartOfMerged()) {
133                     root.appendChild(cell.save(xmlDoc, left - 1, top - 1, era));
134                 }
135                 cell = storage->nextInRow(cell.column(), cell.row());
136             }
137         }
138     }
139     return xmlDoc;
140 }
141 
cellAsText(const Cell & cell,bool addTab)142 static QString cellAsText(const Cell& cell, bool addTab)
143 {
144     QString result;
145     if (!cell.isDefault()) {
146         result += cell.displayText();
147     }
148     if (addTab) {
149         result += '\t';
150     }
151     return result;
152 }
153 
saveAsPlainText(const Region & region)154 QString CopyCommand::saveAsPlainText(const Region &region)
155 {
156     // Only one cell selected? => copy active cell
157     if (region.isSingular()) {
158         const Cell cell(region.firstSheet(), region.firstRange().topLeft());
159         return cell.displayText();
160     }
161 
162     QString result;
163     Region::ConstIterator end(region.constEnd());
164     for (Region::ConstIterator it(region.constBegin()); it != end; ++it) {
165       if (result.length()) result += QLatin1Char('\n');
166       Region::Element *el = *it;
167       QRect used = el->sheet()->usedArea (true);
168       QRect rect = el->rect().intersected (used);
169       for (int row = rect.top(); row <= rect.bottom(); ++row) {
170         for (int col = rect.left(); col <= rect.right(); ++col) {
171           Cell cell (el->sheet(), col, row);
172           result += cellAsText (cell, col != rect.right());
173         }
174         result += QLatin1Char('\n');
175       }
176     }
177     return result;
178 }
179 
saveAsHtml(const Region & region)180 QDomDocument CopyCommand::saveAsHtml(const Region &region)
181 {
182     QDomDocument doc("spreadsheet-html");
183     QDomElement html = doc.createElement("html");
184     doc.appendChild(html);
185     QDomElement body = doc.createElement("body");
186     html.appendChild(body);
187     QDomElement table = doc.createElement("table");
188     body.appendChild(table);
189 
190     const Region::ConstIterator end(region.constEnd());
191     for (Region::ConstIterator it(region.constBegin()); it != end; ++it) {
192         Sheet *const sheet = (*it)->sheet();
193         const QRect range = (*it)->rect();
194 
195         // TODO
196         Q_UNUSED(sheet);
197         Q_UNUSED(range);
198     }
199     return doc;
200 }
201 
saveAsCSV(const Region & region)202 QString CopyCommand::saveAsCSV(const Region &region)
203 {
204     // TODO
205     Q_UNUSED(region);
206     return QString();
207 }
208