tdf#161607 Chart: import-export LeaderLines data

Implemented Importexport of some leaderLines data
(color and width of the lines) from/to OOXML.

It now supports only the solidFill color.
Used properties: "LineColor" and "LineWidth"

Change-Id: Ib33392d0404e1186328176fd93322e02b4006f3c
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/168974
Reviewed-by: Caolán McNamara <caolan.mcnamara@collabora.com>
Tested-by: Jenkins
Tested-by: Caolán McNamara <caolan.mcnamara@collabora.com>
Signed-off-by: Xisco Fauli <xiscofauli@libreoffice.org>
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/169081
Reviewed-by: Attila Szűcs <attila.szucs@collabora.com>
diff --git a/chart2/qa/extras/chart2export2.cxx b/chart2/qa/extras/chart2export2.cxx
index 7d81dbb..440c526 100644
--- a/chart2/qa/extras/chart2export2.cxx
+++ b/chart2/qa/extras/chart2export2.cxx
@@ -549,6 +549,33 @@ CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testLeaderLines)
    }
}

CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testTdf161607PieChartLeaderLinesColorWidth)
{
    // FIXME: validation error in OOXML export
    skipValidation();

    loadFromFile(u"xlsx/tdf161607PieChartLeaderLinesColorWidth.xlsx");
    save(u"Calc Office Open XML"_ustr);
    xmlDocUniquePtr pXmlDoc = parseExport(u"xl/charts/chart1.xml"_ustr);
    CPPUNIT_ASSERT(pXmlDoc);

    // test LeaderLines width
    OUString aWidth = getXPath(
        pXmlDoc,
        "/c:chartSpace/c:chart/c:plotArea/c:doughnutChart/c:ser/c:dLbls/c:leaderLines/c:spPr/"
        "a:ln"_ostr,
        "w"_ostr);
    sal_Int32 nWidth = aWidth.toInt32();
    CPPUNIT_ASSERT_LESSEQUAL(static_cast<sal_Int32>(100), std::abs(nWidth - 88900));

    // test LeaderLines Color
    assertXPath(
        pXmlDoc,
        "/c:chartSpace/c:chart/c:plotArea/c:doughnutChart/c:ser/c:dLbls/c:leaderLines/c:spPr/"
        "a:ln/a:solidFill/a:srgbClr"_ostr,
        "val"_ostr, u"7030a0"_ustr);
}

CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testNumberFormatExportPPTX)
{
    loadFromFile(u"pptx/tdf115859.pptx");
diff --git a/chart2/qa/extras/data/xlsx/tdf161607PieChartLeaderLinesColorWidth.xlsx b/chart2/qa/extras/data/xlsx/tdf161607PieChartLeaderLinesColorWidth.xlsx
new file mode 100644
index 0000000..c8c4e06
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf161607PieChartLeaderLinesColorWidth.xlsx
Binary files differ
diff --git a/chart2/source/view/charttypes/PieChart.cxx b/chart2/source/view/charttypes/PieChart.cxx
index fcb79ef..58193df 100644
--- a/chart2/source/view/charttypes/PieChart.cxx
+++ b/chart2/source/view/charttypes/PieChart.cxx
@@ -27,7 +27,8 @@
#include <ChartType.hxx>
#include <DataSeries.hxx>
#include <DataSeriesProperties.hxx>

#include "../../model/main/DataPointProperties.hxx"
#include <LinePropertiesHelper.hxx>
#include <com/sun/star/chart/DataLabelPlacement.hpp>
#include <com/sun/star/chart2/XColorScheme.hpp>

@@ -686,14 +687,21 @@ void PieChart::createTextLabelShape(
                    drawing::PointSequenceSequence aPoints{ { {nX1, nY1}, {nX2, nY2} } };

                    VLineProperties aVLineProperties;
                    if (aPieLabelInfo.xTextShape.is())
                    {
                        sal_Int32 nColor = 0;
                        aPieLabelInfo.xTextShape->SvxShape::getPropertyValue(u"CharColor"_ustr) >>= nColor;
                        //automatic font color does not work for lines -> fallback to black
                        if (nColor != -1)
                            aVLineProperties.Color <<= nColor;
                    }

                    sal_Int32 nColor = 0;
                    nColor = rSeries.getModel()
                                 ->getFastPropertyValue(
                                     DataPointProperties::PROP_DATAPOINT_BORDER_COLOR)
                                 .get<sal_Int32>();
                    if (nColor != -1)
                        aVLineProperties.Color <<= nColor;
                    sal_Int32 nWidth = 0;
                    nWidth = rSeries.getModel()
                                 ->getFastPropertyValue(LinePropertiesHelper::PROP_LINE_WIDTH)
                                 .get<sal_Int32>();
                    if (nWidth != -1)
                        aVLineProperties.Width <<= nWidth;

                    ShapeFactory::createLine2D(xTextTarget, aPoints, &aVLineProperties);
                }
            }
