kchart

kchart_part.cpp
1
5
6#include <float.h> // For basic data types characteristics.
7
8// For debugging
9#include <iostream>
10using std::cout;
11using std::cerr;
12
13#include "kchart_part.h"
14#include "kchart_view.h"
15#include "kchart_factory.h"
16#include "kchartWizard.h"
17#include "kchart_params.h"
18#include "kdchart/KDChart.h"
19#include "kdchart/KDChartTable.h"
20
21#include <KoTemplateChooseDia.h>
22#include <KoDom.h>
23#include <KoXmlNS.h>
24#include <KoXmlWriter.h>
25#include <KoOasisStore.h>
26#include <KoOasisLoadingContext.h>
27
28#include <kstandarddirs.h>
29#include <tdeglobal.h>
30#include <kdebug.h>
31
32#include <tqdom.h>
33#include <tqtextstream.h>
34#include <tqbuffer.h>
35#include <tqpainter.h>
36
37using namespace std;
38
39// Some hardcoded data for a chart
40
41/* ----- set some data ----- */
42// float a[6] = { 0.5, 0.09, 0.6, 0.85, 0.0, 0.90 },
43// b[6] = { 1.9, 1.3, 0.6, 0.75, 0.1, -2.0 };
44/* ----- X labels ----- */
45// char *t[6] = { "Chicago", "New York", "L.A.", "Atlanta", "Paris, MD\n(USA) ", "London" };
46/* ----- data set colors (RGB) ----- */
47// TQColor sc[2] = { TQColor( 255, 128, 128 ), TQColor( 128, 128, 255 ) };
48
49
50namespace KChart
51{
52
53KChartPart::KChartPart( TQWidget *parentWidget, const char *widgetName,
54 TQObject* parent, const char* name,
55 bool singleViewMode )
56 : KoChart::Part( parentWidget, widgetName, parent, name, singleViewMode ),
57 m_params( 0 ),
58 m_parentWidget( parentWidget ),
59 m_rowLabels(), m_colLabels()
60{
61 kdDebug(35001) << "Constructor started!" << endl;
62
63 setInstance( KChartFactory::global(), false );
64 setTemplateType( "kchart_template" );
65
66 // Init some members that need it.
67 {
68 // Create the chart parameters and let the default be a bar chart
69 // with 3D looks.
70 m_params = new KChartParams( this );
71 m_params->setChartType( KChartParams::Bar );
72 m_params->setBarChartSubType( KChartParams::BarNormal );
73 m_params->setThreeDBars( true );
74
75 //Changed this to use columns rather than rows by default
76 //because I believe that this is the more common format for
77 //entering data (you can see this looking at the fact that
78 //most spreadsheet packages allow far more rows than columns)
79 //-- Robert Knight
80
81 // Handle data in columns by default
82 m_params->setDataDirection( KChartParams::DataColumns );
83 }
84
85 (void)new WizardExt( this );
86 m_bCanChangeValue = true;
87
88 // Display parameters
89 m_displayData = m_currentData;
90
91 // Set the size to minimal.
92 initEmpty();
93}
94
95
96KChartPart::~KChartPart()
97{
98 //kdDebug(35001) << "Part is going to be destroyed now!!!" << endl;
99 delete m_params;
100}
101
102
103// Reimplement KoDocument::initDoc()
104
105bool KChartPart::initDoc(InitDocFlags flags, TQWidget* parentWidget)
106{
107 // Initialize the parameter set for this chart document
108#if 0
109 kdDebug(35001) << "================================================================" << endl;
110 kdDebug(35001) << "InitDOC: flags = " << flags << endl;
111 kdDebug(35001) << "================================================================" << endl;
112#endif
113
114 TQString f;
115
116 // Embedded documents are initially created like a normal empty
117 // document. If this is in KSpread or another program where the
118 // data is external then the document will be updated later on in
119 // the creation process anyway.
120 if (flags == KoDocument::InitDocEmbedded) {
121 initEmpty();
122 return true;
123 }
124
125 // If we are supposed to create a new, empty document, then do so.
126 if (flags == KoDocument::InitDocEmpty) {
127 initEmpty();
128 return true;
129 }
130
131 KoTemplateChooseDia::ReturnType ret;
132 KoTemplateChooseDia::DialogType dlgtype;
133
134 // If we must create a new document, then only present templates
135 // to the user, otherwise also present existing documents and
136 // recent documents.
137 if (flags == KoDocument::InitDocFileNew )
138 dlgtype = KoTemplateChooseDia::OnlyTemplates;
139 else
140 dlgtype = KoTemplateChooseDia::Everything;
141 ret = KoTemplateChooseDia::choose( KChartFactory::global(), f,
142 dlgtype, "kchart_template",
143 parentWidget );
144
145 if ( ret == KoTemplateChooseDia::File ) {
146 KURL url( f );
147 return openURL( url );
148 }
149 else if ( ret == KoTemplateChooseDia::Empty ) {
150 initEmpty();
151 return true;
152 }
153 else if ( ret == KoTemplateChooseDia::Template ) {
154 //TODO: Activate this for KOffice 1.5/2.0
155// if ( f.endsWith("/templates/chart/.source/BarChart.chrt") ) {
156// generateBarChartTemplate();
157// return true;
158// }
159 TQFileInfo fileInfo( f );
160 TQString fileName( fileInfo.dirPath( true ) + "/" +
161 fileInfo.baseName() + ".chrt" );
162
163 resetURL();
164 bool ok = loadNativeFormat( fileName );
165 if ( !ok )
166 showLoadingErrorDialog();
167 setEmpty();
168 //initConfig();
169 return ok;
170 }
171
172 return false;
173}
174
175void KChartPart::initEmpty()
176{
177 initNullChart();
178
179 resetURL();
180 setEmpty();
181}
182
183
184// This method creates the simplest chart imaginable:
185// Data size 1x1, empty, no headers
186//
187void KChartPart::initNullChart()
188{
189 // Fill cells with data if there is none.
190 //kdDebug(35001) << "Initialize null chart." << endl;
191
192 // Empty data. Note, we don't use (0,0) or (1,1) for the size
193 // here, because otherwise KDChart won't draw anything
194 m_currentData.expand(2, 2);
195 m_params->setFirstRowAsLabel(false);
196 m_params->setFirstColAsLabel(false);
197
198 // Fill column and row labels.
199 m_colLabels << TQString("");
200 m_rowLabels << TQString("");
201
202 setChartDefaults();
203
204 m_params->setDrawSolidExcessArrows(true);
205}
206
207
208void KChartPart::generateBarChartTemplate()
209{
210 int col;
211 int row;
212
213 kdDebug()<<"KChartPart::initTestChart()\n";
214
215 // Fill cells with data if there is none.
216 if (m_currentData.rows() == 0) {
217 //kdDebug(35001) << "Initialize with some data!!!" << endl;
218 m_currentData.expand( 4, 4 );
219 m_currentData.setUsedRows( 4 );
220 m_currentData.setUsedCols( 4 );
221 for (row = 0; row < 4; row++) {
222 for (col = 0; col < 4; col++) {
223 m_currentData.setCell(row, col,
224 static_cast <double> (row + col));
225
226 // Fill column label, but only on the first iteration.
227 if (row == 0) {
228 m_colLabels << i18n("Column %1").arg(col + 1);
229 }
230 }
231
232 // Fill row label.
233 m_rowLabels << i18n("Row %1").arg(row + 1);
234 }
235 }
236
237 setChartDefaults();
238 // FIXME: Should this go into setChartDefaults()?
239 m_params->setDrawSolidExcessArrows(true);
240}
241
242
243KoView* KChartPart::createViewInstance( TQWidget* parent, const char* name )
244{
245 return new KChartView( this, parent, name );
246}
247
248
249// ================================================================
250// Painting
251
252
253void KChartPart::paintContent( TQPainter& painter, const TQRect& rect,
254 bool /*transparent*/,
255 double /*zoomX*/, double /*zoomY*/ )
256{
257 int numDatasets;
258
259 // If params is 0, initDoc() has not been called.
260 Q_ASSERT( m_params != 0 );
261
262 KDChartAxisParams xAxisParms;
263 xAxisParms = m_params->axisParams( KDChartAxisParams::AxisPosBottom );
264
265 // Handle data in rows or columns.
266 //
267 // This means getting row or column headers from the document and
268 // set them as X axis labels or legend according to the current
269 // setting. Also, transpose the data if it should be displayed in
270 // columns instead of in rows.
271
272
273 // Create the displayData table.
274 numDatasets = createDisplayData();
275
276 // Create and set the axis labels and legend.
277 TQStringList longLabels;
278 TQStringList shortLabels;
279 createLabelsAndLegend(longLabels, shortLabels);
280
281 // Set the x axis labels.
282 xAxisParms.setAxisLabelStringLists( &longLabels, &shortLabels );
283 m_params->setAxisParams(KDChartAxisParams::AxisPosBottom, xAxisParms);
284
285
286 // Handle some types or subtypes of charts specially, notably:
287 // - Bar charts with lines in them
288
289 if ( m_params->chartType() == KChartParams::Bar) {
290 if ( m_params->barNumLines() > 0 ) {
291
292 // If this is a bar chart and the user wants a few lines in
293 // it, we need to create an additional chart in the same
294 // drawing area.
295
296 // Specify that we want to have an additional chart.
297 m_params->setAdditionalChartType( KDChartParams::Line );
298
299 const int numBarDatasets = numDatasets - m_params->barNumLines();
300
301 // Assign the datasets to the charts: DataEntry, from, to, chart#
302 m_params->setChartSourceMode( KDChartParams::DataEntry,
303 0, numBarDatasets - 1,
304 0 ); // The bar chart
305 m_params->setChartSourceMode( KDChartParams::DataEntry,
306 numBarDatasets, numDatasets - 1,
307 1 ); // The line chart
308 }
309 else {
310 // Otherwise we don't want any extra chart.
311 m_params->setAdditionalChartType( KDChartParams::NoType );
312 }
313 }
314
315 // Ok, we have now created a data set for display, and params with
316 // suitable legends and axis labels. Now start the real painting.
317
318 // Handle transparency.
319 // Wrong: this flickers; better do this as part of the double-buffering.
320 //if ( !transparent )
321 // painter.eraseRect( rect );
322
323 // ## TODO: support zooming
324
325 // Double-buffering
326 if ( m_bufferPixmap.width() < rect.width()
327 || m_bufferPixmap.height() < rect.height() )
328 {
329 m_bufferPixmap.resize( rect.size() );
330 }
331
332 TQPainter bufferPainter( &m_bufferPixmap );
333
334 // We only need to draw the document rectangle "rect".
335 KDChart::paint( &bufferPainter, m_params, &m_displayData, 0, &rect );
336
337 // This is always the empty rect...
338 // Shouldn't creating a TQPainter in a paintEvent set up clipping automatically?
339 // I thought it did (DF)
340 //const TQRect clipRect = painter.clipRegion().boundingRect();
341 //painter.drawPixmap( clipRect.topLeft(), m_bufferPixmap, clipRect );
342
343 painter.drawPixmap( 0, 0, m_bufferPixmap );
344}
345
346
347// Create the data table m_displayData from m_currentData, taking into
348// account if the first row or line contains headers. The chart type
349// HiLo demands special handling.
350//
351// Return number of datasets.
352//
353// Note: While the current KD Chart 1.1.3 version is still expecting data
354// to be in rows, the upcoming KD Chart 2.0 release will be using
355// data in columns instead, to it will be matching KSpread's way.
356// -khz, 2005-11-15
357//
358// FIXME: Rewrite so that we only copy data when necessary.
359// On the other hand, the next version of KDChart is able to
360// get data directly without storing it into a KDChartData
361// class first, so we might never need to.
362//
363int KChartPart::createDisplayData()
364{
365 int rowOffset = 0;
366 int colOffset = 0;
367 int numDatasets = 0;
368
369 if ( !canChangeValue() ) {
370 if ( m_params->firstRowAsLabel() )
371 rowOffset++;
372 if ( m_params->firstColAsLabel() )
373 colOffset++;
374 }
375
376 // After this sequence, m_DisplayData contains the data in the
377 // correct transposition, and the X axis and the legend contain
378 // the correct labels.
379 TQVariant value1;
380 TQVariant value2;
381 int prop;
382 if (m_params->dataDirection() == KChartParams::DataRows) {
383 // Data is handled in rows. This is the way KDChart works also.
384
385 numDatasets = m_currentData.usedRows() - rowOffset;
386 m_displayData.expand( numDatasets,
387 m_currentData.usedCols() - colOffset );
388
389 // Remove the first row and/or col if they are used for headers.
390 for (uint row = rowOffset; row < m_currentData.usedRows(); row++) {
391 for (uint col = colOffset; col < m_currentData.usedCols(); col++) {
392 if ( m_currentData.cellContent( row, col,
393 value1, value2, prop ) ) {
394 m_displayData.setCell(row - rowOffset, col - colOffset,
395 value1, value2);
396 m_displayData.setProp(row - rowOffset, col - colOffset,
397 prop);
398 }
399 }
400 }
401 }
402 else {
403 // Data is handled in columns. We will have to transpose
404 // everything since KDChart wants its data in rows.
405
406 // Resize displayData so that the transposed data has room.
407 numDatasets = m_currentData.usedCols() - colOffset;
408 m_displayData.expand( numDatasets,
409 m_currentData.usedRows() - rowOffset );
410
411 // Copy data and transpose it.
412 for (uint row = colOffset; row < m_currentData.usedCols(); row++) {
413 for (uint col = rowOffset; col < m_currentData.usedRows(); col++) {
414 if ( m_currentData.cellContent( col, row,
415 value1, value2, prop ) ) {
416 m_displayData.setCell(row - colOffset, col - rowOffset,
417 value1, value2);
418 m_displayData.setProp(row - colOffset, col - rowOffset,
419 prop);
420 }
421 }
422 }
423 }
424
425 // If this is a HiLo chart, we need to manually create the correct
426 // values. This is not done by KDChart.
427 //
428 // Here we don't need to transpose, since we can start from the
429 // newly generated displayData.
430 if (m_params->chartType() == KChartParams::HiLo) {
431 KDChartTableData tmpData = m_displayData;
432
433 // Calculate the min, max, open and close values for each row.
434 m_displayData.expand(tmpData.usedRows(), 4);
435 for (uint row = 0; row < tmpData.usedRows(); row++) {
436 double minVal = DBL_MAX;
437 double maxVal = -DBL_MAX;
438
439 // Calculate min and max for this row.
440 //
441 // Note that we have already taken care of different data
442 // directions above.
443 for (uint col = 0; col < tmpData.usedCols(); col++) {
444 double data = tmpData.cellVal(row, col).toDouble();
445
446 if (data < minVal)
447 minVal = data;
448 if (data > maxVal)
449 maxVal = data;
450 }
451 m_displayData.setCell(row, 0, minVal); // min
452 m_displayData.setCell(row, 1, maxVal); // max
453 m_displayData.setCell(row, 2, tmpData.cellVal(row, 0).toDouble()); // open
454 m_displayData.setCell(row, 3, // close
455 tmpData.cellVal(row, tmpData.usedCols() - 1).toDouble());
456 }
457 }
458
459 return numDatasets;
460}
461
462
463void KChartPart::createLabelsAndLegend( TQStringList &longLabels,
464 TQStringList &shortLabels )
465{
466 longLabels.clear();
467 shortLabels.clear();
468
469 const uint dataColumnCount = m_currentData.cols();
470 const uint dataRowCount = m_currentData.rows();
471 const uint columnLabelCount = m_colLabels.count();
472 const uint rowLabelCount = m_rowLabels.count();
473
474 // Handle HiLo charts separately.
475 if (m_params->chartType() == KChartParams::HiLo) {
476
477 // FIXME: In a HiLo chart, the Legend should be the same as the
478 // labels on the X Axis. Should we disable one of them?
479
480 // Set the correct X axis labels and legend.
481 longLabels.clear();
482 shortLabels.clear();
483 if (m_params->dataDirection() == KChartParams::DataRows) {
484
485 // If data are in rows, then the X axis labels should be
486 // taken from the row headers.
487 for ( uint row = 0; row < dataRowCount ; row++ ) {
488
489 TQString label = (row < rowLabelCount) ? m_rowLabels[row] : TQString();
490
491 longLabels << label;
492 shortLabels << label.left( 3 );
493 }
494 }
495 else {
496 // If data are in columns, then the X axis labels should
497 // be taken from the column headers.
498 for ( uint col = 0; col < dataColumnCount; col++ ) {
499
500 TQString label = (col < columnLabelCount) ? m_colLabels[col] : TQString();
501
502 longLabels << m_colLabels[col];
503 shortLabels << m_colLabels[col].left( 3 );
504 }
505 }
506 }
507 else if (m_params->dataDirection() == KChartParams::DataRows) {
508 // Data is handled in rows. This is the way KDChart works also.
509
510 // Set X axis labels from column headers.
511 for ( uint col = 0; col < dataColumnCount; col++ ) {
512
513 TQString label = (col < columnLabelCount) ? m_colLabels[col] : TQString();
514
515 longLabels << label;
516 shortLabels << label.left( 3 );
517 }
518
519 // Set legend from row headers.
520 for ( uint row = 0; row < dataRowCount; row++ ) {
521 TQString label = (row < rowLabelCount) ? m_rowLabels[row] : TQString();
522
523 m_params->setLegendText( row, label );
524 }
525 }
526 else {
527 // Data is handled in columns.
528
529 // Set X axis labels from row headers.
530 for ( uint row = 0; row < dataRowCount; row++ ) {
531
532 TQString label = (row < rowLabelCount) ? m_rowLabels[row] : TQString();
533
534 longLabels << label;
535 shortLabels << label.left( 3 );
536 }
537
538 // Set legend from column headers.
539 for ( uint col = 0; col < dataColumnCount ; col++ ) {
540 TQString label = (col < columnLabelCount) ? m_colLabels[col] : TQString();
541
542 m_params->setLegendText( col, label );
543 }
544 }
545}
546
547
548
549// ================================================================
550
551
552void KChartPart::analyzeHeaders()
553{
554#if 0
555 analyzeHeaders( m_currentData );
556#else
557 doSetData( m_currentData,
558 m_params->firstRowAsLabel(), m_params->firstColAsLabel());
559#endif
560}
561
562
563// This function sets the data from an external source. It is called,
564// for instance, when the chart is initialized from a spreadsheet in
565// KSpread.
566//
567void KChartPart::analyzeHeaders( const KDChartTableData& data )
568{
569 // FIXME(khz): replace this when automatic string detection works in KDChart
570 // Does the top/left cell contain a string?
571 bool isStringTopLeft = (data.cellVal( 0, 0 ).type() == TQVariant::String);
572
573 // Does the first row (without first cell) contain only strings?
574 bool isStringFirstRow = true;
575 for ( uint col = 1; isStringFirstRow && col < data.cols(); col++ ) {
576 isStringFirstRow = (data.cellVal( 0, col ).type() == TQVariant::String);
577 }
578
579 // Just in case, we only have 1 row, we never use it for label text.
580 // This prevents a crash.
581 //
582 // FIXME: Wonder if this is still true for KDChart 1.1.3 / iw
583 // Disabling...
584#if 1
585 if ( data.rows() == 1 )
586 isStringFirstRow = false;
587#endif
588
589 // Does the first column (without first cell) contain only strings?
590 bool isStringFirstCol = true;
591 for ( uint row = 1; isStringFirstCol && row < data.rows(); row++ ) {
592 isStringFirstCol = (data.cellVal( row, 0 ).type() == TQVariant::String);
593 }
594
595 // Just in case, we only have 1 column, we never use it for axis
596 // label text => prevents crash.
597#if 1
598 if ( data.cols() == 1 )
599 isStringFirstRow = false;
600#endif
601
602 bool hasColHeader = false;
603 bool hasRowHeader = false;
604
605 // Let's check if we have a full axis label text column
606 if ( isStringFirstCol && isStringTopLeft
607 || isStringFirstCol && isStringFirstRow )
608 hasColHeader = true;
609
610 // Let's check if we have a full label text row.
611 if ( isStringFirstRow && isStringTopLeft
612 || isStringFirstCol && isStringFirstRow )
613 hasRowHeader = true;
614
615 m_params->setFirstRowAsLabel( hasRowHeader );
616 m_params->setFirstColAsLabel( hasColHeader );
617
618 doSetData(data, hasRowHeader, hasColHeader);
619}
620
621
622
623void KChartPart::doSetData( const KDChartTableData& data,
624 bool firstRowHeader,
625 bool firstColHeader )
626{
627 uint rowStart = 0;
628 uint colStart = 0;
629 uint col;
630 uint row;
631
632 // From this point, we know that the labels and legend are going
633 // to be taken from the data if firstRowHeader or firstColheader
634 // is true.
635
636 if (firstRowHeader)
637 rowStart = 1;
638 if (firstColHeader)
639 colStart = 1;
640
641 // Generate m_rowlabels from the column headers if applicable.
642 m_rowLabels.clear();
643 if ( firstColHeader ) {
644 for( row = rowStart; row < data.rows(); row++ ) {
645 m_rowLabels << data.cellVal( row, 0 ).toString();
646 }
647 }
648 else {
649 for( row = rowStart; row < data.rows(); row++ )
650 m_rowLabels << "";
651
652 // FIXME: Check what this does, and if we don't have to check
653 // the data order (rows / cols).
654 m_params->setLegendSource( KDChartParams::LegendAutomatic );
655 }
656
657 // Generate X labels from the row headers if applicable
658 m_colLabels.clear();
659 if ( firstRowHeader ) {
660 for( col = colStart; col < data.cols(); col++ ) {
661 m_colLabels << data.cellVal( 0, col ).toString();
662 }
663 }
664 else {
665 for( col = colStart; col < data.cols(); col++ )
666 m_colLabels << "";
667 }
668
669 // Doesn't hurt if data == m_currentData, but necessary if not.
670 m_currentData = data;
671
672 //setChartDefaults();
673
674 emit docChanged();
675}
676
677
678void KChartPart::resizeData( int rows, int cols )
679{
680 m_currentData.expand( rows, cols );
681 m_currentData.setUsedRows( rows );
682 m_currentData.setUsedCols( cols );
683}
684
685
686void KChartPart::setCellData( int row, int column, const TQVariant &val)
687{
688 m_currentData.setCell( row, column, val );
689}
690
691
692bool KChartPart::showWizard( TQString &dataArea )
693{
694 KChartWizard *wizard = new KChartWizard( this, m_parentWidget, "wizard" );
695
696 connect( wizard, TQ_SIGNAL(finished()), this, TQ_SLOT(slotModified()) );
697
698 wizard->setDataArea( dataArea );
699
700 bool ret = wizard->exec();
701
702 delete wizard;
703 return ret;
704}
705
706
707void KChartPart::initLabelAndLegend()
708{
709 // Labels and legends are automatically initialized to reasonable
710 // default values in KDChart
711}
712
713
714// Set up some values for the chart Axis, that are not well chosen by
715// default by KDChart.
716//
717
718void KChartPart::setChartDefaults()
719{
720 //
721 // Settings for the Y axis.
722 //
723 KDChartAxisParams yAxis;
724 yAxis = m_params->axisParams( KDChartAxisParams::AxisPosLeft );
725
726 // decimal symbol and thousands separator
727 yAxis.setAxisLabelsRadix( TDEGlobal::locale()->decimalSymbol(),
728 TDEGlobal::locale()->thousandsSeparator() );
729
730 m_params->setAxisParams( KDChartAxisParams::AxisPosLeft, yAxis );
731
732 //
733 // Settings for the X axis.
734 //
735 KDChartAxisParams xAxis;
736 xAxis = m_params->axisParams( KDChartAxisParams::AxisPosBottom );
737
738 // These two shouldn't be necessary to set.
739 xAxis.setAxisFirstLabelText();
740 xAxis.setAxisLastLabelText();
741
742 m_params->setAxisParams( KDChartAxisParams::AxisPosBottom, xAxis );
743
744 // Other parameters for various things.
745 m_params->setLineColor();
746
747 // Setting the background layer.
748 KDFrame frame;
749 frame.setBackground( TQBrush( TQColor( 230, 222, 222 ) ) );
750 m_params->setFrame( KDChartEnums::AreaInnermost, frame, 0, 0, 0, 0 );
751}
752
753
754// ================================================================
755// Loading and Storing
756
757
758// ----------------------------------------------------------------
759// Save and Load program configuration
760
761
762
763void KChartPart::loadConfig( TDEConfig *conf )
764{
765 conf->setGroup("ChartParameters");
766
767 // TODO: the fonts
768 // PENDING(kalle) Put the applicable ones of these back in
769 // TQFont tempfont;
770 // tempfont = conf->readFontEntry("titlefont", &titlefont);
771 // setTitleFont(tempfont);
772 // tempfont = conf->readFontEntry("ytitlefont", &ytitlefont);
773 // setYTitleFont(tempfont);
774 // tempfont = conf->readFontEntry("xtitlefont", &xtitlefont);
775 // setXTitleFont(tempfont);
776 // tempfont = conf->readFontEntry("yaxisfont", &yaxisfont);
777 // setYAxisFont(tempfont);
778 // tempfont = conf->readFontEntry("xaxisfont", &xaxisfont);
779 // setXAxisFont(tempfont);
780 // tempfont = conf->readFontEntry("labelfont", &labelfont);
781 // setLabelFont(tempfont);
782 // tempfont = conf->readFontEntry("annotationfont", &annotationfont);
783 // setAnnotationFont(tempfont);
784
785 // ylabel_fmt = conf->readEntry("ylabel_fmt", ylabel_fmt );
786 // ylabel2_fmt = conf->readEntry("ylabel2_fmt", ylabel2_fmt);
787 // xlabel_spacing = conf->readNumEntry("xlabel_spacing");
788 // ylabel_density = conf->readNumEntry("ylabel_density", ylabel_density);
789 // requested_ymin = conf->readDoubleNumEntry("requested_ymin", requested_ymin);
790 // requested_ymax = conf->readDoubleNumEntry("requested_ymax", requested_ymax );
791 // requested_yinterval = conf->readDoubleNumEntry("requested_yinterval",
792 // requested_yinterval);
793 // shelf = conf->readBoolEntry("shelf", shelf);
794 // grid = conf->readBoolEntry("grid", grid);
795 // xaxis = conf->readBoolEntry("xaxis", xaxis);
796 // yaxis = conf->readBoolEntry("yaxis", yaxis);
797 // yaxis2 = conf->readBoolEntry("yaxis2", yaxis);
798 // llabel = conf->readBoolEntry("llabel", llabel);
799 // yval_style = conf->readNumEntry("yval_style", yval_style);
800 // stack_type = (KChartStackType)conf->readNumEntry("stack_type", stack_type);
801 m_params->setLineMarker(conf->readBoolEntry("lineMarker",
802 m_params->lineMarker()));
803 m_params->setThreeDBarDepth( conf->readDoubleNumEntry("_3d_depth",
804 m_params->threeDBarDepth() ) );
805 m_params->setThreeDBarAngle( conf->readNumEntry( "_3d_angle",
806 m_params->threeDBarAngle() ) );
807
808 KDChartAxisParams leftparams;
809 leftparams = m_params->axisParams( KDChartAxisParams::AxisPosLeft );
810 KDChartAxisParams rightparams;
811 rightparams = m_params->axisParams( KDChartAxisParams::AxisPosRight );
812 KDChartAxisParams bottomparams;
813 bottomparams = m_params->axisParams( KDChartAxisParams::AxisPosBottom );
814
815 bottomparams.setAxisLineColor( conf->readColorEntry( "XTitleColor", 0 ) );
816 leftparams.setAxisLineColor( conf->readColorEntry( "YTitleColor", 0 ) );
817 rightparams.setAxisLineColor( conf->readColorEntry( "YTitle2Color", 0 ) );
818 bottomparams.setAxisLabelsColor( conf->readColorEntry( "XLabelColor", 0 ) );
819 leftparams.setAxisLabelsColor( conf->readColorEntry( "YLabelColor", 0 ) );
820 rightparams.setAxisLabelsColor( conf->readColorEntry( "YLabel2Color", 0 ) );
821 leftparams.setAxisGridColor( conf->readColorEntry( "GridColor", 0 ) );
822 m_params->setOutlineDataColor( conf->readColorEntry( "LineColor", 0 ) );
823 m_params->setAxisParams( KDChartAxisParams::AxisPosLeft,
824 leftparams );
825 m_params->setAxisParams( KDChartAxisParams::AxisPosRight,
826 rightparams );
827 m_params->setAxisParams( KDChartAxisParams::AxisPosBottom,
828 bottomparams );
829
830 // hlc_style = (KChartHLCStyle)conf->readNumEntry("hlc_style", hlc_style);
831 // hlc_cap_width = conf->readNumEntry("hlc_cap_width", hlc_cap_width);
832 // // TODO: Annotation font
833 // num_scatter_pts = conf->readNumEntry("num_scatter_pts", num_scatter_pts);
834 // // TODO: Scatter type
835 // thumbnail = conf->readBoolEntry("thumbnail", thumbnail);
836 // thumblabel = conf->readEntry("thumblabel", thumblabel);
837 // border = conf->readBoolEntry("border", border);
838 // BGColor = conf->readColorEntry("BGColor", &BGColor);
839 // PlotColor = conf->readColorEntry("PlotColor", &PlotColor);
840 // VolColor = conf->readColorEntry("VolColor", &VolColor);
841 // EdgeColor = conf->readColorEntry("EdgeColor", &EdgeColor);
842 // loadColorArray(conf, &SetColor, "SetColor");
843 // loadColorArray(conf, &ExtColor, "ExtColor");
844 // loadColorArray(conf, &ExtVolColor, "ExtVolColor");
845 // transparent_bg = conf->readBoolEntry("transparent_bg", transparent_bg);
846 // // TODO: explode, missing
847 // percent_labels = (KChartPercentType)conf->readNumEntry("percent_labels",
848 // percent_labels);
849 // label_dist = conf->readNumEntry("label_dist", label_dist);
850 // label_line = conf->readBoolEntry("label_line", label_line);
851 m_params->setChartType( (KChartParams::ChartType)conf->readNumEntry( "type", m_params->chartType() ) );
852 // other_threshold = conf->readNumEntry("other_threshold", other_threshold);
853
854 // backgroundPixmapName = conf->readPathEntry( "backgroundPixmapName" );
855 // if( !backgroundPixmapName.isNull() ) {
856 // backgroundPixmap.load( locate( "wallpaper", backgroundPixmapName ));
857 // backgroundPixmapIsDirty = true;
858 // } else
859 // backgroundPixmapIsDirty = false;
860 // backgroundPixmapScaled = conf->readBoolEntry( "backgroundPixmapScaled", true );
861 // backgroundPixmapCentered = conf->readBoolEntry( "backgroundPixmapCentered", true );
862 // backgroundPixmapIntensity = conf->readDoubleNumEntry( "backgroundPixmapIntensity", 0.25 );
863}
864
865
866void KChartPart::defaultConfig( )
867{
868 delete m_params;
869 m_params = new KChartParams( this );
870 setChartDefaults();
871}
872
873
874void KChartPart::saveConfig( TDEConfig *conf )
875{
876 conf->setGroup("ChartParameters");
877
878 // PENDING(kalle) Put some of these back in
879 // the fonts
880 // conf->writeEntry("titlefont", titlefont);
881 // conf->writeEntry("ytitlefont", ytitlefont);
882 // conf->writeEntry("xtitlefont", xtitlefont);
883 // conf->writeEntry("yaxisfont", yaxisfont);
884 // conf->writeEntry("xaxisfont", xaxisfont);
885 // conf->writeEntry("labelfont", labelfont);
886
887 // conf->writeEntry("ylabel_fmt", ylabel_fmt);
888 // conf->writeEntry("ylabel2_fmt", ylabel2_fmt);
889 // conf->writeEntry("xlabel_spacing", xlabel_spacing);
890 // conf->writeEntry("ylabel_density", ylabel_density);
891 // conf->writeEntry("requested_ymin", requested_ymin);
892 // conf->writeEntry("requested_ymax", requested_ymax);
893 // conf->writeEntry("requested_yinterval", requested_yinterval);
894
895 // conf->writeEntry("shelf", shelf);
896 // conf->writeEntry("grid", grid );
897 // conf->writeEntry("xaxis", xaxis);
898 // conf->writeEntry("yaxis", yaxis);
899 // conf->writeEntry("yaxis2", yaxis2);
900 // conf->writeEntry("llabel", llabel);
901 // conf->writeEntry("yval_style", yval_style );
902 // conf->writeEntry("stack_type", (int)stack_type);
903
904 conf->writeEntry( "_3d_depth", m_params->threeDBarDepth() );
905 conf->writeEntry( "_3d_angle", m_params->threeDBarAngle() );
906
907 KDChartAxisParams leftparams;
908 leftparams = m_params->axisParams( KDChartAxisParams::AxisPosLeft );
909 KDChartAxisParams rightparams;
910 rightparams = m_params->axisParams( KDChartAxisParams::AxisPosRight );
911 KDChartAxisParams bottomparams;
912 bottomparams = m_params->axisParams( KDChartAxisParams::AxisPosBottom );
913 conf->writeEntry( "LineColor", m_params->outlineDataColor() );
914 conf->writeEntry( "XTitleColor", bottomparams.axisLineColor() );
915 conf->writeEntry( "YTitleColor", leftparams.axisLineColor() );
916 conf->writeEntry( "YTitle2Color", rightparams.axisLineColor() );
917 conf->writeEntry( "XLabelColor", bottomparams.axisLabelsColor() );
918 conf->writeEntry( "YLabelColor", leftparams.axisLabelsColor() );
919 conf->writeEntry( "YLabel2Color", rightparams.axisLabelsColor() );
920 conf->writeEntry( "GridColor", leftparams.axisGridColor() );
921
922 // conf->writeEntry("hlc_style", (int)hlc_style);
923 // conf->writeEntry("hlc_cap_width", hlc_cap_width );
924 // // TODO: Annotation type!!!
925 // conf->writeEntry("annotationfont", annotationfont);
926 // conf->writeEntry("num_scatter_pts", num_scatter_pts);
927 // // TODO: Scatter type!!!
928 // conf->writeEntry("thumbnail", thumbnail);
929 // conf->writeEntry("thumblabel", thumblabel);
930 // conf->writeEntry("thumbval", thumbval);
931 // conf->writeEntry("border", border);
932 // conf->writeEntry("BGColor", BGColor);
933 // conf->writeEntry("PlotColor", PlotColor);
934 // conf->writeEntry("VolColor", VolColor);
935 // conf->writeEntry("EdgeColor", EdgeColor);
936 // saveColorArray(conf, &SetColor, "SetColor");
937 // saveColorArray(conf, &ExtColor, "ExtColor");
938 // saveColorArray(conf, &ExtVolColor, "ExtVolColor");
939
940
941 // conf->writeEntry("transparent_bg", transparent_bg);
942 // // TODO: explode, missing
943 // conf->writeEntry("percent_labels",(int) percent_labels );
944 // conf->writeEntry("label_dist", label_dist);
945 // conf->writeEntry("label_line", label_line);
946 conf->writeEntry( "type", (int) m_params->chartType() );
947 // conf->writeEntry("other_threshold", other_threshold);
948
949 // background pixmap stuff
950 // if( !backgroundPixmapName.isNull() )
951 // conf->writePathEntry( "backgroundPixmapName", backgroundPixmapName );
952 // conf->writeEntry( "backgroundPixmapIsDirty", backgroundPixmapIsDirty );
953 // conf->writeEntry( "backgroundPixmapScaled", backgroundPixmapScaled );
954 // conf->writeEntry( "backgroundPixmapCentered", backgroundPixmapCentered );
955 // conf->writeEntry( "backgroundPixmapIntensity", backgroundPixmapIntensity );
956 conf->writeEntry( "lineMarker", (int) m_params->lineMarker());
957}
958
959
960// ----------------------------------------------------------------
961// Save and Load OpenDocument file format
962
963
964bool KChartPart::loadOasis( const TQDomDocument& doc,
965 KoOasisStyles& oasisStyles,
966 const TQDomDocument& /*settings*/,
967 KoStore *store )
968{
969 kdDebug(35001) << "kchart loadOasis called" << endl;
970
971 // Set some sensible defaults.
972 setChartDefaults();
973
974 TQDomElement content = doc.documentElement();
975 TQDomElement bodyElem ( KoDom::namedItemNS( content,
976 KoXmlNS::office, "body" ) );
977 if ( bodyElem.isNull() ) {
978 kdError(32001) << "No office:body found!" << endl;
979 setErrorMessage( i18n( "Invalid OASIS OpenDocument file. No office:body tag found." ) );
980 return false;
981 }
982
983 // Get the office:chart element.
984 TQDomElement officeChartElem = KoDom::namedItemNS( bodyElem,
985 KoXmlNS::office, "chart" );
986 if ( officeChartElem.isNull() ) {
987 kdError(32001) << "No office:chart found!" << endl;
988 TQDomElement childElem;
989 TQString localName;
990 forEachElement( childElem, bodyElem ) {
991 localName = childElem.localName();
992 }
993
994 if ( localName.isEmpty() )
995 setErrorMessage( i18n( "Invalid OASIS OpenDocument file. No tag found inside office:body." ) );
996 else
997 setErrorMessage( i18n( "This document is not a chart, but %1. Please try opening it with the appropriate application." ).arg( KoDocument::tagNameToDocumentType( localName ) ) );
998
999 return false;
1000 }
1001
1002 TQDomElement chartElem = KoDom::namedItemNS( officeChartElem,
1003 KoXmlNS::chart, "chart" );
1004 if ( chartElem.isNull() ) {
1005 setErrorMessage( i18n( "Invalid OASIS OpenDocument file. No chart:chart tag found." ) );
1006 return false;
1007 }
1008
1009 // Get the loading context and stylestack from the styles.
1010 KoOasisLoadingContext loadingContext( this, oasisStyles, store );
1011 //KoStyleStack &styleStack = loadingContext.styleStack();
1012
1013#if 0 // Example code!!
1014 // load chart properties into the stylestack.
1015 styleStack.save();
1016 styleStack.setTypeProperties( "chart" ); // load chart properties
1017 loadingContext.fillStyleStack( chartElem, KoXmlNS::chart, "style-name" );
1018
1019 const TQString fillColor = styleStack.attributeNS( KoXmlNS::draw, "fill-color" );
1020 kdDebug() << "fillColor=" << fillColor << endl;
1021
1022 styleStack.restore();
1023#endif
1024
1025 // Load chart parameters, most of these are stored in the
1026 // chart:plot-area element within chart:chart.
1027 TQString errorMessage;
1028 bool ok = m_params->loadOasis( chartElem, loadingContext, errorMessage,
1029 store);
1030 if ( !ok ) {
1031 setErrorMessage( errorMessage );
1032 return false;
1033 }
1034
1035 // TODO Load data direction (see loadAuxiliary)
1036
1037 // Load the data table.
1038 TQDomElement tableElem = KoDom::namedItemNS( chartElem,
1039 KoXmlNS::table, "table" );
1040 if ( !tableElem.isNull() ) {
1041 ok = loadOasisData( tableElem );
1042 if ( !ok )
1043 return false; // TODO setErrorMessage
1044 }
1045
1046 return true;
1047}
1048
1049
1050bool KChartPart::loadOasisData( const TQDomElement& tableElem )
1051{
1052 int numberHeaderColumns = 0;
1053 TQDomElement tableHeaderColumns = KoDom::namedItemNS( tableElem,
1054 KoXmlNS::table,
1055 "table-header-columns" );
1056
1057 TQDomElement elem;
1058 forEachElement( elem, tableHeaderColumns ) {
1059 if ( elem.localName() == "table-column" ) {
1060 int repeated = elem.attributeNS( KoXmlNS::table, "number-columns-repeated", TQString() ).toInt();
1061 numberHeaderColumns += TQMAX( 1, repeated );
1062 }
1063 }
1064
1065 // With 0 you get no titles, and with more than 1 we ignore the others.
1066 Q_ASSERT( numberHeaderColumns == 1 );
1067
1068 int numberDataColumns = 0;
1069 TQDomElement tableColumns = KoDom::namedItemNS( tableElem, KoXmlNS::table, "table-columns" );
1070 forEachElement( elem, tableColumns ) {
1071 if ( elem.localName() == "table-column" ) {
1072 int repeated = elem.attributeNS( KoXmlNS::table, "number-columns-repeated", TQString() ).toInt();
1073 numberDataColumns += TQMAX( 1, repeated );
1074 }
1075 }
1076
1077 // Parse table-header-rows for the column names.
1078 m_colLabels.clear();
1079 TQDomElement tableHeaderRows = KoDom::namedItemNS( tableElem, KoXmlNS::table, "table-header-rows" );
1080 if ( tableHeaderRows.isNull() )
1081 kdWarning(35001) << "No table-header-rows element found!" << endl;
1082 TQDomElement tableHeaderRow = KoDom::namedItemNS( tableHeaderRows, KoXmlNS::table, "table-row" );
1083 if ( tableHeaderRow.isNull() )
1084 kdWarning(35001) << "No table-row inside table-header-rows!" << endl;
1085
1086 int cellNum = 0;
1087 forEachElement( elem, tableHeaderRow ) {
1088 if ( elem.localName() == "table-cell" ) {
1089 ++cellNum;
1090 if ( cellNum > numberHeaderColumns ) {
1091 TQDomElement pElem = KoDom::namedItemNS( elem, KoXmlNS::text, "p" );
1092 m_colLabels.append( pElem.text() );
1093 }
1094 }
1095 }
1096 numberDataColumns = TQMAX( numberDataColumns, cellNum - numberHeaderColumns );
1097 if ( (int)m_colLabels.count() != numberDataColumns )
1098 kdWarning(35001) << "Got " << m_colLabels.count()
1099 << " column titles, expected " << numberDataColumns
1100 << endl;
1101
1102 // Get the number of rows, and read row labels
1103 int numberDataRows = 0;
1104 TQDomElement tableRows = KoDom::namedItemNS( tableElem, KoXmlNS::table, "table-rows" );
1105
1106 m_rowLabels.clear();
1107 forEachElement( elem, tableRows ) {
1108 if ( elem.localName() == "table-row" ) {
1109 int repeated = elem.attributeNS( KoXmlNS::table, "number-rows-repeated", TQString() ).toInt();
1110 Q_ASSERT( repeated <= 1 ); // we don't handle yet the case where data rows are repeated (can this really happen?)
1111 numberDataRows += TQMAX( 1, repeated );
1112 if ( numberHeaderColumns > 0 ) {
1113 TQDomElement firstCell = KoDom::namedItemNS( elem, KoXmlNS::table, "table-cell" );
1114 TQDomElement pElem = KoDom::namedItemNS( firstCell, KoXmlNS::text, "p" );
1115 m_rowLabels.append( pElem.text() );
1116 }
1117 }
1118 }
1119
1120 kdDebug(35001) << "numberHeaderColumns=" << numberHeaderColumns
1121 << " numberDataColumns=" << numberDataColumns
1122 << " numberDataRows=" << numberDataRows << endl;
1123
1124 if ( (int)m_rowLabels.count() != numberDataRows)
1125 kdWarning(35001) << "Got " << m_rowLabels.count()
1126 << " row labels, expected " << numberDataRows << endl;
1127
1128 m_currentData.expand( numberDataRows, numberDataColumns );
1129 m_currentData.setUsedCols( numberDataColumns );
1130 m_currentData.setUsedRows( numberDataRows );
1131
1132 // Now really load the cells.
1133 int row = 0;
1134 TQDomElement rowElem;
1135 forEachElement( rowElem, tableRows ) {
1136 if ( rowElem.localName() == "table-row" ) {
1137 int col = 0;
1138 int cellNum = 0;
1139 TQDomElement cellElem;
1140 forEachElement( cellElem, rowElem ) {
1141 if ( cellElem.localName() == "table-cell" ) {
1142 ++cellNum;
1143 if ( cellNum > numberHeaderColumns ) {
1144 TQString valueType = cellElem.attributeNS( KoXmlNS::office, "value-type", TQString() );
1145 if ( valueType != "float" )
1146 kdWarning(35001) << "Don't know how to handle value-type " << valueType << endl;
1147 else {
1148 TQString value = cellElem.attributeNS( KoXmlNS::office, "value", TQString() );
1149 double val = value.toDouble();
1150
1151 m_currentData.setCell( row, col, val );
1152 }
1153 ++col;
1154 }
1155 }
1156 }
1157 ++row;
1158 }
1159 }
1160
1161 return true;
1162}
1163
1164
1165bool KChartPart::saveOasis( KoStore* store, KoXmlWriter* manifestWriter )
1166{
1167 manifestWriter->addManifestEntry( "content.xml", "text/xml" );
1168 KoOasisStore oasisStore( store );
1169
1170 KoXmlWriter* contentWriter = oasisStore.contentWriter();
1171 if ( !contentWriter )
1172 return false;
1173
1174 KoGenStyles mainStyles;
1175
1176 KoXmlWriter* bodyWriter = oasisStore.bodyWriter();
1177 bodyWriter->startElement( "office:body" );
1178 bodyWriter->startElement( "office:chart" );
1179 bodyWriter->startElement( "chart:chart" );
1180
1181 // Indent to indicate that this is inside some tags.
1182 {
1183 // Saves chart class, title, legend, plot-area
1184 m_params->saveOasis( bodyWriter, mainStyles );
1185
1186 // Save the data table.
1187 saveOasisData( bodyWriter, mainStyles );
1188 }
1189
1190 bodyWriter->endElement(); // chart:chart
1191 bodyWriter->endElement(); // office:chart
1192 bodyWriter->endElement(); // office:body
1193
1194 contentWriter->startElement( "office:automatic-styles" );
1195 writeAutomaticStyles( *contentWriter, mainStyles );
1196 contentWriter->endElement(); // office:automatic-styles
1197
1198 oasisStore.closeContentWriter();
1199
1200 // Done with content.xml
1201
1202#if 0
1203 if ( !store->open( "styles.xml" ) )
1204 return false;
1205 manifestWriter->addManifestEntry( "styles.xml", "text/xml" );
1206 saveOasisDocumentStyles( store, mainStyles, savingContext, saveFlag,
1207 headerFooterContent );
1208 if ( !store->close() ) // done with styles.xml
1209 return false;
1210#endif
1211
1212 return true;
1213}
1214
1215
1216void KChartPart::saveOasisData( KoXmlWriter* bodyWriter,
1217 KoGenStyles& mainStyles ) const
1218{
1219 Q_UNUSED( mainStyles );
1220
1221 const int cols = m_currentData.usedCols()
1222 ? TQMIN(m_currentData.usedCols(), m_currentData.cols())
1223 : m_currentData.cols();
1224 const int rows = m_currentData.usedRows()
1225 ? TQMIN(m_currentData.usedRows(), m_currentData.rows())
1226 : m_currentData.rows();
1227
1228 bodyWriter->startElement( "table:table" );
1229 bodyWriter->addAttribute( "table:name", "local-table" );
1230
1231 // Exactly one header column, always.
1232 bodyWriter->startElement( "table:table-header-columns" );
1233 bodyWriter->startElement( "table:table-column" );
1234 bodyWriter->endElement(); // table:table-column
1235 bodyWriter->endElement(); // table:table-header-columns
1236
1237 // Then "cols" columns
1238 bodyWriter->startElement( "table:table-columns" );
1239 bodyWriter->startElement( "table:table-column" );
1240 bodyWriter->addAttribute( "table:number-columns-repeated", cols );
1241 bodyWriter->endElement(); // table:table-column
1242 bodyWriter->endElement(); // table:table-columns
1243
1244 // Exactly one header row, always.
1245 bodyWriter->startElement( "table:table-header-rows" );
1246 bodyWriter->startElement( "table:table-row" );
1247
1248 // The first column in header row is just the header column - no title needed
1249 bodyWriter->startElement( "table:table-cell" );
1250 bodyWriter->addAttribute( "office:value-type", "string" );
1251 bodyWriter->startElement( "text:p" );
1252 bodyWriter->endElement(); // text:p
1253 bodyWriter->endElement(); // table:table-cell
1254
1255 // Save column labels in the first header row, for instance:
1256 // <table:table-cell office:value-type="string">
1257 // <text:p>Column 1 </text:p>
1258 // </table:table-cell>
1259 TQStringList::const_iterator colLabelIt = m_colLabels.begin();
1260 for ( int col = 0; col < cols ; ++col ) {
1261 if ( colLabelIt != m_colLabels.end() ) {
1262 bodyWriter->startElement( "table:table-cell" );
1263 bodyWriter->addAttribute( "office:value-type", "string" );
1264 bodyWriter->startElement( "text:p" );
1265 bodyWriter->addTextNode( *colLabelIt );
1266 bodyWriter->endElement(); // text:p
1267 bodyWriter->endElement(); // table:table-cell
1268 ++colLabelIt;
1269 }
1270 }
1271
1272 bodyWriter->endElement(); // table:table-row
1273 bodyWriter->endElement(); // table:table-header-rows
1274 bodyWriter->startElement( "table:table-rows" );
1275
1276 TQStringList::const_iterator rowLabelIt = m_rowLabels.begin();
1277 for ( int row = 0; row < rows ; ++row ) {
1278 bodyWriter->startElement( "table:table-row" );
1279
1280 if ( rowLabelIt != m_rowLabels.end() ) {
1281 // Save row labels, similar to column labels
1282 bodyWriter->startElement( "table:table-cell" );
1283 bodyWriter->addAttribute( "office:value-type", "string" );
1284
1285 bodyWriter->startElement( "text:p" );
1286 bodyWriter->addTextNode( *rowLabelIt );
1287 bodyWriter->endElement(); // text:p
1288
1289 bodyWriter->endElement(); // table:table-cell
1290 ++rowLabelIt;
1291 }
1292
1293 for ( int col = 0; col < cols; ++col ) {
1294 TQVariant value( m_currentData.cellVal( row, col ) );
1295 TQString valType;
1296 TQString valStr;
1297
1298 switch ( value.type() ) {
1299 case TQVariant::Invalid:
1300 break;
1301 case TQVariant::String:
1302 valType = "string";
1303 valStr = value.toString();
1304 break;
1305 case TQVariant::Double:
1306 valType = "float";
1307 valStr = TQString::number( value.toDouble(), 'g', DBL_DIG );
1308 break;
1309 case TQVariant::DateTime:
1310 valType = "date";
1311 valStr = ""; /* like in saveXML, but why? */
1312 break;
1313 default: {
1314 kdDebug(35001) << "ERROR: cell " << row << "," << col
1315 << " has unknown type." << endl;
1316 }
1317 }
1318
1319 // Add the value type and the string to the XML tree.
1320 bodyWriter->startElement( "table:table-cell" );
1321 if ( !valType.isEmpty() ) {
1322 bodyWriter->addAttribute( "office:value-type", valType );
1323 if ( value.type() == TQVariant::Double )
1324 bodyWriter->addAttribute( "office:value", valStr );
1325
1326 bodyWriter->startElement( "text:p" );
1327 bodyWriter->addTextNode( valStr );
1328 bodyWriter->endElement(); // text:p
1329 }
1330 bodyWriter->endElement(); // table:table-cell
1331 }
1332 bodyWriter->endElement(); // table:table-row
1333 }
1334
1335 bodyWriter->endElement(); // table:table-rows
1336 bodyWriter->endElement(); // table:table
1337}
1338
1339void KChartPart::writeAutomaticStyles( KoXmlWriter& contentWriter, KoGenStyles& mainStyles ) const
1340{
1341 TQValueList<KoGenStyles::NamedStyle> styles = mainStyles.styles( KoGenStyle::STYLE_AUTO );
1342 TQValueList<KoGenStyles::NamedStyle>::const_iterator it = styles.begin();
1343 for ( ; it != styles.end() ; ++it ) {
1344 (*it).style->writeStyle( &contentWriter, mainStyles, "style:style", (*it).name, "style:chart-properties" );
1345 }
1346
1347}
1348
1349// ----------------------------------------------------------------
1350// Save and Load old KChart file format
1351
1352
1353TQDomDocument KChartPart::saveXML()
1354{
1355 TQDomElement tmpElem;
1356
1357 //kdDebug(35001) << "kchart saveXML called" << endl;
1358
1359 // The biggest part of the saving is done by KDChart itself, so we
1360 // don't have to do it.
1361 TQDomDocument doc = m_params->saveXML( false );
1362
1363 // ----------------------------------------------------------------
1364 // The rest of the saving has to be done by us.
1365
1366 TQDomElement docRoot = doc.documentElement();
1367
1368 // Save auxiliary data.
1369 TQDomElement aux = doc.createElement( "KChartAuxiliary" );
1370 docRoot.appendChild( aux );
1371
1372 // The data direction (rows/columns).
1373 tmpElem = doc.createElement( "direction" );
1374 tmpElem.setAttribute( "value", (int) m_params->dataDirection() );
1375 aux.appendChild( tmpElem );
1376
1377 tmpElem = doc.createElement( "dataaslabel" );
1378 tmpElem.setAttribute( "firstrow",
1379 m_params->firstRowAsLabel() ? "true" : "false" );
1380 tmpElem.setAttribute( "firstcol",
1381 m_params->firstColAsLabel() ? "true" : "false" );
1382 aux.appendChild( tmpElem );
1383
1384 tmpElem = doc.createElement( "barnumlines" );
1385 tmpElem.setAttribute( "value", (int) m_params->barNumLines() );
1386 aux.appendChild( tmpElem );
1387
1388 // Save the data values.
1389 TQDomElement data = doc.createElement( "data" );
1390 docRoot.appendChild( data );
1391
1392 int cols = m_currentData.usedCols()
1393 ? TQMIN(m_currentData.usedCols(), m_currentData.cols())
1394 : m_currentData.cols();
1395 int rows = m_currentData.usedRows()
1396 ? TQMIN(m_currentData.usedRows(), m_currentData.rows())
1397 : m_currentData.rows();
1398 data.setAttribute( "cols", cols );
1399 data.setAttribute( "rows", rows );
1400 kdDebug(35001) << " writing " << cols << "," << rows << " (cols,rows)." << endl;
1401
1402 for (int i=0; i!=rows; ++i) {
1403 for (int j=0; j!=cols; ++j) {
1404 TQDomElement e = doc.createElement( "cell" );
1405 data.appendChild( e );
1406 TQString valType;
1407 TQVariant value( m_currentData.cellVal( i,j ) );
1408 switch ( value.type() ) {
1409 case TQVariant::Invalid: valType = "NoValue"; break;
1410 case TQVariant::String: valType = "String"; break;
1411 case TQVariant::Double: valType = "Double"; break;
1412 case TQVariant::DateTime: valType = "DateTime"; break;
1413 default: {
1414 valType = "(unknown)";
1415 kdDebug(35001) << "ERROR: cell " << i << "," << j
1416 << " has unknown type." << endl;
1417 }
1418 }
1419
1420 e.setAttribute( "valType", valType );
1421 //kdDebug(35001) << " cell " << i << "," << j
1422 // << " saved with type '" << valType << "'." << endl;
1423 switch ( value.type() ) {
1424 case TQVariant::String: e.setAttribute( "value", value.toString() );
1425 break;
1426 case TQVariant::Double: e.setAttribute( "value", TQString::number( value.toDouble() ) );
1427 break;
1428 case TQVariant::DateTime:e.setAttribute( "value", "" );
1429 break;
1430 default: {
1431 e.setAttribute( "value", "" );
1432 if( TQVariant::Invalid != value.type() )
1433 kdDebug(35001) << "ERROR: cell " << i << "," << j
1434 << " has unknown type." << endl;
1435 }
1436 }
1437 }
1438 }
1439
1440 return doc;
1441}
1442
1443
1444bool KChartPart::loadXML( TQIODevice*, const TQDomDocument& doc )
1445{
1446 kdDebug(35001) << "kchart loadXML called" << endl;
1447
1448 // Set some sensible defaults.
1449 setChartDefaults();
1450
1451 // First try to load the KDChart parameters.
1452 bool result = m_params->loadXML( doc );
1453
1454 // If went well, try to load the auxiliary data and the data...
1455 if (result) {
1456 result = loadAuxiliary(doc) && loadData( doc, m_currentData );
1457 }
1458 else {
1459 // ...but if it did, try to load the old XML format.
1460 result = loadOldXML( doc );
1461 }
1462
1463 // If everything is OK, then get the headers from the KDChart parameters.
1464 if (result) {
1465 TQStringList legendLabels;
1466 KDChartAxisParams params;
1467 params = m_params->axisParams( KDChartAxisParams::AxisPosBottom );
1468
1469 // Get the legend.
1470 TQString str;
1471 uint index = 0;
1472 while ((str = m_params->legendText(index++)) != TQString())
1473 legendLabels << str;
1474
1475 if (m_params->dataDirection() == KChartParams::DataRows) {
1476 m_colLabels = params.axisLabelStringList();
1477 m_rowLabels = legendLabels;
1478 }
1479 else {
1480 m_colLabels = legendLabels;
1481 m_rowLabels = params.axisLabelStringList();
1482 }
1483
1484 }
1485
1486 m_params->setDrawSolidExcessArrows(true);
1487
1488 return result;
1489}
1490
1491
1492// Load the auxiliary data.
1493//
1494// Currently, that means the data direction.
1495//
1496bool KChartPart::loadAuxiliary( const TQDomDocument& doc )
1497{
1498 TQDomElement chart = doc.documentElement();
1499 TQDomElement aux = chart.namedItem("KChartAuxiliary").toElement();
1500
1501 // Older XML files might be missing this section. That is OK; the
1502 // defaults will be used.
1503 if (aux.isNull())
1504 return true;
1505
1506 TQDomNode node = aux.firstChild();
1507
1508 // If the aux section exists, it should contain data.
1509 while (!node.isNull()) {
1510
1511 TQDomElement e = node.toElement();
1512 if (e.isNull()) {
1513 // FIXME: Should this be regarded as an error?
1514 node = node.nextSibling();
1515 continue;
1516 }
1517
1518 // Check for direction
1519 if ( e.tagName() == "direction" ) {
1520 if ( e.hasAttribute("value") ) {
1521 bool ok;
1522
1523 // Read the direction. On failure, use the default.
1524 int dir = e.attribute("value").toInt(&ok);
1525 if ( !ok )
1526 dir = (int) KChartParams::DataColumns;
1527
1528 //kdDebug(35001) << "Got aux value \"direction\": " << dir << endl;
1529 m_params->setDataDirection( (KChartParams::DataDirection) dir );
1530 }
1531 else {
1532 kdDebug(35001) << "Error in direction tag." << endl;
1533 }
1534 }
1535
1536 // Check for first row / col as label
1537 else if ( e.tagName() == "dataaslabel" ) {
1538 TQString val;
1539
1540 if ( e.hasAttribute("firstrow") ) {
1541 // Read the direction. On failure, use the default.
1542 val = e.attribute("firstrow");
1543 if ( val == "true" )
1544 m_params->setFirstRowAsLabel( true );
1545 else
1546 m_params->setFirstRowAsLabel( false );
1547 }
1548 else {
1549 kdDebug(35001) << "Error in barnumlines tag." << endl;
1550 m_params->setFirstRowAsLabel( false );
1551 }
1552
1553 if ( e.hasAttribute("firstcol") ) {
1554 // Read the direction. On failure, use the default.
1555 val = e.attribute("firstcol");
1556 if ( val == "true" )
1557 m_params->setFirstColAsLabel( true );
1558 else
1559 m_params->setFirstColAsLabel( false );
1560 }
1561 else {
1562 kdDebug(35001) << "Error in barnumlines tag." << endl;
1563 m_params->setFirstColAsLabel( false );
1564 }
1565 }
1566
1567 // Check for number of lines in a bar chart.
1568 else if ( e.tagName() == "barnumlines" ) {
1569 if ( e.hasAttribute("value") ) {
1570 bool ok;
1571
1572 // Read the number of lines. On failure, use the default.
1573 int barNumLines = e.attribute("value").toInt(&ok);
1574 if ( !ok )
1575 barNumLines = 0;
1576
1577 //kdDebug(35001) << "Got aux value \"barnumlines\": "
1578 // << barNumLines << endl;
1579 m_params->setBarNumLines( barNumLines );
1580 }
1581 else {
1582 kdDebug(35001) << "Error in barnumlines tag." << endl;
1583 }
1584 }
1585#if 0
1586 // Expand with more auxiliary types when needed.
1587 else if ( e.tagName() == "..." ) {
1588 }
1589 and so on...
1590#endif
1591
1592 node = node.nextSibling();
1593 }
1594
1595 return true;
1596}
1597
1598
1599bool KChartPart::loadData( const TQDomDocument& doc,
1600 KDChartTableData& m_currentData )
1601{
1602 kdDebug(35001) << "kchart loadData called" << endl;
1603
1604 TQDomElement chart = doc.documentElement();
1605 TQDomElement data = chart.namedItem("data").toElement();
1606 bool ok;
1607 int cols = data.attribute("cols").toInt(&ok);
1608 kdDebug(35001) << "cols readed as:" << cols << endl;
1609 if ( !ok ){
1610 return false;
1611 }
1612
1613 int rows = data.attribute("rows").toInt(&ok);
1614 if ( !ok ){
1615 return false;
1616 }
1617
1618 kdDebug(35001) << rows << " x " << cols << endl;
1619 m_currentData.expand(rows, cols);
1620 m_currentData.setUsedCols( cols );
1621 m_currentData.setUsedRows( rows );
1622 kdDebug(35001) << "Expanded!" << endl;
1623 TQDomNode n = data.firstChild();
1624 for (int i=0; i!=rows; i++) {
1625 for (int j=0; j!=cols; j++) {
1626 if (n.isNull()) {
1627 kdDebug(35001) << "Some problems, there is less data than it should be!" << endl;
1628 break;
1629 }
1630 TQDomElement e = n.toElement();
1631 if ( !e.isNull() && e.tagName() == "cell" ) {
1632 // add the cell to the corresponding place...
1633 TQVariant t;
1634 if ( e.hasAttribute("value") && e.hasAttribute("valType") ) {
1635 TQString valueType = e.attribute("valType").lower();
1636 if ( "string" == valueType ) {
1637 t = e.attribute("value");
1638 }
1639 else if ( "double" == valueType ) {
1640 bool bOk;
1641 double val = e.attribute("value").toDouble(&bOk);
1642 if ( !bOk )
1643 val = 0.0;
1644 t = val;
1645 /*
1646 } else if ( "datetime" == valueType ) {
1647 t = . . .
1648 */
1649 } else {
1650 t.clear();
1651 if ( "novalue" != valueType )
1652 kdDebug(35001) << "ERROR: cell " << i << "," << j << " has unknown type '" << valueType << "'." << endl;
1653 }
1654 } else
1655 t.clear();
1656
1657 m_currentData.setCell(i,j, t );
1658
1659 /*
1660 if ( e.hasAttribute( "hide" ) ) {
1661 tmpMissing[cols*j+i] = (bool)e.attribute("hide").toInt( &ok );
1662 if ( !ok )
1663 return false;
1664 } else {
1665 tmpMissing[cols*j+i] = false;
1666 }
1667 if ( e.hasAttribute( "dist" ) ) {
1668 tmpExp[cols*j+i] = e.attribute("dist").toInt( &ok );
1669 if ( !ok )
1670 return false;
1671 } else {
1672 tmpExp[cols*j+i] = 0;
1673 }
1674 */
1675
1676 n = n.nextSibling();
1677 }
1678 }
1679 }
1680 /*
1681 m_params->missing=tmpMissing;
1682 m_params->explode=tmpExp;
1683 */
1684 return true;
1685}
1686
1687
1688// ----------------------------------------------------------------
1689// Save and Load real old KChart file format
1690
1691
1692bool KChartPart::loadOldXML( const TQDomDocument& doc )
1693{
1694 kdDebug(35001) << "kchart loadOldXML called" << endl;
1695 if ( doc.doctype().name() != "chart" )
1696 return false;
1697
1698 kdDebug(35001) << "Ok, it is a chart" << endl;
1699
1700 TQDomElement chart = doc.documentElement();
1701 if ( chart.attribute( "mime" ) != "application/x-kchart" && chart.attribute( "mime" ) != "application/vnd.kde.kchart" )
1702 return false;
1703
1704 kdDebug(35001) << "Mimetype ok" << endl;
1705
1706#if 0
1707 TQDomElement data = chart.namedItem("data").toElement();
1708 bool ok;
1709 int cols = data.attribute("cols").toInt(&ok);
1710 kdDebug(35001) << "cols readed as:" << cols << endl;
1711 if (!ok) { return false; }
1712 int rows = data.attribute("rows").toInt(&ok);
1713 if (!ok) { return false; }
1714 kdDebug(35001) << rows << " x " << cols << endl;
1715 m_currentData.expand(rows, cols);
1716 kdDebug(35001) << "Expanded!" << endl;
1717 TQDomNode n = data.firstChild();
1718 TQMemArray<int> tmpExp(rows*cols);
1719 TQMemArray<bool> tmpMissing(rows*cols);
1720
1721 for (int i=0; i!=rows; i++) {
1722 for (int j=0; j!=cols; j++) {
1723 if (n.isNull()) {
1724 kdDebug(35001) << "Some problems, there is less data than it should be!" << endl;
1725 break;
1726 }
1727
1728 TQDomElement e = n.toElement();
1729 if ( !e.isNull() && e.tagName() == "cell" ) {
1730 // add the cell to the corresponding place...
1731 double val = e.attribute("value").toDouble(&ok);
1732 if (!ok) { return false; }
1733 kdDebug(35001) << i << " " << j << "=" << val << endl;
1734 KoChart::Value t( val );
1735 // kdDebug(35001) << "Set cell for " << row << "," << col << endl;
1736 m_currentData.setCell(i,j,t);
1737 if ( e.hasAttribute( "hide" ) ) {
1738 tmpMissing[cols*j+i] = (bool)e.attribute("hide").toInt( &ok );
1739 if ( !ok )
1740 return false;
1741 } else {
1742 tmpMissing[cols*j+i] = false;
1743 }
1744 if ( e.hasAttribute( "dist" ) ) {
1745 tmpExp[cols*j+i] = e.attribute("dist").toInt( &ok );
1746 if ( !ok )
1747 return false;
1748 } else {
1749 tmpExp[cols*j+i] = 0;
1750 }
1751
1752 n = n.nextSibling();
1753 }
1754 }
1755 }
1756 m_params->missing=tmpMissing;
1757 m_params->explode=tmpExp;
1758#endif
1759
1760
1761/*
1762 enum KChartType {
1763 KCHARTTYPE_LINE,
1764 KCHARTTYPE_AREA,
1765 KCHARTTYPE_BAR,
1766 KCHARTTYPE_HILOCLOSE,
1767 KCHARTTYPE_COMBO_LINE_BAR, aka, VOL[ume]
1768 KCHARTTYPE_COMBO_HLC_BAR,
1769 KCHARTTYPE_COMBO_LINE_AREA,
1770 KCHARTTYPE_COMBO_HLC_AREA,
1771 KCHARTTYPE_3DHILOCLOSE,
1772 KCHARTTYPE_3DCOMBO_LINE_BAR,
1773 KCHARTTYPE_3DCOMBO_LINE_AREA,
1774 KCHARTTYPE_3DCOMBO_HLC_BAR,
1775 KCHARTTYPE_3DCOMBO_HLC_AREA,
1776 KCHARTTYPE_3DBAR,
1777 KCHARTTYPE_3DAREA,
1778 KCHARTTYPE_3DLINE,
1779 KCHARTTYPE_3DPIE,
1780 KCHARTTYPE_2DPIE
1781 };
1782*/
1783 bool ok;
1784 TQDomElement params = chart.namedItem( "params" ).toElement();
1785 if ( params.hasAttribute( "type" ) ) {
1786 int type=params.attribute("type").toInt( &ok );
1787 if ( !ok )
1788 return false;
1789 switch(type)
1790 {
1791 case 1:
1792 m_params->setChartType(KChartParams::Line);
1793 break;
1794 case 2:
1795 m_params->setChartType(KChartParams::Area);
1796 break;
1797 case 3:
1798 m_params->setChartType(KChartParams::Bar);
1799 break;
1800 case 4:
1801 m_params->setChartType(KChartParams::HiLo);
1802 break;
1803 case 5:
1804 case 6:
1805 case 7:
1806 case 8:
1807 /* KCHARTTYPE_COMBO_LINE_BAR, aka, VOL[ume]
1808 KCHARTTYPE_COMBO_HLC_BAR,
1809 KCHARTTYPE_COMBO_LINE_AREA,
1810 KCHARTTYPE_COMBO_HLC_AREA,
1811 */
1812 /* line by default*/
1813 m_params->setChartType(KChartParams::Line);
1814 break;
1815 case 9:
1816 m_params->setChartType(KChartParams::HiLo);
1817 break;
1818 case 10:
1819 m_params->setChartType(KChartParams::Bar);
1820 break;
1821 case 11:
1822 m_params->setChartType(KChartParams::Area);
1823 break;
1824 case 12:
1825 m_params->setChartType(KChartParams::Bar);
1826 break;
1827 case 13:
1828 m_params->setChartType(KChartParams::Area);
1829 break;
1830 case 14:
1831 m_params->setChartType(KChartParams::Bar);
1832 break;
1833 case 15:
1834 m_params->setChartType(KChartParams::Area);
1835 break;
1836 case 16:
1837 m_params->setChartType(KChartParams::Line);
1838 break;
1839 case 17:
1840 case 18:
1841 m_params->setChartType(KChartParams::Pie);
1842 break;
1843
1844 }
1845 if ( !ok )
1846 return false;
1847 }
1848#if 0
1849 if ( params.hasAttribute( "subtype" ) ) {
1850 m_params->stack_type = (KChartStackType)params.attribute("subtype").toInt( &ok );
1851 if ( !ok )
1852 return false;
1853 }
1854 if ( params.hasAttribute( "hlc_style" ) ) {
1855 m_params->hlc_style = (KChartHLCStyle)params.attribute("hlc_style").toInt( &ok );
1856 if ( !ok )
1857 return false;
1858 }
1859 if ( params.hasAttribute( "hlc_cap_width" ) ) {
1860 m_params->hlc_cap_width = (short)params.attribute( "hlc_cap_width" ).toShort( &ok );
1861 if ( !ok )
1862 return false;
1863 }
1864
1865 TQDomElement title = params.namedItem( "title" ).toElement();
1866 if ( !title.isNull()) {
1867 TQString t = title.text();
1868 m_params->title=t;
1869 }
1870 TQDomElement titlefont = params.namedItem( "titlefont" ).toElement();
1871 if ( !titlefont.isNull()) {
1872 TQDomElement font = titlefont.namedItem( "font" ).toElement();
1873 if ( !font.isNull() )
1874 m_params->setTitleFont(toFont(font));
1875 }
1876 TQDomElement xtitle = params.namedItem( "xtitle" ).toElement();
1877 if ( !xtitle.isNull()) {
1878 TQString t = xtitle.text();
1879 m_params->xtitle=t;
1880 }
1881 TQDomElement xtitlefont = params.namedItem( "xtitlefont" ).toElement();
1882 if ( !xtitlefont.isNull()) {
1883 TQDomElement font = xtitlefont.namedItem( "font" ).toElement();
1884 if ( !font.isNull() )
1885 m_params->setXTitleFont(toFont(font));
1886 }
1887 TQDomElement ytitle = params.namedItem( "ytitle" ).toElement();
1888 if ( !ytitle.isNull()) {
1889 TQString t = ytitle.text();
1890 m_params->ytitle=t;
1891 }
1892 TQDomElement ytitle2 = params.namedItem( "ytitle2" ).toElement();
1893 if ( !ytitle2.isNull()) {
1894 TQString t = ytitle2.text();
1895 m_params->ytitle2=t;
1896 }
1897 TQDomElement ytitlefont = params.namedItem( "ytitlefont" ).toElement();
1898 if ( !ytitlefont.isNull()) {
1899 TQDomElement font = ytitlefont.namedItem( "font" ).toElement();
1900 if ( !font.isNull() )
1901 m_params->setYTitleFont(toFont(font));
1902 }
1903 TQDomElement ylabelfmt = params.namedItem( "ylabelfmt" ).toElement();
1904 if ( !ylabelfmt.isNull()) {
1905 TQString t = ylabelfmt.text();
1906 m_params->ylabel_fmt=t;
1907 }
1908 TQDomElement ylabel2fmt = params.namedItem( "ylabel2fmt" ).toElement();
1909 if ( !ylabel2fmt.isNull()) {
1910 TQString t = ylabel2fmt.text();
1911 m_params->ylabel2_fmt=t;
1912 }
1913 TQDomElement labelfont = params.namedItem( "labelfont" ).toElement();
1914 if ( !labelfont.isNull()) {
1915 TQDomElement font = labelfont.namedItem( "font" ).toElement();
1916 if ( !font.isNull() )
1917 m_params->setLabelFont(toFont(font));
1918 }
1919
1920 TQDomElement yaxisfont = params.namedItem( "yaxisfont" ).toElement();
1921 if ( !yaxisfont.isNull()) {
1922 TQDomElement font = yaxisfont.namedItem( "font" ).toElement();
1923 if ( !font.isNull() )
1924 m_params->setYAxisFont(toFont(font));
1925 }
1926
1927 TQDomElement xaxisfont = params.namedItem( "xaxisfont" ).toElement();
1928 if ( !xaxisfont.isNull()) {
1929 TQDomElement font = xaxisfont.namedItem( "font" ).toElement();
1930 if ( !font.isNull() )
1931 m_params->setXAxisFont(toFont(font));
1932 }
1933 TQDomElement annotationFont = params.namedItem("annotationfont").toElement();
1934 if ( !annotationFont.isNull()) {
1935 TQDomElement font = annotationFont.namedItem( "font" ).toElement();
1936 if ( !font.isNull() )
1937 m_params->setAnnotationFont(toFont(font));
1938 }
1939
1940 TQDomElement yaxis = params.namedItem( "yaxis" ).toElement();
1941 if ( !yaxis.isNull()) {
1942 if (yaxis.hasAttribute( "yinterval" )) {
1943 m_params->requested_yinterval= yaxis.attribute("yinterval").toDouble( &ok );
1944 if ( !ok ) return false;
1945 }
1946 if (yaxis.hasAttribute( "ymin" )) {
1947 m_params->requested_ymin= yaxis.attribute("ymin").toDouble( &ok );
1948 if ( !ok ) return false;
1949 }
1950 if (yaxis.hasAttribute( "ymax" ) ) {
1951 m_params->requested_ymax= yaxis.attribute("ymax").toDouble( &ok );
1952 if ( !ok ) return false;
1953 }
1954 }
1955#endif
1956
1957 TQDomElement graph = params.namedItem( "graph" ).toElement();
1958 if (!graph.isNull()) {
1959 if (graph.hasAttribute( "grid" )) {
1960 bool b=(bool) graph.attribute("grid").toInt( &ok );
1961 m_params->setAxisShowGrid(KDChartAxisParams::AxisPosLeft,b );
1962 m_params->setAxisShowGrid(KDChartAxisParams::AxisPosBottom,b );
1963 if (!ok) return false;
1964 }
1965 if (graph.hasAttribute( "xaxis" )) {
1966 bool b=(bool) graph.attribute("xaxis").toInt( &ok );
1967 if (!ok) return false;
1968 m_params->setAxisVisible(KDChartAxisParams::AxisPosBottom,b);
1969 }
1970 if (graph.hasAttribute( "yaxis" )) {
1971 bool b=(bool) graph.attribute("yaxis").toInt( &ok );
1972 if (!ok) return false;
1973 m_params->setAxisVisible(KDChartAxisParams::AxisPosLeft,b);
1974 }
1975#if 0
1976 //no implemented
1977 if (graph.hasAttribute( "shelf" )) {
1978 m_params->shelf=(bool) graph.attribute("shelf").toInt( &ok );
1979 if (!ok) return false;
1980 }
1981#endif
1982 if (graph.hasAttribute( "yaxis2" )) {
1983 bool b=(bool) graph.attribute("yaxis2").toInt( &ok );
1984 if (!ok) return false;
1985 m_params->setAxisVisible(KDChartAxisParams::AxisPosRight,b);
1986 }
1987
1988#if 0
1989 //no implemented
1990 if (graph.hasAttribute( "ystyle" )) {
1991 m_params->yval_style=(bool) graph.attribute("ystyle").toInt( &ok );
1992 if (!ok) return false;
1993 }
1994 if (graph.hasAttribute( "border" )) {
1995 m_params->border=(bool) graph.attribute("border").toInt( &ok );
1996 if (!ok) return false;
1997 }
1998 if (graph.hasAttribute( "transbg" )) {
1999 m_params->transparent_bg=(bool) graph.attribute("transbg").toInt( &ok );
2000 if (!ok) return false;
2001 }
2002 if (graph.hasAttribute( "xlabel" )) {
2003 m_params->hasxlabel=(bool) graph.attribute("xlabel").toInt( &ok );
2004 if (!ok) return false;
2005 }
2006 if ( graph.hasAttribute( "xlabel_spacing" ) ) {
2007 m_params->xlabel_spacing = (short)graph.attribute( "xlabel_spacing" ).toShort( &ok );
2008 if ( !ok )
2009 return false;
2010 }
2011 if ( graph.hasAttribute( "ylabel_density" ) ) {
2012 m_params->ylabel_density = (short)graph.attribute( "ylabel_density" ).toShort( &ok );
2013 if ( !ok )
2014 return false;
2015 }
2016 if (graph.hasAttribute( "line")) {
2017 m_params->label_line=(bool) graph.attribute("line").toInt( &ok );
2018 if (!ok) return false;
2019 }
2020 if (graph.hasAttribute( "percent")) {
2021 m_params->percent_labels=(KChartPercentType) graph.attribute("percent").toInt( &ok );
2022 if (!ok) return false;
2023 }
2024 if (graph.hasAttribute("cross")) {
2025 m_params->cross=(bool) graph.attribute("cross").toInt( &ok );
2026 if (!ok) return false;
2027 }
2028 if (graph.hasAttribute("thumbnail")) {
2029 m_params->thumbnail=(bool) graph.attribute("thumbnail").toInt( &ok );
2030 if (!ok) return false;
2031 }
2032 if (graph.hasAttribute("thumblabel")) {
2033 m_params->thumblabel= graph.attribute("thumblabel");
2034 }
2035 if (graph.hasAttribute("thumbval")) {
2036 m_params->thumbval=(bool) graph.attribute("thumbval").toDouble( &ok );
2037 if (!ok)
2038 return false;
2039 }
2040#endif
2041 }
2042
2043#if 0
2044 TQDomElement graphparams = params.namedItem( "graphparams" ).toElement();
2045 if (!graphparams.isNull()) {
2046 if (graphparams.hasAttribute( "dept3d" )) {
2047 m_params->_3d_depth=graphparams.attribute("dept3d").toDouble( &ok );
2048 if (!ok) return false;
2049 }
2050 if (graphparams.hasAttribute( "angle3d" )) {
2051 m_params->_3d_angle=graphparams.attribute("angle3d").toShort( &ok );
2052 if (!ok) return false;
2053 }
2054 if (graphparams.hasAttribute( "barwidth" )) {
2055 m_params->bar_width=graphparams.attribute("barwidth").toShort( &ok );
2056 if (!ok) return false;
2057 }
2058 if (graphparams.hasAttribute( "colpie" )) {
2059 m_params->colPie=graphparams.attribute("colpie").toInt( &ok );
2060 if (!ok) return false;
2061 }
2062 if (graphparams.hasAttribute( "other_threshold" )) {
2063 m_params->other_threshold=graphparams.attribute("other_threshold").toShort( &ok );
2064 if (!ok)
2065 return false;
2066 }
2067 if (graphparams.hasAttribute( "offsetCol" )) {
2068 m_params->offsetCol = graphparams.attribute("offsetCol").toInt( &ok );
2069 if (!ok)
2070 return false;
2071 }
2072 if (graphparams.hasAttribute( "hard_size" )) {
2073 m_params->hard_size = (bool)graphparams.attribute("hard_size").toInt( &ok );
2074 if (!ok)
2075 return false;
2076 }
2077 if (graphparams.hasAttribute( "hard_graphheight" )) {
2078 m_params->hard_graphheight = graphparams.attribute("hard_graphheight").toInt( &ok );
2079 if (!ok)
2080 return false;
2081 }
2082 if (graphparams.hasAttribute( "hard_graphwidth" )) {
2083 m_params->hard_graphwidth = graphparams.attribute("hard_graphwidth").toInt( &ok );
2084 if (!ok)
2085 return false;
2086 }
2087 if (graphparams.hasAttribute( "hard_xorig" )) {
2088 m_params->hard_xorig = graphparams.attribute("hard_xorig").toInt( &ok );
2089 if (!ok)
2090 return false;
2091 }
2092 if (graphparams.hasAttribute( "hard_yorig" )) {
2093 m_params->hard_yorig = graphparams.attribute("hard_yorig").toInt( &ok );
2094 if (!ok)
2095 return false;
2096 }
2097 if (graphparams.hasAttribute( "labeldist" )) {
2098 m_params->label_dist=graphparams.attribute("labeldist").toInt( &ok );
2099 if (!ok) return false;
2100 }
2101 }
2102
2103 TQDomElement graphcolor = params.namedItem( "graphcolor" ).toElement();
2104 if (!graphcolor.isNull()) {
2105 if (graphcolor.hasAttribute( "bgcolor" )) {
2106 m_params->BGColor= TQColor( graphcolor.attribute( "bgcolor" ) );
2107 }
2108 if (graphcolor.hasAttribute( "gridcolor" )) {
2109 m_params->GridColor= TQColor( graphcolor.attribute( "gridcolor" ) );
2110 }
2111 if (graphcolor.hasAttribute( "linecolor" )) {
2112 m_params->LineColor= TQColor( graphcolor.attribute( "linecolor" ) );
2113 }
2114 if (graphcolor.hasAttribute( "plotcolor" )) {
2115 m_params->PlotColor= TQColor( graphcolor.attribute( "plotcolor" ) );
2116 }
2117 if (graphcolor.hasAttribute( "volcolor" )) {
2118 m_params->VolColor= TQColor( graphcolor.attribute( "volcolor" ) );
2119 }
2120 if (graphcolor.hasAttribute( "titlecolor" )) {
2121 m_params->TitleColor= TQColor( graphcolor.attribute( "titlecolor" ) );
2122 }
2123 if (graphcolor.hasAttribute( "xtitlecolor" )) {
2124 m_params->XTitleColor= TQColor( graphcolor.attribute( "xtitlecolor" ) );
2125 }
2126 if (graphcolor.hasAttribute( "ytitlecolor" )) {
2127 m_params->YTitleColor= TQColor( graphcolor.attribute( "ytitlecolor" ) );
2128 }
2129 if (graphcolor.hasAttribute( "ytitle2color" )) {
2130 m_params->YTitle2Color= TQColor( graphcolor.attribute( "ytitle2color" ) );
2131 }
2132 if (graphcolor.hasAttribute( "xlabelcolor" )) {
2133 m_params->XLabelColor= TQColor( graphcolor.attribute( "xlabelcolor" ) );
2134 }
2135 if (graphcolor.hasAttribute( "ylabelcolor" )) {
2136 m_params->YLabelColor= TQColor( graphcolor.attribute( "ylabelcolor" ) );
2137 }
2138 if (graphcolor.hasAttribute( "ylabel2color" )) {
2139 m_params->YLabel2Color= TQColor( graphcolor.attribute( "ylabel2color" ) );
2140 }
2141 }
2142
2143 TQDomElement annotation = params.namedItem( "annotation" ).toElement();
2144 if (!annotation.isNull()) {
2145 m_params->annotation=new KChartAnnotationType;
2146 if (annotation.hasAttribute( "color" )) {
2147 m_params->annotation->color= TQColor( annotation.attribute( "color" ) );
2148 }
2149 if (annotation.hasAttribute( "point" )) {
2150 m_params->annotation->point=annotation.attribute("point").toDouble( &ok );
2151 if (!ok) return false;
2152 }
2153 }
2154
2155 TQDomElement note = params.namedItem( "note" ).toElement();
2156 if ( !note.isNull()) {
2157 TQString t = note.text();
2158 m_params->annotation->note=t;
2159 }
2160
2161 TQDomElement scatter = params.namedItem( "scatter" ).toElement();
2162 if ( !scatter.isNull() ) {
2163 m_params->scatter = new KChartScatterType;
2164 if ( scatter.hasAttribute( "point" ) ) {
2165 m_params->scatter->point = scatter.attribute( "point" ).toDouble( &ok );
2166 if ( !ok )
2167 return false;
2168 }
2169 if ( scatter.hasAttribute( "val" ) ) {
2170 m_params->scatter->val = scatter.attribute( "val" ).toDouble( &ok );
2171 if ( !ok )
2172 return false;
2173 }
2174 if ( scatter.hasAttribute( "width" ) ) {
2175 m_params->scatter->width = scatter.attribute( "val" ).toUShort( &ok );
2176 if ( !ok )
2177 return false;
2178 }
2179 if ( scatter.hasAttribute( "color" )) {
2180 m_params->scatter->color= TQColor( scatter.attribute( "color" ) );
2181 }
2182 if ( scatter.hasAttribute( "ind" ) ) {
2183 m_params->scatter->ind = (KChartScatterIndType)scatter.attribute( "ind" ).toInt( &ok );
2184 if ( !ok )
2185 return false;
2186 }
2187 }
2188
2189 TQDomElement legend = chart.namedItem("legend").toElement();
2190 if (!legend.isNull()) {
2191 int number = legend.attribute("number").toInt(&ok);
2192 if (!ok) { return false; }
2193 TQDomNode name = legend.firstChild();
2194 m_params->legend.clear();
2195 for(int i=0; i<number; i++) {
2196 if (name.isNull()) {
2197 kdDebug(35001) << "Some problems, there is less data than it should be!" << endl;
2198 break;
2199 }
2200 TQDomElement element = name.toElement();
2201 if ( !element.isNull() && element.tagName() == "name" ) {
2202 TQString t = element.text();
2203 m_params->legend+=t;
2204 name = name.nextSibling();
2205 }
2206 }
2207 }
2208
2209 TQDomElement xlbl = chart.namedItem("xlbl").toElement();
2210 if (!xlbl.isNull()) {
2211 int number = xlbl.attribute("number").toInt(&ok);
2212 if (!ok) { return false; }
2213 TQDomNode label = xlbl.firstChild();
2214 m_params->xlbl.clear();
2215 for (int i=0; i<number; i++) {
2216 if (label.isNull()) {
2217 kdDebug(35001) << "Some problems, there is less data than it should be!" << endl;
2218 break;
2219 }
2220 TQDomElement element = label.toElement();
2221 if ( !element.isNull() && element.tagName() == "label" ) {
2222 TQString t = element.text();
2223 m_params->xlbl+=t;
2224 label = label.nextSibling();
2225 }
2226 }
2227 }
2228
2229 TQDomElement backgroundPixmap = chart.namedItem( "backgroundPixmap" ).toElement();
2230 if ( !backgroundPixmap.isNull() ) {
2231 if ( backgroundPixmap.hasAttribute( "name" ) )
2232 m_params->backgroundPixmapName = backgroundPixmap.attribute( "name" );
2233 if ( backgroundPixmap.hasAttribute( "isDirty" ) ) {
2234 m_params->backgroundPixmapIsDirty = (bool)backgroundPixmap.attribute( "isDirty" ).toInt( &ok );
2235 if ( !ok )
2236 return false;
2237 }
2238 if ( backgroundPixmap.hasAttribute( "scaled" ) ) {
2239 m_params->backgroundPixmapScaled = (bool)backgroundPixmap.attribute( "scaled" ).toInt( &ok );
2240 if ( !ok )
2241 return false;
2242 }
2243 if ( backgroundPixmap.hasAttribute( "centered" ) ) {
2244 m_params->backgroundPixmapCentered = (bool)backgroundPixmap.attribute( "centered" ).toInt( &ok );
2245 if ( !ok )
2246 return false;
2247 }
2248 if ( backgroundPixmap.hasAttribute( "intensity" ) ) {
2249 m_params->backgroundPixmapIntensity = backgroundPixmap.attribute( "intensity" ).toFloat( &ok );
2250 if ( !ok )
2251 return false;
2252 }
2253 }
2254
2255 TQDomElement extcolor = chart.namedItem("extcolor").toElement();
2256 if (!extcolor.isNull()) {
2257 unsigned int number = extcolor.attribute("number").toInt(&ok);
2258 if (!ok) { return false; }
2259 TQDomNode color = extcolor.firstChild();
2260
2261 for (unsigned int i=0; i<number; i++) {
2262 if (color.isNull()) {
2263 kdDebug(35001) << "Some problems, there is less data than it should be!" << endl;
2264 break;
2265 }
2266 TQDomElement element = color.toElement();
2267 if ( !element.isNull()) {
2268 if (element.hasAttribute( "name" )) {
2269 m_params->ExtColor.setColor(i,TQColor( element.attribute( "name" ) ));
2270 }
2271 color = color.nextSibling();
2272 }
2273 }
2274 }
2275
2276 if ( !m_params->backgroundPixmapName.isNull() ) {
2277 m_params->backgroundPixmap.load( locate( "wallpaper",
2278 m_params->backgroundPixmapName ));
2279 m_params->backgroundPixmapIsDirty = true;
2280 }
2281#endif
2282 return true;
2283}
2284
2285
2286
2287void KChartPart::slotModified()
2288{
2289 kdDebug(35001) << "slotModified called!" << endl;
2290
2291 setModified(true);
2292}
2293
2294
2295bool KChartPart::showEmbedInitDialog(TQWidget* /*parent*/)
2296{
2297 // Don't show an embed dialog
2298 return true;
2299}
2300
2301
2302} //KChart namespace
2303
2304#include "kchart_part.moc"
Definition of a single entry-point to the charting engine for applications that wish to provide their...
access the chart axis parameters.
TQColor axisLabelsColor() const
Returns the axis labels colour.
TQColor axisGridColor() const
Returns the axis grid color.
void setAxisLabelStringLists(TQStringList *axisLabelStringList, TQStringList *axisShortLabelStringList, const TQString &valueStart=TQString(), const TQString &valueEnd=TQString())
Specifies a TQStringList which the axis label texts are to be taken from, the second parameter (if no...
void setAxisLineColor(TQColor axisLineColor)
Specifies the axis line colour.
void setAxisFirstLabelText(const TQString &axisFirstLabelText=TQString())
Sets a special text that is to be displayed instead_of the first axis label IF the parameter is not a...
void setAxisGridColor(TQColor axisGridColor)
Specifies the axis grid colour.
void setAxisLastLabelText(const TQString &axisLastLabelText=TQString())
Sets a special text that is to be displayed instead_of the last axis label IF the parameter is not a ...
TQStringList axisLabelStringList() const
Returns a TQStringList containing the label texts to be used.
TQColor axisLineColor() const
Returns the axis line colour.
void setAxisLabelsColor(TQColor axisLabelsColor)
Specifies the axis labels colour.
void setAxisLabelsRadix(const TQString &decimalPoint, const TQString &thousandsPoint)
Specifies the way how the axis label strings will be formatted.
virtual TQVariant cellVal(uint _row, uint _col, int coordinate=1) const
static void paint(TQPainter *, KDChartParams *, KDChartTableDataBase *, KDChartDataRegionList *regions=0, const TQRect *rect=0, bool mustCalculateGeometry=true)
Paints a chart with the specified parameters on the specified painter.
Definition KDChart.cpp:256
The main class of KDFrame.
Definition KDFrame.h:88
void setBackground(TQBrush background=TQBrush(TQt::NoBrush))
Specifies the brush to be used to fill the inner area of this frame, calling this methode without pas...
Definition KDFrame.h:730