filters

opencalcstyleexport.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2003 Norbert Andres <nandres@web.de>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18*/
19
20#include <opencalcstyleexport.h>
21
22#include <KoGlobal.h>
23
24#include <kspread_cell.h>
25#include <kspread_doc.h>
26#include <kspread_format.h>
27#include <kspread_sheet.h>
28#include <kspread_style.h>
29#include <kspread_style_manager.h>
30
31#include <tqdom.h>
32
33using namespace KSpread;
34
35OpenCalcStyles::OpenCalcStyles()
36{
37 m_cellStyles.setAutoDelete( true );
38 m_columnStyles.setAutoDelete( true );
39 m_numberStyles.setAutoDelete( true );
40 m_rowStyles.setAutoDelete( true );
41 m_sheetStyles.setAutoDelete( true );
42
43 m_fontList.setAutoDelete( true );
44}
45
46OpenCalcStyles::~OpenCalcStyles()
47{
48}
49
50void OpenCalcStyles::writeStyles( TQDomDocument & doc, TQDomElement & autoStyles )
51{
52 addColumnStyles( doc, autoStyles );
53 addRowStyles( doc, autoStyles );
54 addSheetStyles( doc, autoStyles );
55 addNumberStyles( doc, autoStyles );
56 addCellStyles( doc, autoStyles );
57}
58
59void OpenCalcStyles::writeFontDecl( TQDomDocument & doc, TQDomElement & fontDecls )
60{
61 TQFont * f = m_fontList.first();
62 while ( f )
63 {
64 TQDomElement fontDecl = doc.createElement( "style:font-decl" );
65
66 fontDecl.setAttribute( "style:name", f->family() );
67 fontDecl.setAttribute( "fo:font-family", f->family() );
68 fontDecl.setAttribute( "style:font-pitch", ( f->fixedPitch() ? "fixed" : "variable" ) );
69
70 // missing:
71 // style:font-charset="x-symbol" style:font-family-generic="swiss"
72 // style:font-style-name= "Bold/Standard/Regular"
73
74 fontDecls.appendChild( fontDecl );
75
76 f = m_fontList.next();
77 }
78}
79
80void OpenCalcStyles::addFont( TQFont const & font, bool def )
81{
82 if ( def )
83 m_defaultFont = font;
84
85 TQFont * f = m_fontList.first();
86 while ( f )
87 {
88 if ( f->family() == font.family() )
89 return;
90
91 f = m_fontList.next();
92 }
93
94 f = new TQFont( font );
95 m_fontList.append( f );
96}
97
98TQString OpenCalcStyles::cellStyle( CellStyle const & cs )
99{
100 CellStyle * t = m_cellStyles.first();
101 while ( t )
102 {
103 if ( CellStyle::isEqual( t, cs ) )
104 return t->name;
105
106 t = m_cellStyles.next();
107 }
108
109 t = new CellStyle();
110 t->copyData( cs );
111
112 m_cellStyles.append( t );
113
114 t->name = TQString( "ce%1" ).arg( m_cellStyles.count() );
115
116 return t->name;
117}
118
119TQString OpenCalcStyles::columnStyle( ColumnStyle const & cs )
120{
121 ColumnStyle * t = m_columnStyles.first();
122 while ( t )
123 {
124 if ( ColumnStyle::isEqual( t, cs ) )
125 return t->name;
126
127 t = m_columnStyles.next();
128 }
129
130 t = new ColumnStyle();
131 t->copyData( cs );
132
133 m_columnStyles.append( t );
134
135 t->name = TQString( "co%1" ).arg( m_columnStyles.count() );
136
137 return t->name;
138}
139
140TQString OpenCalcStyles::numberStyle( NumberStyle const & )
141{
142 return "";
143}
144
145TQString OpenCalcStyles::rowStyle( RowStyle const & rs )
146{
147 RowStyle * t = m_rowStyles.first();
148 while ( t )
149 {
150 if ( RowStyle::isEqual( t, rs ) )
151 return t->name;
152
153 t = m_rowStyles.next();
154 }
155
156 t = new RowStyle();
157 t->copyData( rs );
158
159 m_rowStyles.append( t );
160
161 t->name = TQString( "ro%1" ).arg( m_rowStyles.count() );
162
163 return t->name;
164}
165
166TQString OpenCalcStyles::sheetStyle( SheetStyle const & ts )
167{
168 SheetStyle * t = m_sheetStyles.first();
169 while ( t )
170 {
171 if ( SheetStyle::isEqual( t, ts ) )
172 return t->name;
173
174 t = m_sheetStyles.next();
175 }
176
177 t = new SheetStyle();
178 t->copyData( ts );
179
180 m_sheetStyles.append( t );
181
182 t->name = TQString( "ta%1" ).arg( m_sheetStyles.count() );
183
184 return t->name;
185}
186
187TQString convertPenToString( TQPen const & pen )
188{
189 TQString s( TQString( "%1cm solid " ).arg( pen.width() * 0.035 ) );
190 s += pen.color().name();
191
192 return s;
193}
194
195void OpenCalcStyles::addCellStyles( TQDomDocument & doc, TQDomElement & autoStyles )
196{
197 CellStyle * t = m_cellStyles.first();
198 while ( t )
199 {
200 TQDomElement ts = doc.createElement( "style:style" );
201 ts.setAttribute( "style:name", t->name );
202 ts.setAttribute( "style:family", "table-cell" );
203 ts.setAttribute( "style:parent-style-name", "Default" );
204 if ( t->numberStyle.length() > 0 )
205 ts.setAttribute( "style:data-style-name", t->numberStyle );
206
207 TQDomElement prop = doc.createElement( "style:properties" );
208
209 if ( t->font.family() != m_defaultFont.family() )
210 prop.setAttribute( "style:font-name", t->font.family() );
211
212 if ( t->font.bold() != m_defaultFont.bold() )
213 prop.setAttribute( "fo:font-weight", ( t->font.bold() ? "bold" : "light" ) );
214
215 prop.setAttribute( "fo:font-size", TQString( "%1pt" ).arg( t->font.pointSize() ) );
216
217 if ( t->font.underline() != m_defaultFont.underline() )
218 {
219 prop.setAttribute( "style:text-underline", ( t->font.underline() ? "single" : "none" ) );
220 if ( t->font.underline() )
221 prop.setAttribute( "style:text-underline-color", "font-color" );
222 }
223
224 if ( t->font.italic() != m_defaultFont.italic() )
225 prop.setAttribute( "fo:font-style", ( t->font.italic() ? "italic" : "none" ) );
226
227 if ( t->font.strikeOut() != m_defaultFont.strikeOut() )
228 prop.setAttribute( "style:text-crossing-out", ( t->font.strikeOut() ? "single-line" : "none" ) );
229
230 if ( t->color.name() != "#000000" )
231 prop.setAttribute( "fo:color", t->color.name() );
232
233 if ( t->bgColor.name() != "#ffffff" )
234 prop.setAttribute( "fo:background-color", t->bgColor.name() );
235
236 if ( t->alignX != Format::Undefined )
237 {
238 TQString value;
239 if ( t->alignX == Format::Center )
240 value = "center";
241 else if ( t->alignX == Format::Right )
242 value = "end";
243 else if ( t->alignX == Format::Left )
244 value = "start";
245 prop.setAttribute( "fo:text-align", value );
246 }
247
248 if ( t->alignY != Format::Bottom ) // default in OpenCalc
249 prop.setAttribute( "fo:vertical-align", ( t->alignY == Format::Middle ? "middle" : "top" ) );
250
251 if ( t->indent > 0.0 )
252 {
253 prop.setAttribute( "fo:margin-left", TQString( "%1pt" ).arg( t->indent ) );
254 if ( t->alignX == Format::Undefined )
255 prop.setAttribute( "fo:text-align", "start" );
256 }
257
258 if ( t->wrap )
259 prop.setAttribute( "fo:wrap-option", "wrap" );
260
261 if ( t->vertical )
262 {
263 prop.setAttribute( "fo:direction", "ttb" );
264 prop.setAttribute( "style:rotation-angle", "0" );
265 }
266
267 if ( t->angle != 0 )
268 prop.setAttribute( "style:rotation-angle", TQString::number( t->angle ) );
269
270 if ( !t->print )
271 prop.setAttribute( "style:print-content", "false" );
272
273 if ( t->hideAll )
274 prop.setAttribute( "style:cell-protect", "hidden-and-protected" );
275 else
276 if ( t->notProtected && !t->hideFormula )
277 prop.setAttribute( "style:cell-protect", "none" );
278 else
279 if ( t->notProtected && t->hideFormula )
280 prop.setAttribute( "style:cell-protect", "formula-hidden" );
281 else if ( t->hideFormula )
282 prop.setAttribute( "style:cell-protect", "protected formula-hidden" );
283 else if ( !t->notProtected )
284 prop.setAttribute( "style:cell-protect", "protected" );
285
286
287 if ( ( t->left == t->right ) && ( t->left == t->top ) && ( t->left == t->bottom ) )
288 {
289 if ( ( t->left.width() != 0 ) && ( t->left.style() != TQt::NoPen ) )
290 prop.setAttribute( "fo:border", convertPenToString( t->left ) );
291 }
292 else
293 {
294 if ( ( t->left.width() != 0 ) && ( t->left.style() != TQt::NoPen ) )
295 prop.setAttribute( "fo:border-left", convertPenToString( t->left ) );
296
297 if ( ( t->right.width() != 0 ) && ( t->right.style() != TQt::NoPen ) )
298 prop.setAttribute( "fo:border-right", convertPenToString( t->right ) );
299
300 if ( ( t->top.width() != 0 ) && ( t->top.style() != TQt::NoPen ) )
301 prop.setAttribute( "fo:border-top", convertPenToString( t->top ) );
302
303 if ( ( t->bottom.width() != 0 ) && ( t->bottom.style() != TQt::NoPen ) )
304 prop.setAttribute( "fo:border-bottom", convertPenToString( t->bottom ) );
305 }
306
307 ts.appendChild( prop );
308 autoStyles.appendChild( ts );
309
310 t = m_cellStyles.next();
311 }
312}
313
314void OpenCalcStyles::addColumnStyles( TQDomDocument & doc, TQDomElement & autoStyles )
315{
316 ColumnStyle * t = m_columnStyles.first();
317 while ( t )
318 {
319 TQDomElement ts = doc.createElement( "style:style" );
320 ts.setAttribute( "style:name", t->name );
321 ts.setAttribute( "style:family", "table-column" );
322
323 TQDomElement prop = doc.createElement( "style:properties" );
324 if ( t->breakB != ::Style::none )
325 prop.setAttribute( "fo:break-before", ( t->breakB == ::Style::automatic ? "auto" : "page" ) );
326 prop.setAttribute( "style:column-width", TQString( "%1cm" ).arg( t->size ) );
327
328 ts.appendChild( prop );
329 autoStyles.appendChild( ts );
330
331 t = m_columnStyles.next();
332 }
333}
334
335void OpenCalcStyles::addNumberStyles( TQDomDocument & /*doc*/, TQDomElement & /*autoStyles*/ )
336{
337}
338
339void OpenCalcStyles::addRowStyles( TQDomDocument & doc, TQDomElement & autoStyles )
340{
341 RowStyle * t = m_rowStyles.first();
342 while ( t )
343 {
344 TQDomElement ts = doc.createElement( "style:style" );
345 ts.setAttribute( "style:name", t->name );
346 ts.setAttribute( "style:family", "table-row" );
347
348 TQDomElement prop = doc.createElement( "style:properties" );
349 prop.setAttribute( "style:row-height", TQString( "%1cm" ).arg( t->size ) );
350 if ( t->breakB != ::Style::none )
351 prop.setAttribute( "fo:break-before", ( t->breakB == ::Style::automatic ? "auto" : "page" ) );
352
353 ts.appendChild( prop );
354 autoStyles.appendChild( ts );
355
356 t = m_rowStyles.next();
357 }
358}
359
360void OpenCalcStyles::addSheetStyles( TQDomDocument & doc, TQDomElement & autoStyles )
361{
362 SheetStyle * t = m_sheetStyles.first();
363 while ( t )
364 {
365 TQDomElement ts = doc.createElement( "style:style" );
366 ts.setAttribute( "style:name", t->name );
367 ts.setAttribute( "style:family", "table" );
368 ts.setAttribute( "style:master-page-name", "Default" );
369
370 TQDomElement prop = doc.createElement( "style:properties" );
371 prop.setAttribute( "table:display", ( t->visible ? "true" : "false" ) );
372
373 ts.appendChild( prop );
374 autoStyles.appendChild( ts );
375
376 t = m_sheetStyles.next();
377 }
378}
379
380bool SheetStyle::isEqual( SheetStyle const * const t1, SheetStyle const & t2 )
381{
382 if ( t1->visible == t2.visible )
383 return true;
384
385 return false;
386}
387
388CellStyle::CellStyle()
389 : color( TQt::black ),
390 bgColor( TQt::white ),
391 indent( -1.0 ),
392 wrap( false ),
393 vertical( false ),
394 angle( 0 ),
395 print( true ),
396 left ( TQt::black, 0, TQt::NoPen ),
397 right( TQt::black, 0, TQt::NoPen ),
398 top ( TQt::black, 0, TQt::NoPen ),
399 bottom( TQt::black, 0, TQt::NoPen ),
400 hideAll( false ),
401 hideFormula( false ),
402 notProtected ( false ),
403 alignX( Format::Undefined ),
404 alignY( Format::Middle )
405{
406}
407
408void CellStyle::copyData( CellStyle const & ts )
409{
410 font = ts.font;
411 numberStyle = ts.numberStyle;
412 color = ts.color;
413 bgColor = ts.bgColor;
414 indent = ts.indent;
415 wrap = ts.wrap;
416 vertical = ts.vertical;
417 angle = ts.angle;
418 print = ts.print;
419 left = ts.left;
420 right = ts.right;
421 top = ts.top;
422 bottom = ts.bottom;
423 hideAll = ts.hideAll;
424 hideFormula = ts.hideFormula;
425 notProtected = ts.notProtected;
426 alignX = ts.alignX;
427 alignY = ts.alignY;
428}
429
430bool CellStyle::isEqual( CellStyle const * const t1, CellStyle const & t2 )
431{
432 if ( ( t1->font == t2.font ) && ( t1->numberStyle == t2.numberStyle )
433 && ( t1->color == t2.color ) && ( t1->bgColor == t2.bgColor )
434 && ( t1->alignX == t2.alignX ) && ( t1->alignY == t2.alignY )
435 && ( t1->indent == t2.indent ) && ( t1->wrap == t2.wrap )
436 && ( t1->vertical == t2.vertical ) && ( t1->angle == t2.angle )
437 && ( t1->print == t2.print ) && ( t1->left == t2.left )
438 && ( t1->right == t2.right ) && ( t1->top == t2.top )
439 && ( t1->bottom == t2.bottom ) && ( t1->hideAll == t2.hideAll )
440 && ( t1->hideFormula == t2.hideFormula ) && ( t1->notProtected == t2.notProtected )
441 )
442 return true;
443
444 return false;
445}
446
447// all except the number style
448void CellStyle::loadData( CellStyle & cs, Cell const * const cell )
449{
450 int col = cell->column();
451 int row = cell->row();
452
453 Format * f = new Format( 0, cell->sheet()->doc()->styleManager()->defaultStyle() );
454
455 TQFont font = cell->format()->textFont( col, row );
456 if ( font != f->font() )
457 cs.font = font;
458
459 TQColor color = cell->format()->textColor( col, row );
460 if ( color != f->textColor( col, row ) )
461 cs.color = color;
462
463 TQColor bgColor = cell->bgColor( col, row );
464 if ( bgColor != f->bgColor( col, row ) )
465 cs.bgColor = bgColor;
466
467 if ( cell->format()->hasProperty( Format::PAlign ) || !cell->format()->hasNoFallBackProperties( Format::PAlign ) )
468 cs.alignX = cell->format()->align( col, row );
469
470 if ( cell->format()->hasProperty( Format::PAlignY ) || !cell->format()->hasNoFallBackProperties( Format::PAlignY ) )
471 cs.alignY = cell->format()->alignY( col, row );
472
473 if ( cell->format()->hasProperty( Format::PIndent ) || !cell->format()->hasNoFallBackProperties( Format::PIndent ) )
474 cs.indent = cell->format()->getIndent( col, row );
475
476 if ( cell->format()->hasProperty( Format::PAngle ) || !cell->format()->hasNoFallBackProperties( Format::PAngle ) )
477 cs.angle = -cell->format()->getAngle( col, row );
478
479 if ( cell->format()->hasProperty( Format::PMultiRow ) || !cell->format()->hasNoFallBackProperties( Format::PMultiRow ) )
480 cs.wrap = cell->format()->multiRow( col, row );
481
482 if ( cell->format()->hasProperty( Format::PVerticalText )
483 || !cell->format()->hasNoFallBackProperties( Format::PVerticalText ) )
484 cs.vertical = cell->format()->verticalText( col, row );
485
486 if ( cell->format()->hasProperty( Format::PDontPrintText )
487 || !cell->format()->hasNoFallBackProperties( Format::PDontPrintText ) )
488 cs.print = !cell->format()->getDontprintText( col, row );
489
490 if ( cell->format()->hasProperty( Format::PLeftBorder ) || !cell->format()->hasNoFallBackProperties( Format::PLeftBorder ) )
491 cs.left = cell->leftBorderPen( col, row );
492
493 if ( cell->format()->hasProperty( Format::PRightBorder ) || !cell->format()->hasNoFallBackProperties( Format::PRightBorder ) )
494 cs.right = cell->rightBorderPen( col, row );
495
496 if ( cell->format()->hasProperty( Format::PTopBorder ) || !cell->format()->hasNoFallBackProperties( Format::PTopBorder ) )
497 cs.top = cell->topBorderPen( col, row );
498
499 if ( cell->format()->hasProperty( Format::PBottomBorder ) || !cell->format()->hasNoFallBackProperties( Format::PBottomBorder ) )
500 cs.bottom = cell->bottomBorderPen( col, row );
501
502 if ( cell->format()->hasProperty( Format::PNotProtected ) || !cell->format()->hasNoFallBackProperties( Format::PNotProtected ) )
503 cs.notProtected = cell->format()->notProtected( col, row );
504
505 if ( cell->format()->hasProperty( Format::PHideAll ) || !cell->format()->hasNoFallBackProperties( Format::PHideAll ) )
506 cs.hideAll = cell->format()->isHideAll( col, row );
507
508 if ( cell->format()->hasProperty( Format::PHideFormula ) || !cell->format()->hasNoFallBackProperties( Format::PHideFormula ) )
509 cs.hideFormula = cell->format()->isHideFormula( col, row );
510}
511
512bool NumberStyle::isEqual( NumberStyle const * const t1, NumberStyle const & t2 )
513{
514 if ( ( t1->type == t2.type ) && ( t1->pattern == t2.pattern ) )
515 return true;
516
517 return false;
518}
519
520void ColumnStyle::copyData( ColumnStyle const & cs )
521{
522 breakB = cs.breakB;
523 size = cs.size;
524}
525
526bool ColumnStyle::isEqual( ColumnStyle const * const c1, ColumnStyle const & c2 )
527{
528 if ( ( c1->breakB == c2.breakB ) && ( c1->size == c2.size ) )
529 return true;
530
531 return false;
532}
533
534void RowStyle::copyData( RowStyle const & cs )
535{
536 breakB = cs.breakB;
537 size = cs.size;
538}
539
540bool RowStyle::isEqual( RowStyle const * const c1, RowStyle const & c2 )
541{
542 if ( ( c1->breakB == c2.breakB ) && ( c1->size == c2.size ) )
543 return true;
544
545 return false;
546}
This class describe a cell, row or column format.