diff --git a/oox/source/drawingml/chart/seriesconverter.cxx b/oox/source/drawingml/chart/seriesconverter.cxx
index 4efe54f..b3c8b51 100644
--- a/oox/source/drawingml/chart/seriesconverter.cxx
+++ b/oox/source/drawingml/chart/seriesconverter.cxx
@@ -212,6 +212,28 @@ void importBorderProperties( PropertySet& rPropSet, Shape& rShape, const Graphic
    rPropSet.setProperty(PROP_LabelBorderColor, uno::Any(nColor));
}

void lcl_ImportLeaderLineProperties(PropertySet& rPropSet, Shape& rShape,
                                    const GraphicHelper& rGraphicHelper)
{
    LineProperties& rLP = rShape.getLineProperties();
    // no fill has the same effect as no line so skip it
    if (rLP.maLineFill.moFillType.has_value() && rLP.maLineFill.moFillType.value() == XML_noFill)
        return;

    if (rLP.moLineWidth.has_value())
    {
        sal_Int32 nWidth = convertEmuToHmm(rLP.moLineWidth.value());
        rPropSet.setProperty(PROP_LineWidth, uno::Any(nWidth));
    }

    if (rLP.maLineFill.moFillType.has_value() && rLP.maLineFill.moFillType.value() == XML_solidFill)
    {
        const Color& aColor = rLP.maLineFill.maFillColor;
        ::Color nColor = aColor.getColor(rGraphicHelper);
        rPropSet.setProperty(PROP_LineColor, uno::Any(nColor));
    }
}

void importFillProperties( PropertySet& rPropSet, Shape& rShape, const GraphicHelper& rGraphicHelper, ModelObjectHelper& rModelObjHelper )
{
    FillProperties& rFP = rShape.getFillProperties();
@@ -467,6 +489,13 @@ void DataLabelsConverter::convertFromModel( const Reference< XDataSeries >& rxDa
    if( !mrModel.mbShowLeaderLines )
        aPropSet.setProperty( PROP_ShowCustomLeaderLines, false );

    if (mrModel.mxLeaderLines)
    {
        // Import leaderline properties (SolidFill color, and width)
        lcl_ImportLeaderLineProperties(aPropSet, *mrModel.mxLeaderLines,
                                       getFilter().getGraphicHelper());
    }

    // data point label settings
    for (auto const& pointLabel : mrModel.maPointLabels)
    {
diff --git a/oox/source/export/chartexport.cxx b/oox/source/export/chartexport.cxx
index b1db415..c63c849 100644
--- a/oox/source/export/chartexport.cxx
+++ b/oox/source/export/chartexport.cxx
@@ -4102,6 +4102,40 @@ void ChartExport::exportDataLabels(
    xPropSet->getPropertyValue(u"ShowCustomLeaderLines"_ustr) >>= bShowLeaderLines;
    pFS->singleElement(FSNS(XML_c, XML_showLeaderLines), XML_val, ToPsz10(bShowLeaderLines));

    // LeaderLine color, and width
    util::Color aLineColor = -1;
    xPropSet->getPropertyValue(u"LineColor"_ustr) >>= aLineColor;
    // Line width
    sal_Int32 nLineWidth = -1;
    xPropSet->getPropertyValue(u"LineWidth"_ustr) >>= nLineWidth;

    if (aLineColor > 0 || nLineWidth > 0)
    {
        pFS->startElement(FSNS(XML_c, XML_leaderLines));
        pFS->startElement(FSNS(XML_c, XML_spPr));

        if (nLineWidth > 0)
            pFS->startElement(FSNS(XML_a, XML_ln), XML_w,
                              OString::number(convertHmmToEmu(nLineWidth)));
        else
            pFS->startElement(FSNS(XML_a, XML_ln));

        if (aLineColor != -1)
        {
            pFS->startElement(FSNS(XML_a, XML_solidFill));

            OString aStr = I32SHEX(aLineColor);
            pFS->singleElement(FSNS(XML_a, XML_srgbClr), XML_val, aStr);

            pFS->endElement(FSNS(XML_a, XML_solidFill));
        }

        pFS->endElement(FSNS(XML_a, XML_ln));
        pFS->endElement(FSNS(XML_c, XML_spPr));
        pFS->endElement(FSNS(XML_c, XML_leaderLines));
    }


    // Export leader line
    if( eChartType != chart::TYPEID_PIE )
    {