tdf#123206 Import/Export chart custom label text
OOX import supports custom label texts in chart diagrams (produced by e.g. double clicking on a data label, and write custom text), but - since embedded objects are exported and imported to odf right after migration - it is not displayed in case of a Writer document. In order to make it work, we have to support custom label text in the odf structure. This commit only allows the import/export of pure text, it should be improved to store and load formatted string. A new XML token is added, which currently refers to an attribute of the chart:data-point tag. If we want to store formatted string, something more clever has to be done. Change-Id: I80c4a3a0dbcf59f1dc732d795fb716da318411cb Reviewed-on: https://gerrit.libreoffice.org/80156 Tested-by: Jenkins Reviewed-by: Tamás Bunth <btomi96@gmail.com>
This commit is contained in:
@@ -149,6 +149,7 @@ public:
|
||||
void testTdf121744();
|
||||
void testTdf122031();
|
||||
void testTdf115012();
|
||||
void testTdf123206_customLabelText();
|
||||
|
||||
CPPUNIT_TEST_SUITE(Chart2ExportTest);
|
||||
CPPUNIT_TEST(testErrorBarXLSX);
|
||||
@@ -261,6 +262,8 @@ public:
|
||||
CPPUNIT_TEST(testTdf121744);
|
||||
CPPUNIT_TEST(testTdf122031);
|
||||
CPPUNIT_TEST(testTdf115012);
|
||||
CPPUNIT_TEST(testTdf123206_customLabelText);
|
||||
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
protected:
|
||||
@@ -2386,6 +2389,19 @@ void Chart2ExportTest::testTdf115012()
|
||||
assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:dispBlanksAs", "val", "zero");
|
||||
}
|
||||
|
||||
void Chart2ExportTest::testTdf123206_customLabelText()
|
||||
{
|
||||
load("/chart2/qa/extras/data/docx/", "tdf123206.docx");
|
||||
|
||||
Reference<chart2::XChartDocument> xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY);
|
||||
CPPUNIT_ASSERT(xChartDoc.is());
|
||||
|
||||
xmlDocPtr pXmlDoc = parseExport("word/charts/chart","Office Open XML Text");
|
||||
CPPUNIT_ASSERT(pXmlDoc);
|
||||
|
||||
assertXPathContent(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:pieChart/c:ser/c:dLbls/c:dLbl[2]/c:tx/c:rich/a:p/a:r/a:t", "kiscica");
|
||||
}
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION(Chart2ExportTest);
|
||||
|
||||
CPPUNIT_PLUGIN_IMPLEMENT();
|
||||
|
||||
Executable
BIN
Binary file not shown.
@@ -536,6 +536,7 @@ namespace xmloff { namespace token {
|
||||
XML_CUSTOM_ICONSET,
|
||||
XML_CUSTOM_ICONSET_INDEX,
|
||||
XML_CUSTOM_ICONSET_NAME,
|
||||
XML_CUSTOM_LABEL_FIELD,
|
||||
XML_CUT,
|
||||
XML_CUT_OFFS,
|
||||
XML_CX,
|
||||
|
||||
@@ -2400,4 +2400,13 @@ xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.
|
||||
</rng:optional>
|
||||
</rng:define>
|
||||
|
||||
<!-- TODO no proposal -->
|
||||
<rng:define name="chart-data-point-attlist" combine="interleave">
|
||||
<rng:optional>
|
||||
<rng:attribute name="loext:custom-label-field">
|
||||
<rng:ref name="string"/>
|
||||
</rng:attribute>
|
||||
</rng:optional>
|
||||
</rng:define>
|
||||
|
||||
</rng:grammar>
|
||||
|
||||
@@ -81,6 +81,7 @@
|
||||
#include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
|
||||
#include <com/sun/star/chart2/XChartTypeContainer.hpp>
|
||||
#include <com/sun/star/chart2/XDataSeriesContainer.hpp>
|
||||
#include <com/sun/star/chart2/XDataPointCustomLabelField.hpp>
|
||||
#include <com/sun/star/chart2/data/XDataSource.hpp>
|
||||
#include <com/sun/star/chart2/data/XDataSink.hpp>
|
||||
#include <com/sun/star/chart2/data/XDataProvider.hpp>
|
||||
@@ -109,6 +110,19 @@ using ::com::sun::star::uno::Reference;
|
||||
using ::com::sun::star::uno::Any;
|
||||
using ::std::vector;
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
struct SchXMLDataPointStruct
|
||||
{
|
||||
OUString maStyleName;
|
||||
sal_Int32 mnRepeat;
|
||||
OUString msCustomLabelText;
|
||||
|
||||
SchXMLDataPointStruct() : mnRepeat( 1 ) {}
|
||||
};
|
||||
}
|
||||
|
||||
// class SchXMLExportHelper_Impl
|
||||
|
||||
class SchXMLExportHelper_Impl
|
||||
@@ -263,6 +277,33 @@ public:
|
||||
namespace
|
||||
{
|
||||
|
||||
OUString lcl_getCustomLabelField(sal_Int32 nDataPointIndex,
|
||||
const uno::Reference< chart2::XDataSeries >& rSeries)
|
||||
{
|
||||
if( !rSeries.is() )
|
||||
return OUString{};
|
||||
|
||||
const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
|
||||
if( nCurrentODFVersion <= SvtSaveOptions::ODFVER_012 )//do not export to ODF 1.2 or older
|
||||
return OUString{};
|
||||
|
||||
// export custom label text
|
||||
if(Reference<beans::XPropertySet> xLabels = rSeries->getDataPointByIndex(nDataPointIndex); xLabels.is())
|
||||
{
|
||||
if(Any aAny = xLabels->getPropertyValue("CustomLabelFields"); aAny.hasValue())
|
||||
{
|
||||
Sequence<uno::Reference<chart2::XDataPointCustomLabelField>> aCustomLabels;
|
||||
aAny >>= aCustomLabels;
|
||||
OUString sLabel;
|
||||
// TODO export formatted string instead of simple characters
|
||||
for(auto& aLabel : aCustomLabels)
|
||||
sLabel += aLabel->getString();
|
||||
return sLabel;
|
||||
}
|
||||
}
|
||||
return OUString{};
|
||||
}
|
||||
|
||||
class lcl_MatchesRole
|
||||
{
|
||||
public:
|
||||
@@ -919,14 +960,6 @@ bool lcl_exportDomainForThisSequence( const Reference< chart2::data::XDataSequen
|
||||
return bDomainExported;
|
||||
}
|
||||
|
||||
struct SchXMLDataPointStruct
|
||||
{
|
||||
OUString maStyleName;
|
||||
sal_Int32 mnRepeat;
|
||||
|
||||
SchXMLDataPointStruct() : mnRepeat( 1 ) {}
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
// class SchXMLExportHelper
|
||||
@@ -3232,6 +3265,8 @@ void SchXMLExportHelper_Impl::exportDataPoints(
|
||||
|
||||
SchXMLDataPointStruct aPoint;
|
||||
aPoint.maStyleName = maAutoStyleNameQueue.front();
|
||||
if(bExportNumFmt)
|
||||
aPoint.msCustomLabelText = lcl_getCustomLabelField(nElement, xSeries);
|
||||
maAutoStyleNameQueue.pop();
|
||||
aDataPointVector.push_back( aPoint );
|
||||
}
|
||||
@@ -3259,6 +3294,7 @@ void SchXMLExportHelper_Impl::exportDataPoints(
|
||||
{
|
||||
SchXMLDataPointStruct aPoint;
|
||||
aPoint.mnRepeat = nCurrIndex - nLastIndex - 1;
|
||||
aPoint.msCustomLabelText = lcl_getCustomLabelField(nCurrIndex, xSeries);
|
||||
aDataPointVector.push_back( aPoint );
|
||||
}
|
||||
|
||||
@@ -3291,6 +3327,7 @@ void SchXMLExportHelper_Impl::exportDataPoints(
|
||||
SAL_WARN_IF( maAutoStyleNameQueue.empty(), "xmloff.chart", "Autostyle queue empty!" );
|
||||
SchXMLDataPointStruct aPoint;
|
||||
aPoint.maStyleName = maAutoStyleNameQueue.front();
|
||||
aPoint.msCustomLabelText = lcl_getCustomLabelField(nCurrIndex, xSeries);
|
||||
maAutoStyleNameQueue.pop();
|
||||
|
||||
aDataPointVector.push_back( aPoint );
|
||||
@@ -3306,6 +3343,7 @@ void SchXMLExportHelper_Impl::exportDataPoints(
|
||||
|
||||
// if we get here the property states are empty
|
||||
SchXMLDataPointStruct aPoint;
|
||||
aPoint.msCustomLabelText = lcl_getCustomLabelField(nCurrIndex, xSeries);
|
||||
aDataPointVector.push_back( aPoint );
|
||||
|
||||
nLastIndex = nCurrIndex;
|
||||
@@ -3335,10 +3373,13 @@ void SchXMLExportHelper_Impl::exportDataPoints(
|
||||
{
|
||||
aPoint = rPoint;
|
||||
|
||||
if( aPoint.maStyleName == aLastPoint.maStyleName )
|
||||
if( aPoint.maStyleName == aLastPoint.maStyleName && aPoint.msCustomLabelText.isEmpty() )
|
||||
aPoint.mnRepeat += aLastPoint.mnRepeat;
|
||||
else if( aLastPoint.mnRepeat > 0 )
|
||||
{
|
||||
// export custom label text
|
||||
if(!aLastPoint.msCustomLabelText.isEmpty())
|
||||
mrExport.AddAttribute( XML_NAMESPACE_LO_EXT, XML_CUSTOM_LABEL_FIELD, aLastPoint.msCustomLabelText);
|
||||
// write last element
|
||||
if( !aLastPoint.maStyleName.isEmpty() )
|
||||
mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_STYLE_NAME, aLastPoint.maStyleName );
|
||||
@@ -3354,6 +3395,10 @@ void SchXMLExportHelper_Impl::exportDataPoints(
|
||||
// write last element if it hasn't been written in last iteration
|
||||
if( aPoint.maStyleName == aLastPoint.maStyleName )
|
||||
{
|
||||
// export custom label text
|
||||
if(!aLastPoint.msCustomLabelText.isEmpty())
|
||||
mrExport.AddAttribute( XML_NAMESPACE_LO_EXT, XML_CUSTOM_LABEL_FIELD, aLastPoint.msCustomLabelText);
|
||||
|
||||
if( !aLastPoint.maStyleName.isEmpty() )
|
||||
mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_STYLE_NAME, aLastPoint.maStyleName );
|
||||
|
||||
|
||||
@@ -609,6 +609,7 @@ void SchXMLDataPointContext::StartElement( const uno::Reference< xml::sax::XAttr
|
||||
sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0;
|
||||
OUString sAutoStyleName;
|
||||
sal_Int32 nRepeat = 1;
|
||||
OUString sCustomLabelField;
|
||||
|
||||
for( sal_Int16 i = 0; i < nAttrCount; i++ )
|
||||
{
|
||||
@@ -623,6 +624,13 @@ void SchXMLDataPointContext::StartElement( const uno::Reference< xml::sax::XAttr
|
||||
else if( IsXMLToken( aLocalName, XML_REPEATED ) )
|
||||
nRepeat = xAttrList->getValueByIndex( i ).toInt32();
|
||||
}
|
||||
else if( nPrefix == XML_NAMESPACE_LO_EXT)
|
||||
{
|
||||
if( IsXMLToken( aLocalName, XML_CUSTOM_LABEL_FIELD))
|
||||
{
|
||||
sCustomLabelField = xAttrList->getValueByIndex( i );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !sAutoStyleName.isEmpty())
|
||||
@@ -631,6 +639,7 @@ void SchXMLDataPointContext::StartElement( const uno::Reference< xml::sax::XAttr
|
||||
DataRowPointStyle::DATA_POINT,
|
||||
m_xSeries, mrIndex, nRepeat, sAutoStyleName );
|
||||
aStyle.mbSymbolSizeForSeriesIsMissingInFile = mbSymbolSizeForSeriesIsMissingInFile;
|
||||
aStyle.msCustomLabelField = sCustomLabelField;
|
||||
mrStyleVector.push_back( aStyle );
|
||||
}
|
||||
mrIndex += nRepeat;
|
||||
|
||||
@@ -30,6 +30,10 @@
|
||||
#include <com/sun/star/chart2/data/XDataSink.hpp>
|
||||
#include <com/sun/star/chart2/data/XPivotTableDataProvider.hpp>
|
||||
|
||||
#include <com/sun/star/chart2/XDataPointCustomLabelField.hpp>
|
||||
#include <com/sun/star/chart2/DataPointCustomLabelFieldType.hpp>
|
||||
#include <com/sun/star/chart2/DataPointCustomLabelField.hpp>
|
||||
|
||||
#include <com/sun/star/chart/ChartAxisAssign.hpp>
|
||||
#include <com/sun/star/chart/ChartSymbolType.hpp>
|
||||
#include <com/sun/star/chart/ErrorBarStyle.hpp>
|
||||
@@ -1085,6 +1089,17 @@ void SchXMLSeries2Context::setStylesToDataPoints( SeriesDefaultsAndStyles& rSeri
|
||||
if( seriesStyle.mbSymbolSizeForSeriesIsMissingInFile )
|
||||
lcl_resetSymbolSizeForPointsIfNecessary( xPointProp, rImport, pPropStyleContext, pStylesCtxt );
|
||||
}
|
||||
|
||||
if(!seriesStyle.msCustomLabelField.isEmpty())
|
||||
{
|
||||
Sequence< Reference<chart2::XDataPointCustomLabelField>> xLabels(1);
|
||||
Reference< uno::XComponentContext > xContext( comphelper::getProcessComponentContext() );
|
||||
Reference< chart2::XDataPointCustomLabelField > xCustomLabel = chart2::DataPointCustomLabelField::create(xContext);
|
||||
xLabels[0] = xCustomLabel;
|
||||
xCustomLabel->setString(seriesStyle.msCustomLabelField);
|
||||
xCustomLabel->setFieldType(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT);
|
||||
xPointProp->setPropertyValue("CustomLabelFields", uno::Any(xLabels));
|
||||
}
|
||||
}
|
||||
catch( const uno::Exception & )
|
||||
{
|
||||
|
||||
@@ -168,6 +168,7 @@ struct DataRowPointStyle
|
||||
sal_Int32 m_nPointRepeat;
|
||||
OUString msStyleName;
|
||||
OUString msSeriesStyleNameForDonuts;
|
||||
OUString msCustomLabelField;
|
||||
sal_Int32 mnAttachedAxis;
|
||||
bool mbSymbolSizeForSeriesIsMissingInFile;
|
||||
|
||||
|
||||
@@ -537,6 +537,7 @@ namespace xmloff { namespace token {
|
||||
TOKEN( "custom-iconset", XML_CUSTOM_ICONSET ),
|
||||
TOKEN( "custom-iconset-index", XML_CUSTOM_ICONSET_INDEX ),
|
||||
TOKEN( "custom-iconset-name", XML_CUSTOM_ICONSET_NAME ),
|
||||
TOKEN( "custom-label-field", XML_CUSTOM_LABEL_FIELD ),
|
||||
TOKEN( "cut", XML_CUT ),
|
||||
TOKEN( "cut-offs", XML_CUT_OFFS ),
|
||||
TOKEN( "cx", XML_CX ),
|
||||
|
||||
@@ -460,6 +460,7 @@ custom5
|
||||
custom-iconset
|
||||
custom-iconset-index
|
||||
custom-iconset-name
|
||||
custom-label-field
|
||||
cut
|
||||
cut-offs
|
||||
cx
|
||||
|
||||
Reference in New Issue
Block a user