summaryrefslogtreecommitdiffstats
path: root/kchart/kchart_params.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kchart/kchart_params.cpp')
-rw-r--r--kchart/kchart_params.cpp1043
1 files changed, 1043 insertions, 0 deletions
diff --git a/kchart/kchart_params.cpp b/kchart/kchart_params.cpp
new file mode 100644
index 00000000..2cd8da51
--- /dev/null
+++ b/kchart/kchart_params.cpp
@@ -0,0 +1,1043 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001,2002,2003,2004 Laurent Montel <montel@kde.org>
+ Copyright (C) 2006 Thorsten Zachmann <zachmann@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+//#include <stdlib.h>
+#include <iostream>
+using std::cout;
+using std::cerr;
+
+
+#include <dcopobject.h>
+#include <tdelocale.h>
+#include <kdebug.h>
+
+#include <KoXmlNS.h>
+#include <KoXmlWriter.h>
+#include <KoDom.h>
+#include <KoOasisLoadingContext.h>
+
+#include <tqregexp.h>
+
+#include "kdchart/KDChartParams.h"
+#include "kdchart/KDChartAxisParams.h"
+
+#include "kchart_params.h"
+#include "kchart_part.h"
+#include "KChartParamsIface.h"
+
+
+namespace KChart
+{
+
+
+KChartParams::KChartParams( KChartPart *_part )
+ : KDChartParams(),
+ m_part( _part )
+{
+ // Default values for subtypes.
+ m_firstRowAsLabel = false;
+ m_firstColAsLabel = false;
+
+ // Default values for OpenDocument extensions.
+ m_barNumLines = 0;
+
+ m_dcop = 0;
+ //dcopObject(); // build it
+}
+
+
+KChartParams::~KChartParams()
+{
+ delete m_dcop;
+}
+
+
+// ----------------------------------------------------------------
+
+
+TQString KChartParams::chartTypeToString( ChartType _type) const
+{
+#if 0
+ if (_type == BarLines )
+ return "BarLines";
+ else
+#endif
+ return KDChartParams::chartTypeToString( (KDChartParams::ChartType) _type );
+}
+
+
+KChartParams::ChartType
+KChartParams::stringToChartType( const TQString& _string )
+{
+#if 0
+ if ( _string == "BarLines" )
+ return BarLines;
+ else
+#endif
+ return (ChartType) KDChartParams::stringToChartType( _string );
+}
+
+
+void KChartParams::setFirstRowAsLabel( bool _val )
+{
+ m_firstRowAsLabel = _val;
+
+ // The rest of this method is only applicable if the data is from
+ // an external source, e.g. from kspread.
+ if ( m_part->canChangeValue() )
+ return;
+
+ m_part->doSetData( *m_part->data(),
+ m_firstRowAsLabel, m_firstColAsLabel );
+}
+
+void KChartParams::setFirstColAsLabel( bool _val )
+{
+ m_firstColAsLabel = _val;
+
+ // The rest of this method is only applicable if the data is from
+ // an external source, e.g. kspread.
+ if ( m_part->canChangeValue() )
+ return;
+
+ m_part->doSetData( *m_part->data(),
+ m_firstRowAsLabel, m_firstColAsLabel );
+}
+
+
+DCOPObject* KChartParams::dcopObject()
+{
+ if ( !m_dcop )
+ m_dcop = new KChartParamsIface( this );
+ return m_dcop;
+}
+
+
+// ================================================================
+// Loading and Saving
+
+
+
+static const struct {
+ const char *oasisClass;
+ KChartParams::ChartType chartType;
+} oasisChartTypes[] = {
+ { "chart:bar", KChartParams::Bar },
+ { "chart:line", KChartParams::Line },
+ { "chart:area", KChartParams::Area },
+ { "chart:circle", KChartParams::Pie },
+ //{ "chart:xxx", KChartParams::HiLo },
+ //{ "chart:stock", KChartParams::??? },
+ //{ "chart:add-in", KChartParams::??? },
+ //{ "chart:scatter",KChartParams::??? },
+ { "chart:ring", KChartParams::Ring },
+ { "chart:radar", KChartParams::Polar }
+ //{ "chart:xxx", KChartParams::BoxWhisker },
+
+ //{ "chart:xxx", KChartParams::BarLines },
+ // FIXME: More?
+};
+
+
+static const unsigned int numOasisChartTypes
+ = sizeof oasisChartTypes / sizeof *oasisChartTypes;
+
+
+#if 0 // Example code!!
+ KoOasisLoadingContext loadingContext( this, oasisStyles, store );
+ KoStyleStack &styleStack = loadingContext.styleStack();
+
+ styleStack.save();
+ styleStack.setTypeProperties( "graphic" ); // load graphic-properties
+ loadingContext.fillStyleStack( chartElem, KoXmlNS::chart, "style-name" );
+
+ const TQString fillColor = styleStack.attributeNS( KoXmlNS::draw, "fill-color" );
+ kDebug() << "fillColor=" << fillColor << endl;
+
+ styleStack.restore();
+#endif
+
+
+// Load the data from an OpenDocument chart:chart element.
+
+void KChartParams::loadOasisFont( KoOasisLoadingContext& context, TQFont& font, TQColor& color )
+{
+ KoStyleStack& styleStack = context.styleStack();
+ styleStack.setTypeProperties( "text" ); // load all style attributes from "style:text-properties"
+
+ if ( styleStack.hasAttributeNS( KoXmlNS::fo, "color" ) ) { // 3.10.3
+ color.setNamedColor( styleStack.attributeNS( KoXmlNS::fo, "color" ) ); // #rrggbb format
+ }
+ if ( styleStack.hasAttributeNS( KoXmlNS::fo, "font-family" ) // 3.10.9
+ || styleStack.hasAttributeNS( KoXmlNS::style, "font-name" ) ) { // 3.10.8
+ // Hmm, the remove "'" could break it's in the middle of the fontname...
+ TQString fontName = styleStack.attributeNS( KoXmlNS::fo, "font-family" ).remove( "'" );
+ if ( fontName.isEmpty() ) {
+ // ##### TODO. This is wrong. style:font-name refers to a font-decl entry.
+ // We have to look it up there, and retrieve _all_ font attributes from it, not just the name.
+ fontName = styleStack.attributeNS( KoXmlNS::style, "font-name" ).remove( "'" );
+ }
+ // 'Thorndale' is not known outside OpenOffice so we substitute it
+ // with 'Times New Roman' that looks nearly the same.
+ if ( fontName == "Thorndale" )
+ fontName = "Times New Roman";
+
+ fontName.remove( TQRegExp( "\\sCE$" ) ); // Arial CE -> Arial
+ font.setFamily( fontName );
+ }
+ if ( styleStack.hasAttributeNS( KoXmlNS::fo, "font-size" ) ) { // 3.10.14
+ double pointSize = styleStack.fontSize();
+ font.setPointSizeFloat( pointSize );
+ kdDebug(35001) << "font size: " << pointSize << endl;
+ }
+ if ( styleStack.hasAttributeNS( KoXmlNS::fo, "font-weight" ) ) { // 3.10.24
+ TQString fontWeight = styleStack.attributeNS( KoXmlNS::fo, "font-weight" );
+ int boldness;
+ if ( fontWeight == "normal" )
+ boldness = 50;
+ else if ( fontWeight == "bold" )
+ boldness = 75;
+ else
+ // XSL/CSS has 100,200,300...900. Not the same scale as TQt!
+ // See http://www.w3.org/TR/2001/REC-xsl-20011015/slice7.html#font-weight
+ boldness = fontWeight.toInt() / 10;
+ font.setWeight( boldness );
+ }
+ if ( styleStack.hasAttributeNS( KoXmlNS::fo, "font-style" ) ) { // 3.10.19
+ if ( styleStack.attributeNS( KoXmlNS::fo, "font-style" ) == "italic" ||
+ styleStack.attributeNS( KoXmlNS::fo, "font-style" ) == "oblique" ) { // no difference in kotext
+ font.setItalic( true );
+ }
+ }
+}
+
+bool KChartParams::loadOasis( const TQDomElement &chartElem,
+ KoOasisLoadingContext &loadingContext,
+ TQString &errorMessage,
+ KoStore */*store*/ )
+{
+ const TQString chartClass = chartElem.attributeNS( KoXmlNS::chart,
+ "class", TQString() );
+ bool knownType = false;
+
+ // Find out what KChart charttype the OASIS charttype corresponds to.
+ for ( unsigned int i = 0 ; i < numOasisChartTypes ; ++i ) {
+ if ( chartClass == oasisChartTypes[i].oasisClass ) {
+ kdDebug(35001) << "found chart of type " << chartClass << endl;
+ //cerr << "found chart of type " << chartClass.latin1() << "\n";
+
+ setChartType( oasisChartTypes[i].chartType );
+ knownType = true;
+ break;
+ }
+ }
+
+ // If we can't find out what charttype it is, we might as well end here.
+ if ( !knownType ) {
+ errorMessage = i18n( "Unknown chart type %1" ).arg( chartClass );
+ kdDebug(35001) << errorMessage << endl;
+ return false;
+ }
+
+ // Title TODO (more details, e.g. font, placement etc)
+ TQDomElement titleElem = KoDom::namedItemNS( chartElem,
+ KoXmlNS::chart, "title" );
+ if ( !titleElem.isNull() ) {
+ loadingContext.styleStack().save();
+ loadingContext.fillStyleStack( titleElem, KoXmlNS::chart, "style-name", "chart" );
+ TQFont font;
+ TQColor color;
+ loadOasisFont( loadingContext, font, color );
+ setHeaderFooterFont( KDChartParams::HdFtPosHeader, font, true, font.pointSize()*4 );
+ setHeaderFooterColor( KDChartParams::HdFtPosHeader, color );
+ loadingContext.styleStack().restore();
+
+ TQDomElement pElem = KoDom::namedItemNS( titleElem,
+ KoXmlNS::text, "p" );
+ setHeader1Text( pElem.text() );
+ }
+
+ // Subtitle TODO (more details)
+ TQDomElement subtitleElem = KoDom::namedItemNS( chartElem, KoXmlNS::chart,
+ "subtitle" );
+ if ( !subtitleElem.isNull() ) {
+ loadingContext.styleStack().save();
+ loadingContext.fillStyleStack( subtitleElem, KoXmlNS::chart, "style-name", "chart" );
+ TQFont font;
+ TQColor color;
+ loadOasisFont( loadingContext, font, color );
+ setHeaderFooterFont( KDChartParams::HdFtPosHeader2, font, true, font.pointSize()*4 );
+ setHeaderFooterColor( KDChartParams::HdFtPosHeader2, color );
+ loadingContext.styleStack().restore();
+
+ TQDomElement pElem = KoDom::namedItemNS( subtitleElem,
+ KoXmlNS::text, "p" );
+ setHeader2Text( pElem.text() );
+ }
+
+ // Footer TODO (more details)
+ TQDomElement footerElem = KoDom::namedItemNS( chartElem, KoXmlNS::chart,
+ "footer" );
+ if ( !footerElem.isNull() ) {
+ loadingContext.styleStack().save();
+ loadingContext.fillStyleStack( footerElem, KoXmlNS::chart, "style-name", "chart" );
+ TQFont font;
+ TQColor color;
+ loadOasisFont( loadingContext, font, color );
+ setHeaderFooterFont( KDChartParams::HdFtPosFooter, font, true, font.pointSize()*4 );
+ setHeaderFooterColor( KDChartParams::HdFtPosFooter, color );
+ loadingContext.styleStack().restore();
+
+ TQDomElement pElem = KoDom::namedItemNS( footerElem,
+ KoXmlNS::text, "p" );
+ setFooterText( pElem.text() );
+ }
+
+ // TODO: Get legend settings
+ TQDomElement legendElem = KoDom::namedItemNS( chartElem, KoXmlNS::chart,
+ "legend" );
+ if ( !legendElem.isNull() )
+ {
+ loadingContext.styleStack().save();
+ loadingContext.fillStyleStack( legendElem, KoXmlNS::chart, "style-name", "chart" );
+ TQFont font;
+ TQColor color;
+ loadOasisFont( loadingContext, font, color );
+ //tz I didn't find that Oasis support seperate font/colors for the title and the rest of the legent
+ setLegendFont( font, false );
+ setLegendFontRelSize( font.pointSize()*4 );
+ setLegendTitleFont( font, false);
+ setLegendTitleFontRelSize( font.pointSize()*4 );
+ setLegendTextColor( color );
+ setLegendTitleTextColor( color );
+ loadingContext.styleStack().restore();
+ TQString lp;
+ if ( legendElem.hasAttributeNS( KoXmlNS::chart, "legend-position" ) )
+ {
+ lp = legendElem.attributeNS( KoXmlNS::chart, "legend-position", TQString() );
+ }
+ TQString lalign;
+ if ( legendElem.hasAttributeNS( KoXmlNS::chart, "legend-align" ) )
+ {
+ lalign = legendElem.attributeNS( KoXmlNS::chart, "legend-align", TQString() );
+ }
+
+ LegendPosition lpos = NoLegend;
+ int align = 1;
+ if ( lalign == "start" )
+ {
+ align = 0;
+ }
+ else if ( lalign == "end" )
+ {
+ align = 2;
+ }
+
+ if ( lp == "start" )
+ {
+ lpos = LegendLeft;
+ if ( align == 0 )
+ lpos = LegendTopLeftLeft;
+ else if ( align == 2 )
+ lpos = LegendBottomLeftLeft;
+ }
+ else if ( lp == "end" )
+ {
+ lpos = LegendRight;
+ if ( align == 0 )
+ lpos = LegendTopRightRight;
+ else if ( align == 2 )
+ lpos = LegendBottomRightRight;
+ }
+ else if ( lp == "top" )
+ {
+ lpos = LegendTop;
+ if ( align == 0 )
+ lpos = LegendTopLeftTop;
+ else if ( align == 2 )
+ lpos = LegendTopRightTop;
+ }
+ else if ( lp == "bottom" )
+ {
+ lpos = LegendBottom;
+ if ( align == 0 )
+ lpos = LegendBottomLeftBottom;
+ else if ( align == 2 )
+ lpos = LegendBottomRightBottom;
+ }
+ else if ( lp == "top-start" )
+ {
+ lpos = LegendTopLeft;
+ }
+ else if ( lp == "bottom-start" )
+ {
+ lpos = LegendBottomLeft;
+ }
+ else if ( lp == "top-end" )
+ {
+ lpos = LegendTopRight;
+ }
+ else if ( lp == "bottom-end" )
+ {
+ lpos = LegendBottomRight;
+ }
+
+ setLegendPosition( lpos );
+ //bodyWriter->addAttribute( "koffice:title", legendTitleText() );
+ if ( legendElem.hasAttributeNS( KoXmlNS::koffice, "title" ) )
+ {
+ setLegendTitleText( legendElem.attributeNS( KoXmlNS::koffice, "title", TQString() ) );
+ }
+ }
+ else
+ {
+ setLegendPosition( NoLegend );
+ }
+
+ // Get the plot-area. This is where the action is.
+ TQDomElement plotareaElem = KoDom::namedItemNS( chartElem,
+ KoXmlNS::chart, "plot-area" );
+ if ( !plotareaElem.isNull() ) {
+ return loadOasisPlotarea( plotareaElem, loadingContext, errorMessage );
+ }
+
+ return false;
+}
+
+
+bool KChartParams::loadOasisPlotarea( const TQDomElement &plotareaElem,
+ KoOasisLoadingContext &loadingContext,
+ TQString &errorMessage )
+{
+ TQString tmp;
+
+ //cerr << ">>> ==========================================================\n";
+
+ // FIXME: attribute table:cell-range-address - the cells in a spreadsheet
+
+ // Get whether there is a label on the first row or column of the data.
+ // This info is in the attribute chart:data-source-has-labels.
+ //
+ // NOTE: Only used in spreadsheets.
+ tmp = plotareaElem.attributeNS( KoXmlNS::chart,
+ "data-source-has-labels", TQString() );
+ m_firstRowAsLabel = false;
+ m_firstColAsLabel = false;
+ if ( tmp == "none" || tmp == "" )
+ ; // NOTHING
+ else if ( tmp == "row" )
+ m_firstRowAsLabel = true;
+ else if ( tmp == "column" )
+ m_firstColAsLabel = true;
+ else if ( tmp == "both" ) {
+ m_firstRowAsLabel = true;
+ m_firstColAsLabel = true;
+ }
+ else {
+ errorMessage = "Unknown value for chart:data-source-has-labels:"
+ + tmp;
+ return false;
+ }
+
+ // ----------------------------------------------------------------
+ // Now get the style and use it to get the contents.
+ // This is hidden in the attribute chart:style-name.
+ KoStyleStack &styleStack = loadingContext.styleStack();
+
+
+ tmp = plotareaElem.attributeNS( KoXmlNS::chart, "style-name",
+ TQString() );
+ //kdDebug(35001) << "Style name for the plot area: " << tmp << endl;
+ styleStack.save();
+ styleStack.setTypeProperties( "chart" ); // load chart properties
+ loadingContext.fillStyleStack( plotareaElem, KoXmlNS::chart, "style-name", "chart" );
+
+ if ( styleStack.attributeNS( KoXmlNS::chart, "three-dimensional" ) == "true" ) {
+ setThreeDBars( true );
+ setThreeDLines( true );
+ setThreeDPies( true );
+ }
+ else {
+ setThreeDBars( false );
+ setThreeDLines( false );
+ setThreeDPies( false );
+ }
+
+ switch ( m_chartType ) {
+ case NoType:
+ break;
+
+ case Bar:
+ // Find out subtype
+ tmp = styleStack.attributeNS( KoXmlNS::chart, "vertical" );
+ // FIXME:Qt::Vertical is ignored. At least store it so we can
+ // save it again even if we don't support it.
+
+ //kdDebug(35001) << " ======> Qt::Vertical: " << tmp << " <======" << endl;
+ // Set the bar chart subtype.
+ if ( styleStack.attributeNS( KoXmlNS::chart, "stacked" ) == "true" )
+ setBarChartSubType( BarStacked );
+ else if ( styleStack.attributeNS( KoXmlNS::chart, "percentage" ) == "true" )
+ setBarChartSubType( BarPercent );
+ else
+ setBarChartSubType( BarNormal );
+
+ break;
+
+ // chart:vertical - true if vertical bars (only bar charts)
+ // chart:stacked - true for stacked bars
+ // chart:percentage - true for percentage (mut. excl with stacked)
+ // chart:connect-bars - true if lines to connect bars should be drawn
+ // only used for stacked and percentage bars.
+ // FIXME: Support lines on bar charts.
+ // chart:lines-used - 0-n, number of lines on a bar chart. (def: 0)
+
+ case Line:
+ // Set the line chart subtype.
+ if ( styleStack.attributeNS( KoXmlNS::chart, "stacked" ) == "true" )
+ setLineChartSubType( LineStacked );
+ else if ( styleStack.attributeNS( KoXmlNS::chart, "percentage" ) == "true" )
+ setLineChartSubType( LinePercent );
+ else
+ setLineChartSubType( LineNormal );
+
+ break;
+
+ // FIXME: Why is this even there? Seems like an unnecessary attr.
+ // chart:lines - true for line charts, false otherwise
+
+ // chart:stacked - true for stacked bars
+ // chart:percentage - true for percentage (mut. excl with stacked)
+
+ // chart:symbol-type - used with line charts, should be "automatic"
+
+ case Area:
+ // Set the area chart subtype.
+ if ( styleStack.attributeNS( KoXmlNS::chart, "stacked" ) == "true" )
+ setAreaChartSubType( AreaStacked );
+ else if ( styleStack.attributeNS( KoXmlNS::chart, "percentage" ) == "true" )
+ setAreaChartSubType( AreaPercent );
+ else
+ setAreaChartSubType( AreaNormal );
+
+ break;
+
+ // chart:stacked - true for stacked bars
+ // chart:percentage - true for percentage (mut. excl with stacked)
+
+ case Pie:
+ break;
+
+ case HiLo:
+ break;
+
+ case Ring:
+ break;
+
+ case Polar:
+ break;
+
+ case BoxWhisker:
+ break;
+ }
+ // TODO:
+ // And get the info from the style. Here is the contents:
+
+
+ // TODO: These items are currently not used. They should be at least
+ // be stored so that we can save them again.
+ // chart:interpolation - "cubic-spline" if using cubic splines
+ // chart:splines -
+ // chart:spline-order - "2" for cubic splines
+ // chart:spline-resolution - how smooth (default: 20)
+
+ // -- Used when chart:class == "stock:
+ // chart:stock-updown-bars - boolean
+ // chart:stock-with-volume - boolean
+ // chart:japanese-candle-sticks - boolean
+
+ // chart:series-source - "rows" or "columns"
+ // "columns" is the default
+ if ( styleStack.attributeNS( KoXmlNS::chart, "series-source" ) == "rows" ) {
+ setDataDirection( DataRows );
+ }
+
+ // chart:data-label-number - "value" / "percentage" / "none" (def: none)
+
+ // chart:data-label-text - true if data hapoints have text labels
+ // chart:data-label-symbol - true if data hapoints have legend symbol
+ // (default: false for both)
+
+ styleStack.restore();
+
+ // ----------------------------------------------------------------
+ // In the plot-area element there are two chart:axis elements
+
+ TQDomElement xAxisElem;
+ TQDomElement yAxisElem;
+
+ TQDomElement axisElem;
+ forEachElement( axisElem, plotareaElem ) {
+
+ // If this element is not an axis, then continue
+ if ( axisElem.tagName() != "axis" )
+ continue;
+
+ tmp = axisElem.attributeNS( KoXmlNS::chart, "name",
+ TQString());
+ //kdDebug(35001) << "Got axis " << tmp << endl;
+ //cerr << "Got axis " << tmp.latin1() << "\n";
+ if ( tmp == "primary-x" )
+ xAxisElem = axisElem;
+ else if ( tmp == "primary-y" )
+ yAxisElem = axisElem;
+ else
+ // Only supports two axes so far.
+ continue;
+ }
+
+ // Load the axes. Pie charts use only the y axis.
+ if ( m_chartType != Pie
+ && !loadOasisAxis( xAxisElem, loadingContext, errorMessage,
+ KDChartAxisParams::AxisPosBottom) )
+ return false;
+ if ( !loadOasisAxis( yAxisElem, loadingContext, errorMessage,
+ KDChartAxisParams::AxisPosLeft) )
+ return false;
+
+ // Attributes for the axes:
+ // chart:name - either "primary-x" or "primary-y"
+
+#if 0
+ const TQString fillColor = styleStack.attributeNS( KoXmlNS::draw,
+ "fill-color" );
+ kdDebug() << "fillColor=" << fillColor << endl;
+#endif
+
+ //cerr << "<<< ==========================================================\n";
+
+ return true;
+}
+
+
+bool KChartParams::loadOasisAxis( const TQDomElement &axisElem,
+ KoOasisLoadingContext &loadingContext,
+ TQString &errorMessage,
+ KDChartAxisParams::AxisPos axisPos )
+{
+ Q_UNUSED( errorMessage );
+
+ TQString tmp;
+ TQDomElement tmpElem;
+ KoStyleStack &styleStack = loadingContext.styleStack();
+
+ // Get the axis to manipulate.
+ // TODO
+
+ // Get the axis title (== axis label) if any.
+ TQDomElement titleElem = KoDom::namedItemNS( axisElem,
+ KoXmlNS::chart, "title" );
+ if ( !titleElem.isNull() ) {
+ tmpElem = KoDom::namedItemNS( titleElem, KoXmlNS::text, "p" );
+ setAxisTitle( axisPos, tmpElem.text() );
+ }
+
+
+
+ //cerr << ">>> ----------------------------------------------------------\n";
+ //cerr << "Loading axis " << axisElem.attributeNS( KoXmlNS::chart, "name",
+ // TQString()).latin1()
+ // << "\n";
+
+ tmp = axisElem.attributeNS( KoXmlNS::chart, "style-name", TQString() );
+ //kdDebug(35001) << "Style name for the axis: " << tmp << endl;
+ //cerr << "Style name for the axis: " << tmp.latin1() << "\n";
+ styleStack.save();
+ styleStack.setTypeProperties( "chart" ); // load chart properties
+ loadingContext.fillStyleStack( axisElem, KoXmlNS::chart, "style-name", "chart" );
+
+ // chart:class - "category" / "value" / "domain" (domain for scatter)
+ // child: chart:categories
+
+ // child: chart:title - Name of title if any.
+ // child: chart:grid
+ // attr: chart:class - "major" / "minor"
+
+ // chart:style-name - Associated style with the following info:
+ // --------------------------------
+ // chart:display-label - true if an axis label should be shown.
+
+ // chart:tick-marks-major-inner - true if display tickmarks at major
+ // chart:tick-marks-major-outer or minor intervals outside / inside
+ // chart:tick-minor-major-inner the chart area.
+ // chart:tick-minor-major-outer
+
+ // chart:logarithmic - true if logarithmic scale
+
+ // text:line-break - true if categories can be broken
+
+ // chart:text-overlap - true if labels can overlap
+
+ // chart:label-arrangement - "side-by-side" / "stagger-even" /
+ // "stagger-odd" (def: side-by-side)
+
+ // chart:visible - true if labels + ticks should be shown.
+
+ // children:
+ // chart:
+ // chart:
+ // chart:
+ // chart:
+ // chart:
+ styleStack.restore();
+
+ //cerr << "<<< ----------------------------------------------------------\n";
+ return true;
+}
+
+
+// ----------------------------------------------------------------
+
+
+void KChartParams::saveOasis( KoXmlWriter* bodyWriter, KoGenStyles& mainStyles ) const
+{
+ bool knownType = false;
+ for ( unsigned int i = 0 ; i < numOasisChartTypes ; ++i ) {
+ if ( m_chartType == oasisChartTypes[i].chartType ) {
+ bodyWriter->addAttribute( "chart:class", oasisChartTypes[i].oasisClass );
+ knownType = true;
+ break;
+ }
+ }
+
+ if ( !knownType ) {
+ kdError(32001) << "Unknown chart type in KChartParams::saveOasis, extend oasisChartTypes!" << endl;
+ }
+
+ bodyWriter->startElement( "chart:title" );
+ TQRect rect( headerFooterRect( KDChartParams::HdFtPosHeader ) );
+ bodyWriter->addAttributePt( "svg:x", rect.x() );
+ bodyWriter->addAttributePt( "svg:y", rect.y() );
+ bodyWriter->addAttribute( "chart:style-name", saveOasisFont( mainStyles, header1Font(), headerFooterColor( KDChartParams::HdFtPosHeader ) ) );
+ bodyWriter->startElement( "text:p" );
+ bodyWriter->addTextNode( header1Text() );
+ bodyWriter->endElement(); // text:p
+ bodyWriter->endElement(); // chart:title
+
+ TQString subTitle( header2Text() );
+ if ( !subTitle.isEmpty() ) {
+
+ kdDebug(32001) << "header rect: " << headerFooterRect( KDChartParams::HdFtPosHeader2 ) << endl;
+ TQRect rect( headerFooterRect( KDChartParams::HdFtPosHeader2 ) );
+ bodyWriter->startElement( "chart:subtitle" );
+ bodyWriter->addAttributePt( "svg:x", rect.x() );
+ bodyWriter->addAttributePt( "svg:y", rect.y() );
+ bodyWriter->addAttribute( "chart:style-name",
+ saveOasisFont( mainStyles,
+ header2Font(),
+ headerFooterColor( KDChartParams::HdFtPosHeader2 ) ) );
+
+ bodyWriter->startElement( "text:p" );
+ bodyWriter->addTextNode( subTitle );
+ bodyWriter->endElement(); // text:p
+ bodyWriter->endElement(); // chart:subtitle
+ }
+
+
+ TQString footer( footerText() );
+ if ( !footer.isEmpty() ) {
+ TQRect rect( headerFooterRect( KDChartParams::HdFtPosFooter ) );
+ bodyWriter->startElement( "chart:footer" );
+ bodyWriter->addAttributePt( "svg:x", rect.x() );
+ bodyWriter->addAttributePt( "svg:y", rect.y() );
+ bodyWriter->addAttribute( "chart:style-name",
+ saveOasisFont( mainStyles,
+ footerFont(),
+ headerFooterColor( KDChartParams::HdFtPosFooter ) ) );
+
+ bodyWriter->startElement( "text:p" );
+ bodyWriter->addTextNode( footer );
+ bodyWriter->endElement(); // text:p
+ bodyWriter->endElement(); // chart:footer
+ }
+
+ // TODO legend
+ LegendPosition lpos = legendPosition();
+ if ( lpos != NoLegend ) {
+ bodyWriter->startElement( "chart:legend" );
+ TQString lp;
+ TQString lalign;
+ switch ( lpos ) {
+ case LegendTop:
+ lp = "top";
+ lalign = "center";
+ break;
+ case LegendBottom:
+ lp = "bottom";
+ lalign = "center";
+ break;
+ case LegendLeft:
+ lp = "start";
+ lalign = "center";
+ break;
+ case LegendRight:
+ lp = "end";
+ lalign = "center";
+ break;
+ case LegendTopLeft:
+ lp = "top-start";
+ break;
+ case LegendTopLeftTop:
+ lp = "top";
+ lalign = "start";
+ break;
+ case LegendTopLeftLeft:
+ lp = "start";
+ lalign = "start";
+ break;
+ case LegendTopRight:
+ lp = "top-end";
+ break;
+ case LegendTopRightTop:
+ lp = "top";
+ lalign = "end";
+ break;
+ case LegendTopRightRight:
+ lp = "end";
+ lalign = "start";
+ break;
+ case LegendBottomLeft:
+ lp = "bottom-start";
+ break;
+ case LegendBottomLeftBottom:
+ lp = "bottom";
+ lalign = "start";
+ break;
+ case LegendBottomLeftLeft:
+ lp = "start";
+ lalign = "end";
+ break;
+ case LegendBottomRight:
+ lp = "bottom-end";
+ break;
+ case LegendBottomRightBottom:
+ lp = "bottom";
+ lalign = "end";
+ break;
+ case LegendBottomRightRight:
+ lp = "end";
+ lalign = "end";
+ break;
+ default:
+ lp = "end";
+ lalign = "center";
+ break;
+ }
+
+ bodyWriter->addAttribute( "chart:legend-position", lp );
+ bodyWriter->addAttribute( "chart:legend-align", lalign );
+ bodyWriter->addAttribute( "chart:style-name",
+ saveOasisFont( mainStyles,
+ legendFont(),
+ legendTextColor() ) );
+ bodyWriter->addAttribute( "koffice:title", legendTitleText() );
+ bodyWriter->endElement(); // chart:legend
+ }
+
+ bodyWriter->startElement( "chart:plot-area" );
+ saveOasisPlotArea( bodyWriter, mainStyles );
+ bodyWriter->endElement();
+
+ // TODO...
+}
+
+
+void KChartParams::saveOasisPlotArea( KoXmlWriter* bodyWriter, KoGenStyles& mainStyles ) const
+{
+ TQString dataSourceHasLabels;
+ if ( m_firstRowAsLabel )
+ if ( m_firstColAsLabel )
+ dataSourceHasLabels = "both";
+ else
+ dataSourceHasLabels = "row";
+ else
+ if ( m_firstColAsLabel )
+ dataSourceHasLabels = "column";
+ else
+ dataSourceHasLabels = "none";
+ bodyWriter->addAttribute( "chart:data-source-has-labels", dataSourceHasLabels );
+
+ // Prepare the style for the plot area
+ KoGenStyle plotAreaStyle( KoGenStyle::STYLE_AUTO, "chart" );
+
+ switch ( m_chartType ) {
+ case NoType:
+ break;
+
+ case Bar:
+ switch( barChartSubType() ) {
+ case BarStacked:
+ plotAreaStyle.addProperty( "chart:stacked", "true" );
+ break;
+ case BarPercent:
+ plotAreaStyle.addProperty( "chart:percentage", "true" );
+ break;
+ case BarNormal:
+ break;
+ case BarMultiRows:
+ break;
+ }
+ plotAreaStyle.addProperty( "chart:vertical", "false" ); // #### always?
+ plotAreaStyle.addProperty( "chart:lines-used", 0 ); // FIXME: for now
+
+ if ( threeDBars() )
+ plotAreaStyle.addProperty( "chart:three-dimensional", "true" );
+
+ case Line:
+ switch( lineChartSubType() ) {
+ case LineStacked:
+ plotAreaStyle.addProperty( "chart:stacked", "true" );
+ break;
+ case LinePercent:
+ plotAreaStyle.addProperty( "chart:percentage", "true" );
+ break;
+ case LineNormal:
+ break;
+ }
+ plotAreaStyle.addProperty( "chart:symbol-type", "automatic" );
+
+ if ( threeDLines() )
+ plotAreaStyle.addProperty( "chart:three-dimensional", "true" );
+
+ break;
+
+ case Area:
+ switch( areaChartSubType() ) {
+ case AreaStacked:
+ plotAreaStyle.addProperty( "chart:stacked", "true" );
+ break;
+ case AreaPercent:
+ plotAreaStyle.addProperty( "chart:percentage", "true" );
+ break;
+ case AreaNormal:
+ break;
+ }
+ //plotAreaStyle.addProperty( "chart:lines-used", 0 ); // #### for now
+
+ // TODO - very similar
+
+ case Pie:
+ if ( threeDPies() )
+ plotAreaStyle.addProperty( "chart:three-dimensional", "true" );
+
+ break;
+
+ case HiLo:
+ break;
+
+ case Ring:
+ break;
+
+ case Polar:
+ break;
+
+ case BoxWhisker:
+ break;
+ }
+
+ // chart:series-source
+ plotAreaStyle.addProperty( "chart:series-source",
+ ( dataDirection() == DataRows ) ? "rows" : "columns" );
+
+ // Register the style, and get back its auto-generated name
+ const TQString styleName = mainStyles.lookup( plotAreaStyle, "ch" );
+
+ bodyWriter->addAttribute( "chart:style-name", styleName );
+
+ saveOasisAxis( bodyWriter, mainStyles, KDChartAxisParams::AxisPosBottom, "x" );
+ saveOasisAxis( bodyWriter, mainStyles, KDChartAxisParams::AxisPosLeft, "y" );
+
+ // TODO chart:series
+ // TODO chart:wall
+ // TODO chart:floor
+}
+
+
+void KChartParams::saveOasisAxis( KoXmlWriter* bodyWriter,
+ KoGenStyles& mainStyles,
+ KDChartAxisParams::AxisPos axisPos,
+ const char* axisName ) const
+{
+ bodyWriter->startElement( "chart:axis" );
+
+ bodyWriter->addAttribute( "chart:dimension", axisName );
+ bodyWriter->addAttribute( "chart:name", TQCString( "primary-" ) + axisName );
+
+ KoGenStyle axisStyle( KoGenStyle::STYLE_AUTO, "chart" );
+
+ // TODO: Save axis style properties, like
+ axisStyle.addProperty( "chart:display-label", "true" ); // ###
+
+
+ const TQString styleName = mainStyles.lookup( axisStyle, "ch" );
+ bodyWriter->addAttribute( "chart:style-name", styleName );
+
+ // Write axis titles if any.
+ TQString tmpStr = axisTitle( axisPos );
+ if ( tmpStr != "" ) {
+ bodyWriter->startElement( "chart:title" );
+ // TODO: Save style, svg:x, svg:y
+
+ // Write the text in the axis title.
+ bodyWriter->startElement( "text:p" );
+ bodyWriter->addTextNode( tmpStr
+ .remove( TQRegExp( "^<qt><center>" ) )
+ .remove( TQRegExp( "</center></qt>$" ) ) );
+ bodyWriter->endElement(); // text:p
+
+ bodyWriter->endElement(); // chart:title
+ }
+
+ // TODO x axis has chart:categories, y axis has chart:grid ?
+ // Maybe that part should be done by the caller of saveOasisAxis then
+ // including the opening/closing of the chart:axis element...
+
+ bodyWriter->endElement(); // chart:axis
+}
+
+
+TQString KChartParams::saveOasisFont( KoGenStyles& mainStyles, const TQFont& font, const TQColor& color ) const
+{
+ KoGenStyle::PropertyType tt = KoGenStyle::TextType;
+ KoGenStyle autoStyle( KoGenStyle::STYLE_AUTO, "chart", 0 );
+ autoStyle.addProperty( "fo:font-family", font.family(), tt );
+ autoStyle.addPropertyPt( "fo:font-size", font.pointSize(), tt );
+ autoStyle.addProperty( "fo:color", color.isValid() ? color.name() : "#000000", tt );
+ int w = font.weight();
+ autoStyle.addProperty( "fo:font-weight", w == 50 ? "normal" : w == 75 ? "bold" : TQString::number( tqRound( w / 10 ) * 100 ), tt );
+ autoStyle.addProperty( "fo:font-style", font.italic() ? "italic" : "normal", tt );
+
+ return mainStyles.lookup( autoStyle, "ch", KoGenStyles::ForceNumbering );
+}
+
+
+} //KChart namespace
+