[Libreoffice-commits] core.git: chart2/qa chart2/source include/oox oox/source

Balazs Varga (via logerrit) logerrit at kemper.freedesktop.org
Wed Jul 24 12:05:15 UTC 2019


 chart2/qa/extras/chart2import.cxx                          |   38 +++++++++++--
 chart2/qa/extras/data/docx/testMultilevelCategoryAxis.docx |binary
 chart2/source/tools/InternalData.cxx                       |   11 +++
 include/oox/drawingml/chart/datasourcemodel.hxx            |    1 
 oox/source/drawingml/chart/chartconverter.cxx              |   29 +++++----
 oox/source/drawingml/chart/datasourcecontext.cxx           |   25 ++++++++
 oox/source/drawingml/chart/datasourcemodel.cxx             |    3 -
 oox/source/export/chartexport.cxx                          |    8 ++
 8 files changed, 94 insertions(+), 21 deletions(-)

New commits:
commit fa0a981af41a2606541eec1cb20a379a739691e0
Author:     Balazs Varga <balazs.varga991 at gmail.com>
AuthorDate: Wed Jul 17 12:57:47 2019 +0200
Commit:     László Németh <nemeth at numbertext.org>
CommitDate: Wed Jul 24 14:04:06 2019 +0200

    tdf#114166 DOCX chart import: fix missing complex categories
    
    Now complex category labels are visible, and the inner data
    table contains the correct texts of the category columns.
    
    Note: repeating call of createDataSequenceByValueArray() API function
    can create all columns of the complex categories. See also
    commit 6c4e21a234f12e1310ba06f9859e08b424acf8bf
    "bnc#812796: Correctly handle static value array for OOXML charts."
    
    Change-Id: I333b79be35a24a912bb9e662116d0c85809a8fb2
    Reviewed-on: https://gerrit.libreoffice.org/75776
    Reviewed-by: László Németh <nemeth at numbertext.org>
    Tested-by: László Németh <nemeth at numbertext.org>

diff --git a/chart2/qa/extras/chart2import.cxx b/chart2/qa/extras/chart2import.cxx
index 107daed69fea..710d15ebd60e 100644
--- a/chart2/qa/extras/chart2import.cxx
+++ b/chart2/qa/extras/chart2import.cxx
@@ -131,6 +131,7 @@ public:
     void testDataPointInheritedColorDOCX();
     void testExternalStrRefsXLSX();
     void testSourceNumberFormatComplexCategoriesXLS();
+    void testMultilevelCategoryAxis();
     void testTdf123504();
     void testTdf122765();
 
@@ -216,6 +217,7 @@ public:
     CPPUNIT_TEST(testDataPointInheritedColorDOCX);
     CPPUNIT_TEST(testExternalStrRefsXLSX);
     CPPUNIT_TEST(testSourceNumberFormatComplexCategoriesXLS);
+    CPPUNIT_TEST(testMultilevelCategoryAxis);
     CPPUNIT_TEST(testTdf123504);
     CPPUNIT_TEST(testTdf122765);
 
@@ -1534,10 +1536,10 @@ void Chart2ImportTest::testInternalDataProvider() {
     // Parse mixed types, mixed role
     xDataSeq = rxDataProvider->createDataSequenceByValueArray("categories", "{42;\"hello\";0;\"world\"}");
     xSequence = xDataSeq->getData();
-    CPPUNIT_ASSERT_EQUAL(uno::Any(OUString("42")),    xSequence[0]);
-    CPPUNIT_ASSERT_EQUAL(uno::Any(OUString("hello")), xSequence[1]);
-    CPPUNIT_ASSERT_EQUAL(uno::Any(OUString("0")),     xSequence[2]);
-    CPPUNIT_ASSERT_EQUAL(uno::Any(OUString("world")), xSequence[3]);
+    CPPUNIT_ASSERT_EQUAL(uno::Any(OUString("Row 1 42")), xSequence[0]);
+    CPPUNIT_ASSERT_EQUAL(uno::Any(OUString("Row 2 hello")), xSequence[1]);
+    CPPUNIT_ASSERT_EQUAL(uno::Any(OUString("Row 3 0")), xSequence[2]);
+    CPPUNIT_ASSERT_EQUAL(uno::Any(OUString("Row 4 world")), xSequence[3]);
 }
 
 void Chart2ImportTest::testTdf90510()
@@ -1946,6 +1948,34 @@ void Chart2ImportTest::testSourceNumberFormatComplexCategoriesXLS()
     CPPUNIT_ASSERT(nNumberFormat != 0);
 }
 
