summaryrefslogtreecommitdiffstats
path: root/kchart/kchart_part.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kchart/kchart_part.cpp')
-rw-r--r--kchart/kchart_part.cpp2306
1 files changed, 2306 insertions, 0 deletions
diff --git a/kchart/kchart_part.cpp b/kchart/kchart_part.cpp
new file mode 100644
index 000000000..fb6a64143
--- /dev/null
+++ b/kchart/kchart_part.cpp
@@ -0,0 +1,2306 @@
+/**
+ *
+ * Kalle Dalheimer <kalle@kde.org>
+ */
+
+#include <float.h> // For basic data types characteristics.
+
+// For debugging
+#include <iostream>
+using std::cout;
+using std::cerr;
+
+#include "kchart_part.h"
+#include "kchart_view.h"
+#include "kchart_factory.h"
+#include "kchartWizard.h"
+#include "kchart_params.h"
+#include "kdchart/KDChart.h"
+#include "kdchart/KDChartTable.h"
+
+#include <KoTemplateChooseDia.h>
+#include <KoDom.h>
+#include <KoXmlNS.h>
+#include <KoXmlWriter.h>
+#include <KoOasisStore.h>
+#include <KoOasisLoadingContext.h>
+
+#include <kstandarddirs.h>
+#include <tdeglobal.h>
+#include <kdebug.h>
+
+#include <tqdom.h>
+#include <tqtextstream.h>
+#include <tqbuffer.h>
+#include <tqpainter.h>
+
+using namespace std;
+
+// Some hardcoded data for a chart
+
+/* ----- set some data ----- */
+// float a[6] = { 0.5, 0.09, 0.6, 0.85, 0.0, 0.90 },
+// b[6] = { 1.9, 1.3, 0.6, 0.75, 0.1, -2.0 };
+/* ----- X labels ----- */
+// char *t[6] = { "Chicago", "New York", "L.A.", "Atlanta", "Paris, MD\n(USA) ", "London" };
+/* ----- data set colors (RGB) ----- */
+// TQColor sc[2] = { TQColor( 255, 128, 128 ), TQColor( 128, 128, 255 ) };
+
+
+namespace KChart
+{
+
+KChartPart::KChartPart( TQWidget *parentWidget, const char *widgetName,
+ TQObject* parent, const char* name,
+ bool singleViewMode )
+ : KoChart::Part( parentWidget, widgetName, parent, name, singleViewMode ),
+ m_params( 0 ),
+ m_parentWidget( parentWidget ),
+ m_rowLabels(), m_colLabels()
+{
+ kdDebug(35001) << "Constructor started!" << endl;
+
+ setInstance( KChartFactory::global(), false );
+ setTemplateType( "kchart_template" );
+
+ // Init some members that need it.
+ {
+ // Create the chart parameters and let the default be a bar chart
+ // with 3D looks.
+ m_params = new KChartParams( this );
+ m_params->setChartType( KChartParams::Bar );
+ m_params->setBarChartSubType( KChartParams::BarNormal );
+ m_params->setThreeDBars( true );
+
+ //Changed this to use columns rather than rows by default
+ //because I believe that this is the more common format for
+ //entering data (you can see this looking at the fact that
+ //most spreadsheet packages allow far more rows than columns)
+ //-- Robert Knight
+
+ // Handle data in columns by default
+ m_params->setDataDirection( KChartParams::DataColumns );
+ }
+
+ (void)new WizardExt( this );
+ m_bCanChangeValue = true;
+
+ // Display parameters
+ m_displayData = m_currentData;
+
+ // Set the size to minimal.
+ initEmpty();
+}
+
+
+KChartPart::~KChartPart()
+{
+ //kdDebug(35001) << "Part is going to be destroyed now!!!" << endl;
+ delete m_params;
+}
+
+
+// Reimplement KoDocument::initDoc()
+
+bool KChartPart::initDoc(InitDocFlags flags, TQWidget* parentWidget)
+{
+ // Initialize the parameter set for this chart document
+#if 0
+ kdDebug(35001) << "================================================================" << endl;
+ kdDebug(35001) << "InitDOC: flags = " << flags << endl;
+ kdDebug(35001) << "================================================================" << endl;
+#endif
+
+ TQString f;
+
+ // Embedded documents are initially created like a normal empty
+ // document. If this is in KSpread or another program where the
+ // data is external then the document will be updated later on in
+ // the creation process anyway.
+ if (flags == KoDocument::InitDocEmbedded) {
+ initEmpty();
+ return true;
+ }
+
+ // If we are supposed to create a new, empty document, then do so.
+ if (flags == KoDocument::InitDocEmpty) {
+ initEmpty();
+ return true;
+ }
+
+ KoTemplateChooseDia::ReturnType ret;
+ KoTemplateChooseDia::DialogType dlgtype;
+
+ // If we must create a new document, then only present templates
+ // to the user, otherwise also present existing documents and
+ // recent documents.
+ if (flags == KoDocument::InitDocFileNew )
+ dlgtype = KoTemplateChooseDia::OnlyTemplates;
+ else
+ dlgtype = KoTemplateChooseDia::Everything;
+ ret = KoTemplateChooseDia::choose( KChartFactory::global(), f,
+ dlgtype, "kchart_template",
+ parentWidget );
+
+ if ( ret == KoTemplateChooseDia::File ) {
+ KURL url( f );
+ return openURL( url );
+ }
+ else if ( ret == KoTemplateChooseDia::Empty ) {
+ initEmpty();
+ return true;
+ }
+ else if ( ret == KoTemplateChooseDia::Template ) {
+ //TODO: Activate this for KOffice 1.5/2.0
+// if ( f.endsWith("/templates/chart/.source/BarChart.chrt") ) {
+// generateBarChartTemplate();
+// return true;
+// }
+ TQFileInfo fileInfo( f );
+ TQString fileName( fileInfo.dirPath( true ) + "/" +
+ fileInfo.baseName() + ".chrt" );
+
+ resetURL();
+ bool ok = loadNativeFormat( fileName );
+ if ( !ok )
+ showLoadingErrorDialog();
+ setEmpty();
+ //initConfig();
+ return ok;
+ }
+
+ return false;
+}
+
+void KChartPart::initEmpty()
+{
+ initNullChart();
+
+ resetURL();
+ setEmpty();
+}
+
+
+// This method creates the simplest chart imaginable:
+// Data size 1x1, empty, no headers
+//
+void KChartPart::initNullChart()
+{
+ // Fill cells with data if there is none.
+ //kdDebug(35001) << "Initialize null chart." << endl;
+
+ // Empty data. Note, we don't use (0,0) or (1,1) for the size
+ // here, because otherwise KDChart won't draw anything
+ m_currentData.expand(2, 2);
+ m_params->setFirstRowAsLabel(false);
+ m_params->setFirstColAsLabel(false);
+
+ // Fill column and row labels.
+ m_colLabels << TQString("");
+ m_rowLabels << TQString("");
+
+ setChartDefaults();
+
+ m_params->setDrawSolidExcessArrows(true);
+}
+
+
+void KChartPart::generateBarChartTemplate()
+{
+ int col;
+ int row;
+
+ kdDebug()<<"KChartPart::initTestChart()\n";
+
+ // Fill cells with data if there is none.
+ if (m_currentData.rows() == 0) {
+ //kdDebug(35001) << "Initialize with some data!!!" << endl;
+ m_currentData.expand( 4, 4 );
+ m_currentData.setUsedRows( 4 );
+ m_currentData.setUsedCols( 4 );
+ for (row = 0; row < 4; row++) {
+ for (col = 0; col < 4; col++) {
+ m_currentData.setCell(row, col,
+ static_cast <double> (row + col));
+
+ // Fill column label, but only on the first iteration.
+ if (row == 0) {
+ m_colLabels << i18n("Column %1").arg(col + 1);
+ }
+ }
+
+ // Fill row label.
+ m_rowLabels << i18n("Row %1").arg(row + 1);
+ }
+ }
+
+ setChartDefaults();
+ // FIXME: Should this go into setChartDefaults()?
+ m_params->setDrawSolidExcessArrows(true);
+}
+
+
+KoView* KChartPart::createViewInstance( TQWidget* parent, const char* name )
+{
+ return new KChartView( this, parent, name );
+}
+
+
+// ================================================================
+// Painting
+
+
+void KChartPart::paintContent( TQPainter& painter, const TQRect& rect,
+ bool /*transparent*/,
+ double /*zoomX*/, double /*zoomY*/ )
+{
+ int numDatasets;
+
+ // If params is 0, initDoc() has not been called.
+ Q_ASSERT( m_params != 0 );
+
+ KDChartAxisParams xAxisParms;
+ xAxisParms = m_params->axisParams( KDChartAxisParams::AxisPosBottom );
+
+ // Handle data in rows or columns.
+ //
+ // This means getting row or column headers from the document and
+ // set them as X axis labels or legend according to the current
+ // setting. Also, transpose the data if it should be displayed in
+ // columns instead of in rows.
+
+
+ // Create the displayData table.
+ numDatasets = createDisplayData();
+
+ // Create and set the axis labels and legend.
+ TQStringList longLabels;
+ TQStringList shortLabels;
+ createLabelsAndLegend(longLabels, shortLabels);
+
+ // Set the x axis labels.
+ xAxisParms.setAxisLabelStringLists( &longLabels, &shortLabels );
+ m_params->setAxisParams(KDChartAxisParams::AxisPosBottom, xAxisParms);
+
+
+ // Handle some types or subtypes of charts specially, notably:
+ // - Bar charts with lines in them
+
+ if ( m_params->chartType() == KChartParams::Bar) {
+ if ( m_params->barNumLines() > 0 ) {
+
+ // If this is a bar chart and the user wants a few lines in
+ // it, we need to create an additional chart in the same
+ // drawing area.
+
+ // Specify that we want to have an additional chart.
+ m_params->setAdditionalChartType( KDChartParams::Line );
+
+ const int numBarDatasets = numDatasets - m_params->barNumLines();
+
+ // Assign the datasets to the charts: DataEntry, from, to, chart#
+ m_params->setChartSourceMode( KDChartParams::DataEntry,
+ 0, numBarDatasets - 1,
+ 0 ); // The bar chart
+ m_params->setChartSourceMode( KDChartParams::DataEntry,
+ numBarDatasets, numDatasets - 1,
+ 1 ); // The line chart
+ }
+ else {
+ // Otherwise we don't want any extra chart.
+ m_params->setAdditionalChartType( KDChartParams::NoType );
+ }
+ }
+
+ // Ok, we have now created a data set for display, and params with
+ // suitable legends and axis labels. Now start the real painting.
+
+ // Handle transparency.
+ // Wrong: this flickers; better do this as part of the double-buffering.
+ //if ( !transparent )
+ // painter.eraseRect( rect );
+
+ // ## TODO: support zooming
+
+ // Double-buffering
+ if ( m_bufferPixmap.width() < rect.width()
+ || m_bufferPixmap.height() < rect.height() )
+ {
+ m_bufferPixmap.resize( rect.size() );
+ }
+
+ TQPainter bufferPainter( &m_bufferPixmap );
+
+ // We only need to draw the document rectangle "rect".
+ KDChart::paint( &bufferPainter, m_params, &m_displayData, 0, &rect );
+
+ // This is always the empty rect...
+ // Shouldn't creating a TQPainter in a paintEvent set up clipping automatically?
+ // I thought it did (DF)
+ //const TQRect clipRect = painter.clipRegion().boundingRect();
+ //painter.drawPixmap( clipRect.topLeft(), m_bufferPixmap, clipRect );
+
+ painter.drawPixmap( 0, 0, m_bufferPixmap );
+}
+
+
+// Create the data table m_displayData from m_currentData, taking into
+// account if the first row or line contains headers. The chart type
+// HiLo demands special handling.
+//
+// Return number of datasets.
+//
+// Note: While the current KD Chart 1.1.3 version is still expecting data
+// to be in rows, the upcoming KD Chart 2.0 release will be using
+// data in columns instead, to it will be matching KSpread's way.
+// -khz, 2005-11-15
+//
+// FIXME: Rewrite so that we only copy data when necessary.
+// On the other hand, the next version of KDChart is able to
+// get data directly without storing it into a KDChartData
+// class first, so we might never need to.
+//
+int KChartPart::createDisplayData()
+{
+ int rowOffset = 0;
+ int colOffset = 0;
+ int numDatasets = 0;
+
+ if ( !canChangeValue() ) {
+ if ( m_params->firstRowAsLabel() )
+ rowOffset++;
+ if ( m_params->firstColAsLabel() )
+ colOffset++;
+ }
+
+ // After this sequence, m_DisplayData contains the data in the
+ // correct transposition, and the X axis and the legend contain
+ // the correct labels.
+ TQVariant value1;
+ TQVariant value2;
+ int prop;
+ if (m_params->dataDirection() == KChartParams::DataRows) {
+ // Data is handled in rows. This is the way KDChart works also.
+
+ numDatasets = m_currentData.usedRows() - rowOffset;
+ m_displayData.expand( numDatasets,
+ m_currentData.usedCols() - colOffset );
+
+ // Remove the first row and/or col if they are used for headers.
+ for (uint row = rowOffset; row < m_currentData.usedRows(); row++) {
+ for (uint col = colOffset; col < m_currentData.usedCols(); col++) {
+ if ( m_currentData.cellContent( row, col,
+ value1, value2, prop ) ) {
+ m_displayData.setCell(row - rowOffset, col - colOffset,
+ value1, value2);
+ m_displayData.setProp(row - rowOffset, col - colOffset,
+ prop);
+ }
+ }
+ }
+ }
+ else {
+ // Data is handled in columns. We will have to transpose
+ // everything since KDChart wants its data in rows.
+
+ // Resize displayData so that the transposed data has room.
+ numDatasets = m_currentData.usedCols() - colOffset;
+ m_displayData.expand( numDatasets,
+ m_currentData.usedRows() - rowOffset );
+
+ // Copy data and transpose it.
+ for (uint row = colOffset; row < m_currentData.usedCols(); row++) {
+ for (uint col = rowOffset; col < m_currentData.usedRows(); col++) {
+ if ( m_currentData.cellContent( col, row,
+ value1, value2, prop ) ) {
+ m_displayData.setCell(row - colOffset, col - rowOffset,
+ value1, value2);
+ m_displayData.setProp(row - colOffset, col - rowOffset,
+ prop);
+ }
+ }
+ }
+ }
+
+ // If this is a HiLo chart, we need to manually create the correct
+ // values. This is not done by KDChart.
+ //
+ // Here we don't need to transpose, since we can start from the
+ // newly generated displayData.
+ if (m_params->chartType() == KChartParams::HiLo) {
+ KDChartTableData tmpData = m_displayData;
+
+ // Calculate the min, max, open and close values for each row.
+ m_displayData.expand(tmpData.usedRows(), 4);
+ for (uint row = 0; row < tmpData.usedRows(); row++) {
+ double minVal = DBL_MAX;
+ double maxVal = -DBL_MAX;
+
+ // Calculate min and max for this row.
+ //
+ // Note that we have already taken care of different data
+ // directions above.
+ for (uint col = 0; col < tmpData.usedCols(); col++) {
+ double data = tmpData.cellVal(row, col).toDouble();
+
+ if (data < minVal)
+ minVal = data;
+ if (data > maxVal)
+ maxVal = data;
+ }
+ m_displayData.setCell(row, 0, minVal); // min
+ m_displayData.setCell(row, 1, maxVal); // max
+ m_displayData.setCell(row, 2, tmpData.cellVal(row, 0).toDouble()); // open
+ m_displayData.setCell(row, 3, // close
+ tmpData.cellVal(row, tmpData.usedCols() - 1).toDouble());
+ }
+ }
+
+ return numDatasets;
+}
+
+
+void KChartPart::createLabelsAndLegend( TQStringList &longLabels,
+ TQStringList &shortLabels )
+{
+ longLabels.clear();
+ shortLabels.clear();
+
+ const uint dataColumnCount = m_currentData.cols();
+ const uint dataRowCount = m_currentData.rows();
+ const uint columnLabelCount = m_colLabels.count();
+ const uint rowLabelCount = m_rowLabels.count();
+
+ // Handle HiLo charts separately.
+ if (m_params->chartType() == KChartParams::HiLo) {
+
+ // FIXME: In a HiLo chart, the Legend should be the same as the
+ // labels on the X Axis. Should we disable one of them?
+
+ // Set the correct X axis labels and legend.
+ longLabels.clear();
+ shortLabels.clear();
+ if (m_params->dataDirection() == KChartParams::DataRows) {
+
+ // If data are in rows, then the X axis labels should be
+ // taken from the row headers.
+ for ( uint row = 0; row < dataRowCount ; row++ ) {
+
+ TQString label = (row < rowLabelCount) ? m_rowLabels[row] : TQString();
+
+ longLabels << label;
+ shortLabels << label.left( 3 );
+ }
+ }
+ else {
+ // If data are in columns, then the X axis labels should
+ // be taken from the column headers.
+ for ( uint col = 0; col < dataColumnCount; col++ ) {
+
+ TQString label = (col < columnLabelCount) ? m_colLabels[col] : TQString();
+
+ longLabels << m_colLabels[col];
+ shortLabels << m_colLabels[col].left( 3 );
+ }
+ }
+ }
+ else if (m_params->dataDirection() == KChartParams::DataRows) {
+ // Data is handled in rows. This is the way KDChart works also.
+
+ // Set X axis labels from column headers.
+ for ( uint col = 0; col < dataColumnCount; col++ ) {
+
+ TQString label = (col < columnLabelCount) ? m_colLabels[col] : TQString();
+
+ longLabels << label;
+ shortLabels << label.left( 3 );
+ }
+
+ // Set legend from row headers.
+ for ( uint row = 0; row < dataRowCount; row++ ) {
+ TQString label = (row < rowLabelCount) ? m_rowLabels[row] : TQString();
+
+ m_params->setLegendText( row, label );
+ }
+ }
+ else {
+ // Data is handled in columns.
+
+ // Set X axis labels from row headers.
+ for ( uint row = 0; row < dataRowCount; row++ ) {
+
+ TQString label = (row < rowLabelCount) ? m_rowLabels[row] : TQString();
+
+ longLabels << label;
+ shortLabels << label.left( 3 );
+ }
+
+ // Set legend from column headers.
+ for ( uint col = 0; col < dataColumnCount ; col++ ) {
+ TQString label = (col < columnLabelCount) ? m_colLabels[col] : TQString();
+
+ m_params->setLegendText( col, label );
+ }
+ }
+}
+
+
+
+// ================================================================
+
+
+void KChartPart::analyzeHeaders()
+{
+#if 0
+ analyzeHeaders( m_currentData );
+#else
+ doSetData( m_currentData,
+ m_params->firstRowAsLabel(), m_params->firstColAsLabel());
+#endif
+}
+
+
+// This function sets the data from an external source. It is called,
+// for instance, when the chart is initialized from a spreadsheet in
+// KSpread.
+//
+void KChartPart::analyzeHeaders( const KDChartTableData& data )
+{
+ // FIXME(khz): replace this when automatic string detection works in KDChart
+ // Does the top/left cell contain a string?
+ bool isStringTopLeft = (data.cellVal( 0, 0 ).type() == TQVariant::String);
+
+ // Does the first row (without first cell) contain only strings?
+ bool isStringFirstRow = true;
+ for ( uint col = 1; isStringFirstRow && col < data.cols(); col++ ) {
+ isStringFirstRow = (data.cellVal( 0, col ).type() == TQVariant::String);
+ }
+
+ // Just in case, we only have 1 row, we never use it for label text.
+ // This prevents a crash.
+ //
+ // FIXME: Wonder if this is still true for KDChart 1.1.3 / iw
+ // Disabling...
+#if 1
+ if ( data.rows() == 1 )
+ isStringFirstRow = false;
+#endif
+
+ // Does the first column (without first cell) contain only strings?
+ bool isStringFirstCol = true;
+ for ( uint row = 1; isStringFirstCol && row < data.rows(); row++ ) {
+ isStringFirstCol = (data.cellVal( row, 0 ).type() == TQVariant::String);
+ }
+
+ // Just in case, we only have 1 column, we never use it for axis
+ // label text => prevents crash.
+#if 1
+ if ( data.cols() == 1 )
+ isStringFirstRow = FALSE;
+#endif
+
+ bool hasColHeader = false;
+ bool hasRowHeader = false;
+
+ // Let's check if we have a full axis label text column
+ if ( isStringFirstCol && isStringTopLeft
+ || isStringFirstCol && isStringFirstRow )
+ hasColHeader = true;
+
+ // Let's check if we have a full label text row.
+ if ( isStringFirstRow && isStringTopLeft
+ || isStringFirstCol && isStringFirstRow )
+ hasRowHeader = true;
+
+ m_params->setFirstRowAsLabel( hasRowHeader );
+ m_params->setFirstColAsLabel( hasColHeader );
+
+ doSetData(data, hasRowHeader, hasColHeader);
+}
+
+
+
+void KChartPart::doSetData( const KDChartTableData& data,
+ bool firstRowHeader,
+ bool firstColHeader )
+{
+ uint rowStart = 0;
+ uint colStart = 0;
+ uint col;
+ uint row;
+
+ // From this point, we know that the labels and legend are going
+ // to be taken from the data if firstRowHeader or firstColheader
+ // is true.
+
+ if (firstRowHeader)
+ rowStart = 1;
+ if (firstColHeader)
+ colStart = 1;
+
+ // Generate m_rowlabels from the column headers if applicable.
+ m_rowLabels.clear();
+ if ( firstColHeader ) {
+ for( row = rowStart; row < data.rows(); row++ ) {
+ m_rowLabels << data.cellVal( row, 0 ).toString();
+ }
+ }
+ else {
+ for( row = rowStart; row < data.rows(); row++ )
+ m_rowLabels << "";
+
+ // FIXME: Check what this does, and if we don't have to check
+ // the data order (rows / cols).
+ m_params->setLegendSource( KDChartParams::LegendAutomatic );
+ }
+
+ // Generate X labels from the row headers if applicable
+ m_colLabels.clear();
+ if ( firstRowHeader ) {
+ for( col = colStart; col < data.cols(); col++ ) {
+ m_colLabels << data.cellVal( 0, col ).toString();
+ }
+ }
+ else {
+ for( col = colStart; col < data.cols(); col++ )
+ m_colLabels << "";
+ }
+
+ // Doesn't hurt if data == m_currentData, but necessary if not.
+ m_currentData = data;
+
+ //setChartDefaults();
+
+ emit docChanged();
+}
+
+
+void KChartPart::resizeData( int rows, int cols )
+{
+ m_currentData.expand( rows, cols );
+ m_currentData.setUsedRows( rows );
+ m_currentData.setUsedCols( cols );
+}
+
+
+void KChartPart::setCellData( int row, int column, const TQVariant &val)
+{
+ m_currentData.setCell( row, column, val );
+}
+
+
+bool KChartPart::showWizard( TQString &dataArea )
+{
+ KChartWizard *wizard = new KChartWizard( this, m_parentWidget, "wizard" );
+
+ connect( wizard, TQT_SIGNAL(finished()), this, TQT_SLOT(slotModified()) );
+
+ wizard->setDataArea( dataArea );
+
+ bool ret = wizard->exec();
+
+ delete wizard;
+ return ret;
+}
+
+
+void KChartPart::initLabelAndLegend()
+{
+ // Labels and legends are automatically initialized to reasonable
+ // default values in KDChart
+}
+
+
+// Set up some values for the chart Axis, that are not well chosen by
+// default by KDChart.
+//
+
+void KChartPart::setChartDefaults()
+{
+ //
+ // Settings for the Y axis.
+ //
+ KDChartAxisParams yAxis;
+ yAxis = m_params->axisParams( KDChartAxisParams::AxisPosLeft );
+
+ // decimal symbol and thousands separator
+ yAxis.setAxisLabelsRadix( TDEGlobal::locale()->decimalSymbol(),
+ TDEGlobal::locale()->thousandsSeparator() );
+
+ m_params->setAxisParams( KDChartAxisParams::AxisPosLeft, yAxis );
+
+ //
+ // Settings for the X axis.
+ //
+ KDChartAxisParams xAxis;
+ xAxis = m_params->axisParams( KDChartAxisParams::AxisPosBottom );
+
+ // These two shouldn't be necessary to set.
+ xAxis.setAxisFirstLabelText();
+ xAxis.setAxisLastLabelText();
+
+ m_params->setAxisParams( KDChartAxisParams::AxisPosBottom, xAxis );
+
+ // Other parameters for various things.
+ m_params->setLineColor();
+
+ // Setting the background layer.
+ KDFrame frame;
+ frame.setBackground( TQBrush( TQColor( 230, 222, 222 ) ) );
+ m_params->setFrame( KDChartEnums::AreaInnermost, frame, 0, 0, 0, 0 );
+}
+
+
+// ================================================================
+// Loading and Storing
+
+
+// ----------------------------------------------------------------
+// Save and Load program configuration
+
+
+
+void KChartPart::loadConfig( TDEConfig *conf )
+{
+ conf->setGroup("ChartParameters");
+
+ // TODO: the fonts
+ // PENDING(kalle) Put the applicable ones of these back in
+ // TQFont tempfont;
+ // tempfont = conf->readFontEntry("titlefont", &titlefont);
+ // setTitleFont(tempfont);
+ // tempfont = conf->readFontEntry("ytitlefont", &ytitlefont);
+ // setYTitleFont(tempfont);
+ // tempfont = conf->readFontEntry("xtitlefont", &xtitlefont);
+ // setXTitleFont(tempfont);
+ // tempfont = conf->readFontEntry("yaxisfont", &yaxisfont);
+ // setYAxisFont(tempfont);
+ // tempfont = conf->readFontEntry("xaxisfont", &xaxisfont);
+ // setXAxisFont(tempfont);
+ // tempfont = conf->readFontEntry("labelfont", &labelfont);
+ // setLabelFont(tempfont);
+ // tempfont = conf->readFontEntry("annotationfont", &annotationfont);
+ // setAnnotationFont(tempfont);
+
+ // ylabel_fmt = conf->readEntry("ylabel_fmt", ylabel_fmt );
+ // ylabel2_fmt = conf->readEntry("ylabel2_fmt", ylabel2_fmt);
+ // xlabel_spacing = conf->readNumEntry("xlabel_spacing");
+ // ylabel_density = conf->readNumEntry("ylabel_density", ylabel_density);
+ // requested_ymin = conf->readDoubleNumEntry("requested_ymin", requested_ymin);
+ // requested_ymax = conf->readDoubleNumEntry("requested_ymax", requested_ymax );
+ // requested_yinterval = conf->readDoubleNumEntry("requested_yinterval",
+ // requested_yinterval);
+ // shelf = conf->readBoolEntry("shelf", shelf);
+ // grid = conf->readBoolEntry("grid", grid);
+ // xaxis = conf->readBoolEntry("xaxis", xaxis);
+ // yaxis = conf->readBoolEntry("yaxis", yaxis);
+ // yaxis2 = conf->readBoolEntry("yaxis2", yaxis);
+ // llabel = conf->readBoolEntry("llabel", llabel);
+ // yval_style = conf->readNumEntry("yval_style", yval_style);
+ // stack_type = (KChartStackType)conf->readNumEntry("stack_type", stack_type);
+ m_params->setLineMarker(conf->readBoolEntry("lineMarker",
+ m_params->lineMarker()));
+ m_params->setThreeDBarDepth( conf->readDoubleNumEntry("_3d_depth",
+ m_params->threeDBarDepth() ) );
+ m_params->setThreeDBarAngle( conf->readNumEntry( "_3d_angle",
+ m_params->threeDBarAngle() ) );
+
+ KDChartAxisParams leftparams;
+ leftparams = m_params->axisParams( KDChartAxisParams::AxisPosLeft );
+ KDChartAxisParams rightparams;
+ rightparams = m_params->axisParams( KDChartAxisParams::AxisPosRight );
+ KDChartAxisParams bottomparams;
+ bottomparams = m_params->axisParams( KDChartAxisParams::AxisPosBottom );
+
+ bottomparams.setAxisLineColor( conf->readColorEntry( "XTitleColor", 0 ) );
+ leftparams.setAxisLineColor( conf->readColorEntry( "YTitleColor", 0 ) );
+ rightparams.setAxisLineColor( conf->readColorEntry( "YTitle2Color", 0 ) );
+ bottomparams.setAxisLabelsColor( conf->readColorEntry( "XLabelColor", 0 ) );
+ leftparams.setAxisLabelsColor( conf->readColorEntry( "YLabelColor", 0 ) );
+ rightparams.setAxisLabelsColor( conf->readColorEntry( "YLabel2Color", 0 ) );
+ leftparams.setAxisGridColor( conf->readColorEntry( "GridColor", 0 ) );
+ m_params->setOutlineDataColor( conf->readColorEntry( "LineColor", 0 ) );
+ m_params->setAxisParams( KDChartAxisParams::AxisPosLeft,
+ leftparams );
+ m_params->setAxisParams( KDChartAxisParams::AxisPosRight,
+ rightparams );
+ m_params->setAxisParams( KDChartAxisParams::AxisPosBottom,
+ bottomparams );
+
+ // hlc_style = (KChartHLCStyle)conf->readNumEntry("hlc_style", hlc_style);
+ // hlc_cap_width = conf->readNumEntry("hlc_cap_width", hlc_cap_width);
+ // // TODO: Annotation font
+ // num_scatter_pts = conf->readNumEntry("num_scatter_pts", num_scatter_pts);
+ // // TODO: Scatter type
+ // thumbnail = conf->readBoolEntry("thumbnail", thumbnail);
+ // thumblabel = conf->readEntry("thumblabel", thumblabel);
+ // border = conf->readBoolEntry("border", border);
+ // BGColor = conf->readColorEntry("BGColor", &BGColor);
+ // PlotColor = conf->readColorEntry("PlotColor", &PlotColor);
+ // VolColor = conf->readColorEntry("VolColor", &VolColor);
+ // EdgeColor = conf->readColorEntry("EdgeColor", &EdgeColor);
+ // loadColorArray(conf, &SetColor, "SetColor");
+ // loadColorArray(conf, &ExtColor, "ExtColor");
+ // loadColorArray(conf, &ExtVolColor, "ExtVolColor");
+ // transparent_bg = conf->readBoolEntry("transparent_bg", transparent_bg);
+ // // TODO: explode, missing
+ // percent_labels = (KChartPercentType)conf->readNumEntry("percent_labels",
+ // percent_labels);
+ // label_dist = conf->readNumEntry("label_dist", label_dist);
+ // label_line = conf->readBoolEntry("label_line", label_line);
+ m_params->setChartType( (KChartParams::ChartType)conf->readNumEntry( "type", m_params->chartType() ) );
+ // other_threshold = conf->readNumEntry("other_threshold", other_threshold);
+
+ // backgroundPixmapName = conf->readPathEntry( "backgroundPixmapName" );
+ // if( !backgroundPixmapName.isNull() ) {
+ // backgroundPixmap.load( locate( "wallpaper", backgroundPixmapName ));
+ // backgroundPixmapIsDirty = true;
+ // } else
+ // backgroundPixmapIsDirty = false;
+ // backgroundPixmapScaled = conf->readBoolEntry( "backgroundPixmapScaled", true );
+ // backgroundPixmapCentered = conf->readBoolEntry( "backgroundPixmapCentered", true );
+ // backgroundPixmapIntensity = conf->readDoubleNumEntry( "backgroundPixmapIntensity", 0.25 );
+}
+
+
+void KChartPart::defaultConfig( )
+{
+ delete m_params;
+ m_params = new KChartParams( this );
+ setChartDefaults();
+}
+
+
+void KChartPart::saveConfig( TDEConfig *conf )
+{
+ conf->setGroup("ChartParameters");
+
+ // PENDING(kalle) Put some of these back in
+ // the fonts
+ // conf->writeEntry("titlefont", titlefont);
+ // conf->writeEntry("ytitlefont", ytitlefont);
+ // conf->writeEntry("xtitlefont", xtitlefont);
+ // conf->writeEntry("yaxisfont", yaxisfont);
+ // conf->writeEntry("xaxisfont", xaxisfont);
+ // conf->writeEntry("labelfont", labelfont);
+
+ // conf->writeEntry("ylabel_fmt", ylabel_fmt);
+ // conf->writeEntry("ylabel2_fmt", ylabel2_fmt);
+ // conf->writeEntry("xlabel_spacing", xlabel_spacing);
+ // conf->writeEntry("ylabel_density", ylabel_density);
+ // conf->writeEntry("requested_ymin", requested_ymin);
+ // conf->writeEntry("requested_ymax", requested_ymax);
+ // conf->writeEntry("requested_yinterval", requested_yinterval);
+
+ // conf->writeEntry("shelf", shelf);
+ // conf->writeEntry("grid", grid );
+ // conf->writeEntry("xaxis", xaxis);
+ // conf->writeEntry("yaxis", yaxis);
+ // conf->writeEntry("yaxis2", yaxis2);
+ // conf->writeEntry("llabel", llabel);
+ // conf->writeEntry("yval_style", yval_style );
+ // conf->writeEntry("stack_type", (int)stack_type);
+
+ conf->writeEntry( "_3d_depth", m_params->threeDBarDepth() );
+ conf->writeEntry( "_3d_angle", m_params->threeDBarAngle() );
+
+ KDChartAxisParams leftparams;
+ leftparams = m_params->axisParams( KDChartAxisParams::AxisPosLeft );
+ KDChartAxisParams rightparams;
+ rightparams = m_params->axisParams( KDChartAxisParams::AxisPosRight );
+ KDChartAxisParams bottomparams;
+ bottomparams = m_params->axisParams( KDChartAxisParams::AxisPosBottom );
+ conf->writeEntry( "LineColor", m_params->outlineDataColor() );
+ conf->writeEntry( "XTitleColor", bottomparams.axisLineColor() );
+ conf->writeEntry( "YTitleColor", leftparams.axisLineColor() );
+ conf->writeEntry( "YTitle2Color", rightparams.axisLineColor() );
+ conf->writeEntry( "XLabelColor", bottomparams.axisLabelsColor() );
+ conf->writeEntry( "YLabelColor", leftparams.axisLabelsColor() );
+ conf->writeEntry( "YLabel2Color", rightparams.axisLabelsColor() );
+ conf->writeEntry( "GridColor", leftparams.axisGridColor() );
+
+ // conf->writeEntry("hlc_style", (int)hlc_style);
+ // conf->writeEntry("hlc_cap_width", hlc_cap_width );
+ // // TODO: Annotation type!!!
+ // conf->writeEntry("annotationfont", annotationfont);
+ // conf->writeEntry("num_scatter_pts", num_scatter_pts);
+ // // TODO: Scatter type!!!
+ // conf->writeEntry("thumbnail", thumbnail);
+ // conf->writeEntry("thumblabel", thumblabel);
+ // conf->writeEntry("thumbval", thumbval);
+ // conf->writeEntry("border", border);
+ // conf->writeEntry("BGColor", BGColor);
+ // conf->writeEntry("PlotColor", PlotColor);
+ // conf->writeEntry("VolColor", VolColor);
+ // conf->writeEntry("EdgeColor", EdgeColor);
+ // saveColorArray(conf, &SetColor, "SetColor");
+ // saveColorArray(conf, &ExtColor, "ExtColor");
+ // saveColorArray(conf, &ExtVolColor, "ExtVolColor");
+
+
+ // conf->writeEntry("transparent_bg", transparent_bg);
+ // // TODO: explode, missing
+ // conf->writeEntry("percent_labels",(int) percent_labels );
+ // conf->writeEntry("label_dist", label_dist);
+ // conf->writeEntry("label_line", label_line);
+ conf->writeEntry( "type", (int) m_params->chartType() );
+ // conf->writeEntry("other_threshold", other_threshold);
+
+ // background pixmap stuff
+ // if( !backgroundPixmapName.isNull() )
+ // conf->writePathEntry( "backgroundPixmapName", backgroundPixmapName );
+ // conf->writeEntry( "backgroundPixmapIsDirty", backgroundPixmapIsDirty );
+ // conf->writeEntry( "backgroundPixmapScaled", backgroundPixmapScaled );
+ // conf->writeEntry( "backgroundPixmapCentered", backgroundPixmapCentered );
+ // conf->writeEntry( "backgroundPixmapIntensity", backgroundPixmapIntensity );
+ conf->writeEntry( "lineMarker", (int) m_params->lineMarker());
+}
+
+
+// ----------------------------------------------------------------
+// Save and Load OpenDocument file format
+
+
+bool KChartPart::loadOasis( const TQDomDocument& doc,
+ KoOasisStyles& oasisStyles,
+ const TQDomDocument& /*settings*/,
+ KoStore *store )
+{
+ kdDebug(35001) << "kchart loadOasis called" << endl;
+
+ // Set some sensible defaults.
+ setChartDefaults();
+
+ TQDomElement content = doc.documentElement();
+ TQDomElement bodyElem ( KoDom::namedItemNS( content,
+ KoXmlNS::office, "body" ) );
+ if ( bodyElem.isNull() ) {
+ kdError(32001) << "No office:body found!" << endl;
+ setErrorMessage( i18n( "Invalid OASIS OpenDocument file. No office:body tag found." ) );
+ return false;
+ }
+
+ // Get the office:chart element.
+ TQDomElement officeChartElem = KoDom::namedItemNS( bodyElem,
+ KoXmlNS::office, "chart" );
+ if ( officeChartElem.isNull() ) {
+ kdError(32001) << "No office:chart found!" << endl;
+ TQDomElement childElem;
+ TQString localName;
+ forEachElement( childElem, bodyElem ) {
+ localName = childElem.localName();
+ }
+
+ if ( localName.isEmpty() )
+ setErrorMessage( i18n( "Invalid OASIS OpenDocument file. No tag found inside office:body." ) );
+ else
+ setErrorMessage( i18n( "This document is not a chart, but %1. Please try opening it with the appropriate application." ).arg( KoDocument::tagNameToDocumentType( localName ) ) );
+
+ return false;
+ }
+
+ TQDomElement chartElem = KoDom::namedItemNS( officeChartElem,
+ KoXmlNS::chart, "chart" );
+ if ( chartElem.isNull() ) {
+ setErrorMessage( i18n( "Invalid OASIS OpenDocument file. No chart:chart tag found." ) );
+ return false;
+ }
+
+ // Get the loading context and stylestack from the styles.
+ KoOasisLoadingContext loadingContext( this, oasisStyles, store );
+ //KoStyleStack &styleStack = loadingContext.styleStack();
+
+#if 0 // Example code!!
+ // load chart properties into the stylestack.
+ styleStack.save();
+ styleStack.setTypeProperties( "chart" ); // load chart properties
+ loadingContext.fillStyleStack( chartElem, KoXmlNS::chart, "style-name" );
+
+ const TQString fillColor = styleStack.attributeNS( KoXmlNS::draw, "fill-color" );
+ kdDebug() << "fillColor=" << fillColor << endl;
+
+ styleStack.restore();
+#endif
+
+ // Load chart parameters, most of these are stored in the
+ // chart:plot-area element within chart:chart.
+ TQString errorMessage;
+ bool ok = m_params->loadOasis( chartElem, loadingContext, errorMessage,
+ store);
+ if ( !ok ) {
+ setErrorMessage( errorMessage );
+ return false;
+ }
+
+ // TODO Load data direction (see loadAuxiliary)
+
+ // Load the data table.
+ TQDomElement tableElem = KoDom::namedItemNS( chartElem,
+ KoXmlNS::table, "table" );
+ if ( !tableElem.isNull() ) {
+ ok = loadOasisData( tableElem );
+ if ( !ok )
+ return false; // TODO setErrorMessage
+ }
+
+ return true;
+}
+
+
+bool KChartPart::loadOasisData( const TQDomElement& tableElem )
+{
+ int numberHeaderColumns = 0;
+ TQDomElement tableHeaderColumns = KoDom::namedItemNS( tableElem,
+ KoXmlNS::table,
+ "table-header-columns" );
+
+ TQDomElement elem;
+ forEachElement( elem, tableHeaderColumns ) {
+ if ( elem.localName() == "table-column" ) {
+ int repeated = elem.attributeNS( KoXmlNS::table, "number-columns-repeated", TQString() ).toInt();
+ numberHeaderColumns += TQMAX( 1, repeated );
+ }
+ }
+
+ // With 0 you get no titles, and with more than 1 we ignore the others.
+ Q_ASSERT( numberHeaderColumns == 1 );
+
+ int numberDataColumns = 0;
+ TQDomElement tableColumns = KoDom::namedItemNS( tableElem, KoXmlNS::table, "table-columns" );
+ forEachElement( elem, tableColumns ) {
+ if ( elem.localName() == "table-column" ) {
+ int repeated = elem.attributeNS( KoXmlNS::table, "number-columns-repeated", TQString() ).toInt();
+ numberDataColumns += TQMAX( 1, repeated );
+ }
+ }
+
+ // Parse table-header-rows for the column names.
+ m_colLabels.clear();
+ TQDomElement tableHeaderRows = KoDom::namedItemNS( tableElem, KoXmlNS::table, "table-header-rows" );
+ if ( tableHeaderRows.isNull() )
+ kdWarning(35001) << "No table-header-rows element found!" << endl;
+ TQDomElement tableHeaderRow = KoDom::namedItemNS( tableHeaderRows, KoXmlNS::table, "table-row" );
+ if ( tableHeaderRow.isNull() )
+ kdWarning(35001) << "No table-row inside table-header-rows!" << endl;
+
+ int cellNum = 0;
+ forEachElement( elem, tableHeaderRow ) {
+ if ( elem.localName() == "table-cell" ) {
+ ++cellNum;
+ if ( cellNum > numberHeaderColumns ) {
+ TQDomElement pElem = KoDom::namedItemNS( elem, KoXmlNS::text, "p" );
+ m_colLabels.append( pElem.text() );
+ }
+ }
+ }
+ numberDataColumns = TQMAX( numberDataColumns, cellNum - numberHeaderColumns );
+ if ( (int)m_colLabels.count() != numberDataColumns )
+ kdWarning(35001) << "Got " << m_colLabels.count()
+ << " column titles, expected " << numberDataColumns
+ << endl;
+
+ // Get the number of rows, and read row labels
+ int numberDataRows = 0;
+ TQDomElement tableRows = KoDom::namedItemNS( tableElem, KoXmlNS::table, "table-rows" );
+
+ m_rowLabels.clear();
+ forEachElement( elem, tableRows ) {
+ if ( elem.localName() == "table-row" ) {
+ int repeated = elem.attributeNS( KoXmlNS::table, "number-rows-repeated", TQString() ).toInt();
+ Q_ASSERT( repeated <= 1 ); // we don't handle yet the case where data rows are repeated (can this really happen?)
+ numberDataRows += TQMAX( 1, repeated );
+ if ( numberHeaderColumns > 0 ) {
+ TQDomElement firstCell = KoDom::namedItemNS( elem, KoXmlNS::table, "table-cell" );
+ TQDomElement pElem = KoDom::namedItemNS( firstCell, KoXmlNS::text, "p" );
+ m_rowLabels.append( pElem.text() );
+ }
+ }
+ }
+
+ kdDebug(35001) << "numberHeaderColumns=" << numberHeaderColumns
+ << " numberDataColumns=" << numberDataColumns
+ << " numberDataRows=" << numberDataRows << endl;
+
+ if ( (int)m_rowLabels.count() != numberDataRows)
+ kdWarning(35001) << "Got " << m_rowLabels.count()
+ << " row labels, expected " << numberDataRows << endl;
+
+ m_currentData.expand( numberDataRows, numberDataColumns );
+ m_currentData.setUsedCols( numberDataColumns );
+ m_currentData.setUsedRows( numberDataRows );
+
+ // Now really load the cells.
+ int row = 0;
+ TQDomElement rowElem;
+ forEachElement( rowElem, tableRows ) {
+ if ( rowElem.localName() == "table-row" ) {
+ int col = 0;
+ int cellNum = 0;
+ TQDomElement cellElem;
+ forEachElement( cellElem, rowElem ) {
+ if ( cellElem.localName() == "table-cell" ) {
+ ++cellNum;
+ if ( cellNum > numberHeaderColumns ) {
+ TQString valueType = cellElem.attributeNS( KoXmlNS::office, "value-type", TQString() );
+ if ( valueType != "float" )
+ kdWarning(35001) << "Don't know how to handle value-type " << valueType << endl;
+ else {
+ TQString value = cellElem.attributeNS( KoXmlNS::office, "value", TQString() );
+ double val = value.toDouble();
+
+ m_currentData.setCell( row, col, val );
+ }
+ ++col;
+ }
+ }
+ }
+ ++row;
+ }
+ }
+
+ return true;
+}
+
+
+bool KChartPart::saveOasis( KoStore* store, KoXmlWriter* manifestWriter )
+{
+ manifestWriter->addManifestEntry( "content.xml", "text/xml" );
+ KoOasisStore oasisStore( store );
+
+ KoXmlWriter* contentWriter = oasisStore.contentWriter();
+ if ( !contentWriter )
+ return false;
+
+ KoGenStyles mainStyles;
+
+ KoXmlWriter* bodyWriter = oasisStore.bodyWriter();
+ bodyWriter->startElement( "office:body" );
+ bodyWriter->startElement( "office:chart" );
+ bodyWriter->startElement( "chart:chart" );
+
+ // Indent to indicate that this is inside some tags.
+ {
+ // Saves chart class, title, legend, plot-area
+ m_params->saveOasis( bodyWriter, mainStyles );
+
+ // Save the data table.
+ saveOasisData( bodyWriter, mainStyles );
+ }
+
+ bodyWriter->endElement(); // chart:chart
+ bodyWriter->endElement(); // office:chart
+ bodyWriter->endElement(); // office:body
+
+ contentWriter->startElement( "office:automatic-styles" );
+ writeAutomaticStyles( *contentWriter, mainStyles );
+ contentWriter->endElement(); // office:automatic-styles
+
+ oasisStore.closeContentWriter();
+
+ // Done with content.xml
+
+#if 0
+ if ( !store->open( "styles.xml" ) )
+ return false;
+ manifestWriter->addManifestEntry( "styles.xml", "text/xml" );
+ saveOasisDocumentStyles( store, mainStyles, savingContext, saveFlag,
+ headerFooterContent );
+ if ( !store->close() ) // done with styles.xml
+ return false;
+#endif
+
+ return true;
+}
+
+
+void KChartPart::saveOasisData( KoXmlWriter* bodyWriter,
+ KoGenStyles& mainStyles ) const
+{
+ Q_UNUSED( mainStyles );
+
+ const int cols = m_currentData.usedCols()
+ ? TQMIN(m_currentData.usedCols(), m_currentData.cols())
+ : m_currentData.cols();
+ const int rows = m_currentData.usedRows()
+ ? TQMIN(m_currentData.usedRows(), m_currentData.rows())
+ : m_currentData.rows();
+
+ bodyWriter->startElement( "table:table" );
+ bodyWriter->addAttribute( "table:name", "local-table" );
+
+ // Exactly one header column, always.
+ bodyWriter->startElement( "table:table-header-columns" );
+ bodyWriter->startElement( "table:table-column" );
+ bodyWriter->endElement(); // table:table-column
+ bodyWriter->endElement(); // table:table-header-columns
+
+ // Then "cols" columns
+ bodyWriter->startElement( "table:table-columns" );
+ bodyWriter->startElement( "table:table-column" );
+ bodyWriter->addAttribute( "table:number-columns-repeated", cols );
+ bodyWriter->endElement(); // table:table-column
+ bodyWriter->endElement(); // table:table-columns
+
+ // Exactly one header row, always.
+ bodyWriter->startElement( "table:table-header-rows" );
+ bodyWriter->startElement( "table:table-row" );
+
+ // The first column in header row is just the header column - no title needed
+ bodyWriter->startElement( "table:table-cell" );
+ bodyWriter->addAttribute( "office:value-type", "string" );
+ bodyWriter->startElement( "text:p" );
+ bodyWriter->endElement(); // text:p
+ bodyWriter->endElement(); // table:table-cell
+
+ // Save column labels in the first header row, for instance:
+ // <table:table-cell office:value-type="string">
+ // <text:p>Column 1 </text:p>
+ // </table:table-cell>
+ TQStringList::const_iterator colLabelIt = m_colLabels.begin();
+ for ( int col = 0; col < cols ; ++col ) {
+ if ( colLabelIt != m_colLabels.end() ) {
+ bodyWriter->startElement( "table:table-cell" );
+ bodyWriter->addAttribute( "office:value-type", "string" );
+ bodyWriter->startElement( "text:p" );
+ bodyWriter->addTextNode( *colLabelIt );
+ bodyWriter->endElement(); // text:p
+ bodyWriter->endElement(); // table:table-cell
+ ++colLabelIt;
+ }
+ }
+
+ bodyWriter->endElement(); // table:table-row
+ bodyWriter->endElement(); // table:table-header-rows
+ bodyWriter->startElement( "table:table-rows" );
+
+ TQStringList::const_iterator rowLabelIt = m_rowLabels.begin();
+ for ( int row = 0; row < rows ; ++row ) {
+ bodyWriter->startElement( "table:table-row" );
+
+ if ( rowLabelIt != m_rowLabels.end() ) {
+ // Save row labels, similar to column labels
+ bodyWriter->startElement( "table:table-cell" );
+ bodyWriter->addAttribute( "office:value-type", "string" );
+
+ bodyWriter->startElement( "text:p" );
+ bodyWriter->addTextNode( *rowLabelIt );
+ bodyWriter->endElement(); // text:p
+
+ bodyWriter->endElement(); // table:table-cell
+ ++rowLabelIt;
+ }
+
+ for ( int col = 0; col < cols; ++col ) {
+ TQVariant value( m_currentData.cellVal( row, col ) );
+ TQString valType;
+ TQString valStr;
+
+ switch ( value.type() ) {
+ case TQVariant::Invalid:
+ break;
+ case TQVariant::String:
+ valType = "string";
+ valStr = value.toString();
+ break;
+ case TQVariant::Double:
+ valType = "float";
+ valStr = TQString::number( value.toDouble(), 'g', DBL_DIG );
+ break;
+ case TQVariant::DateTime:
+ valType = "date";
+ valStr = ""; /* like in saveXML, but why? */
+ break;
+ default: {
+ kdDebug(35001) << "ERROR: cell " << row << "," << col
+ << " has unknown type." << endl;
+ }
+ }
+
+ // Add the value type and the string to the XML tree.
+ bodyWriter->startElement( "table:table-cell" );
+ if ( !valType.isEmpty() ) {
+ bodyWriter->addAttribute( "office:value-type", valType );
+ if ( value.type() == TQVariant::Double )
+ bodyWriter->addAttribute( "office:value", valStr );
+
+ bodyWriter->startElement( "text:p" );
+ bodyWriter->addTextNode( valStr );
+ bodyWriter->endElement(); // text:p
+ }
+ bodyWriter->endElement(); // table:table-cell
+ }
+ bodyWriter->endElement(); // table:table-row
+ }
+
+ bodyWriter->endElement(); // table:table-rows
+ bodyWriter->endElement(); // table:table
+}
+
+void KChartPart::writeAutomaticStyles( KoXmlWriter& contentWriter, KoGenStyles& mainStyles ) const
+{
+ TQValueList<KoGenStyles::NamedStyle> styles = mainStyles.styles( KoGenStyle::STYLE_AUTO );
+ TQValueList<KoGenStyles::NamedStyle>::const_iterator it = styles.begin();
+ for ( ; it != styles.end() ; ++it ) {
+ (*it).style->writeStyle( &contentWriter, mainStyles, "style:style", (*it).name, "style:chart-properties" );
+ }
+
+}
+
+// ----------------------------------------------------------------
+// Save and Load old KChart file format
+
+
+TQDomDocument KChartPart::saveXML()
+{
+ TQDomElement tmpElem;
+
+ //kdDebug(35001) << "kchart saveXML called" << endl;
+
+ // The biggest part of the saving is done by KDChart itself, so we
+ // don't have to do it.
+ TQDomDocument doc = m_params->saveXML( false );
+
+ // ----------------------------------------------------------------
+ // The rest of the saving has to be done by us.
+
+ TQDomElement docRoot = doc.documentElement();
+
+ // Save auxiliary data.
+ TQDomElement aux = doc.createElement( "KChartAuxiliary" );
+ docRoot.appendChild( aux );
+
+ // The data direction (rows/columns).
+ tmpElem = doc.createElement( "direction" );
+ tmpElem.setAttribute( "value", (int) m_params->dataDirection() );
+ aux.appendChild( tmpElem );
+
+ tmpElem = doc.createElement( "dataaslabel" );
+ tmpElem.setAttribute( "firstrow",
+ m_params->firstRowAsLabel() ? "true" : "false" );
+ tmpElem.setAttribute( "firstcol",
+ m_params->firstColAsLabel() ? "true" : "false" );
+ aux.appendChild( tmpElem );
+
+ tmpElem = doc.createElement( "barnumlines" );
+ tmpElem.setAttribute( "value", (int) m_params->barNumLines() );
+ aux.appendChild( tmpElem );
+
+ // Save the data values.
+ TQDomElement data = doc.createElement( "data" );
+ docRoot.appendChild( data );
+
+ int cols = m_currentData.usedCols()
+ ? TQMIN(m_currentData.usedCols(), m_currentData.cols())
+ : m_currentData.cols();
+ int rows = m_currentData.usedRows()
+ ? TQMIN(m_currentData.usedRows(), m_currentData.rows())
+ : m_currentData.rows();
+ data.setAttribute( "cols", cols );
+ data.setAttribute( "rows", rows );
+ kdDebug(35001) << " writing " << cols << "," << rows << " (cols,rows)." << endl;
+
+ for (int i=0; i!=rows; ++i) {
+ for (int j=0; j!=cols; ++j) {
+ TQDomElement e = doc.createElement( "cell" );
+ data.appendChild( e );
+ TQString valType;
+ TQVariant value( m_currentData.cellVal( i,j ) );
+ switch ( value.type() ) {
+ case TQVariant::Invalid: valType = "NoValue"; break;
+ case TQVariant::String: valType = "String"; break;
+ case TQVariant::Double: valType = "Double"; break;
+ case TQVariant::DateTime: valType = "DateTime"; break;
+ default: {
+ valType = "(unknown)";
+ kdDebug(35001) << "ERROR: cell " << i << "," << j
+ << " has unknown type." << endl;
+ }
+ }
+
+ e.setAttribute( "valType", valType );
+ //kdDebug(35001) << " cell " << i << "," << j
+ // << " saved with type '" << valType << "'." << endl;
+ switch ( value.type() ) {
+ case TQVariant::String: e.setAttribute( "value", value.toString() );
+ break;
+ case TQVariant::Double: e.setAttribute( "value", TQString::number( value.toDouble() ) );
+ break;
+ case TQVariant::DateTime:e.setAttribute( "value", "" );
+ break;
+ default: {
+ e.setAttribute( "value", "" );
+ if( TQVariant::Invalid != value.type() )
+ kdDebug(35001) << "ERROR: cell " << i << "," << j
+ << " has unknown type." << endl;
+ }
+ }
+ }
+ }
+
+ return doc;
+}
+
+
+bool KChartPart::loadXML( TQIODevice*, const TQDomDocument& doc )
+{
+ kdDebug(35001) << "kchart loadXML called" << endl;
+
+ // Set some sensible defaults.
+ setChartDefaults();
+
+ // First try to load the KDChart parameters.
+ bool result = m_params->loadXML( doc );
+
+ // If went well, try to load the auxiliary data and the data...
+ if (result) {
+ result = loadAuxiliary(doc) && loadData( doc, m_currentData );
+ }
+ else {
+ // ...but if it did, try to load the old XML format.
+ result = loadOldXML( doc );
+ }
+
+ // If everything is OK, then get the headers from the KDChart parameters.
+ if (result) {
+ TQStringList legendLabels;
+ KDChartAxisParams params;
+ params = m_params->axisParams( KDChartAxisParams::AxisPosBottom );
+
+ // Get the legend.
+ TQString str;
+ uint index = 0;
+ while ((str = m_params->legendText(index++)) != TQString())
+ legendLabels << str;
+
+ if (m_params->dataDirection() == KChartParams::DataRows) {
+ m_colLabels = params.axisLabelStringList();
+ m_rowLabels = legendLabels;
+ }
+ else {
+ m_colLabels = legendLabels;
+ m_rowLabels = params.axisLabelStringList();
+ }
+
+ }
+
+ m_params->setDrawSolidExcessArrows(true);
+
+ return result;
+}
+
+
+// Load the auxiliary data.
+//
+// Currently, that means the data direction.
+//
+bool KChartPart::loadAuxiliary( const TQDomDocument& doc )
+{
+ TQDomElement chart = doc.documentElement();
+ TQDomElement aux = chart.namedItem("KChartAuxiliary").toElement();
+
+ // Older XML files might be missing this section. That is OK; the
+ // defaults will be used.
+ if (aux.isNull())
+ return true;
+
+ TQDomNode node = aux.firstChild();
+
+ // If the aux section exists, it should contain data.
+ while (!node.isNull()) {
+
+ TQDomElement e = node.toElement();
+ if (e.isNull()) {
+ // FIXME: Should this be regarded as an error?
+ node = node.nextSibling();
+ continue;
+ }
+
+ // Check for direction
+ if ( e.tagName() == "direction" ) {
+ if ( e.hasAttribute("value") ) {
+ bool ok;
+
+ // Read the direction. On failure, use the default.
+ int dir = e.attribute("value").toInt(&ok);
+ if ( !ok )
+ dir = (int) KChartParams::DataColumns;
+
+ //kdDebug(35001) << "Got aux value \"direction\": " << dir << endl;
+ m_params->setDataDirection( (KChartParams::DataDirection) dir );
+ }
+ else {
+ kdDebug(35001) << "Error in direction tag." << endl;
+ }
+ }
+
+ // Check for first row / col as label
+ else if ( e.tagName() == "dataaslabel" ) {
+ TQString val;
+
+ if ( e.hasAttribute("firstrow") ) {
+ // Read the direction. On failure, use the default.
+ val = e.attribute("firstrow");
+ if ( val == "true" )
+ m_params->setFirstRowAsLabel( true );
+ else
+ m_params->setFirstRowAsLabel( false );
+ }
+ else {
+ kdDebug(35001) << "Error in barnumlines tag." << endl;
+ m_params->setFirstRowAsLabel( false );
+ }
+
+ if ( e.hasAttribute("firstcol") ) {
+ // Read the direction. On failure, use the default.
+ val = e.attribute("firstcol");
+ if ( val == "true" )
+ m_params->setFirstColAsLabel( true );
+ else
+ m_params->setFirstColAsLabel( false );
+ }
+ else {
+ kdDebug(35001) << "Error in barnumlines tag." << endl;
+ m_params->setFirstColAsLabel( false );
+ }
+ }
+
+ // Check for number of lines in a bar chart.
+ else if ( e.tagName() == "barnumlines" ) {
+ if ( e.hasAttribute("value") ) {
+ bool ok;
+
+ // Read the number of lines. On failure, use the default.
+ int barNumLines = e.attribute("value").toInt(&ok);
+ if ( !ok )
+ barNumLines = 0;
+
+ //kdDebug(35001) << "Got aux value \"barnumlines\": "
+ // << barNumLines << endl;
+ m_params->setBarNumLines( barNumLines );
+ }
+ else {
+ kdDebug(35001) << "Error in barnumlines tag." << endl;
+ }
+ }
+#if 0
+ // Expand with more auxiliary types when needed.
+ else if ( e.tagName() == "..." ) {
+ }
+ and so on...
+#endif
+
+ node = node.nextSibling();
+ }
+
+ return true;
+}
+
+
+bool KChartPart::loadData( const TQDomDocument& doc,
+ KDChartTableData& m_currentData )
+{
+ kdDebug(35001) << "kchart loadData called" << endl;
+
+ TQDomElement chart = doc.documentElement();
+ TQDomElement data = chart.namedItem("data").toElement();
+ bool ok;
+ int cols = data.attribute("cols").toInt(&ok);
+ kdDebug(35001) << "cols readed as:" << cols << endl;
+ if ( !ok ){
+ return false;
+ }
+
+ int rows = data.attribute("rows").toInt(&ok);
+ if ( !ok ){
+ return false;
+ }
+
+ kdDebug(35001) << rows << " x " << cols << endl;
+ m_currentData.expand(rows, cols);
+ m_currentData.setUsedCols( cols );
+ m_currentData.setUsedRows( rows );
+ kdDebug(35001) << "Expanded!" << endl;
+ TQDomNode n = data.firstChild();
+ //TQArray<int> tmpExp(rows*cols);
+ //TQArray<bool> tmpMissing(rows*cols);
+ for (int i=0; i!=rows; i++) {
+ for (int j=0; j!=cols; j++) {
+ if (n.isNull()) {
+ kdDebug(35001) << "Some problems, there is less data than it should be!" << endl;
+ break;
+ }
+ TQDomElement e = n.toElement();
+ if ( !e.isNull() && e.tagName() == "cell" ) {
+ // add the cell to the corresponding place...
+ TQVariant t;
+ if ( e.hasAttribute("value") && e.hasAttribute("valType") ) {
+ TQString valueType = e.attribute("valType").lower();
+ if ( "string" == valueType ) {
+ t = e.attribute("value");
+ }
+ else if ( "double" == valueType ) {
+ bool bOk;
+ double val = e.attribute("value").toDouble(&bOk);
+ if ( !bOk )
+ val = 0.0;
+ t = val;
+ /*
+ } else if ( "datetime" == valueType ) {
+ t = . . .
+ */
+ } else {
+ t.clear();
+ if ( "novalue" != valueType )
+ kdDebug(35001) << "ERROR: cell " << i << "," << j << " has unknown type '" << valueType << "'." << endl;
+ }
+ } else
+ t.clear();
+
+ m_currentData.setCell(i,j, t );
+
+ /*
+ if ( e.hasAttribute( "hide" ) ) {
+ tmpMissing[cols*j+i] = (bool)e.attribute("hide").toInt( &ok );
+ if ( !ok )
+ return false;
+ } else {
+ tmpMissing[cols*j+i] = false;
+ }
+ if ( e.hasAttribute( "dist" ) ) {
+ tmpExp[cols*j+i] = e.attribute("dist").toInt( &ok );
+ if ( !ok )
+ return false;
+ } else {
+ tmpExp[cols*j+i] = 0;
+ }
+ */
+
+ n = n.nextSibling();
+ }
+ }
+ }
+ /*
+ m_params->missing=tmpMissing;
+ m_params->explode=tmpExp;
+ */
+ return true;
+}
+
+
+// ----------------------------------------------------------------
+// Save and Load real old KChart file format
+
+
+bool KChartPart::loadOldXML( const TQDomDocument& doc )
+{
+ kdDebug(35001) << "kchart loadOldXML called" << endl;
+ if ( doc.doctype().name() != "chart" )
+ return false;
+
+ kdDebug(35001) << "Ok, it is a chart" << endl;
+
+ TQDomElement chart = doc.documentElement();
+ if ( chart.attribute( "mime" ) != "application/x-kchart" && chart.attribute( "mime" ) != "application/vnd.kde.kchart" )
+ return false;
+
+ kdDebug(35001) << "Mimetype ok" << endl;
+
+#if 0
+ TQDomElement data = chart.namedItem("data").toElement();
+ bool ok;
+ int cols = data.attribute("cols").toInt(&ok);
+ kdDebug(35001) << "cols readed as:" << cols << endl;
+ if (!ok) { return false; }
+ int rows = data.attribute("rows").toInt(&ok);
+ if (!ok) { return false; }
+ kdDebug(35001) << rows << " x " << cols << endl;
+ m_currentData.expand(rows, cols);
+ kdDebug(35001) << "Expanded!" << endl;
+ TQDomNode n = data.firstChild();
+ TQArray<int> tmpExp(rows*cols);
+ TQArray<bool> tmpMissing(rows*cols);
+
+ for (int i=0; i!=rows; i++) {
+ for (int j=0; j!=cols; j++) {
+ if (n.isNull()) {
+ kdDebug(35001) << "Some problems, there is less data than it should be!" << endl;
+ break;
+ }
+
+ TQDomElement e = n.toElement();
+ if ( !e.isNull() && e.tagName() == "cell" ) {
+ // add the cell to the corresponding place...
+ double val = e.attribute("value").toDouble(&ok);
+ if (!ok) { return false; }
+ kdDebug(35001) << i << " " << j << "=" << val << endl;
+ KoChart::Value t( val );
+ // kdDebug(35001) << "Set cell for " << row << "," << col << endl;
+ m_currentData.setCell(i,j,t);
+ if ( e.hasAttribute( "hide" ) ) {
+ tmpMissing[cols*j+i] = (bool)e.attribute("hide").toInt( &ok );
+ if ( !ok )
+ return false;
+ } else {
+ tmpMissing[cols*j+i] = false;
+ }
+ if ( e.hasAttribute( "dist" ) ) {
+ tmpExp[cols*j+i] = e.attribute("dist").toInt( &ok );
+ if ( !ok )
+ return false;
+ } else {
+ tmpExp[cols*j+i] = 0;
+ }
+
+ n = n.nextSibling();
+ }
+ }
+ }
+ m_params->missing=tmpMissing;
+ m_params->explode=tmpExp;
+#endif
+
+
+/*
+ enum KChartType {
+ KCHARTTYPE_LINE,
+ KCHARTTYPE_AREA,
+ KCHARTTYPE_BAR,
+ KCHARTTYPE_HILOCLOSE,
+ KCHARTTYPE_COMBO_LINE_BAR, aka, VOL[ume]
+ KCHARTTYPE_COMBO_HLC_BAR,
+ KCHARTTYPE_COMBO_LINE_AREA,
+ KCHARTTYPE_COMBO_HLC_AREA,
+ KCHARTTYPE_3DHILOCLOSE,
+ KCHARTTYPE_3DCOMBO_LINE_BAR,
+ KCHARTTYPE_3DCOMBO_LINE_AREA,
+ KCHARTTYPE_3DCOMBO_HLC_BAR,
+ KCHARTTYPE_3DCOMBO_HLC_AREA,
+ KCHARTTYPE_3DBAR,
+ KCHARTTYPE_3DAREA,
+ KCHARTTYPE_3DLINE,
+ KCHARTTYPE_3DPIE,
+ KCHARTTYPE_2DPIE
+ };
+*/
+ bool ok;
+ TQDomElement params = chart.namedItem( "params" ).toElement();
+ if ( params.hasAttribute( "type" ) ) {
+ int type=params.attribute("type").toInt( &ok );
+ if ( !ok )
+ return false;
+ switch(type)
+ {
+ case 1:
+ m_params->setChartType(KChartParams::Line);
+ break;
+ case 2:
+ m_params->setChartType(KChartParams::Area);
+ break;
+ case 3:
+ m_params->setChartType(KChartParams::Bar);
+ break;
+ case 4:
+ m_params->setChartType(KChartParams::HiLo);
+ break;
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ /* KCHARTTYPE_COMBO_LINE_BAR, aka, VOL[ume]
+ KCHARTTYPE_COMBO_HLC_BAR,
+ KCHARTTYPE_COMBO_LINE_AREA,
+ KCHARTTYPE_COMBO_HLC_AREA,
+ */
+ /* line by default*/
+ m_params->setChartType(KChartParams::Line);
+ break;
+ case 9:
+ m_params->setChartType(KChartParams::HiLo);
+ break;
+ case 10:
+ m_params->setChartType(KChartParams::Bar);
+ break;
+ case 11:
+ m_params->setChartType(KChartParams::Area);
+ break;
+ case 12:
+ m_params->setChartType(KChartParams::Bar);
+ break;
+ case 13:
+ m_params->setChartType(KChartParams::Area);
+ break;
+ case 14:
+ m_params->setChartType(KChartParams::Bar);
+ break;
+ case 15:
+ m_params->setChartType(KChartParams::Area);
+ break;
+ case 16:
+ m_params->setChartType(KChartParams::Line);
+ break;
+ case 17:
+ case 18:
+ m_params->setChartType(KChartParams::Pie);
+ break;
+
+ }
+ if ( !ok )
+ return false;
+ }
+#if 0
+ if ( params.hasAttribute( "subtype" ) ) {
+ m_params->stack_type = (KChartStackType)params.attribute("subtype").toInt( &ok );
+ if ( !ok )
+ return false;
+ }
+ if ( params.hasAttribute( "hlc_style" ) ) {
+ m_params->hlc_style = (KChartHLCStyle)params.attribute("hlc_style").toInt( &ok );
+ if ( !ok )
+ return false;
+ }
+ if ( params.hasAttribute( "hlc_cap_width" ) ) {
+ m_params->hlc_cap_width = (short)params.attribute( "hlc_cap_width" ).toShort( &ok );
+ if ( !ok )
+ return false;
+ }
+
+ TQDomElement title = params.namedItem( "title" ).toElement();
+ if ( !title.isNull()) {
+ TQString t = title.text();
+ m_params->title=t;
+ }
+ TQDomElement titlefont = params.namedItem( "titlefont" ).toElement();
+ if ( !titlefont.isNull()) {
+ TQDomElement font = titlefont.namedItem( "font" ).toElement();
+ if ( !font.isNull() )
+ m_params->setTitleFont(toFont(font));
+ }
+ TQDomElement xtitle = params.namedItem( "xtitle" ).toElement();
+ if ( !xtitle.isNull()) {
+ TQString t = xtitle.text();
+ m_params->xtitle=t;
+ }
+ TQDomElement xtitlefont = params.namedItem( "xtitlefont" ).toElement();
+ if ( !xtitlefont.isNull()) {
+ TQDomElement font = xtitlefont.namedItem( "font" ).toElement();
+ if ( !font.isNull() )
+ m_params->setXTitleFont(toFont(font));
+ }
+ TQDomElement ytitle = params.namedItem( "ytitle" ).toElement();
+ if ( !ytitle.isNull()) {
+ TQString t = ytitle.text();
+ m_params->ytitle=t;
+ }
+ TQDomElement ytitle2 = params.namedItem( "ytitle2" ).toElement();
+ if ( !ytitle2.isNull()) {
+ TQString t = ytitle2.text();
+ m_params->ytitle2=t;
+ }
+ TQDomElement ytitlefont = params.namedItem( "ytitlefont" ).toElement();
+ if ( !ytitlefont.isNull()) {
+ TQDomElement font = ytitlefont.namedItem( "font" ).toElement();
+ if ( !font.isNull() )
+ m_params->setYTitleFont(toFont(font));
+ }
+ TQDomElement ylabelfmt = params.namedItem( "ylabelfmt" ).toElement();
+ if ( !ylabelfmt.isNull()) {
+ TQString t = ylabelfmt.text();
+ m_params->ylabel_fmt=t;
+ }
+ TQDomElement ylabel2fmt = params.namedItem( "ylabel2fmt" ).toElement();
+ if ( !ylabel2fmt.isNull()) {
+ TQString t = ylabel2fmt.text();
+ m_params->ylabel2_fmt=t;
+ }
+ TQDomElement labelfont = params.namedItem( "labelfont" ).toElement();
+ if ( !labelfont.isNull()) {
+ TQDomElement font = labelfont.namedItem( "font" ).toElement();
+ if ( !font.isNull() )
+ m_params->setLabelFont(toFont(font));
+ }
+
+ TQDomElement yaxisfont = params.namedItem( "yaxisfont" ).toElement();
+ if ( !yaxisfont.isNull()) {
+ TQDomElement font = yaxisfont.namedItem( "font" ).toElement();
+ if ( !font.isNull() )
+ m_params->setYAxisFont(toFont(font));
+ }
+
+ TQDomElement xaxisfont = params.namedItem( "xaxisfont" ).toElement();
+ if ( !xaxisfont.isNull()) {
+ TQDomElement font = xaxisfont.namedItem( "font" ).toElement();
+ if ( !font.isNull() )
+ m_params->setXAxisFont(toFont(font));
+ }
+ TQDomElement annotationFont = params.namedItem("annotationfont").toElement();
+ if ( !annotationFont.isNull()) {
+ TQDomElement font = annotationFont.namedItem( "font" ).toElement();
+ if ( !font.isNull() )
+ m_params->setAnnotationFont(toFont(font));
+ }
+
+ TQDomElement yaxis = params.namedItem( "yaxis" ).toElement();
+ if ( !yaxis.isNull()) {
+ if (yaxis.hasAttribute( "yinterval" )) {
+ m_params->requested_yinterval= yaxis.attribute("yinterval").toDouble( &ok );
+ if ( !ok ) return false;
+ }
+ if (yaxis.hasAttribute( "ymin" )) {
+ m_params->requested_ymin= yaxis.attribute("ymin").toDouble( &ok );
+ if ( !ok ) return false;
+ }
+ if (yaxis.hasAttribute( "ymax" ) ) {
+ m_params->requested_ymax= yaxis.attribute("ymax").toDouble( &ok );
+ if ( !ok ) return false;
+ }
+ }
+#endif
+
+ TQDomElement graph = params.namedItem( "graph" ).toElement();
+ if (!graph.isNull()) {
+ if (graph.hasAttribute( "grid" )) {
+ bool b=(bool) graph.attribute("grid").toInt( &ok );
+ m_params->setAxisShowGrid(KDChartAxisParams::AxisPosLeft,b );
+ m_params->setAxisShowGrid(KDChartAxisParams::AxisPosBottom,b );
+ if (!ok) return false;
+ }
+ if (graph.hasAttribute( "xaxis" )) {
+ bool b=(bool) graph.attribute("xaxis").toInt( &ok );
+ if (!ok) return false;
+ m_params->setAxisVisible(KDChartAxisParams::AxisPosBottom,b);
+ }
+ if (graph.hasAttribute( "yaxis" )) {
+ bool b=(bool) graph.attribute("yaxis").toInt( &ok );
+ if (!ok) return false;
+ m_params->setAxisVisible(KDChartAxisParams::AxisPosLeft,b);
+ }
+#if 0
+ //no implemented
+ if (graph.hasAttribute( "shelf" )) {
+ m_params->shelf=(bool) graph.attribute("shelf").toInt( &ok );
+ if (!ok) return false;
+ }
+#endif
+ if (graph.hasAttribute( "yaxis2" )) {
+ bool b=(bool) graph.attribute("yaxis2").toInt( &ok );
+ if (!ok) return false;
+ m_params->setAxisVisible(KDChartAxisParams::AxisPosRight,b);
+ }
+
+#if 0
+ //no implemented
+ if (graph.hasAttribute( "ystyle" )) {
+ m_params->yval_style=(bool) graph.attribute("ystyle").toInt( &ok );
+ if (!ok) return false;
+ }
+ if (graph.hasAttribute( "border" )) {
+ m_params->border=(bool) graph.attribute("border").toInt( &ok );
+ if (!ok) return false;
+ }
+ if (graph.hasAttribute( "transbg" )) {
+ m_params->transparent_bg=(bool) graph.attribute("transbg").toInt( &ok );
+ if (!ok) return false;
+ }
+ if (graph.hasAttribute( "xlabel" )) {
+ m_params->hasxlabel=(bool) graph.attribute("xlabel").toInt( &ok );
+ if (!ok) return false;
+ }
+ if ( graph.hasAttribute( "xlabel_spacing" ) ) {
+ m_params->xlabel_spacing = (short)graph.attribute( "xlabel_spacing" ).toShort( &ok );
+ if ( !ok )
+ return false;
+ }
+ if ( graph.hasAttribute( "ylabel_density" ) ) {
+ m_params->ylabel_density = (short)graph.attribute( "ylabel_density" ).toShort( &ok );
+ if ( !ok )
+ return false;
+ }
+ if (graph.hasAttribute( "line")) {
+ m_params->label_line=(bool) graph.attribute("line").toInt( &ok );
+ if (!ok) return false;
+ }
+ if (graph.hasAttribute( "percent")) {
+ m_params->percent_labels=(KChartPercentType) graph.attribute("percent").toInt( &ok );
+ if (!ok) return false;
+ }
+ if (graph.hasAttribute("cross")) {
+ m_params->cross=(bool) graph.attribute("cross").toInt( &ok );
+ if (!ok) return false;
+ }
+ if (graph.hasAttribute("thumbnail")) {
+ m_params->thumbnail=(bool) graph.attribute("thumbnail").toInt( &ok );
+ if (!ok) return false;
+ }
+ if (graph.hasAttribute("thumblabel")) {
+ m_params->thumblabel= graph.attribute("thumblabel");
+ }
+ if (graph.hasAttribute("thumbval")) {
+ m_params->thumbval=(bool) graph.attribute("thumbval").toDouble( &ok );
+ if (!ok)
+ return false;
+ }
+#endif
+ }
+
+#if 0
+ TQDomElement graphparams = params.namedItem( "graphparams" ).toElement();
+ if (!graphparams.isNull()) {
+ if (graphparams.hasAttribute( "dept3d" )) {
+ m_params->_3d_depth=graphparams.attribute("dept3d").toDouble( &ok );
+ if (!ok) return false;
+ }
+ if (graphparams.hasAttribute( "angle3d" )) {
+ m_params->_3d_angle=graphparams.attribute("angle3d").toShort( &ok );
+ if (!ok) return false;
+ }
+ if (graphparams.hasAttribute( "barwidth" )) {
+ m_params->bar_width=graphparams.attribute("barwidth").toShort( &ok );
+ if (!ok) return false;
+ }
+ if (graphparams.hasAttribute( "colpie" )) {
+ m_params->colPie=graphparams.attribute("colpie").toInt( &ok );
+ if (!ok) return false;
+ }
+ if (graphparams.hasAttribute( "other_threshold" )) {
+ m_params->other_threshold=graphparams.attribute("other_threshold").toShort( &ok );
+ if (!ok)
+ return false;
+ }
+ if (graphparams.hasAttribute( "offsetCol" )) {
+ m_params->offsetCol = graphparams.attribute("offsetCol").toInt( &ok );
+ if (!ok)
+ return false;
+ }
+ if (graphparams.hasAttribute( "hard_size" )) {
+ m_params->hard_size = (bool)graphparams.attribute("hard_size").toInt( &ok );
+ if (!ok)
+ return false;
+ }
+ if (graphparams.hasAttribute( "hard_graphheight" )) {
+ m_params->hard_graphheight = graphparams.attribute("hard_graphheight").toInt( &ok );
+ if (!ok)
+ return false;
+ }
+ if (graphparams.hasAttribute( "hard_graphwidth" )) {
+ m_params->hard_graphwidth = graphparams.attribute("hard_graphwidth").toInt( &ok );
+ if (!ok)
+ return false;
+ }
+ if (graphparams.hasAttribute( "hard_xorig" )) {
+ m_params->hard_xorig = graphparams.attribute("hard_xorig").toInt( &ok );
+ if (!ok)
+ return false;
+ }
+ if (graphparams.hasAttribute( "hard_yorig" )) {
+ m_params->hard_yorig = graphparams.attribute("hard_yorig").toInt( &ok );
+ if (!ok)
+ return false;
+ }
+ if (graphparams.hasAttribute( "labeldist" )) {
+ m_params->label_dist=graphparams.attribute("labeldist").toInt( &ok );
+ if (!ok) return false;
+ }
+ }
+
+ TQDomElement graphcolor = params.namedItem( "graphcolor" ).toElement();
+ if (!graphcolor.isNull()) {
+ if (graphcolor.hasAttribute( "bgcolor" )) {
+ m_params->BGColor= TQColor( graphcolor.attribute( "bgcolor" ) );
+ }
+ if (graphcolor.hasAttribute( "gridcolor" )) {
+ m_params->GridColor= TQColor( graphcolor.attribute( "gridcolor" ) );
+ }
+ if (graphcolor.hasAttribute( "linecolor" )) {
+ m_params->LineColor= TQColor( graphcolor.attribute( "linecolor" ) );
+ }
+ if (graphcolor.hasAttribute( "plotcolor" )) {
+ m_params->PlotColor= TQColor( graphcolor.attribute( "plotcolor" ) );
+ }
+ if (graphcolor.hasAttribute( "volcolor" )) {
+ m_params->VolColor= TQColor( graphcolor.attribute( "volcolor" ) );
+ }
+ if (graphcolor.hasAttribute( "titlecolor" )) {
+ m_params->TitleColor= TQColor( graphcolor.attribute( "titlecolor" ) );
+ }
+ if (graphcolor.hasAttribute( "xtitlecolor" )) {
+ m_params->XTitleColor= TQColor( graphcolor.attribute( "xtitlecolor" ) );
+ }
+ if (graphcolor.hasAttribute( "ytitlecolor" )) {
+ m_params->YTitleColor= TQColor( graphcolor.attribute( "ytitlecolor" ) );
+ }
+ if (graphcolor.hasAttribute( "ytitle2color" )) {
+ m_params->YTitle2Color= TQColor( graphcolor.attribute( "ytitle2color" ) );
+ }
+ if (graphcolor.hasAttribute( "xlabelcolor" )) {
+ m_params->XLabelColor= TQColor( graphcolor.attribute( "xlabelcolor" ) );
+ }
+ if (graphcolor.hasAttribute( "ylabelcolor" )) {
+ m_params->YLabelColor= TQColor( graphcolor.attribute( "ylabelcolor" ) );
+ }
+ if (graphcolor.hasAttribute( "ylabel2color" )) {
+ m_params->YLabel2Color= TQColor( graphcolor.attribute( "ylabel2color" ) );
+ }
+ }
+
+ TQDomElement annotation = params.namedItem( "annotation" ).toElement();
+ if (!annotation.isNull()) {
+ m_params->annotation=new KChartAnnotationType;
+ if (annotation.hasAttribute( "color" )) {
+ m_params->annotation->color= TQColor( annotation.attribute( "color" ) );
+ }
+ if (annotation.hasAttribute( "point" )) {
+ m_params->annotation->point=annotation.attribute("point").toDouble( &ok );
+ if (!ok) return false;
+ }
+ }
+
+ TQDomElement note = params.namedItem( "note" ).toElement();
+ if ( !note.isNull()) {
+ TQString t = note.text();
+ m_params->annotation->note=t;
+ }
+
+ TQDomElement scatter = params.namedItem( "scatter" ).toElement();
+ if ( !scatter.isNull() ) {
+ m_params->scatter = new KChartScatterType;
+ if ( scatter.hasAttribute( "point" ) ) {
+ m_params->scatter->point = scatter.attribute( "point" ).toDouble( &ok );
+ if ( !ok )
+ return false;
+ }
+ if ( scatter.hasAttribute( "val" ) ) {
+ m_params->scatter->val = scatter.attribute( "val" ).toDouble( &ok );
+ if ( !ok )
+ return false;
+ }
+ if ( scatter.hasAttribute( "width" ) ) {
+ m_params->scatter->width = scatter.attribute( "val" ).toUShort( &ok );
+ if ( !ok )
+ return false;
+ }
+ if ( scatter.hasAttribute( "color" )) {
+ m_params->scatter->color= TQColor( scatter.attribute( "color" ) );
+ }
+ if ( scatter.hasAttribute( "ind" ) ) {
+ m_params->scatter->ind = (KChartScatterIndType)scatter.attribute( "ind" ).toInt( &ok );
+ if ( !ok )
+ return false;
+ }
+ }
+
+ TQDomElement legend = chart.namedItem("legend").toElement();
+ if (!legend.isNull()) {
+ int number = legend.attribute("number").toInt(&ok);
+ if (!ok) { return false; }
+ TQDomNode name = legend.firstChild();
+ m_params->legend.clear();
+ for(int i=0; i<number; i++) {
+ if (name.isNull()) {
+ kdDebug(35001) << "Some problems, there is less data than it should be!" << endl;
+ break;
+ }
+ TQDomElement element = name.toElement();
+ if ( !element.isNull() && element.tagName() == "name" ) {
+ TQString t = element.text();
+ m_params->legend+=t;
+ name = name.nextSibling();
+ }
+ }
+ }
+
+ TQDomElement xlbl = chart.namedItem("xlbl").toElement();
+ if (!xlbl.isNull()) {
+ int number = xlbl.attribute("number").toInt(&ok);
+ if (!ok) { return false; }
+ TQDomNode label = xlbl.firstChild();
+ m_params->xlbl.clear();
+ for (int i=0; i<number; i++) {
+ if (label.isNull()) {
+ kdDebug(35001) << "Some problems, there is less data than it should be!" << endl;
+ break;
+ }
+ TQDomElement element = label.toElement();
+ if ( !element.isNull() && element.tagName() == "label" ) {
+ TQString t = element.text();
+ m_params->xlbl+=t;
+ label = label.nextSibling();
+ }
+ }
+ }
+
+ TQDomElement backgroundPixmap = chart.namedItem( "backgroundPixmap" ).toElement();
+ if ( !backgroundPixmap.isNull() ) {
+ if ( backgroundPixmap.hasAttribute( "name" ) )
+ m_params->backgroundPixmapName = backgroundPixmap.attribute( "name" );
+ if ( backgroundPixmap.hasAttribute( "isDirty" ) ) {
+ m_params->backgroundPixmapIsDirty = (bool)backgroundPixmap.attribute( "isDirty" ).toInt( &ok );
+ if ( !ok )
+ return false;
+ }
+ if ( backgroundPixmap.hasAttribute( "scaled" ) ) {
+ m_params->backgroundPixmapScaled = (bool)backgroundPixmap.attribute( "scaled" ).toInt( &ok );
+ if ( !ok )
+ return false;
+ }
+ if ( backgroundPixmap.hasAttribute( "centered" ) ) {
+ m_params->backgroundPixmapCentered = (bool)backgroundPixmap.attribute( "centered" ).toInt( &ok );
+ if ( !ok )
+ return false;
+ }
+ if ( backgroundPixmap.hasAttribute( "intensity" ) ) {
+ m_params->backgroundPixmapIntensity = backgroundPixmap.attribute( "intensity" ).toFloat( &ok );
+ if ( !ok )
+ return false;
+ }
+ }
+
+ TQDomElement extcolor = chart.namedItem("extcolor").toElement();
+ if (!extcolor.isNull()) {
+ unsigned int number = extcolor.attribute("number").toInt(&ok);
+ if (!ok) { return false; }
+ TQDomNode color = extcolor.firstChild();
+
+ for (unsigned int i=0; i<number; i++) {
+ if (color.isNull()) {
+ kdDebug(35001) << "Some problems, there is less data than it should be!" << endl;
+ break;
+ }
+ TQDomElement element = color.toElement();
+ if ( !element.isNull()) {
+ if (element.hasAttribute( "name" )) {
+ m_params->ExtColor.setColor(i,TQColor( element.attribute( "name" ) ));
+ }
+ color = color.nextSibling();
+ }
+ }
+ }
+
+ if ( !m_params->backgroundPixmapName.isNull() ) {
+ m_params->backgroundPixmap.load( locate( "wallpaper",
+ m_params->backgroundPixmapName ));
+ m_params->backgroundPixmapIsDirty = true;
+ }
+#endif
+ return true;
+}
+
+
+
+void KChartPart::slotModified()
+{
+ kdDebug(35001) << "slotModified called!" << endl;
+
+ setModified(true);
+}
+
+
+bool KChartPart::showEmbedInitDialog(TQWidget* /*parent*/)
+{
+ // Don't show an embed dialog
+ return true;
+}
+
+
+} //KChart namespace
+
+#include "kchart_part.moc"