00001
00006 #include <float.h>
00007
00008
00009 #include <iostream>
00010 using std::cout;
00011 using std::cerr;
00012
00013 #include "kchart_part.h"
00014 #include "kchart_view.h"
00015 #include "kchart_factory.h"
00016 #include "kchartWizard.h"
00017 #include "kchart_params.h"
00018 #include "kdchart/KDChart.h"
00019 #include "kdchart/KDChartTable.h"
00020
00021 #include <KoTemplateChooseDia.h>
00022 #include <KoDom.h>
00023 #include <KoXmlNS.h>
00024 #include <KoXmlWriter.h>
00025 #include <KoOasisStore.h>
00026 #include <KoOasisLoadingContext.h>
00027
00028 #include <kstandarddirs.h>
00029 #include <kglobal.h>
00030 #include <kdebug.h>
00031
00032 #include <qdom.h>
00033 #include <qtextstream.h>
00034 #include <qbuffer.h>
00035 #include <qpainter.h>
00036
00037 using namespace std;
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 namespace KChart
00051 {
00052
00053 KChartPart::KChartPart( QWidget *parentWidget, const char *widgetName,
00054 QObject* parent, const char* name,
00055 bool singleViewMode )
00056 : KoChart::Part( parentWidget, widgetName, parent, name, singleViewMode ),
00057 m_params( 0 ),
00058 m_parentWidget( parentWidget ),
00059 m_rowLabels(), m_colLabels()
00060 {
00061 kdDebug(35001) << "Constructor started!" << endl;
00062
00063 setInstance( KChartFactory::global(), false );
00064 setTemplateType( "kchart_template" );
00065
00066
00067 {
00068
00069
00070 m_params = new KChartParams( this );
00071 m_params->setChartType( KChartParams::Bar );
00072 m_params->setBarChartSubType( KChartParams::BarNormal );
00073 m_params->setThreeDBars( true );
00074
00075
00076
00077
00078
00079
00080
00081
00082 m_params->setDataDirection( KChartParams::DataColumns );
00083 }
00084
00085 (void)new WizardExt( this );
00086 m_bCanChangeValue = true;
00087
00088
00089 m_displayData = m_currentData;
00090
00091
00092 initEmpty();
00093 }
00094
00095
00096 KChartPart::~KChartPart()
00097 {
00098
00099 delete m_params;
00100 }
00101
00102
00103
00104
00105 bool KChartPart::initDoc(InitDocFlags flags, QWidget* parentWidget)
00106 {
00107
00108 #if 0
00109 kdDebug(35001) << "================================================================" << endl;
00110 kdDebug(35001) << "InitDOC: flags = " << flags << endl;
00111 kdDebug(35001) << "================================================================" << endl;
00112 #endif
00113
00114 QString f;
00115
00116
00117
00118
00119
00120 if (flags == KoDocument::InitDocEmbedded) {
00121 initEmpty();
00122 return true;
00123 }
00124
00125
00126 if (flags == KoDocument::InitDocEmpty) {
00127 initEmpty();
00128 return true;
00129 }
00130
00131 KoTemplateChooseDia::ReturnType ret;
00132 KoTemplateChooseDia::DialogType dlgtype;
00133
00134
00135
00136
00137 if (flags == KoDocument::InitDocFileNew )
00138 dlgtype = KoTemplateChooseDia::OnlyTemplates;
00139 else
00140 dlgtype = KoTemplateChooseDia::Everything;
00141 ret = KoTemplateChooseDia::choose( KChartFactory::global(), f,
00142 dlgtype, "kchart_template",
00143 parentWidget );
00144
00145 if ( ret == KoTemplateChooseDia::File ) {
00146 KURL url( f );
00147 return openURL( url );
00148 }
00149 else if ( ret == KoTemplateChooseDia::Empty ) {
00150 initEmpty();
00151 return true;
00152 }
00153 else if ( ret == KoTemplateChooseDia::Template ) {
00154
00155
00156
00157
00158
00159 QFileInfo fileInfo( f );
00160 QString fileName( fileInfo.dirPath( true ) + "/" +
00161 fileInfo.baseName() + ".chrt" );
00162
00163 resetURL();
00164 bool ok = loadNativeFormat( fileName );
00165 if ( !ok )
00166 showLoadingErrorDialog();
00167 setEmpty();
00168
00169 return ok;
00170 }
00171
00172 return false;
00173 }
00174
00175 void KChartPart::initEmpty()
00176 {
00177 initNullChart();
00178
00179 resetURL();
00180 setEmpty();
00181 }
00182
00183
00184
00185
00186
00187 void KChartPart::initNullChart()
00188 {
00189
00190
00191
00192
00193
00194 m_currentData.expand(2, 2);
00195 m_params->setFirstRowAsLabel(false);
00196 m_params->setFirstColAsLabel(false);
00197
00198
00199 m_colLabels << QString("");
00200 m_rowLabels << QString("");
00201
00202 setChartDefaults();
00203
00204 m_params->setDrawSolidExcessArrows(true);
00205 }
00206
00207
00208 void KChartPart::generateBarChartTemplate()
00209 {
00210 int col;
00211 int row;
00212
00213 kdDebug()<<"KChartPart::initTestChart()\n";
00214
00215
00216 if (m_currentData.rows() == 0) {
00217
00218 m_currentData.expand( 4, 4 );
00219 m_currentData.setUsedRows( 4 );
00220 m_currentData.setUsedCols( 4 );
00221 for (row = 0; row < 4; row++) {
00222 for (col = 0; col < 4; col++) {
00223 m_currentData.setCell(row, col,
00224 static_cast <double> (row + col));
00225
00226
00227 if (row == 0) {
00228 m_colLabels << i18n("Column %1").arg(col + 1);
00229 }
00230 }
00231
00232
00233 m_rowLabels << i18n("Row %1").arg(row + 1);
00234 }
00235 }
00236
00237 setChartDefaults();
00238
00239 m_params->setDrawSolidExcessArrows(true);
00240 }
00241
00242
00243 KoView* KChartPart::createViewInstance( QWidget* parent, const char* name )
00244 {
00245 return new KChartView( this, parent, name );
00246 }
00247
00248
00249
00250
00251
00252
00253 void KChartPart::paintContent( QPainter& painter, const QRect& rect,
00254 bool ,
00255 double , double )
00256 {
00257
00258 Q_ASSERT( m_params != 0 );
00259
00260 KDChartAxisParams bottomparms;
00261 bottomparms = m_params->axisParams( KDChartAxisParams::AxisPosBottom );
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272 createDisplayData();
00273
00274
00275 QStringList longLabels;
00276 QStringList shortLabels;
00277
00278 longLabels.clear();
00279 shortLabels.clear();
00280
00281 const uint dataColumnCount = m_currentData.cols();
00282 const uint dataRowCount = m_currentData.rows();
00283 const uint columnLabelCount = m_colLabels.count();
00284 const uint rowLabelCount = m_rowLabels.count();
00285
00286 if (m_params->dataDirection() == KChartParams::DataRows) {
00287
00288
00289
00290 for ( uint col = 0; col < dataColumnCount; col++ ) {
00291
00292 QString label = (col < columnLabelCount) ? m_colLabels[col] : QString::null;
00293
00294 longLabels << label;
00295 shortLabels << label.left( 3 );
00296 }
00297
00298
00299 for ( uint row = 0; row < dataRowCount; row++ ) {
00300 QString label = (row < rowLabelCount) ? m_rowLabels[row] : QString::null;
00301
00302 m_params->setLegendText( row, label );
00303 }
00304 }
00305 else {
00306
00307
00308
00309 for ( uint row = 0; row < dataRowCount; row++ ) {
00310
00311 QString label = (row < rowLabelCount) ? m_rowLabels[row] : QString::null;
00312
00313 longLabels << label;
00314 shortLabels << label.left( 3 );
00315 }
00316
00317
00318 for ( uint col = 0; col < dataColumnCount ; col++ ) {
00319 QString label = (col < columnLabelCount) ? m_colLabels[col] : QString::null;
00320
00321 m_params->setLegendText( col, label );
00322 }
00323 }
00324
00325
00326
00327 if (m_params->chartType() == KChartParams::HiLo) {
00328
00329
00330 longLabels.clear();
00331 shortLabels.clear();
00332 if (m_params->dataDirection() == KChartParams::DataRows) {
00333
00334
00335
00336 for ( uint row = 0; row < dataRowCount ; row++ ) {
00337
00338 QString label = (row < rowLabelCount) ? m_rowLabels[row] : QString::null;
00339
00340 longLabels << label;
00341 shortLabels << label.left( 3 );
00342 }
00343 }
00344 else {
00345
00346
00347 for ( uint col = 0; col < dataColumnCount; col++ ) {
00348
00349 QString label = (col < columnLabelCount) ? m_colLabels[col] : QString::null;
00350
00351 longLabels << m_colLabels[col];
00352 shortLabels << m_colLabels[col].left( 3 );
00353 }
00354 }
00355 }
00356
00357
00358 bottomparms.setAxisLabelStringLists( &longLabels, &shortLabels );
00359 m_params->setAxisParams(KDChartAxisParams::AxisPosBottom, bottomparms);
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372 if ( m_bufferPixmap.width() < rect.width()
00373 || m_bufferPixmap.height() < rect.height() )
00374 {
00375 m_bufferPixmap.resize( rect.size() );
00376 }
00377
00378 QPainter bufferPainter( &m_bufferPixmap );
00379
00380
00381 KDChart::paint( &bufferPainter, m_params, &m_displayData, 0, &rect );
00382
00383
00384
00385
00386
00387
00388
00389 painter.drawPixmap( 0, 0, m_bufferPixmap );
00390 }
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408 void KChartPart::createDisplayData()
00409 {
00410 int rowOffset = 0;
00411 int colOffset = 0;
00412 int numDatasets = 0;
00413
00414 if ( m_params->firstRowAsLabel() )
00415 rowOffset++;
00416 if ( m_params->firstColAsLabel() )
00417 colOffset++;
00418
00419
00420
00421
00422 QVariant value1;
00423 QVariant value2;
00424 int prop;
00425 if (m_params->dataDirection() == KChartParams::DataRows) {
00426
00427
00428 numDatasets = m_currentData.usedRows() - rowOffset;
00429 m_displayData.expand( numDatasets,
00430 m_currentData.usedCols() - colOffset );
00431
00432 for (uint row = rowOffset; row < m_currentData.usedRows(); row++) {
00433 for (uint col = colOffset; col < m_currentData.usedCols(); col++) {
00434 if ( m_currentData.cellContent( row, col,
00435 value1, value2, prop ) ) {
00436 m_displayData.setCell(row - rowOffset, col - colOffset,
00437 value1, value2);
00438 m_displayData.setProp(row - rowOffset, col - colOffset,
00439 prop);
00440 }
00441
00442 }
00443 }
00444 }
00445 else {
00446
00447
00448
00449
00450 numDatasets = m_currentData.usedCols() - colOffset;
00451 m_displayData.expand( numDatasets,
00452 m_currentData.usedRows() - rowOffset );
00453
00454
00455 for (uint row = colOffset; row < m_currentData.usedCols(); row++) {
00456 for (uint col = rowOffset; col < m_currentData.usedRows(); col++) {
00457 if ( m_currentData.cellContent( col, row,
00458 value1, value2, prop ) ) {
00459 m_displayData.setCell(row - colOffset, col - rowOffset,
00460 value1, value2);
00461 m_displayData.setProp(row - colOffset, col - rowOffset,
00462 prop);
00463 }
00464 }
00465 }
00466 }
00467
00468 if ( m_params->chartType() == KChartParams::Bar
00469 && m_params->barNumLines() > 0 ) {
00470
00471
00472 m_params->setAdditionalChartType( KDChartParams::Line );
00473
00474 const int numBarDatasets = numDatasets - m_params->barNumLines();
00475
00476
00477 m_params->setChartSourceMode( KDChartParams::DataEntry,
00478 0, numBarDatasets - 1,
00479 0 );
00480 m_params->setChartSourceMode( KDChartParams::DataEntry,
00481 numBarDatasets, numDatasets - 1,
00482 1 );
00483 }
00484 else {
00485
00486 m_params->setAdditionalChartType( KDChartParams::NoType );
00487 }
00488
00489
00490
00491
00492
00493
00494 if (m_params->chartType() == KChartParams::HiLo) {
00495 KDChartTableData tmpData = m_displayData;
00496
00497
00498 m_displayData.expand(tmpData.usedRows(), 4);
00499 for (uint row = 0; row < tmpData.usedRows(); row++) {
00500 double minVal = DBL_MAX;
00501 double maxVal = -DBL_MAX;
00502
00503
00504
00505
00506
00507 for (uint col = 0; col < tmpData.usedCols(); col++) {
00508 double data = tmpData.cellVal(row, col).toDouble();
00509
00510 if (data < minVal)
00511 minVal = data;
00512 if (data > maxVal)
00513 maxVal = data;
00514 }
00515 m_displayData.setCell(row, 0, minVal);
00516 m_displayData.setCell(row, 1, maxVal);
00517 m_displayData.setCell(row, 2, tmpData.cellVal(row, 0).toDouble());
00518 m_displayData.setCell(row, 3,
00519 tmpData.cellVal(row, tmpData.usedCols() - 1).toDouble());
00520 }
00521 }
00522 }
00523
00524
00525
00526
00527
00528 void KChartPart::analyzeHeaders()
00529 {
00530 #if 0
00531 analyzeHeaders( m_currentData );
00532 #else
00533 doSetData( m_currentData,
00534 m_params->firstRowAsLabel(), m_params->firstColAsLabel());
00535 #endif
00536 }
00537
00538
00539
00540
00541
00542
00543 void KChartPart::analyzeHeaders( const KDChartTableData& data )
00544 {
00545
00546
00547 bool isStringTopLeft = (data.cellVal( 0, 0 ).type() == QVariant::String);
00548
00549
00550 bool isStringFirstRow = true;
00551 for ( uint col = 1; isStringFirstRow && col < data.cols(); col++ ) {
00552 isStringFirstRow = (data.cellVal( 0, col ).type() == QVariant::String);
00553 }
00554
00555
00556
00557
00558
00559
00560 #if 1
00561 if ( data.rows() == 1 )
00562 isStringFirstRow = false;
00563 #endif
00564
00565
00566 bool isStringFirstCol = true;
00567 for ( uint row = 1; isStringFirstCol && row < data.rows(); row++ ) {
00568 isStringFirstCol = (data.cellVal( row, 0 ).type() == QVariant::String);
00569 }
00570
00571
00572
00573 #if 1
00574 if ( data.cols() == 1 )
00575 isStringFirstRow = FALSE;
00576 #endif
00577
00578 bool hasColHeader = false;
00579 bool hasRowHeader = false;
00580
00581
00582 if ( isStringFirstCol && isStringTopLeft
00583 || isStringFirstCol && isStringFirstRow )
00584 hasColHeader = true;
00585
00586
00587 if ( isStringFirstRow && isStringTopLeft
00588 || isStringFirstCol && isStringFirstRow )
00589 hasRowHeader = true;
00590
00591 m_params->setFirstRowAsLabel( hasRowHeader );
00592 m_params->setFirstColAsLabel( hasColHeader );
00593
00594 doSetData(data, hasRowHeader, hasColHeader);
00595 }
00596
00597
00598
00599 void KChartPart::doSetData( const KDChartTableData& data,
00600 bool hasRowHeader,
00601 bool hasColHeader )
00602 {
00603 uint rowStart = 0;
00604 uint colStart = 0;
00605 uint col;
00606 uint row;
00607
00608
00609
00610
00611 return;
00612
00613 if (hasRowHeader)
00614 rowStart = 1;
00615 if (hasColHeader)
00616 colStart = 1;
00617
00618
00619 m_rowLabels.clear();
00620 if ( hasColHeader ) {
00621 for( row = rowStart; row < data.rows(); row++ )
00622 m_rowLabels << data.cellVal( row, 0 ).toString();
00623 }
00624 else
00625 m_params->setLegendSource( KDChartParams::LegendAutomatic );
00626
00627
00628 m_colLabels.clear();
00629 if ( hasRowHeader ) {
00630 for( col = colStart; col < data.cols(); col++ )
00631 m_colLabels << data.cellVal( 0, col ).toString();
00632 }
00633
00634 #if 0
00635
00636
00637
00638 if ( hasColHeader || hasRowHeader ) {
00639 KDChartTableData matrix( data.rows() - rowStart, data.cols() - colStart );
00640
00641 for ( col = colStart; col < data.cols(); col++ ) {
00642 for ( row = rowStart; row < data.rows(); row++ ) {
00643 matrix.setCell( row - rowStart, col - colStart,
00644 data.cellVal( row, col ).toDouble() );
00645 }
00646 }
00647 m_currentData = matrix;
00648 }
00649 else
00650 #endif
00651 m_currentData = data;
00652
00653 setChartDefaults();
00654
00655 emit docChanged();
00656 }
00657
00658
00659 void KChartPart::resizeData( int rows, int cols )
00660 {
00661 m_currentData.expand( rows, cols );
00662 m_currentData.setUsedRows( rows );
00663 m_currentData.setUsedCols( cols );
00664 }
00665
00666
00667 void KChartPart::setCellData( int row, int column, const QVariant &val)
00668 {
00669 m_currentData.setCell( row, column, val );
00670 }
00671
00672
00673 bool KChartPart::showWizard( QString &area )
00674 {
00675 KChartWizard *wizard = new KChartWizard( this, m_parentWidget, "wizard" );
00676
00677 connect( wizard, SIGNAL(finished()), this, SLOT(slotModified()) );
00678
00679 wizard->setDataArea( area );
00680
00681 bool ret = wizard->exec();
00682
00683 delete wizard;
00684 return ret;
00685 }
00686
00687
00688 void KChartPart::initLabelAndLegend()
00689 {
00690
00691
00692 }
00693
00694
00695
00696
00697
00698
00699 void KChartPart::setChartDefaults()
00700 {
00701
00702
00703
00704 KDChartAxisParams yAxis;
00705 yAxis = m_params->axisParams( KDChartAxisParams::AxisPosLeft );
00706
00707
00708 yAxis.setAxisLabelsRadix( KGlobal::locale()->decimalSymbol(),
00709 KGlobal::locale()->thousandsSeparator() );
00710
00711 m_params->setAxisParams( KDChartAxisParams::AxisPosLeft, yAxis );
00712
00713
00714
00715
00716 KDChartAxisParams xAxis;
00717 xAxis = m_params->axisParams( KDChartAxisParams::AxisPosBottom );
00718
00719
00720 xAxis.setAxisFirstLabelText();
00721 xAxis.setAxisLastLabelText();
00722
00723 m_params->setAxisParams( KDChartAxisParams::AxisPosBottom, xAxis );
00724
00725
00726 m_params->setLineColor();
00727
00728
00729 KDFrame frame;
00730 frame.setBackground( QBrush( QColor( 230, 222, 222 ) ) );
00731 m_params->setFrame( KDChartEnums::AreaInnermost, frame, 0, 0, 0, 0 );
00732 }
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744 void KChartPart::loadConfig( KConfig *conf )
00745 {
00746 conf->setGroup("ChartParameters");
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782 m_params->setLineMarker(conf->readBoolEntry("lineMarker",
00783 m_params->lineMarker()));
00784 m_params->setThreeDBarDepth( conf->readDoubleNumEntry("_3d_depth",
00785 m_params->threeDBarDepth() ) );
00786 m_params->setThreeDBarAngle( conf->readNumEntry( "_3d_angle",
00787 m_params->threeDBarAngle() ) );
00788
00789 KDChartAxisParams leftparams;
00790 leftparams = m_params->axisParams( KDChartAxisParams::AxisPosLeft );
00791 KDChartAxisParams rightparams;
00792 rightparams = m_params->axisParams( KDChartAxisParams::AxisPosRight );
00793 KDChartAxisParams bottomparams;
00794 bottomparams = m_params->axisParams( KDChartAxisParams::AxisPosBottom );
00795
00796 bottomparams.setAxisLineColor( conf->readColorEntry( "XTitleColor", 0 ) );
00797 leftparams.setAxisLineColor( conf->readColorEntry( "YTitleColor", 0 ) );
00798 rightparams.setAxisLineColor( conf->readColorEntry( "YTitle2Color", 0 ) );
00799 bottomparams.setAxisLabelsColor( conf->readColorEntry( "XLabelColor", 0 ) );
00800 leftparams.setAxisLabelsColor( conf->readColorEntry( "YLabelColor", 0 ) );
00801 rightparams.setAxisLabelsColor( conf->readColorEntry( "YLabel2Color", 0 ) );
00802 leftparams.setAxisGridColor( conf->readColorEntry( "GridColor", 0 ) );
00803 m_params->setOutlineDataColor( conf->readColorEntry( "LineColor", 0 ) );
00804 m_params->setAxisParams( KDChartAxisParams::AxisPosLeft,
00805 leftparams );
00806 m_params->setAxisParams( KDChartAxisParams::AxisPosRight,
00807 rightparams );
00808 m_params->setAxisParams( KDChartAxisParams::AxisPosBottom,
00809 bottomparams );
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832 m_params->setChartType( (KChartParams::ChartType)conf->readNumEntry( "type", m_params->chartType() ) );
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844 }
00845
00846
00847 void KChartPart::defaultConfig( )
00848 {
00849 delete m_params;
00850 m_params = new KChartParams( this );
00851 setChartDefaults();
00852 }
00853
00854
00855 void KChartPart::saveConfig( KConfig *conf )
00856 {
00857 conf->setGroup("ChartParameters");
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885 conf->writeEntry( "_3d_depth", m_params->threeDBarDepth() );
00886 conf->writeEntry( "_3d_angle", m_params->threeDBarAngle() );
00887
00888 KDChartAxisParams leftparams;
00889 leftparams = m_params->axisParams( KDChartAxisParams::AxisPosLeft );
00890 KDChartAxisParams rightparams;
00891 rightparams = m_params->axisParams( KDChartAxisParams::AxisPosRight );
00892 KDChartAxisParams bottomparams;
00893 bottomparams = m_params->axisParams( KDChartAxisParams::AxisPosBottom );
00894 conf->writeEntry( "LineColor", m_params->outlineDataColor() );
00895 conf->writeEntry( "XTitleColor", bottomparams.axisLineColor() );
00896 conf->writeEntry( "YTitleColor", leftparams.axisLineColor() );
00897 conf->writeEntry( "YTitle2Color", rightparams.axisLineColor() );
00898 conf->writeEntry( "XLabelColor", bottomparams.axisLabelsColor() );
00899 conf->writeEntry( "YLabelColor", leftparams.axisLabelsColor() );
00900 conf->writeEntry( "YLabel2Color", rightparams.axisLabelsColor() );
00901 conf->writeEntry( "GridColor", leftparams.axisGridColor() );
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927 conf->writeEntry( "type", (int) m_params->chartType() );
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937 conf->writeEntry( "lineMarker", (int) m_params->lineMarker());
00938 }
00939
00940
00941
00942
00943
00944
00945 bool KChartPart::loadOasis( const QDomDocument& doc,
00946 KoOasisStyles& oasisStyles,
00947 const QDomDocument& ,
00948 KoStore *store )
00949 {
00950 kdDebug(35001) << "kchart loadOasis called" << endl;
00951
00952
00953 setChartDefaults();
00954
00955 QDomElement content = doc.documentElement();
00956 QDomElement bodyElem ( KoDom::namedItemNS( content,
00957 KoXmlNS::office, "body" ) );
00958 if ( bodyElem.isNull() ) {
00959 kdError(32001) << "No office:body found!" << endl;
00960 setErrorMessage( i18n( "Invalid OASIS OpenDocument file. No office:body tag found." ) );
00961 return false;
00962 }
00963
00964
00965 QDomElement officeChartElem = KoDom::namedItemNS( bodyElem,
00966 KoXmlNS::office, "chart" );
00967 if ( officeChartElem.isNull() ) {
00968 kdError(32001) << "No office:chart found!" << endl;
00969 QDomElement childElem;
00970 QString localName;
00971 forEachElement( childElem, bodyElem ) {
00972 localName = childElem.localName();
00973 }
00974
00975 if ( localName.isEmpty() )
00976 setErrorMessage( i18n( "Invalid OASIS OpenDocument file. No tag found inside office:body." ) );
00977 else
00978 setErrorMessage( i18n( "This document is not a chart, but %1. Please try opening it with the appropriate application." ).arg( KoDocument::tagNameToDocumentType( localName ) ) );
00979
00980 return false;
00981 }
00982
00983 QDomElement chartElem = KoDom::namedItemNS( officeChartElem,
00984 KoXmlNS::chart, "chart" );
00985 if ( chartElem.isNull() ) {
00986 setErrorMessage( i18n( "Invalid OASIS OpenDocument file. No chart:chart tag found." ) );
00987 return false;
00988 }
00989
00990
00991 KoOasisLoadingContext loadingContext( this, oasisStyles, store );
00992
00993
00994 #if 0 // Example code!!
00995
00996 styleStack.save();
00997 styleStack.setTypeProperties( "chart" );
00998 loadingContext.fillStyleStack( chartElem, KoXmlNS::chart, "style-name" );
00999
01000 const QString fillColor = styleStack.attributeNS( KoXmlNS::draw, "fill-color" );
01001 kdDebug() << "fillColor=" << fillColor << endl;
01002
01003 styleStack.restore();
01004 #endif
01005
01006
01007
01008 QString errorMessage;
01009 bool ok = m_params->loadOasis( chartElem, loadingContext, errorMessage,
01010 store);
01011 if ( !ok ) {
01012 setErrorMessage( errorMessage );
01013 return false;
01014 }
01015
01016
01017
01018
01019 QDomElement tableElem = KoDom::namedItemNS( chartElem,
01020 KoXmlNS::table, "table" );
01021 if ( !tableElem.isNull() ) {
01022 ok = loadOasisData( tableElem );
01023 if ( !ok )
01024 return false;
01025 }
01026
01027 return true;
01028 }
01029
01030
01031 bool KChartPart::loadOasisData( const QDomElement& tableElem )
01032 {
01033 int numberHeaderColumns = 0;
01034 QDomElement tableHeaderColumns = KoDom::namedItemNS( tableElem,
01035 KoXmlNS::table,
01036 "table-header-columns" );
01037
01038 QDomElement elem;
01039 forEachElement( elem, tableHeaderColumns ) {
01040 if ( elem.localName() == "table-column" ) {
01041 int repeated = elem.attributeNS( KoXmlNS::table, "number-columns-repeated", QString::null ).toInt();
01042 numberHeaderColumns += QMAX( 1, repeated );
01043 }
01044 }
01045
01046
01047 Q_ASSERT( numberHeaderColumns == 1 );
01048
01049 int numberDataColumns = 0;
01050 QDomElement tableColumns = KoDom::namedItemNS( tableElem, KoXmlNS::table, "table-columns" );
01051 forEachElement( elem, tableColumns ) {
01052 if ( elem.localName() == "table-column" ) {
01053 int repeated = elem.attributeNS( KoXmlNS::table, "number-columns-repeated", QString::null ).toInt();
01054 numberDataColumns += QMAX( 1, repeated );
01055 }
01056 }
01057
01058
01059 m_colLabels.clear();
01060 QDomElement tableHeaderRows = KoDom::namedItemNS( tableElem, KoXmlNS::table, "table-header-rows" );
01061 if ( tableHeaderRows.isNull() )
01062 kdWarning(35001) << "No table-header-rows element found!" << endl;
01063 QDomElement tableHeaderRow = KoDom::namedItemNS( tableHeaderRows, KoXmlNS::table, "table-row" );
01064 if ( tableHeaderRow.isNull() )
01065 kdWarning(35001) << "No table-row inside table-header-rows!" << endl;
01066
01067 int cellNum = 0;
01068 forEachElement( elem, tableHeaderRow ) {
01069 if ( elem.localName() == "table-cell" ) {
01070 ++cellNum;
01071 if ( cellNum > numberHeaderColumns ) {
01072 QDomElement pElem = KoDom::namedItemNS( elem, KoXmlNS::text, "p" );
01073 m_colLabels.append( pElem.text() );
01074 }
01075 }
01076 }
01077 numberDataColumns = QMAX( numberDataColumns, cellNum - numberHeaderColumns );
01078 if ( (int)m_colLabels.count() != numberDataColumns )
01079 kdWarning(35001) << "Got " << m_colLabels.count()
01080 << " column titles, expected " << numberDataColumns
01081 << endl;
01082
01083
01084 int numberDataRows = 0;
01085 QDomElement tableRows = KoDom::namedItemNS( tableElem, KoXmlNS::table, "table-rows" );
01086
01087 m_rowLabels.clear();
01088 forEachElement( elem, tableRows ) {
01089 if ( elem.localName() == "table-row" ) {
01090 int repeated = elem.attributeNS( KoXmlNS::table, "number-rows-repeated", QString::null ).toInt();
01091 Q_ASSERT( repeated <= 1 );
01092 numberDataRows += QMAX( 1, repeated );
01093 if ( numberHeaderColumns > 0 ) {
01094 QDomElement firstCell = KoDom::namedItemNS( elem, KoXmlNS::table, "table-cell" );
01095 QDomElement pElem = KoDom::namedItemNS( firstCell, KoXmlNS::text, "p" );
01096 m_rowLabels.append( pElem.text() );
01097 }
01098 }
01099 }
01100
01101 kdDebug(35001) << "numberHeaderColumns=" << numberHeaderColumns
01102 << " numberDataColumns=" << numberDataColumns
01103 << " numberDataRows=" << numberDataRows << endl;
01104
01105 if ( (int)m_rowLabels.count() != numberDataRows)
01106 kdWarning(35001) << "Got " << m_rowLabels.count()
01107 << " row labels, expected " << numberDataRows << endl;
01108
01109 m_currentData.expand( numberDataRows, numberDataColumns );
01110 m_currentData.setUsedCols( numberDataColumns );
01111 m_currentData.setUsedRows( numberDataRows );
01112
01113
01114 int row = 0;
01115 QDomElement rowElem;
01116 forEachElement( rowElem, tableRows ) {
01117 if ( rowElem.localName() == "table-row" ) {
01118 int col = 0;
01119 int cellNum = 0;
01120 QDomElement cellElem;
01121 forEachElement( cellElem, rowElem ) {
01122 if ( cellElem.localName() == "table-cell" ) {
01123 ++cellNum;
01124 if ( cellNum > numberHeaderColumns ) {
01125 QString valueType = cellElem.attributeNS( KoXmlNS::office, "value-type", QString::null );
01126 if ( valueType != "float" )
01127 kdWarning(35001) << "Don't know how to handle value-type " << valueType << endl;
01128 else {
01129 QString value = cellElem.attributeNS( KoXmlNS::office, "value", QString::null );
01130 double val = value.toDouble();
01131
01132 m_currentData.setCell( row, col, val );
01133 }
01134 ++col;
01135 }
01136 }
01137 }
01138 ++row;
01139 }
01140 }
01141
01142 return true;
01143 }
01144
01145
01146 bool KChartPart::saveOasis( KoStore* store, KoXmlWriter* manifestWriter )
01147 {
01148 manifestWriter->addManifestEntry( "content.xml", "text/xml" );
01149 KoOasisStore oasisStore( store );
01150
01151 KoXmlWriter* contentWriter = oasisStore.contentWriter();
01152 if ( !contentWriter )
01153 return false;
01154
01155 KoGenStyles mainStyles;
01156
01157 KoXmlWriter* bodyWriter = oasisStore.bodyWriter();
01158 bodyWriter->startElement( "office:body" );
01159 bodyWriter->startElement( "office:chart" );
01160 bodyWriter->startElement( "chart:chart" );
01161
01162
01163 {
01164
01165 m_params->saveOasis( bodyWriter, mainStyles );
01166
01167
01168 saveOasisData( bodyWriter, mainStyles );
01169 }
01170
01171 bodyWriter->endElement();
01172 bodyWriter->endElement();
01173 bodyWriter->endElement();
01174
01175 contentWriter->startElement( "office:automatic-styles" );
01176 writeAutomaticStyles( *contentWriter, mainStyles );
01177 contentWriter->endElement();
01178
01179 oasisStore.closeContentWriter();
01180
01181
01182
01183 #if 0
01184 if ( !store->open( "styles.xml" ) )
01185 return false;
01186 manifestWriter->addManifestEntry( "styles.xml", "text/xml" );
01187 saveOasisDocumentStyles( store, mainStyles, savingContext, saveFlag,
01188 headerFooterContent );
01189 if ( !store->close() )
01190 return false;
01191 #endif
01192
01193 return true;
01194 }
01195
01196
01197 void KChartPart::saveOasisData( KoXmlWriter* bodyWriter,
01198 KoGenStyles& mainStyles ) const
01199 {
01200 Q_UNUSED( mainStyles );
01201
01202 const int cols = m_currentData.usedCols()
01203 ? QMIN(m_currentData.usedCols(), m_currentData.cols())
01204 : m_currentData.cols();
01205 const int rows = m_currentData.usedRows()
01206 ? QMIN(m_currentData.usedRows(), m_currentData.rows())
01207 : m_currentData.rows();
01208
01209 bodyWriter->startElement( "table:table" );
01210 bodyWriter->addAttribute( "table:name", "local-table" );
01211
01212
01213 bodyWriter->startElement( "table:table-header-columns" );
01214 bodyWriter->startElement( "table:table-column" );
01215 bodyWriter->endElement();
01216 bodyWriter->endElement();
01217
01218
01219 bodyWriter->startElement( "table:table-columns" );
01220 bodyWriter->startElement( "table:table-column" );
01221 bodyWriter->addAttribute( "table:number-columns-repeated", cols );
01222 bodyWriter->endElement();
01223 bodyWriter->endElement();
01224
01225
01226 bodyWriter->startElement( "table:table-header-rows" );
01227 bodyWriter->startElement( "table:table-row" );
01228
01229
01230 bodyWriter->startElement( "table:table-cell" );
01231 bodyWriter->addAttribute( "office:value-type", "string" );
01232 bodyWriter->startElement( "text:p" );
01233 bodyWriter->endElement();
01234 bodyWriter->endElement();
01235
01236
01237
01238
01239
01240 QStringList::const_iterator colLabelIt = m_colLabels.begin();
01241 for ( int col = 0; col < cols ; ++col ) {
01242 if ( colLabelIt != m_colLabels.end() ) {
01243 bodyWriter->startElement( "table:table-cell" );
01244 bodyWriter->addAttribute( "office:value-type", "string" );
01245 bodyWriter->startElement( "text:p" );
01246 bodyWriter->addTextNode( *colLabelIt );
01247 bodyWriter->endElement();
01248 bodyWriter->endElement();
01249 ++colLabelIt;
01250 }
01251 }
01252
01253 bodyWriter->endElement();
01254 bodyWriter->endElement();
01255 bodyWriter->startElement( "table:table-rows" );
01256
01257 QStringList::const_iterator rowLabelIt = m_rowLabels.begin();
01258 for ( int row = 0; row < rows ; ++row ) {
01259 bodyWriter->startElement( "table:table-row" );
01260
01261 if ( rowLabelIt != m_rowLabels.end() ) {
01262
01263 bodyWriter->startElement( "table:table-cell" );
01264 bodyWriter->addAttribute( "office:value-type", "string" );
01265
01266 bodyWriter->startElement( "text:p" );
01267 bodyWriter->addTextNode( *rowLabelIt );
01268 bodyWriter->endElement();
01269
01270 bodyWriter->endElement();
01271 ++rowLabelIt;
01272 }
01273
01274 for ( int col = 0; col < cols; ++col ) {
01275 QVariant value( m_currentData.cellVal( row, col ) );
01276 QString valType;
01277 QString valStr;
01278
01279 switch ( value.type() ) {
01280 case QVariant::Invalid:
01281 break;
01282 case QVariant::String:
01283 valType = "string";
01284 valStr = value.toString();
01285 break;
01286 case QVariant::Double:
01287 valType = "float";
01288 valStr = QString::number( value.toDouble(), 'g', DBL_DIG );
01289 break;
01290 case QVariant::DateTime:
01291 valType = "date";
01292 valStr = "";
01293 break;
01294 default: {
01295 kdDebug(35001) << "ERROR: cell " << row << "," << col
01296 << " has unknown type." << endl;
01297 }
01298 }
01299
01300
01301 bodyWriter->startElement( "table:table-cell" );
01302 if ( !valType.isEmpty() ) {
01303 bodyWriter->addAttribute( "office:value-type", valType );
01304 if ( value.type() == QVariant::Double )
01305 bodyWriter->addAttribute( "office:value", valStr );
01306
01307 bodyWriter->startElement( "text:p" );
01308 bodyWriter->addTextNode( valStr );
01309 bodyWriter->endElement();
01310 }
01311 bodyWriter->endElement();
01312 }
01313 bodyWriter->endElement();
01314 }
01315
01316 bodyWriter->endElement();
01317 bodyWriter->endElement();
01318 }
01319
01320 void KChartPart::writeAutomaticStyles( KoXmlWriter& contentWriter, KoGenStyles& mainStyles ) const
01321 {
01322 QValueList<KoGenStyles::NamedStyle> styles = mainStyles.styles( KoGenStyle::STYLE_AUTO );
01323 QValueList<KoGenStyles::NamedStyle>::const_iterator it = styles.begin();
01324 for ( ; it != styles.end() ; ++it ) {
01325 (*it).style->writeStyle( &contentWriter, mainStyles, "style:style", (*it).name, "style:chart-properties" );
01326 }
01327
01328 }
01329
01330
01331
01332
01333
01334 QDomDocument KChartPart::saveXML()
01335 {
01336 QDomElement tmpElem;
01337
01338
01339
01340
01341
01342 QDomDocument doc = m_params->saveXML( false );
01343
01344
01345
01346
01347 QDomElement docRoot = doc.documentElement();
01348
01349
01350 QDomElement aux = doc.createElement( "KChartAuxiliary" );
01351 docRoot.appendChild( aux );
01352
01353
01354 tmpElem = doc.createElement( "direction" );
01355 tmpElem.setAttribute( "value", (int) m_params->dataDirection() );
01356 aux.appendChild( tmpElem );
01357
01358 tmpElem = doc.createElement( "dataaslabel" );
01359 tmpElem.setAttribute( "firstrow",
01360 m_params->firstRowAsLabel() ? "true" : "false" );
01361 tmpElem.setAttribute( "firstcol",
01362 m_params->firstColAsLabel() ? "true" : "false" );
01363 aux.appendChild( tmpElem );
01364
01365 tmpElem = doc.createElement( "barnumlines" );
01366 tmpElem.setAttribute( "value", (int) m_params->barNumLines() );
01367 aux.appendChild( tmpElem );
01368
01369
01370 QDomElement data = doc.createElement( "data" );
01371 docRoot.appendChild( data );
01372
01373 int cols = m_currentData.usedCols()
01374 ? QMIN(m_currentData.usedCols(), m_currentData.cols())
01375 : m_currentData.cols();
01376 int rows = m_currentData.usedRows()
01377 ? QMIN(m_currentData.usedRows(), m_currentData.rows())
01378 : m_currentData.rows();
01379 data.setAttribute( "cols", cols );
01380 data.setAttribute( "rows", rows );
01381 kdDebug(35001) << " writing " << cols << "," << rows << " (cols,rows)." << endl;
01382
01383 for (int i=0; i!=rows; ++i) {
01384 for (int j=0; j!=cols; ++j) {
01385 QDomElement e = doc.createElement( "cell" );
01386 data.appendChild( e );
01387 QString valType;
01388 QVariant value( m_currentData.cellVal( i,j ) );
01389 switch ( value.type() ) {
01390 case QVariant::Invalid: valType = "NoValue"; break;
01391 case QVariant::String: valType = "String"; break;
01392 case QVariant::Double: valType = "Double"; break;
01393 case QVariant::DateTime: valType = "DateTime"; break;
01394 default: {
01395 valType = "(unknown)";
01396 kdDebug(35001) << "ERROR: cell " << i << "," << j
01397 << " has unknown type." << endl;
01398 }
01399 }
01400
01401 e.setAttribute( "valType", valType );
01402
01403
01404 switch ( value.type() ) {
01405 case QVariant::String: e.setAttribute( "value", value.toString() );
01406 break;
01407 case QVariant::Double: e.setAttribute( "value", QString::number( value.toDouble() ) );
01408 break;
01409 case QVariant::DateTime:e.setAttribute( "value", "" );
01410 break;
01411 default: {
01412 e.setAttribute( "value", "" );
01413 if( QVariant::Invalid != value.type() )
01414 kdDebug(35001) << "ERROR: cell " << i << "," << j
01415 << " has unknown type." << endl;
01416 }
01417 }
01418 }
01419 }
01420
01421 return doc;
01422 }
01423
01424
01425 bool KChartPart::loadXML( QIODevice*, const QDomDocument& doc )
01426 {
01427 kdDebug(35001) << "kchart loadXML called" << endl;
01428
01429
01430 bool result = m_params->loadXML( doc );
01431
01432
01433 if (result) {
01434 result = loadAuxiliary(doc) && loadData( doc, m_currentData );
01435 }
01436 else {
01437
01438 result = loadOldXML( doc );
01439 }
01440
01441
01442 if (result) {
01443 QStringList legendLabels;
01444 KDChartAxisParams params;
01445 params = m_params->axisParams( KDChartAxisParams::AxisPosBottom );
01446
01447
01448 QString str;
01449 uint index = 0;
01450 while ((str = m_params->legendText(index++)) != QString::null)
01451 legendLabels << str;
01452
01453 if (m_params->dataDirection() == KChartParams::DataRows) {
01454 m_colLabels = params.axisLabelStringList();
01455 m_rowLabels = legendLabels;
01456 }
01457 else {
01458 m_colLabels = legendLabels;
01459 m_rowLabels = params.axisLabelStringList();
01460 }
01461
01462 setChartDefaults();
01463 }
01464
01465 m_params->setDrawSolidExcessArrows(true);
01466
01467 return result;
01468 }
01469
01470
01471
01472
01473
01474
01475 bool KChartPart::loadAuxiliary( const QDomDocument& doc )
01476 {
01477 QDomElement chart = doc.documentElement();
01478 QDomElement aux = chart.namedItem("KChartAuxiliary").toElement();
01479
01480
01481
01482 if (aux.isNull())
01483 return true;
01484
01485 QDomNode node = aux.firstChild();
01486
01487
01488 while (!node.isNull()) {
01489
01490 QDomElement e = node.toElement();
01491 if (e.isNull()) {
01492
01493 node = node.nextSibling();
01494 continue;
01495 }
01496
01497
01498 if ( e.tagName() == "direction" ) {
01499 if ( e.hasAttribute("value") ) {
01500 bool ok;
01501
01502
01503 int dir = e.attribute("value").toInt(&ok);
01504 if ( !ok )
01505 dir = (int) KChartParams::DataColumns;
01506
01507
01508 m_params->setDataDirection( (KChartParams::DataDirection) dir );
01509 }
01510 else {
01511 kdDebug(35001) << "Error in direction tag." << endl;
01512 }
01513 }
01514
01515
01516 else if ( e.tagName() == "dataaslabel" ) {
01517 QString val;
01518
01519 if ( e.hasAttribute("firstrow") ) {
01520
01521 val = e.attribute("firstrow");
01522 if ( val == "true" )
01523 m_params->setFirstRowAsLabel( true );
01524 else
01525 m_params->setFirstRowAsLabel( false );
01526 }
01527 else {
01528 kdDebug(35001) << "Error in barnumlines tag." << endl;
01529 m_params->setFirstRowAsLabel( false );
01530 }
01531
01532 if ( e.hasAttribute("firstcol") ) {
01533
01534 val = e.attribute("firstcol");
01535 if ( val == "true" )
01536 m_params->setFirstColAsLabel( true );
01537 else
01538 m_params->setFirstColAsLabel( false );
01539 }
01540 else {
01541 kdDebug(35001) << "Error in barnumlines tag." << endl;
01542 m_params->setFirstColAsLabel( false );
01543 }
01544 }
01545
01546
01547 else if ( e.tagName() == "barnumlines" ) {
01548 if ( e.hasAttribute("value") ) {
01549 bool ok;
01550
01551
01552 int barNumLines = e.attribute("value").toInt(&ok);
01553 if ( !ok )
01554 barNumLines = 0;
01555
01556
01557
01558 m_params->setBarNumLines( barNumLines );
01559 }
01560 else {
01561 kdDebug(35001) << "Error in barnumlines tag." << endl;
01562 }
01563 }
01564 #if 0
01565
01566 else if ( e.tagName() == "..." ) {
01567 }
01568 and so on...
01569 #endif
01570
01571 node = node.nextSibling();
01572 }
01573
01574 return true;
01575 }
01576
01577
01578 bool KChartPart::loadData( const QDomDocument& doc,
01579 KDChartTableData& m_currentData )
01580 {
01581 kdDebug(35001) << "kchart loadData called" << endl;
01582
01583 QDomElement chart = doc.documentElement();
01584 QDomElement data = chart.namedItem("data").toElement();
01585 bool ok;
01586 int cols = data.attribute("cols").toInt(&ok);
01587 kdDebug(35001) << "cols readed as:" << cols << endl;
01588 if ( !ok ){
01589 return false;
01590 }
01591
01592 int rows = data.attribute("rows").toInt(&ok);
01593 if ( !ok ){
01594 return false;
01595 }
01596
01597 kdDebug(35001) << rows << " x " << cols << endl;
01598 m_currentData.expand(rows, cols);
01599 m_currentData.setUsedCols( cols );
01600 m_currentData.setUsedRows( rows );
01601 kdDebug(35001) << "Expanded!" << endl;
01602 QDomNode n = data.firstChild();
01603
01604
01605 for (int i=0; i!=rows; i++) {
01606 for (int j=0; j!=cols; j++) {
01607 if (n.isNull()) {
01608 kdDebug(35001) << "Some problems, there is less data than it should be!" << endl;
01609 break;
01610 }
01611 QDomElement e = n.toElement();
01612 if ( !e.isNull() && e.tagName() == "cell" ) {
01613
01614 QVariant t;
01615 if ( e.hasAttribute("value") && e.hasAttribute("valType") ) {
01616 QString valueType = e.attribute("valType").lower();
01617 if ( "string" == valueType ) {
01618 t = e.attribute("value");
01619 }
01620 else if ( "double" == valueType ) {
01621 bool bOk;
01622 double val = e.attribute("value").toDouble(&bOk);
01623 if ( !bOk )
01624 val = 0.0;
01625 t = val;
01626
01627
01628
01629
01630 } else {
01631 t.clear();
01632 if ( "novalue" != valueType )
01633 kdDebug(35001) << "ERROR: cell " << i << "," << j << " has unknown type '" << valueType << "'." << endl;
01634 }
01635 } else
01636 t.clear();
01637
01638 m_currentData.setCell(i,j, t );
01639
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657 n = n.nextSibling();
01658 }
01659 }
01660 }
01661
01662
01663
01664
01665 return true;
01666 }
01667
01668
01669
01670
01671
01672
01673 bool KChartPart::loadOldXML( const QDomDocument& doc )
01674 {
01675 kdDebug(35001) << "kchart loadOldXML called" << endl;
01676 if ( doc.doctype().name() != "chart" )
01677 return false;
01678
01679 kdDebug(35001) << "Ok, it is a chart" << endl;
01680
01681 QDomElement chart = doc.documentElement();
01682 if ( chart.attribute( "mime" ) != "application/x-kchart" && chart.attribute( "mime" ) != "application/vnd.kde.kchart" )
01683 return false;
01684
01685 kdDebug(35001) << "Mimetype ok" << endl;
01686
01687 #if 0
01688 QDomElement data = chart.namedItem("data").toElement();
01689 bool ok;
01690 int cols = data.attribute("cols").toInt(&ok);
01691 kdDebug(35001) << "cols readed as:" << cols << endl;
01692 if (!ok) { return false; }
01693 int rows = data.attribute("rows").toInt(&ok);
01694 if (!ok) { return false; }
01695 kdDebug(35001) << rows << " x " << cols << endl;
01696 m_currentData.expand(rows, cols);
01697 kdDebug(35001) << "Expanded!" << endl;
01698 QDomNode n = data.firstChild();
01699 QArray<int> tmpExp(rows*cols);
01700 QArray<bool> tmpMissing(rows*cols);
01701
01702 for (int i=0; i!=rows; i++) {
01703 for (int j=0; j!=cols; j++) {
01704 if (n.isNull()) {
01705 kdDebug(35001) << "Some problems, there is less data than it should be!" << endl;
01706 break;
01707 }
01708
01709 QDomElement e = n.toElement();
01710 if ( !e.isNull() && e.tagName() == "cell" ) {
01711
01712 double val = e.attribute("value").toDouble(&ok);
01713 if (!ok) { return false; }
01714 kdDebug(35001) << i << " " << j << "=" << val << endl;
01715 KoChart::Value t( val );
01716
01717 m_currentData.setCell(i,j,t);
01718 if ( e.hasAttribute( "hide" ) ) {
01719 tmpMissing[cols*j+i] = (bool)e.attribute("hide").toInt( &ok );
01720 if ( !ok )
01721 return false;
01722 } else {
01723 tmpMissing[cols*j+i] = false;
01724 }
01725 if ( e.hasAttribute( "dist" ) ) {
01726 tmpExp[cols*j+i] = e.attribute("dist").toInt( &ok );
01727 if ( !ok )
01728 return false;
01729 } else {
01730 tmpExp[cols*j+i] = 0;
01731 }
01732
01733 n = n.nextSibling();
01734 }
01735 }
01736 }
01737 m_params->missing=tmpMissing;
01738 m_params->explode=tmpExp;
01739 #endif
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763
01764 bool ok;
01765 QDomElement params = chart.namedItem( "params" ).toElement();
01766 if ( params.hasAttribute( "type" ) ) {
01767 int type=params.attribute("type").toInt( &ok );
01768 if ( !ok )
01769 return false;
01770 switch(type)
01771 {
01772 case 1:
01773 m_params->setChartType(KChartParams::Line);
01774 break;
01775 case 2:
01776 m_params->setChartType(KChartParams::Area);
01777 break;
01778 case 3:
01779 m_params->setChartType(KChartParams::Bar);
01780 break;
01781 case 4:
01782 m_params->setChartType(KChartParams::HiLo);
01783 break;
01784 case 5:
01785 case 6:
01786 case 7:
01787 case 8:
01788
01789
01790
01791
01792
01793
01794 m_params->setChartType(KChartParams::Line);
01795 break;
01796 case 9:
01797 m_params->setChartType(KChartParams::HiLo);
01798 break;
01799 case 10:
01800 m_params->setChartType(KChartParams::Bar);
01801 break;
01802 case 11:
01803 m_params->setChartType(KChartParams::Area);
01804 break;
01805 case 12:
01806 m_params->setChartType(KChartParams::Bar);
01807 break;
01808 case 13:
01809 m_params->setChartType(KChartParams::Area);
01810 break;
01811 case 14:
01812 m_params->setChartType(KChartParams::Bar);
01813 break;
01814 case 15:
01815 m_params->setChartType(KChartParams::Area);
01816 break;
01817 case 16:
01818 m_params->setChartType(KChartParams::Line);
01819 break;
01820 case 17:
01821 case 18:
01822 m_params->setChartType(KChartParams::Pie);
01823 break;
01824
01825 }
01826 if ( !ok )
01827 return false;
01828 }
01829 #if 0
01830 if ( params.hasAttribute( "subtype" ) ) {
01831 m_params->stack_type = (KChartStackType)params.attribute("subtype").toInt( &ok );
01832 if ( !ok )
01833 return false;
01834 }
01835 if ( params.hasAttribute( "hlc_style" ) ) {
01836 m_params->hlc_style = (KChartHLCStyle)params.attribute("hlc_style").toInt( &ok );
01837 if ( !ok )
01838 return false;
01839 }
01840 if ( params.hasAttribute( "hlc_cap_width" ) ) {
01841 m_params->hlc_cap_width = (short)params.attribute( "hlc_cap_width" ).toShort( &ok );
01842 if ( !ok )
01843 return false;
01844 }
01845
01846 QDomElement title = params.namedItem( "title" ).toElement();
01847 if ( !title.isNull()) {
01848 QString t = title.text();
01849 m_params->title=t;
01850 }
01851 QDomElement titlefont = params.namedItem( "titlefont" ).toElement();
01852 if ( !titlefont.isNull()) {
01853 QDomElement font = titlefont.namedItem( "font" ).toElement();
01854 if ( !font.isNull() )
01855 m_params->setTitleFont(toFont(font));
01856 }
01857 QDomElement xtitle = params.namedItem( "xtitle" ).toElement();
01858 if ( !xtitle.isNull()) {
01859 QString t = xtitle.text();
01860 m_params->xtitle=t;
01861 }
01862 QDomElement xtitlefont = params.namedItem( "xtitlefont" ).toElement();
01863 if ( !xtitlefont.isNull()) {
01864 QDomElement font = xtitlefont.namedItem( "font" ).toElement();
01865 if ( !font.isNull() )
01866 m_params->setXTitleFont(toFont(font));
01867 }
01868 QDomElement ytitle = params.namedItem( "ytitle" ).toElement();
01869 if ( !ytitle.isNull()) {
01870 QString t = ytitle.text();
01871 m_params->ytitle=t;
01872 }
01873 QDomElement ytitle2 = params.namedItem( "ytitle2" ).toElement();
01874 if ( !ytitle2.isNull()) {
01875 QString t = ytitle2.text();
01876 m_params->ytitle2=t;
01877 }
01878 QDomElement ytitlefont = params.namedItem( "ytitlefont" ).toElement();
01879 if ( !ytitlefont.isNull()) {
01880 QDomElement font = ytitlefont.namedItem( "font" ).toElement();
01881 if ( !font.isNull() )
01882 m_params->setYTitleFont(toFont(font));
01883 }
01884 QDomElement ylabelfmt = params.namedItem( "ylabelfmt" ).toElement();
01885 if ( !ylabelfmt.isNull()) {
01886 QString t = ylabelfmt.text();
01887 m_params->ylabel_fmt=t;
01888 }
01889 QDomElement ylabel2fmt = params.namedItem( "ylabel2fmt" ).toElement();
01890 if ( !ylabel2fmt.isNull()) {
01891 QString t = ylabel2fmt.text();
01892 m_params->ylabel2_fmt=t;
01893 }
01894 QDomElement labelfont = params.namedItem( "labelfont" ).toElement();
01895 if ( !labelfont.isNull()) {
01896 QDomElement font = labelfont.namedItem( "font" ).toElement();
01897 if ( !font.isNull() )
01898 m_params->setLabelFont(toFont(font));
01899 }
01900
01901 QDomElement yaxisfont = params.namedItem( "yaxisfont" ).toElement();
01902 if ( !yaxisfont.isNull()) {
01903 QDomElement font = yaxisfont.namedItem( "font" ).toElement();
01904 if ( !font.isNull() )
01905 m_params->setYAxisFont(toFont(font));
01906 }
01907
01908 QDomElement xaxisfont = params.namedItem( "xaxisfont" ).toElement();
01909 if ( !xaxisfont.isNull()) {
01910 QDomElement font = xaxisfont.namedItem( "font" ).toElement();
01911 if ( !font.isNull() )
01912 m_params->setXAxisFont(toFont(font));
01913 }
01914 QDomElement annotationFont = params.namedItem("annotationfont").toElement();
01915 if ( !annotationFont.isNull()) {
01916 QDomElement font = annotationFont.namedItem( "font" ).toElement();
01917 if ( !font.isNull() )
01918 m_params->setAnnotationFont(toFont(font));
01919 }
01920
01921 QDomElement yaxis = params.namedItem( "yaxis" ).toElement();
01922 if ( !yaxis.isNull()) {
01923 if (yaxis.hasAttribute( "yinterval" )) {
01924 m_params->requested_yinterval= yaxis.attribute("yinterval").toDouble( &ok );
01925 if ( !ok ) return false;
01926 }
01927 if (yaxis.hasAttribute( "ymin" )) {
01928 m_params->requested_ymin= yaxis.attribute("ymin").toDouble( &ok );
01929 if ( !ok ) return false;
01930 }
01931 if (yaxis.hasAttribute( "ymax" ) ) {
01932 m_params->requested_ymax= yaxis.attribute("ymax").toDouble( &ok );
01933 if ( !ok ) return false;
01934 }
01935 }
01936 #endif
01937
01938 QDomElement graph = params.namedItem( "graph" ).toElement();
01939 if (!graph.isNull()) {
01940 if (graph.hasAttribute( "grid" )) {
01941 bool b=(bool) graph.attribute("grid").toInt( &ok );
01942 m_params->setAxisShowGrid(KDChartAxisParams::AxisPosLeft,b );
01943 m_params->setAxisShowGrid(KDChartAxisParams::AxisPosBottom,b );
01944 if (!ok) return false;
01945 }
01946 if (graph.hasAttribute( "xaxis" )) {
01947 bool b=(bool) graph.attribute("xaxis").toInt( &ok );
01948 if (!ok) return false;
01949 m_params->setAxisVisible(KDChartAxisParams::AxisPosBottom,b);
01950 }
01951 if (graph.hasAttribute( "yaxis" )) {
01952 bool b=(bool) graph.attribute("yaxis").toInt( &ok );
01953 if (!ok) return false;
01954 m_params->setAxisVisible(KDChartAxisParams::AxisPosLeft,b);
01955 }
01956 #if 0
01957
01958 if (graph.hasAttribute( "shelf" )) {
01959 m_params->shelf=(bool) graph.attribute("shelf").toInt( &ok );
01960 if (!ok) return false;
01961 }
01962 #endif
01963 if (graph.hasAttribute( "yaxis2" )) {
01964 bool b=(bool) graph.attribute("yaxis2").toInt( &ok );
01965 if (!ok) return false;
01966 m_params->setAxisVisible(KDChartAxisParams::AxisPosRight,b);
01967 }
01968
01969 #if 0
01970
01971 if (graph.hasAttribute( "ystyle" )) {
01972 m_params->yval_style=(bool) graph.attribute("ystyle").toInt( &ok );
01973 if (!ok) return false;
01974 }
01975 if (graph.hasAttribute( "border" )) {
01976 m_params->border=(bool) graph.attribute("border").toInt( &ok );
01977 if (!ok) return false;
01978 }
01979 if (graph.hasAttribute( "transbg" )) {
01980 m_params->transparent_bg=(bool) graph.attribute("transbg").toInt( &ok );
01981 if (!ok) return false;
01982 }
01983 if (graph.hasAttribute( "xlabel" )) {
01984 m_params->hasxlabel=(bool) graph.attribute("xlabel").toInt( &ok );
01985 if (!ok) return false;
01986 }
01987 if ( graph.hasAttribute( "xlabel_spacing" ) ) {
01988 m_params->xlabel_spacing = (short)graph.attribute( "xlabel_spacing" ).toShort( &ok );
01989 if ( !ok )
01990 return false;
01991 }
01992 if ( graph.hasAttribute( "ylabel_density" ) ) {
01993 m_params->ylabel_density = (short)graph.attribute( "ylabel_density" ).toShort( &ok );
01994 if ( !ok )
01995 return false;
01996 }
01997 if (graph.hasAttribute( "line")) {
01998 m_params->label_line=(bool) graph.attribute("line").toInt( &ok );
01999 if (!ok) return false;
02000 }
02001 if (graph.hasAttribute( "percent")) {
02002 m_params->percent_labels=(KChartPercentType) graph.attribute("percent").toInt( &ok );
02003 if (!ok) return false;
02004 }
02005 if (graph.hasAttribute("cross")) {
02006 m_params->cross=(bool) graph.attribute("cross").toInt( &ok );
02007 if (!ok) return false;
02008 }
02009 if (graph.hasAttribute("thumbnail")) {
02010 m_params->thumbnail=(bool) graph.attribute("thumbnail").toInt( &ok );
02011 if (!ok) return false;
02012 }
02013 if (graph.hasAttribute("thumblabel")) {
02014 m_params->thumblabel= graph.attribute("thumblabel");
02015 }
02016 if (graph.hasAttribute("thumbval")) {
02017 m_params->thumbval=(bool) graph.attribute("thumbval").toDouble( &ok );
02018 if (!ok)
02019 return false;
02020 }
02021 #endif
02022 }
02023
02024 #if 0
02025 QDomElement graphparams = params.namedItem( "graphparams" ).toElement();
02026 if (!graphparams.isNull()) {
02027 if (graphparams.hasAttribute( "dept3d" )) {
02028 m_params->_3d_depth=graphparams.attribute("dept3d").toDouble( &ok );
02029 if (!ok) return false;
02030 }
02031 if (graphparams.hasAttribute( "angle3d" )) {
02032 m_params->_3d_angle=graphparams.attribute("angle3d").toShort( &ok );
02033 if (!ok) return false;
02034 }
02035 if (graphparams.hasAttribute( "barwidth" )) {
02036 m_params->bar_width=graphparams.attribute("barwidth").toShort( &ok );
02037 if (!ok) return false;
02038 }
02039 if (graphparams.hasAttribute( "colpie" )) {
02040 m_params->colPie=graphparams.attribute("colpie").toInt( &ok );
02041 if (!ok) return false;
02042 }
02043 if (graphparams.hasAttribute( "other_threshold" )) {
02044 m_params->other_threshold=graphparams.attribute("other_threshold").toShort( &ok );
02045 if (!ok)
02046 return false;
02047 }
02048 if (graphparams.hasAttribute( "offsetCol" )) {
02049 m_params->offsetCol = graphparams.attribute("offsetCol").toInt( &ok );
02050 if (!ok)
02051 return false;
02052 }
02053 if (graphparams.hasAttribute( "hard_size" )) {
02054 m_params->hard_size = (bool)graphparams.attribute("hard_size").toInt( &ok );
02055 if (!ok)
02056 return false;
02057 }
02058 if (graphparams.hasAttribute( "hard_graphheight" )) {
02059 m_params->hard_graphheight = graphparams.attribute("hard_graphheight").toInt( &ok );
02060 if (!ok)
02061 return false;
02062 }
02063 if (graphparams.hasAttribute( "hard_graphwidth" )) {
02064 m_params->hard_graphwidth = graphparams.attribute("hard_graphwidth").toInt( &ok );
02065 if (!ok)
02066 return false;
02067 }
02068 if (graphparams.hasAttribute( "hard_xorig" )) {
02069 m_params->hard_xorig = graphparams.attribute("hard_xorig").toInt( &ok );
02070 if (!ok)
02071 return false;
02072 }
02073 if (graphparams.hasAttribute( "hard_yorig" )) {
02074 m_params->hard_yorig = graphparams.attribute("hard_yorig").toInt( &ok );
02075 if (!ok)
02076 return false;
02077 }
02078 if (graphparams.hasAttribute( "labeldist" )) {
02079 m_params->label_dist=graphparams.attribute("labeldist").toInt( &ok );
02080 if (!ok) return false;
02081 }
02082 }
02083
02084 QDomElement graphcolor = params.namedItem( "graphcolor" ).toElement();
02085 if (!graphcolor.isNull()) {
02086 if (graphcolor.hasAttribute( "bgcolor" )) {
02087 m_params->BGColor= QColor( graphcolor.attribute( "bgcolor" ) );
02088 }
02089 if (graphcolor.hasAttribute( "gridcolor" )) {
02090 m_params->GridColor= QColor( graphcolor.attribute( "gridcolor" ) );
02091 }
02092 if (graphcolor.hasAttribute( "linecolor" )) {
02093 m_params->LineColor= QColor( graphcolor.attribute( "linecolor" ) );
02094 }
02095 if (graphcolor.hasAttribute( "plotcolor" )) {
02096 m_params->PlotColor= QColor( graphcolor.attribute( "plotcolor" ) );
02097 }
02098 if (graphcolor.hasAttribute( "volcolor" )) {
02099 m_params->VolColor= QColor( graphcolor.attribute( "volcolor" ) );
02100 }
02101 if (graphcolor.hasAttribute( "titlecolor" )) {
02102 m_params->TitleColor= QColor( graphcolor.attribute( "titlecolor" ) );
02103 }
02104 if (graphcolor.hasAttribute( "xtitlecolor" )) {
02105 m_params->XTitleColor= QColor( graphcolor.attribute( "xtitlecolor" ) );
02106 }
02107 if (graphcolor.hasAttribute( "ytitlecolor" )) {
02108 m_params->YTitleColor= QColor( graphcolor.attribute( "ytitlecolor" ) );
02109 }
02110 if (graphcolor.hasAttribute( "ytitle2color" )) {
02111 m_params->YTitle2Color= QColor( graphcolor.attribute( "ytitle2color" ) );
02112 }
02113 if (graphcolor.hasAttribute( "xlabelcolor" )) {
02114 m_params->XLabelColor= QColor( graphcolor.attribute( "xlabelcolor" ) );
02115 }
02116 if (graphcolor.hasAttribute( "ylabelcolor" )) {
02117 m_params->YLabelColor= QColor( graphcolor.attribute( "ylabelcolor" ) );
02118 }
02119 if (graphcolor.hasAttribute( "ylabel2color" )) {
02120 m_params->YLabel2Color= QColor( graphcolor.attribute( "ylabel2color" ) );
02121 }
02122 }
02123
02124 QDomElement annotation = params.namedItem( "annotation" ).toElement();
02125 if (!annotation.isNull()) {
02126 m_params->annotation=new KChartAnnotationType;
02127 if (annotation.hasAttribute( "color" )) {
02128 m_params->annotation->color= QColor( annotation.attribute( "color" ) );
02129 }
02130 if (annotation.hasAttribute( "point" )) {
02131 m_params->annotation->point=annotation.attribute("point").toDouble( &ok );
02132 if (!ok) return false;
02133 }
02134 }
02135
02136 QDomElement note = params.namedItem( "note" ).toElement();
02137 if ( !note.isNull()) {
02138 QString t = note.text();
02139 m_params->annotation->note=t;
02140 }
02141
02142 QDomElement scatter = params.namedItem( "scatter" ).toElement();
02143 if ( !scatter.isNull() ) {
02144 m_params->scatter = new KChartScatterType;
02145 if ( scatter.hasAttribute( "point" ) ) {
02146 m_params->scatter->point = scatter.attribute( "point" ).toDouble( &ok );
02147 if ( !ok )
02148 return false;
02149 }
02150 if ( scatter.hasAttribute( "val" ) ) {
02151 m_params->scatter->val = scatter.attribute( "val" ).toDouble( &ok );
02152 if ( !ok )
02153 return false;
02154 }
02155 if ( scatter.hasAttribute( "width" ) ) {
02156 m_params->scatter->width = scatter.attribute( "val" ).toUShort( &ok );
02157 if ( !ok )
02158 return false;
02159 }
02160 if ( scatter.hasAttribute( "color" )) {
02161 m_params->scatter->color= QColor( scatter.attribute( "color" ) );
02162 }
02163 if ( scatter.hasAttribute( "ind" ) ) {
02164 m_params->scatter->ind = (KChartScatterIndType)scatter.attribute( "ind" ).toInt( &ok );
02165 if ( !ok )
02166 return false;
02167 }
02168 }
02169
02170 QDomElement legend = chart.namedItem("legend").toElement();
02171 if (!legend.isNull()) {
02172 int number = legend.attribute("number").toInt(&ok);
02173 if (!ok) { return false; }
02174 QDomNode name = legend.firstChild();
02175 m_params->legend.clear();
02176 for(int i=0; i<number; i++) {
02177 if (name.isNull()) {
02178 kdDebug(35001) << "Some problems, there is less data than it should be!" << endl;
02179 break;
02180 }
02181 QDomElement element = name.toElement();
02182 if ( !element.isNull() && element.tagName() == "name" ) {
02183 QString t = element.text();
02184 m_params->legend+=t;
02185 name = name.nextSibling();
02186 }
02187 }
02188 }
02189
02190 QDomElement xlbl = chart.namedItem("xlbl").toElement();
02191 if (!xlbl.isNull()) {
02192 int number = xlbl.attribute("number").toInt(&ok);
02193 if (!ok) { return false; }
02194 QDomNode label = xlbl.firstChild();
02195 m_params->xlbl.clear();
02196 for (int i=0; i<number; i++) {
02197 if (label.isNull()) {
02198 kdDebug(35001) << "Some problems, there is less data than it should be!" << endl;
02199 break;
02200 }
02201 QDomElement element = label.toElement();
02202 if ( !element.isNull() && element.tagName() == "label" ) {
02203 QString t = element.text();
02204 m_params->xlbl+=t;
02205 label = label.nextSibling();
02206 }
02207 }
02208 }
02209
02210 QDomElement backgroundPixmap = chart.namedItem( "backgroundPixmap" ).toElement();
02211 if ( !backgroundPixmap.isNull() ) {
02212 if ( backgroundPixmap.hasAttribute( "name" ) )
02213 m_params->backgroundPixmapName = backgroundPixmap.attribute( "name" );
02214 if ( backgroundPixmap.hasAttribute( "isDirty" ) ) {
02215 m_params->backgroundPixmapIsDirty = (bool)backgroundPixmap.attribute( "isDirty" ).toInt( &ok );
02216 if ( !ok )
02217 return false;
02218 }
02219 if ( backgroundPixmap.hasAttribute( "scaled" ) ) {
02220 m_params->backgroundPixmapScaled = (bool)backgroundPixmap.attribute( "scaled" ).toInt( &ok );
02221 if ( !ok )
02222 return false;
02223 }
02224 if ( backgroundPixmap.hasAttribute( "centered" ) ) {
02225 m_params->backgroundPixmapCentered = (bool)backgroundPixmap.attribute( "centered" ).toInt( &ok );
02226 if ( !ok )
02227 return false;
02228 }
02229 if ( backgroundPixmap.hasAttribute( "intensity" ) ) {
02230 m_params->backgroundPixmapIntensity = backgroundPixmap.attribute( "intensity" ).toFloat( &ok );
02231 if ( !ok )
02232 return false;
02233 }
02234 }
02235
02236 QDomElement extcolor = chart.namedItem("extcolor").toElement();
02237 if (!extcolor.isNull()) {
02238 unsigned int number = extcolor.attribute("number").toInt(&ok);
02239 if (!ok) { return false; }
02240 QDomNode color = extcolor.firstChild();
02241
02242 for (unsigned int i=0; i<number; i++) {
02243 if (color.isNull()) {
02244 kdDebug(35001) << "Some problems, there is less data than it should be!" << endl;
02245 break;
02246 }
02247 QDomElement element = color.toElement();
02248 if ( !element.isNull()) {
02249 if (element.hasAttribute( "name" )) {
02250 m_params->ExtColor.setColor(i,QColor( element.attribute( "name" ) ));
02251 }
02252 color = color.nextSibling();
02253 }
02254 }
02255 }
02256
02257 if ( !m_params->backgroundPixmapName.isNull() ) {
02258 m_params->backgroundPixmap.load( locate( "wallpaper",
02259 m_params->backgroundPixmapName ));
02260 m_params->backgroundPixmapIsDirty = true;
02261 }
02262 #endif
02263 return true;
02264 }
02265
02266
02267
02268 void KChartPart::slotModified()
02269 {
02270 kdDebug(35001) << "slotModified called!" << endl;
02271
02272 setModified(true);
02273 }
02274
02275
02276 bool KChartPart::showEmbedInitDialog(QWidget* )
02277 {
02278
02279 return true;
02280 }
02281
02282
02283 }
02284
02285 #include "kchart_part.moc"