+void Chart2ImportTest::testMultilevelCategoryAxis()
+{
+    load("/chart2/qa/extras/data/docx/", "testMultilevelCategoryAxis.docx");
+    uno::Reference< chart2::XChartDocument > xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY);
+    CPPUNIT_ASSERT(xChartDoc.is());
+
+    // Test the internal data.
+    CPPUNIT_ASSERT(xChartDoc->hasInternalDataProvider());
+
+    Reference<chart2::XInternalDataProvider> xInternalProvider(xChartDoc->getDataProvider(), uno::UNO_QUERY);
+    CPPUNIT_ASSERT(xInternalProvider.is());
+
+    Reference<chart::XComplexDescriptionAccess> xDescAccess(xInternalProvider, uno::UNO_QUERY);
+    CPPUNIT_ASSERT(xDescAccess.is());
+
+    // Get the complex category labels.
+    Sequence<Sequence<OUString> > aCategories = xDescAccess->getComplexRowDescriptions();
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(4), aCategories.getLength());
+    CPPUNIT_ASSERT_EQUAL(OUString("2011"), aCategories[0][0]);
+    CPPUNIT_ASSERT_EQUAL(OUString(""), aCategories[1][0]);
+    CPPUNIT_ASSERT_EQUAL(OUString("2012"), aCategories[2][0]);
+    CPPUNIT_ASSERT_EQUAL(OUString(""), aCategories[3][0]);
+    CPPUNIT_ASSERT_EQUAL(OUString("Categoria 1"), aCategories[0][1]);
+    CPPUNIT_ASSERT_EQUAL(OUString("Categoria 2"), aCategories[1][1]);
+    CPPUNIT_ASSERT_EQUAL(OUString("Categoria 3"), aCategories[2][1]);
+    CPPUNIT_ASSERT_EQUAL(OUString("Categoria 4"), aCategories[3][1]);
+}
+
 void Chart2ImportTest::testTdf123504()
 {
     load("/chart2/qa/extras/data/ods/", "pie_chart_100_and_0.ods");
diff --git a/chart2/qa/extras/data/docx/testMultilevelCategoryAxis.docx b/chart2/qa/extras/data/docx/testMultilevelCategoryAxis.docx
new file mode 100644
index 000000000000..75605de72fc5
Binary files /dev/null and b/chart2/qa/extras/data/docx/testMultilevelCategoryAxis.docx differ
diff --git a/chart2/source/tools/InternalData.cxx b/chart2/source/tools/InternalData.cxx
index b99578fab118..b7a5118004ba 100644
--- a/chart2/source/tools/InternalData.cxx
+++ b/chart2/source/tools/InternalData.cxx
@@ -220,7 +220,16 @@ void InternalData::setComplexRowLabel( sal_Int32 nRowIndex, const vector< uno::A
         m_aRowLabels.resize(nRowIndex+1);
         enlargeData( 0, nRowIndex+1 );
     }
-    m_aRowLabels[nRowIndex] = rComplexLabel;
+    sal_Int32 nSize = static_cast<sal_Int32>( m_aRowLabels[nRowIndex].size() );
+    if( nSize >= 1 )
+    {
+        m_aRowLabels[nRowIndex].resize(nSize+1);
+        m_aRowLabels[nRowIndex][nSize] = rComplexLabel[0];
+    }
+    else
+    {
+        m_aRowLabels[nRowIndex] = rComplexLabel;
+    }
 }
 
 vector< uno::Any > InternalData::getComplexColumnLabel( sal_Int32 nColumnIndex ) const
diff --git a/include/oox/drawingml/chart/datasourcemodel.hxx b/include/oox/drawingml/chart/datasourcemodel.hxx
index 097bfd188720..e2d9336bf4b2 100644
--- a/include/oox/drawingml/chart/datasourcemodel.hxx
+++ b/include/oox/drawingml/chart/datasourcemodel.hxx
@@ -40,6 +40,7 @@ struct DataSequenceModel
     OUString     maFormula;          /// Formula reference, e.g. into a spreadsheet.
     OUString     maFormatCode;       /// Number format for double values.
     sal_Int32           mnPointCount;       /// Number of points in this series source.
+    sal_Int32           mnLevelCount;       /// Number of category levels.
 
     explicit            DataSequenceModel();
                         ~DataSequenceModel();
diff --git a/oox/source/drawingml/chart/chartconverter.cxx b/oox/source/drawingml/chart/chartconverter.cxx
index f86ea8adb760..538f9956abc7 100644
--- a/oox/source/drawingml/chart/chartconverter.cxx
+++ b/oox/source/drawingml/chart/chartconverter.cxx
@@ -56,12 +56,12 @@ static OUString lclGenerateApiString( const OUString& rString )
     return "\"" + aRetString + "\"";
 }
 
-static OUString lclGenerateApiArray(const std::vector<Any>& rRow)
+static OUString lclGenerateApiArray(const std::vector<Any>& rRow, sal_Int32 nStart, sal_Int32 nCount)
 {
     OSL_ENSURE( !rRow.empty(), "ChartConverter::lclGenerateApiArray - missing matrix values" );
     OUStringBuffer aBuffer;
     aBuffer.append( API_TOKEN_ARRAY_OPEN );
-    for (auto aBeg = rRow.begin(), aIt = aBeg, aEnd = rRow.end(); aIt != aEnd; ++aIt)
+    for (auto aBeg = rRow.begin() + nStart, aIt = aBeg, aEnd = aBeg + nCount; aIt != aEnd; ++aIt)
     {
         double fValue = 0.0;
         OUString aString;
@@ -124,21 +124,26 @@ Reference< XDataSequence > ChartConverter::createDataSequence(
     if( rxDataProvider.is() )
     {
         OUString aRangeRep;
-        if( !rDataSeq.maData.empty() )
+        if( !rDataSeq.maData.empty() ) try
         {
             // create a single-row array from constant source data
-            std::vector<Any> aRow(rDataSeq.mnPointCount);
+            // (multiple levels in the case of complex categories)
+            std::vector<Any> aRow(rDataSeq.mnLevelCount * rDataSeq.mnPointCount);
             for (auto const& elem : rDataSeq.maData)
                 aRow.at(elem.first) = elem.second;
 
-            aRangeRep = lclGenerateApiArray(aRow);
-        }
-
-        if( !aRangeRep.isEmpty() ) try
-        {
-            // create the data sequence
-            xDataSeq = rxDataProvider->createDataSequenceByValueArray(rRole, aRangeRep);
-            return xDataSeq;
+            for (sal_Int32 i = rDataSeq.mnLevelCount-1; i >= 0; i--)
+            {
+                aRangeRep = lclGenerateApiArray( aRow, i * rDataSeq.mnPointCount, rDataSeq.mnPointCount);
+
+                if (!aRangeRep.isEmpty())
+                {
+                    // create or add a new level to the data sequence
+                    xDataSeq = rxDataProvider->createDataSequenceByValueArray(rRole, aRangeRep);
+                    if (i == 0)
+                        return xDataSeq;
+                }
+            }
         }
         catch( Exception& )
         {
diff --git a/oox/source/drawingml/chart/datasourcecontext.cxx b/oox/source/drawingml/chart/datasourcecontext.cxx
index e50723b378d0..7fa7b12852a7 100644
--- a/oox/source/drawingml/chart/datasourcecontext.cxx
+++ b/oox/source/drawingml/chart/datasourcecontext.cxx
@@ -180,6 +180,7 @@ ContextHandlerRef StringSequenceContext::onCreateContext( sal_Int32 nElement, co
             switch( nElement )
             {
                 case C_TOKEN( f ):
+                case C_TOKEN( multiLvlStrCache ):
                     return this;
             }
         break;
@@ -206,6 +207,28 @@ ContextHandlerRef StringSequenceContext::onCreateContext( sal_Int32 nElement, co
             }
         break;
 
+        case C_TOKEN( multiLvlStrCache ):
+            switch (nElement)
+            {
+                case C_TOKEN( ptCount ):
+                    mrModel.mnPointCount = rAttribs.getInteger(XML_val, -1);
+                    mrModel.mnLevelCount--; // normalize level count
+                    return nullptr;
+                case C_TOKEN( lvl ):
+                    mrModel.mnLevelCount++;
+                    return this;
+            }
+            break;
+
+        case C_TOKEN( lvl ):
+            switch (nElement)
+            {
+                case C_TOKEN(pt):
+                    mnPtIndex = rAttribs.getInteger(XML_idx, -1);
+                    return this;
+            }
+            break;
+
         case C_TOKEN( pt ):
             switch( nElement )
             {
@@ -226,7 +249,7 @@ void StringSequenceContext::onCharacters( const OUString& rChars )
         break;
         case C_TOKEN( v ):
             if( mnPtIndex >= 0 )
-                mrModel.maData[ mnPtIndex ] <<= rChars;
+                mrModel.maData[ (mrModel.mnLevelCount-1) * mrModel.mnPointCount + mnPtIndex ] <<= rChars;
         break;
     }
 }
diff --git a/oox/source/drawingml/chart/datasourcemodel.cxx b/oox/source/drawingml/chart/datasourcemodel.cxx
index c5c054e67a99..ecb9afe4f2cb 100644
--- a/oox/source/drawingml/chart/datasourcemodel.cxx
+++ b/oox/source/drawingml/chart/datasourcemodel.cxx
@@ -24,7 +24,8 @@ namespace drawingml {
 namespace chart {
 
 DataSequenceModel::DataSequenceModel() :
-    mnPointCount( -1 )
+    mnPointCount( -1 ),
+    mnLevelCount( 1 )
 {
 }
 
diff --git a/oox/source/export/chartexport.cxx b/oox/source/export/chartexport.cxx
index dd9d19651e29..ec19bc4042ad 100644
--- a/oox/source/export/chartexport.cxx
+++ b/oox/source/export/chartexport.cxx
@@ -515,8 +515,12 @@ Sequence< Sequence< OUString > > ChartExport::getSplitCategoriesList( const OUSt
                             aFinalSplitSource[nLevelCount - i - 1].realloc(aAnyCategories.getLength());
                             for (auto const& elemLabel : aAnyCategories)
                             {
-                                aFinalSplitSource[nLevelCount - i - 1][nElemLabel] = elemLabel[i].get<OUString>();
-                                nElemLabel++;
+                                // make sure elemLabel[i] exists!
+                                if (elemLabel.getLength() > i)
+                                {
+                                    aFinalSplitSource[nLevelCount - i - 1][nElemLabel] = elemLabel[i].get<OUString>();
+                                    nElemLabel++;
+                                }
                             }
                         }
                         return aFinalSplitSource;


More information about the Libreoffice-commits mailing list