tdf#165742 Step 5.9d: Support for <cx:geography> tag

Add support for import, storage, and export of <cx:geography> and its
children. This tag is used to express geography for regionMap charts. Also
includes one simple round-trip test.

Change-Id: Iccaef8b8cd2848ae3e48532c72507469c55ebefc
Reviewed-on: https://gerrit.collaboraoffice.com/c/core/+/719
Tested-by: Jenkins CPCI <releng@collaboraoffice.com>
Reviewed-by: Tomaž Vajngerl <tomaz.vajngerl@collabora.com>
(cherry picked from commit d5bfa4677609d5618a82d4aa3e182bba00054a01)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/204150
Tested-by: Jenkins
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
This commit is contained in:
Kurt Nordback
2026-04-23 15:47:47 +02:00
committed by Xisco Fauli
parent 922bfef520
commit cf04cdbcfa
17 changed files with 1917 additions and 3 deletions
+27
View File
@@ -1899,6 +1899,33 @@ CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testTdf166249)
"val", u"128");
}
CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testChartexGeography)
{
loadFromFile(u"xlsx/regionMap.xlsx");
save(TestFilter::XLSX);
xmlDocUniquePtr pXmlDoc = parseExport(u"xl/charts/chartEx1.xml"_ustr);
CPPUNIT_ASSERT(pXmlDoc);
static constexpr OString sSeriesBase
= "/cx:chartSpace/cx:chart/cx:plotArea/cx:plotAreaRegion/cx:series"_ostr;
OString sLayoutPr = sSeriesBase + "/cx:layoutPr"_ostr;
OString sGeo = sLayoutPr + "/cx:geography"_ostr;
// geography element with correct attributes
assertXPath(pXmlDoc, sGeo, "cultureLanguage", u"en-US");
assertXPath(pXmlDoc, sGeo, "cultureRegion", u"GB");
// geoCache with provider
OString sCache = sGeo + "/cx:geoCache"_ostr;
assertXPath(pXmlDoc, sCache, "provider", u"{E9337A44-BEBE-4D9F-B70C-5C5E7DAFC167}");
// binary element exists and starts with the expected base64 prefix
OString sBinary = sCache + "/cx:binary"_ostr;
assertXPath(pXmlDoc, sBinary, 1);
OUString sBinaryContent = getXPathContent(pXmlDoc, sBinary);
CPPUNIT_ASSERT(sBinaryContent.startsWith(u"7HvJkt24kuWvpOWm"));
}
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
@@ -47,6 +47,15 @@ namespace chart::DataSeriesProperties
PROP_DATASERIES_REGION_LABEL_LAYOUT,
PROP_DATASERIES_QUARTILE_METHOD,
PROP_DATASERIES_SUBTOTAL_INDICES,
PROP_DATASERIES_HAS_GEOGRAPHY,
PROP_DATASERIES_GEOGRAPHY_PROJECTION_TYPE,
PROP_DATASERIES_GEOGRAPHY_VIEWED_REGION_TYPE,
PROP_DATASERIES_GEOGRAPHY_CULTURE_LANGUAGE,
PROP_DATASERIES_GEOGRAPHY_CULTURE_REGION,
PROP_DATASERIES_GEOGRAPHY_ATTRIBUTION,
PROP_DATASERIES_GEOCACHE_PROVIDER,
PROP_DATASERIES_GEOCACHE_BINARY,
PROP_DATASERIES_GEOCACHE_CLEAR_DATA,
};
void AddPropertiesToVector(
@@ -20,6 +20,7 @@
#include <DataSeriesProperties.hxx>
#include "DataPointProperties.hxx"
#include <com/sun/star/beans/PropertyAttribute.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/chart2/StackingDirection.hpp>
using namespace ::com::sun::star;
@@ -141,6 +142,60 @@ void DataSeriesProperties::AddPropertiesToVector(
beans::PropertyAttribute::BOUND
| beans::PropertyAttribute::MAYBEVOID );
rOutProperties.emplace_back( "HasGeography",
PROP_DATASERIES_HAS_GEOGRAPHY,
cppu::UnoType<sal_Bool>::get(),
beans::PropertyAttribute::BOUND
| beans::PropertyAttribute::MAYBEVOID );
rOutProperties.emplace_back( "GeographyProjectionType",
PROP_DATASERIES_GEOGRAPHY_PROJECTION_TYPE,
cppu::UnoType<OUString>::get(),
beans::PropertyAttribute::BOUND
| beans::PropertyAttribute::MAYBEVOID );
rOutProperties.emplace_back( "GeographyViewedRegionType",
PROP_DATASERIES_GEOGRAPHY_VIEWED_REGION_TYPE,
cppu::UnoType<OUString>::get(),
beans::PropertyAttribute::BOUND
| beans::PropertyAttribute::MAYBEVOID );
rOutProperties.emplace_back( "GeographyCultureLanguage",
PROP_DATASERIES_GEOGRAPHY_CULTURE_LANGUAGE,
cppu::UnoType<OUString>::get(),
beans::PropertyAttribute::BOUND
| beans::PropertyAttribute::MAYBEVOID );
rOutProperties.emplace_back( "GeographyCultureRegion",
PROP_DATASERIES_GEOGRAPHY_CULTURE_REGION,
cppu::UnoType<OUString>::get(),
beans::PropertyAttribute::BOUND
| beans::PropertyAttribute::MAYBEVOID );
rOutProperties.emplace_back( "GeographyAttribution",
PROP_DATASERIES_GEOGRAPHY_ATTRIBUTION,
cppu::UnoType<OUString>::get(),
beans::PropertyAttribute::BOUND
| beans::PropertyAttribute::MAYBEVOID );
rOutProperties.emplace_back( "GeoCacheProvider",
PROP_DATASERIES_GEOCACHE_PROVIDER,
cppu::UnoType<OUString>::get(),
beans::PropertyAttribute::BOUND
| beans::PropertyAttribute::MAYBEVOID );
rOutProperties.emplace_back( "GeoCacheBinary",
PROP_DATASERIES_GEOCACHE_BINARY,
cppu::UnoType<OUString>::get(),
beans::PropertyAttribute::BOUND
| beans::PropertyAttribute::MAYBEVOID );
rOutProperties.emplace_back( "GeoCacheClearData",
PROP_DATASERIES_GEOCACHE_CLEAR_DATA,
cppu::UnoType<uno::Sequence<beans::PropertyValue>>::get(),
beans::PropertyAttribute::BOUND
| beans::PropertyAttribute::MAYBEVOID );
// add properties of service DataPointProperties
DataPointProperties::AddPropertiesToVector( rOutProperties );
}
@@ -0,0 +1,23 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/uno/Reference.hxx>
#include <sax/fshelper.hxx>
namespace oox::drawingml::chart
{
void exportGeography(const css::uno::Reference<css::beans::XPropertySet>& xSeriesProp,
const sax_fastparser::FSHelperPtr& pFS);
} // namespace oox::drawingml::chart
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
+3
View File
@@ -92,6 +92,7 @@ $(eval $(call gb_Library_set_componentfile,oox,oox/util/oox,services))
ifeq (,$(ENABLE_WASM_STRIP_CHART))
$(eval $(call gb_Library_add_exception_objects,oox,\
oox/source/export/chartexport \
oox/source/export/chartgeographyexport \
oox/source/drawingml/chart/axiscontext \
oox/source/drawingml/chart/axisconverter \
oox/source/drawingml/chart/axismodel \
@@ -106,6 +107,8 @@ $(eval $(call gb_Library_add_exception_objects,oox,\
oox/source/drawingml/chart/datasourceconverter \
oox/source/drawingml/chart/datasourcemodel \
oox/source/drawingml/chart/datatablecontext \
oox/source/drawingml/chart/geographycontext \
oox/source/drawingml/chart/geographyconverter \
oox/source/drawingml/chart/datatableconverter \
oox/source/drawingml/chart/modelbase \
oox/source/drawingml/chart/objectformatter \
@@ -0,0 +1,43 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <oox/core/contexthandler2.hxx>
namespace oox::drawingml::chart
{
struct GeographyModel;
struct GeoLocationQueryResultModel;
struct GeoDataEntityQueryResultModel;
struct GeoDataPointToEntityQueryResultModel;
struct GeoChildEntitiesQueryResultModel;
struct GeoParentEntitiesQueryResultModel;
class GeographyContext final : public ::oox::core::ContextHandler2
{
public:
explicit GeographyContext(::oox::core::ContextHandler2Helper& rParent, GeographyModel& rModel);
virtual ::oox::core::ContextHandlerRef onCreateContext(sal_Int32 nElement,
const AttributeList& rAttribs) override;
virtual void onCharacters(const OUString& rChars) override;
private:
GeographyModel& mrModel;
GeoLocationQueryResultModel* mpCurLocResult = nullptr;
GeoDataEntityQueryResultModel* mpCurDataResult = nullptr;
GeoDataPointToEntityQueryResultModel* mpCurPtResult = nullptr;
GeoChildEntitiesQueryResultModel* mpCurChildResult = nullptr;
GeoParentEntitiesQueryResultModel* mpCurParentResult = nullptr;
};
} // namespace oox::drawingml::chart
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
@@ -0,0 +1,34 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/uno/Sequence.hxx>
namespace oox
{
class PropertySet;
}
namespace oox::drawingml::chart
{
struct GeographyModel;
struct GeoClearModel;
void convertGeography(const GeographyModel& rModel, PropertySet& rSeriesProp);
css::uno::Sequence<css::beans::PropertyValue> geoClearToPropertyValues(const GeoClearModel& rModel);
GeoClearModel
geoClearFromPropertyValues(const css::uno::Sequence<css::beans::PropertyValue>& rProps);
} // namespace oox::drawingml::chart
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
+178
View File
@@ -0,0 +1,178 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <optional>
#include <vector>
#include <rtl/ustring.hxx>
namespace oox::drawingml::chart
{
struct GeoAddressModel
{
std::optional<OUString> mosAddress1;
std::optional<OUString> mosCountryRegion;
std::optional<OUString> mosAdminDistrict1;
std::optional<OUString> mosAdminDistrict2;
std::optional<OUString> mosPostalCode;
std::optional<OUString> mosLocality;
std::optional<OUString> mosIsoCountryCode;
};
struct GeoLocationQueryModel
{
std::optional<OUString> mosCountryRegion;
std::optional<OUString> mosAdminDistrict1;
std::optional<OUString> mosAdminDistrict2;
std::optional<OUString> mosPostalCode;
std::optional<OUString> mosEntityType;
};
struct GeoLocationModel
{
std::optional<OUString> mosLatitude;
std::optional<OUString> mosLongitude;
std::optional<OUString> mosEntityName;
std::optional<OUString> mosEntityType;
std::optional<GeoAddressModel> mxAddress;
};
struct GeoLocationQueryResultModel
{
std::optional<GeoLocationQueryModel> mxQuery;
std::vector<GeoLocationModel> maLocations;
};
struct GeoDataEntityQueryModel
{
std::optional<OUString> mosEntityType;
std::optional<OUString> mosEntityId;
};
struct GeoPolygonModel
{
std::optional<OUString> mosPolygonId;
std::optional<OUString> mosNumPoints;
std::optional<OUString> mosPcaRings;
};
struct GeoCopyrightModel
{
OUString msText;
};
struct GeoDataModel
{
std::optional<OUString> mosEntityName;
std::optional<OUString> mosEntityId;
std::optional<OUString> mosEast;
std::optional<OUString> mosWest;
std::optional<OUString> mosNorth;
std::optional<OUString> mosSouth;
std::vector<GeoPolygonModel> maPolygons;
std::vector<GeoCopyrightModel> maCopyrights;
};
struct GeoDataEntityQueryResultModel
{
std::optional<GeoDataEntityQueryModel> mxQuery;
std::optional<GeoDataModel> mxData;
};
struct GeoDataPointQueryModel
{
std::optional<OUString> mosEntityType;
std::optional<OUString> mosLatitude;
std::optional<OUString> mosLongitude;
};
struct GeoDataPointToEntityQueryModel
{
std::optional<OUString> mosEntityType;
std::optional<OUString> mosEntityId;
};
struct GeoDataPointToEntityQueryResultModel
{
std::optional<GeoDataPointQueryModel> mxPointQuery;
std::optional<GeoDataPointToEntityQueryModel> mxEntityQuery;
};
struct GeoChildEntitiesQueryModel
{
std::optional<OUString> mosEntityId;
std::vector<OUString> maEntityTypes;
};
struct GeoHierarchyEntityModel
{
std::optional<OUString> mosEntityName;
std::optional<OUString> mosEntityId;
std::optional<OUString> mosEntityType;
};
struct GeoChildEntitiesQueryResultModel
{
std::optional<GeoChildEntitiesQueryModel> mxQuery;
std::vector<GeoHierarchyEntityModel> maEntities;
};
struct GeoParentEntitiesQueryModel
{
std::optional<OUString> mosEntityId;
};
struct GeoEntityModel
{
std::optional<OUString> mosEntityName;
std::optional<OUString> mosEntityType;
};
struct GeoParentEntityModel
{
std::optional<OUString> mosEntityId;
};
struct GeoParentEntitiesQueryResultModel
{
std::optional<GeoParentEntitiesQueryModel> mxQuery;
std::optional<GeoEntityModel> mxEntity;
std::optional<GeoParentEntityModel> mxParentEntity;
};
struct GeoClearModel
{
std::vector<GeoLocationQueryResultModel> maLocResults;
std::vector<GeoDataEntityQueryResultModel> maDataResults;
std::vector<GeoDataPointToEntityQueryResultModel> maPtResults;
std::vector<GeoChildEntitiesQueryResultModel> maChildResults;
std::vector<GeoParentEntitiesQueryResultModel> maParentResults;
};
struct GeoCacheModel
{
std::optional<OUString> mosProvider;
std::optional<OUString> mosBinary;
std::optional<GeoClearModel> mxClear;
};
struct GeographyModel
{
std::optional<OUString> mosProjectionType;
std::optional<OUString> mosViewedRegionType;
std::optional<OUString> mosCultureLanguage;
std::optional<OUString> mosCultureRegion;
std::optional<OUString> mosAttribution;
std::optional<GeoCacheModel> mxGeoCache;
};
} // namespace oox::drawingml::chart
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
+2
View File
@@ -24,6 +24,7 @@
#include <oox/drawingml/chart/datasourcemodel.hxx>
#include <drawingml/chart/titlemodel.hxx>
#include <drawingml/chart/geographymodel.hxx>
namespace oox::drawingml::chart {
@@ -209,6 +210,7 @@ struct LayoutPropsModel
std::optional<OUString> mosQuartileMethod;
std::vector<sal_Int32> maSubtotalIndices;
std::optional<GeographyModel> mxGeography;
};
enum class DataSourceType: sal_Int32
@@ -0,0 +1,323 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <drawingml/chart/geographycontext.hxx>
#include <drawingml/chart/geographymodel.hxx>
#include <oox/helper/attributelist.hxx>
#include <oox/token/namespaces.hxx>
#include <oox/token/tokens.hxx>
namespace oox::drawingml::chart
{
using ::oox::core::ContextHandlerRef;
GeographyContext::GeographyContext(::oox::core::ContextHandler2Helper& rParent,
GeographyModel& rModel)
: ContextHandler2(rParent)
, mrModel(rModel)
{
}
// Handle the CT_Geography complex type in the chartex schema
ContextHandlerRef GeographyContext::onCreateContext(sal_Int32 nElement,
const AttributeList& rAttribs)
{
switch (getCurrentElement())
{
case CX_TOKEN(geography):
switch (nElement)
{
case CX_TOKEN(geoCache):
mrModel.mxGeoCache.emplace();
mrModel.mxGeoCache->mosProvider = rAttribs.getString(XML_provider);
return this;
}
break;
case CX_TOKEN(geoCache):
switch (nElement)
{
case CX_TOKEN(binary):
return this;
case CX_TOKEN(clear):
mrModel.mxGeoCache->mxClear.emplace();
return this;
}
break;
case CX_TOKEN(clear):
switch (nElement)
{
case CX_TOKEN(geoLocationQueryResults):
case CX_TOKEN(geoDataEntityQueryResults):
case CX_TOKEN(geoDataPointToEntityQueryResults):
case CX_TOKEN(geoChildEntitiesQueryResults):
case CX_TOKEN(geoParentEntitiesQueryResults):
return this;
}
break;
case CX_TOKEN(geoLocationQueryResults):
if (nElement == CX_TOKEN(geoLocationQueryResult))
{
auto& rClear = *mrModel.mxGeoCache->mxClear;
rClear.maLocResults.emplace_back();
mpCurLocResult = &rClear.maLocResults.back();
return this;
}
break;
case CX_TOKEN(geoLocationQueryResult):
switch (nElement)
{
case CX_TOKEN(geoLocationQuery):
{
mpCurLocResult->mxQuery.emplace();
auto& q = *mpCurLocResult->mxQuery;
q.mosCountryRegion = rAttribs.getString(XML_countryRegion);
q.mosAdminDistrict1 = rAttribs.getString(XML_adminDistrict1);
q.mosAdminDistrict2 = rAttribs.getString(XML_adminDistrict2);
q.mosPostalCode = rAttribs.getString(XML_postalCode);
q.mosEntityType = rAttribs.getString(XML_entityType);
return nullptr;
}
case CX_TOKEN(geoLocations):
return this;
}
break;
case CX_TOKEN(geoLocations):
if (nElement == CX_TOKEN(geoLocation))
{
mpCurLocResult->maLocations.emplace_back();
auto& loc = mpCurLocResult->maLocations.back();
loc.mosLatitude = rAttribs.getString(XML_latitude);
loc.mosLongitude = rAttribs.getString(XML_longitude);
loc.mosEntityName = rAttribs.getString(XML_entityName);
loc.mosEntityType = rAttribs.getString(XML_entityType);
return this;
}
break;
case CX_TOKEN(geoLocation):
if (nElement == CX_TOKEN(address))
{
auto& loc = mpCurLocResult->maLocations.back();
loc.mxAddress.emplace();
auto& a = *loc.mxAddress;
a.mosAddress1 = rAttribs.getString(XML_address1);
a.mosCountryRegion = rAttribs.getString(XML_countryRegion);
a.mosAdminDistrict1 = rAttribs.getString(XML_adminDistrict1);
a.mosAdminDistrict2 = rAttribs.getString(XML_adminDistrict2);
a.mosPostalCode = rAttribs.getString(XML_postalCode);
a.mosLocality = rAttribs.getString(XML_locality);
a.mosIsoCountryCode = rAttribs.getString(XML_isoCountryCode);
return nullptr;
}
break;
case CX_TOKEN(geoDataEntityQueryResults):
if (nElement == CX_TOKEN(geoDataEntityQueryResult))
{
auto& rClear = *mrModel.mxGeoCache->mxClear;
rClear.maDataResults.emplace_back();
mpCurDataResult = &rClear.maDataResults.back();
return this;
}
break;
case CX_TOKEN(geoDataEntityQueryResult):
switch (nElement)
{
case CX_TOKEN(geoDataEntityQuery):
{
mpCurDataResult->mxQuery.emplace();
auto& q = *mpCurDataResult->mxQuery;
q.mosEntityType = rAttribs.getString(XML_entityType);
q.mosEntityId = rAttribs.getString(XML_entityId);
return nullptr;
}
case CX_TOKEN(geoData):
{
mpCurDataResult->mxData.emplace();
auto& d = *mpCurDataResult->mxData;
d.mosEntityName = rAttribs.getString(XML_entityName);
d.mosEntityId = rAttribs.getString(XML_entityId);
d.mosEast = rAttribs.getString(XML_east);
d.mosWest = rAttribs.getString(XML_west);
d.mosNorth = rAttribs.getString(XML_north);
d.mosSouth = rAttribs.getString(XML_south);
return this;
}
}
break;
case CX_TOKEN(geoData):
switch (nElement)
{
case CX_TOKEN(geoPolygons):
return this;
case CX_TOKEN(copyrights):
return this;
}
break;
case CX_TOKEN(geoPolygons):
if (nElement == CX_TOKEN(geoPolygon))
{
auto& d = *mpCurDataResult->mxData;
d.maPolygons.emplace_back();
auto& p = d.maPolygons.back();
p.mosPolygonId = rAttribs.getString(XML_polygonId);
p.mosNumPoints = rAttribs.getString(XML_numPoints);
p.mosPcaRings = rAttribs.getString(XML_pcaRings);
return nullptr;
}
break;
case CX_TOKEN(copyrights):
if (nElement == CX_TOKEN(copyright))
return this;
break;
case CX_TOKEN(geoDataPointToEntityQueryResults):
if (nElement == CX_TOKEN(geoDataPointToEntityQueryResult))
{
auto& rClear = *mrModel.mxGeoCache->mxClear;
rClear.maPtResults.emplace_back();
mpCurPtResult = &rClear.maPtResults.back();
return this;
}
break;
case CX_TOKEN(geoDataPointToEntityQueryResult):
switch (nElement)
{
case CX_TOKEN(geoDataPointQuery):
{
mpCurPtResult->mxPointQuery.emplace();
auto& q = *mpCurPtResult->mxPointQuery;
q.mosEntityType = rAttribs.getString(XML_entityType);
q.mosLatitude = rAttribs.getString(XML_latitude);
q.mosLongitude = rAttribs.getString(XML_longitude);
return nullptr;
}
case CX_TOKEN(geoDataPointToEntityQuery):
{
mpCurPtResult->mxEntityQuery.emplace();
auto& q = *mpCurPtResult->mxEntityQuery;
q.mosEntityType = rAttribs.getString(XML_entityType);
q.mosEntityId = rAttribs.getString(XML_entityId);
return nullptr;
}
}
break;
case CX_TOKEN(geoChildEntitiesQueryResults):
if (nElement == CX_TOKEN(geoChildEntitiesQueryResult))
{
auto& rClear = *mrModel.mxGeoCache->mxClear;
rClear.maChildResults.emplace_back();
mpCurChildResult = &rClear.maChildResults.back();
return this;
}
break;
case CX_TOKEN(geoChildEntitiesQueryResult):
switch (nElement)
{
case CX_TOKEN(geoChildEntitiesQuery):
{
mpCurChildResult->mxQuery.emplace();
mpCurChildResult->mxQuery->mosEntityId = rAttribs.getString(XML_entityId);
return this;
}
case CX_TOKEN(geoChildEntities):
return this;
}
break;
case CX_TOKEN(geoChildEntitiesQuery):
if (nElement == CX_TOKEN(geoChildTypes))
return this;
break;
case CX_TOKEN(geoChildTypes):
if (nElement == CX_TOKEN(entityType))
return this;
break;
case CX_TOKEN(geoChildEntities):
if (nElement == CX_TOKEN(geoHierarchyEntity))
{
mpCurChildResult->maEntities.emplace_back();
auto& e = mpCurChildResult->maEntities.back();
e.mosEntityName = rAttribs.getString(XML_entityName);
e.mosEntityId = rAttribs.getString(XML_entityId);
e.mosEntityType = rAttribs.getString(XML_entityType);
return nullptr;
}
break;
case CX_TOKEN(geoParentEntitiesQueryResults):
if (nElement == CX_TOKEN(geoParentEntitiesQueryResult))
{
auto& rClear = *mrModel.mxGeoCache->mxClear;
rClear.maParentResults.emplace_back();
mpCurParentResult = &rClear.maParentResults.back();
return this;
}
break;
case CX_TOKEN(geoParentEntitiesQueryResult):
switch (nElement)
{
case CX_TOKEN(geoParentEntitiesQuery):
mpCurParentResult->mxQuery.emplace();
mpCurParentResult->mxQuery->mosEntityId = rAttribs.getString(XML_entityId);
return nullptr;
case CX_TOKEN(geoEntity):
mpCurParentResult->mxEntity.emplace();
mpCurParentResult->mxEntity->mosEntityName = rAttribs.getString(XML_entityName);
mpCurParentResult->mxEntity->mosEntityType = rAttribs.getString(XML_entityType);
return nullptr;
case CX_TOKEN(geoParentEntity):
mpCurParentResult->mxParentEntity.emplace();
mpCurParentResult->mxParentEntity->mosEntityId
= rAttribs.getString(XML_entityId);
return nullptr;
}
break;
}
return nullptr;
}
// Handle character data
void GeographyContext::onCharacters(const OUString& rChars)
{
switch (getCurrentElement())
{
case CX_TOKEN(binary):
if (mrModel.mxGeoCache.has_value())
mrModel.mxGeoCache->mosBinary = rChars;
break;
case CX_TOKEN(copyright):
if (mpCurDataResult && mpCurDataResult->mxData.has_value())
mpCurDataResult->mxData->maCopyrights.push_back({ rChars });
break;
case CX_TOKEN(entityType):
if (mpCurChildResult && mpCurChildResult->mxQuery.has_value())
mpCurChildResult->mxQuery->maEntityTypes.push_back(rChars);
break;
}
}
} // namespace oox::drawingml::chart
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
@@ -0,0 +1,790 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <drawingml/chart/geographyconverter.hxx>
#include <drawingml/chart/geographymodel.hxx>
#include <oox/helper/propertyset.hxx>
#include <oox/token/properties.hxx>
#include <comphelper/sequence.hxx>
using namespace ::com::sun::star;
namespace oox::drawingml::chart
{
namespace
{
uno::Sequence<beans::PropertyValue> addressToProps(const GeoAddressModel& rAddr)
{
std::vector<beans::PropertyValue> aVec;
if (rAddr.mosAddress1.has_value())
aVec.push_back({ u"address1"_ustr, 0, uno::Any(*rAddr.mosAddress1),
beans::PropertyState_DIRECT_VALUE });
if (rAddr.mosCountryRegion.has_value())
aVec.push_back({ u"countryRegion"_ustr, 0, uno::Any(*rAddr.mosCountryRegion),
beans::PropertyState_DIRECT_VALUE });
if (rAddr.mosAdminDistrict1.has_value())
aVec.push_back({ u"adminDistrict1"_ustr, 0, uno::Any(*rAddr.mosAdminDistrict1),
beans::PropertyState_DIRECT_VALUE });
if (rAddr.mosAdminDistrict2.has_value())
aVec.push_back({ u"adminDistrict2"_ustr, 0, uno::Any(*rAddr.mosAdminDistrict2),
beans::PropertyState_DIRECT_VALUE });
if (rAddr.mosPostalCode.has_value())
aVec.push_back({ u"postalCode"_ustr, 0, uno::Any(*rAddr.mosPostalCode),
beans::PropertyState_DIRECT_VALUE });
if (rAddr.mosLocality.has_value())
aVec.push_back({ u"locality"_ustr, 0, uno::Any(*rAddr.mosLocality),
beans::PropertyState_DIRECT_VALUE });
if (rAddr.mosIsoCountryCode.has_value())
aVec.push_back({ u"isoCountryCode"_ustr, 0, uno::Any(*rAddr.mosIsoCountryCode),
beans::PropertyState_DIRECT_VALUE });
return comphelper::containerToSequence(aVec);
}
GeoAddressModel addressFromProps(const uno::Sequence<beans::PropertyValue>& rProps)
{
GeoAddressModel aAddr;
for (const auto& rProp : rProps)
{
OUString sVal;
if (!(rProp.Value >>= sVal))
continue;
if (rProp.Name == "address1")
aAddr.mosAddress1 = sVal;
else if (rProp.Name == "countryRegion")
aAddr.mosCountryRegion = sVal;
else if (rProp.Name == "adminDistrict1")
aAddr.mosAdminDistrict1 = sVal;
else if (rProp.Name == "adminDistrict2")
aAddr.mosAdminDistrict2 = sVal;
else if (rProp.Name == "postalCode")
aAddr.mosPostalCode = sVal;
else if (rProp.Name == "locality")
aAddr.mosLocality = sVal;
else if (rProp.Name == "isoCountryCode")
aAddr.mosIsoCountryCode = sVal;
}
return aAddr;
}
uno::Sequence<beans::PropertyValue> locationToProps(const GeoLocationModel& rLoc)
{
std::vector<beans::PropertyValue> aVec;
if (rLoc.mosLatitude.has_value())
aVec.push_back({ u"latitude"_ustr, 0, uno::Any(*rLoc.mosLatitude),
beans::PropertyState_DIRECT_VALUE });
if (rLoc.mosLongitude.has_value())
aVec.push_back({ u"longitude"_ustr, 0, uno::Any(*rLoc.mosLongitude),
beans::PropertyState_DIRECT_VALUE });
if (rLoc.mosEntityName.has_value())
aVec.push_back({ u"entityName"_ustr, 0, uno::Any(*rLoc.mosEntityName),
beans::PropertyState_DIRECT_VALUE });
if (rLoc.mosEntityType.has_value())
aVec.push_back({ u"entityType"_ustr, 0, uno::Any(*rLoc.mosEntityType),
beans::PropertyState_DIRECT_VALUE });
if (rLoc.mxAddress.has_value())
aVec.push_back({ u"address"_ustr, 0, uno::Any(addressToProps(*rLoc.mxAddress)),
beans::PropertyState_DIRECT_VALUE });
return comphelper::containerToSequence(aVec);
}
GeoLocationModel locationFromProps(const uno::Sequence<beans::PropertyValue>& rProps)
{
GeoLocationModel aLoc;
for (const auto& rProp : rProps)
{
if (rProp.Name == "latitude")
{
OUString s;
if (rProp.Value >>= s)
aLoc.mosLatitude = s;
}
else if (rProp.Name == "longitude")
{
OUString s;
if (rProp.Value >>= s)
aLoc.mosLongitude = s;
}
else if (rProp.Name == "entityName")
{
OUString s;
if (rProp.Value >>= s)
aLoc.mosEntityName = s;
}
else if (rProp.Name == "entityType")
{
OUString s;
if (rProp.Value >>= s)
aLoc.mosEntityType = s;
}
else if (rProp.Name == "address")
{
uno::Sequence<beans::PropertyValue> aInner;
if (rProp.Value >>= aInner)
aLoc.mxAddress = addressFromProps(aInner);
}
}
return aLoc;
}
uno::Sequence<beans::PropertyValue> locQueryToProps(const GeoLocationQueryModel& rQ)
{
std::vector<beans::PropertyValue> aVec;
if (rQ.mosCountryRegion.has_value())
aVec.push_back({ u"countryRegion"_ustr, 0, uno::Any(*rQ.mosCountryRegion),
beans::PropertyState_DIRECT_VALUE });
if (rQ.mosAdminDistrict1.has_value())
aVec.push_back({ u"adminDistrict1"_ustr, 0, uno::Any(*rQ.mosAdminDistrict1),
beans::PropertyState_DIRECT_VALUE });
if (rQ.mosAdminDistrict2.has_value())
aVec.push_back({ u"adminDistrict2"_ustr, 0, uno::Any(*rQ.mosAdminDistrict2),
beans::PropertyState_DIRECT_VALUE });
if (rQ.mosPostalCode.has_value())
aVec.push_back({ u"postalCode"_ustr, 0, uno::Any(*rQ.mosPostalCode),
beans::PropertyState_DIRECT_VALUE });
if (rQ.mosEntityType.has_value())
aVec.push_back({ u"entityType"_ustr, 0, uno::Any(*rQ.mosEntityType),
beans::PropertyState_DIRECT_VALUE });
return comphelper::containerToSequence(aVec);
}
GeoLocationQueryModel locQueryFromProps(const uno::Sequence<beans::PropertyValue>& rProps)
{
GeoLocationQueryModel aQ;
for (const auto& rProp : rProps)
{
OUString s;
if (!(rProp.Value >>= s))
continue;
if (rProp.Name == "countryRegion")
aQ.mosCountryRegion = s;
else if (rProp.Name == "adminDistrict1")
aQ.mosAdminDistrict1 = s;
else if (rProp.Name == "adminDistrict2")
aQ.mosAdminDistrict2 = s;
else if (rProp.Name == "postalCode")
aQ.mosPostalCode = s;
else if (rProp.Name == "entityType")
aQ.mosEntityType = s;
}
return aQ;
}
uno::Sequence<beans::PropertyValue> locResultToProps(const GeoLocationQueryResultModel& rR)
{
std::vector<beans::PropertyValue> aVec;
if (rR.mxQuery.has_value())
aVec.push_back({ u"query"_ustr, 0, uno::Any(locQueryToProps(*rR.mxQuery)),
beans::PropertyState_DIRECT_VALUE });
std::vector<uno::Sequence<beans::PropertyValue>> aLocs;
for (const auto& rLoc : rR.maLocations)
aLocs.push_back(locationToProps(rLoc));
if (!aLocs.empty())
aVec.push_back({ u"locations"_ustr, 0, uno::Any(comphelper::containerToSequence(aLocs)),
beans::PropertyState_DIRECT_VALUE });
return comphelper::containerToSequence(aVec);
}
GeoLocationQueryResultModel locResultFromProps(const uno::Sequence<beans::PropertyValue>& rProps)
{
GeoLocationQueryResultModel aR;
for (const auto& rProp : rProps)
{
if (rProp.Name == "query")
{
uno::Sequence<beans::PropertyValue> aInner;
if (rProp.Value >>= aInner)
aR.mxQuery = locQueryFromProps(aInner);
}
else if (rProp.Name == "locations")
{
uno::Sequence<uno::Sequence<beans::PropertyValue>> aArr;
if (rProp.Value >>= aArr)
for (const auto& rL : aArr)
aR.maLocations.push_back(locationFromProps(rL));
}
}
return aR;
}
uno::Sequence<beans::PropertyValue> polygonToProps(const GeoPolygonModel& rP)
{
std::vector<beans::PropertyValue> aVec;
if (rP.mosPolygonId.has_value())
aVec.push_back({ u"polygonId"_ustr, 0, uno::Any(*rP.mosPolygonId),
beans::PropertyState_DIRECT_VALUE });
if (rP.mosNumPoints.has_value())
aVec.push_back({ u"numPoints"_ustr, 0, uno::Any(*rP.mosNumPoints),
beans::PropertyState_DIRECT_VALUE });
if (rP.mosPcaRings.has_value())
aVec.push_back(
{ u"pcaRings"_ustr, 0, uno::Any(*rP.mosPcaRings), beans::PropertyState_DIRECT_VALUE });
return comphelper::containerToSequence(aVec);
}
GeoPolygonModel polygonFromProps(const uno::Sequence<beans::PropertyValue>& rProps)
{
GeoPolygonModel aP;
for (const auto& rProp : rProps)
{
OUString s;
if (!(rProp.Value >>= s))
continue;
if (rProp.Name == "polygonId")
aP.mosPolygonId = s;
else if (rProp.Name == "numPoints")
aP.mosNumPoints = s;
else if (rProp.Name == "pcaRings")
aP.mosPcaRings = s;
}
return aP;
}
uno::Sequence<beans::PropertyValue> geoDataToProps(const GeoDataModel& rD)
{
std::vector<beans::PropertyValue> aVec;
if (rD.mosEntityName.has_value())
aVec.push_back({ u"entityName"_ustr, 0, uno::Any(*rD.mosEntityName),
beans::PropertyState_DIRECT_VALUE });
if (rD.mosEntityId.has_value())
aVec.push_back(
{ u"entityId"_ustr, 0, uno::Any(*rD.mosEntityId), beans::PropertyState_DIRECT_VALUE });
if (rD.mosEast.has_value())
aVec.push_back(
{ u"east"_ustr, 0, uno::Any(*rD.mosEast), beans::PropertyState_DIRECT_VALUE });
if (rD.mosWest.has_value())
aVec.push_back(
{ u"west"_ustr, 0, uno::Any(*rD.mosWest), beans::PropertyState_DIRECT_VALUE });
if (rD.mosNorth.has_value())
aVec.push_back(
{ u"north"_ustr, 0, uno::Any(*rD.mosNorth), beans::PropertyState_DIRECT_VALUE });
if (rD.mosSouth.has_value())
aVec.push_back(
{ u"south"_ustr, 0, uno::Any(*rD.mosSouth), beans::PropertyState_DIRECT_VALUE });
if (!rD.maPolygons.empty())
{
std::vector<uno::Sequence<beans::PropertyValue>> aPolys;
for (const auto& rP : rD.maPolygons)
aPolys.push_back(polygonToProps(rP));
aVec.push_back({ u"polygons"_ustr, 0, uno::Any(comphelper::containerToSequence(aPolys)),
beans::PropertyState_DIRECT_VALUE });
}
if (!rD.maCopyrights.empty())
{
std::vector<OUString> aCR;
for (const auto& rC : rD.maCopyrights)
aCR.push_back(rC.msText);
aVec.push_back({ u"copyrights"_ustr, 0, uno::Any(comphelper::containerToSequence(aCR)),
beans::PropertyState_DIRECT_VALUE });
}
return comphelper::containerToSequence(aVec);
}
GeoDataModel geoDataFromProps(const uno::Sequence<beans::PropertyValue>& rProps)
{
GeoDataModel aD;
for (const auto& rProp : rProps)
{
if (rProp.Name == "polygons")
{
uno::Sequence<uno::Sequence<beans::PropertyValue>> aArr;
if (rProp.Value >>= aArr)
for (const auto& rP : aArr)
aD.maPolygons.push_back(polygonFromProps(rP));
}
else if (rProp.Name == "copyrights")
{
uno::Sequence<OUString> aArr;
if (rProp.Value >>= aArr)
for (const auto& rC : aArr)
aD.maCopyrights.push_back({ rC });
}
else
{
OUString s;
if (!(rProp.Value >>= s))
continue;
if (rProp.Name == "entityName")
aD.mosEntityName = s;
else if (rProp.Name == "entityId")
aD.mosEntityId = s;
else if (rProp.Name == "east")
aD.mosEast = s;
else if (rProp.Name == "west")
aD.mosWest = s;
else if (rProp.Name == "north")
aD.mosNorth = s;
else if (rProp.Name == "south")
aD.mosSouth = s;
}
}
return aD;
}
uno::Sequence<beans::PropertyValue> dataEntityQueryToProps(const GeoDataEntityQueryModel& rQ)
{
std::vector<beans::PropertyValue> aVec;
if (rQ.mosEntityType.has_value())
aVec.push_back({ u"entityType"_ustr, 0, uno::Any(*rQ.mosEntityType),
beans::PropertyState_DIRECT_VALUE });
if (rQ.mosEntityId.has_value())
aVec.push_back(
{ u"entityId"_ustr, 0, uno::Any(*rQ.mosEntityId), beans::PropertyState_DIRECT_VALUE });
return comphelper::containerToSequence(aVec);
}
GeoDataEntityQueryModel dataEntityQueryFromProps(const uno::Sequence<beans::PropertyValue>& rProps)
{
GeoDataEntityQueryModel aQ;
for (const auto& rProp : rProps)
{
OUString s;
if (!(rProp.Value >>= s))
continue;
if (rProp.Name == "entityType")
aQ.mosEntityType = s;
else if (rProp.Name == "entityId")
aQ.mosEntityId = s;
}
return aQ;
}
uno::Sequence<beans::PropertyValue> dataEntityResultToProps(const GeoDataEntityQueryResultModel& rR)
{
std::vector<beans::PropertyValue> aVec;
if (rR.mxQuery.has_value())
aVec.push_back({ u"query"_ustr, 0, uno::Any(dataEntityQueryToProps(*rR.mxQuery)),
beans::PropertyState_DIRECT_VALUE });
if (rR.mxData.has_value())
aVec.push_back({ u"data"_ustr, 0, uno::Any(geoDataToProps(*rR.mxData)),
beans::PropertyState_DIRECT_VALUE });
return comphelper::containerToSequence(aVec);
}
GeoDataEntityQueryResultModel
dataEntityResultFromProps(const uno::Sequence<beans::PropertyValue>& rProps)
{
GeoDataEntityQueryResultModel aR;
for (const auto& rProp : rProps)
{
uno::Sequence<beans::PropertyValue> aInner;
if (!(rProp.Value >>= aInner))
continue;
if (rProp.Name == "query")
aR.mxQuery = dataEntityQueryFromProps(aInner);
else if (rProp.Name == "data")
aR.mxData = geoDataFromProps(aInner);
}
return aR;
}
uno::Sequence<beans::PropertyValue> ptQueryToProps(const GeoDataPointQueryModel& rQ)
{
std::vector<beans::PropertyValue> aVec;
if (rQ.mosEntityType.has_value())
aVec.push_back({ u"entityType"_ustr, 0, uno::Any(*rQ.mosEntityType),
beans::PropertyState_DIRECT_VALUE });
if (rQ.mosLatitude.has_value())
aVec.push_back(
{ u"latitude"_ustr, 0, uno::Any(*rQ.mosLatitude), beans::PropertyState_DIRECT_VALUE });
if (rQ.mosLongitude.has_value())
aVec.push_back({ u"longitude"_ustr, 0, uno::Any(*rQ.mosLongitude),
beans::PropertyState_DIRECT_VALUE });
return comphelper::containerToSequence(aVec);
}
GeoDataPointQueryModel ptQueryFromProps(const uno::Sequence<beans::PropertyValue>& rProps)
{
GeoDataPointQueryModel aQ;
for (const auto& rProp : rProps)
{
OUString s;
if (!(rProp.Value >>= s))
continue;
if (rProp.Name == "entityType")
aQ.mosEntityType = s;
else if (rProp.Name == "latitude")
aQ.mosLatitude = s;
else if (rProp.Name == "longitude")
aQ.mosLongitude = s;
}
return aQ;
}
uno::Sequence<beans::PropertyValue> ptEntityQueryToProps(const GeoDataPointToEntityQueryModel& rQ)
{
std::vector<beans::PropertyValue> aVec;
if (rQ.mosEntityType.has_value())
aVec.push_back({ u"entityType"_ustr, 0, uno::Any(*rQ.mosEntityType),
beans::PropertyState_DIRECT_VALUE });
if (rQ.mosEntityId.has_value())
aVec.push_back(
{ u"entityId"_ustr, 0, uno::Any(*rQ.mosEntityId), beans::PropertyState_DIRECT_VALUE });
return comphelper::containerToSequence(aVec);
}
GeoDataPointToEntityQueryModel
ptEntityQueryFromProps(const uno::Sequence<beans::PropertyValue>& rProps)
{
GeoDataPointToEntityQueryModel aQ;
for (const auto& rProp : rProps)
{
OUString s;
if (!(rProp.Value >>= s))
continue;
if (rProp.Name == "entityType")
aQ.mosEntityType = s;
else if (rProp.Name == "entityId")
aQ.mosEntityId = s;
}
return aQ;
}
uno::Sequence<beans::PropertyValue> ptResultToProps(const GeoDataPointToEntityQueryResultModel& rR)
{
std::vector<beans::PropertyValue> aVec;
if (rR.mxPointQuery.has_value())
aVec.push_back({ u"pointQuery"_ustr, 0, uno::Any(ptQueryToProps(*rR.mxPointQuery)),
beans::PropertyState_DIRECT_VALUE });
if (rR.mxEntityQuery.has_value())
aVec.push_back({ u"entityQuery"_ustr, 0, uno::Any(ptEntityQueryToProps(*rR.mxEntityQuery)),
beans::PropertyState_DIRECT_VALUE });
return comphelper::containerToSequence(aVec);
}
GeoDataPointToEntityQueryResultModel
ptResultFromProps(const uno::Sequence<beans::PropertyValue>& rProps)
{
GeoDataPointToEntityQueryResultModel aR;
for (const auto& rProp : rProps)
{
uno::Sequence<beans::PropertyValue> aInner;
if (!(rProp.Value >>= aInner))
continue;
if (rProp.Name == "pointQuery")
aR.mxPointQuery = ptQueryFromProps(aInner);
else if (rProp.Name == "entityQuery")
aR.mxEntityQuery = ptEntityQueryFromProps(aInner);
}
return aR;
}
uno::Sequence<beans::PropertyValue> childQueryToProps(const GeoChildEntitiesQueryModel& rQ)
{
std::vector<beans::PropertyValue> aVec;
if (rQ.mosEntityId.has_value())
aVec.push_back(
{ u"entityId"_ustr, 0, uno::Any(*rQ.mosEntityId), beans::PropertyState_DIRECT_VALUE });
if (!rQ.maEntityTypes.empty())
aVec.push_back({ u"entityTypes"_ustr, 0,
uno::Any(comphelper::containerToSequence(rQ.maEntityTypes)),
beans::PropertyState_DIRECT_VALUE });
return comphelper::containerToSequence(aVec);
}
GeoChildEntitiesQueryModel childQueryFromProps(const uno::Sequence<beans::PropertyValue>& rProps)
{
GeoChildEntitiesQueryModel aQ;
for (const auto& rProp : rProps)
{
if (rProp.Name == "entityId")
{
OUString s;
if (rProp.Value >>= s)
aQ.mosEntityId = s;
}
else if (rProp.Name == "entityTypes")
{
uno::Sequence<OUString> aArr;
if (rProp.Value >>= aArr)
for (const auto& rS : aArr)
aQ.maEntityTypes.push_back(rS);
}
}
return aQ;
}
uno::Sequence<beans::PropertyValue> hierarchyEntityToProps(const GeoHierarchyEntityModel& rE)
{
std::vector<beans::PropertyValue> aVec;
if (rE.mosEntityName.has_value())
aVec.push_back({ u"entityName"_ustr, 0, uno::Any(*rE.mosEntityName),
beans::PropertyState_DIRECT_VALUE });
if (rE.mosEntityId.has_value())
aVec.push_back(
{ u"entityId"_ustr, 0, uno::Any(*rE.mosEntityId), beans::PropertyState_DIRECT_VALUE });
if (rE.mosEntityType.has_value())
aVec.push_back({ u"entityType"_ustr, 0, uno::Any(*rE.mosEntityType),
beans::PropertyState_DIRECT_VALUE });
return comphelper::containerToSequence(aVec);
}
GeoHierarchyEntityModel hierarchyEntityFromProps(const uno::Sequence<beans::PropertyValue>& rProps)
{
GeoHierarchyEntityModel aE;
for (const auto& rProp : rProps)
{
OUString s;
if (!(rProp.Value >>= s))
continue;
if (rProp.Name == "entityName")
aE.mosEntityName = s;
else if (rProp.Name == "entityId")
aE.mosEntityId = s;
else if (rProp.Name == "entityType")
aE.mosEntityType = s;
}
return aE;
}
uno::Sequence<beans::PropertyValue> childResultToProps(const GeoChildEntitiesQueryResultModel& rR)
{
std::vector<beans::PropertyValue> aVec;
if (rR.mxQuery.has_value())
aVec.push_back({ u"query"_ustr, 0, uno::Any(childQueryToProps(*rR.mxQuery)),
beans::PropertyState_DIRECT_VALUE });
if (!rR.maEntities.empty())
{
std::vector<uno::Sequence<beans::PropertyValue>> aArr;
for (const auto& rE : rR.maEntities)
aArr.push_back(hierarchyEntityToProps(rE));
aVec.push_back({ u"entities"_ustr, 0, uno::Any(comphelper::containerToSequence(aArr)),
beans::PropertyState_DIRECT_VALUE });
}
return comphelper::containerToSequence(aVec);
}
GeoChildEntitiesQueryResultModel
childResultFromProps(const uno::Sequence<beans::PropertyValue>& rProps)
{
GeoChildEntitiesQueryResultModel aR;
for (const auto& rProp : rProps)
{
if (rProp.Name == "query")
{
uno::Sequence<beans::PropertyValue> aInner;
if (rProp.Value >>= aInner)
aR.mxQuery = childQueryFromProps(aInner);
}
else if (rProp.Name == "entities")
{
uno::Sequence<uno::Sequence<beans::PropertyValue>> aArr;
if (rProp.Value >>= aArr)
for (const auto& rE : aArr)
aR.maEntities.push_back(hierarchyEntityFromProps(rE));
}
}
return aR;
}
uno::Sequence<beans::PropertyValue> parentResultToProps(const GeoParentEntitiesQueryResultModel& rR)
{
std::vector<beans::PropertyValue> aVec;
if (rR.mxQuery.has_value())
{
std::vector<beans::PropertyValue> aQ;
if (rR.mxQuery->mosEntityId.has_value())
aQ.push_back({ u"entityId"_ustr, 0, uno::Any(*rR.mxQuery->mosEntityId),
beans::PropertyState_DIRECT_VALUE });
aVec.push_back({ u"query"_ustr, 0, uno::Any(comphelper::containerToSequence(aQ)),
beans::PropertyState_DIRECT_VALUE });
}
if (rR.mxEntity.has_value())
{
std::vector<beans::PropertyValue> aE;
if (rR.mxEntity->mosEntityName.has_value())
aE.push_back({ u"entityName"_ustr, 0, uno::Any(*rR.mxEntity->mosEntityName),
beans::PropertyState_DIRECT_VALUE });
if (rR.mxEntity->mosEntityType.has_value())
aE.push_back({ u"entityType"_ustr, 0, uno::Any(*rR.mxEntity->mosEntityType),
beans::PropertyState_DIRECT_VALUE });
aVec.push_back({ u"entity"_ustr, 0, uno::Any(comphelper::containerToSequence(aE)),
beans::PropertyState_DIRECT_VALUE });
}
if (rR.mxParentEntity.has_value())
{
std::vector<beans::PropertyValue> aP;
if (rR.mxParentEntity->mosEntityId.has_value())
aP.push_back({ u"entityId"_ustr, 0, uno::Any(*rR.mxParentEntity->mosEntityId),
beans::PropertyState_DIRECT_VALUE });
aVec.push_back({ u"parentEntity"_ustr, 0, uno::Any(comphelper::containerToSequence(aP)),
beans::PropertyState_DIRECT_VALUE });
}
return comphelper::containerToSequence(aVec);
}
GeoParentEntitiesQueryResultModel
parentResultFromProps(const uno::Sequence<beans::PropertyValue>& rProps)
{
GeoParentEntitiesQueryResultModel aR;
for (const auto& rProp : rProps)
{
uno::Sequence<beans::PropertyValue> aInner;
if (!(rProp.Value >>= aInner))
continue;
if (rProp.Name == "query")
{
aR.mxQuery.emplace();
for (const auto& rQ : aInner)
{
OUString s;
if (rQ.Name == "entityId" && (rQ.Value >>= s))
aR.mxQuery->mosEntityId = s;
}
}
else if (rProp.Name == "entity")
{
aR.mxEntity.emplace();
for (const auto& rE : aInner)
{
OUString s;
if (!(rE.Value >>= s))
continue;
if (rE.Name == "entityName")
aR.mxEntity->mosEntityName = s;
else if (rE.Name == "entityType")
aR.mxEntity->mosEntityType = s;
}
}
else if (rProp.Name == "parentEntity")
{
aR.mxParentEntity.emplace();
for (const auto& rP : aInner)
{
OUString s;
if (rP.Name == "entityId" && (rP.Value >>= s))
aR.mxParentEntity->mosEntityId = s;
}
}
}
return aR;
}
} // anonymous namespace
uno::Sequence<beans::PropertyValue> geoClearToPropertyValues(const GeoClearModel& rModel)
{
std::vector<beans::PropertyValue> aVec;
if (!rModel.maLocResults.empty())
{
std::vector<uno::Sequence<beans::PropertyValue>> aArr;
for (const auto& rR : rModel.maLocResults)
aArr.push_back(locResultToProps(rR));
aVec.push_back({ u"locResults"_ustr, 0, uno::Any(comphelper::containerToSequence(aArr)),
beans::PropertyState_DIRECT_VALUE });
}
if (!rModel.maDataResults.empty())
{
std::vector<uno::Sequence<beans::PropertyValue>> aArr;
for (const auto& rR : rModel.maDataResults)
aArr.push_back(dataEntityResultToProps(rR));
aVec.push_back({ u"dataResults"_ustr, 0, uno::Any(comphelper::containerToSequence(aArr)),
beans::PropertyState_DIRECT_VALUE });
}
if (!rModel.maPtResults.empty())
{
std::vector<uno::Sequence<beans::PropertyValue>> aArr;
for (const auto& rR : rModel.maPtResults)
aArr.push_back(ptResultToProps(rR));
aVec.push_back({ u"ptResults"_ustr, 0, uno::Any(comphelper::containerToSequence(aArr)),
beans::PropertyState_DIRECT_VALUE });
}
if (!rModel.maChildResults.empty())
{
std::vector<uno::Sequence<beans::PropertyValue>> aArr;
for (const auto& rR : rModel.maChildResults)
aArr.push_back(childResultToProps(rR));
aVec.push_back({ u"childResults"_ustr, 0, uno::Any(comphelper::containerToSequence(aArr)),
beans::PropertyState_DIRECT_VALUE });
}
if (!rModel.maParentResults.empty())
{
std::vector<uno::Sequence<beans::PropertyValue>> aArr;
for (const auto& rR : rModel.maParentResults)
aArr.push_back(parentResultToProps(rR));
aVec.push_back({ u"parentResults"_ustr, 0, uno::Any(comphelper::containerToSequence(aArr)),
beans::PropertyState_DIRECT_VALUE });
}
return comphelper::containerToSequence(aVec);
}
GeoClearModel geoClearFromPropertyValues(const uno::Sequence<beans::PropertyValue>& rProps)
{
GeoClearModel aModel;
for (const auto& rProp : rProps)
{
if (rProp.Name == "locResults")
{
uno::Sequence<uno::Sequence<beans::PropertyValue>> aArr;
if (rProp.Value >>= aArr)
for (const auto& rR : aArr)
aModel.maLocResults.push_back(locResultFromProps(rR));
}
else if (rProp.Name == "dataResults")
{
uno::Sequence<uno::Sequence<beans::PropertyValue>> aArr;
if (rProp.Value >>= aArr)
for (const auto& rR : aArr)
aModel.maDataResults.push_back(dataEntityResultFromProps(rR));
}
else if (rProp.Name == "ptResults")
{
uno::Sequence<uno::Sequence<beans::PropertyValue>> aArr;
if (rProp.Value >>= aArr)
for (const auto& rR : aArr)
aModel.maPtResults.push_back(ptResultFromProps(rR));
}
else if (rProp.Name == "childResults")
{
uno::Sequence<uno::Sequence<beans::PropertyValue>> aArr;
if (rProp.Value >>= aArr)
for (const auto& rR : aArr)
aModel.maChildResults.push_back(childResultFromProps(rR));
}
else if (rProp.Name == "parentResults")
{
uno::Sequence<uno::Sequence<beans::PropertyValue>> aArr;
if (rProp.Value >>= aArr)
for (const auto& rR : aArr)
aModel.maParentResults.push_back(parentResultFromProps(rR));
}
}
return aModel;
}
void convertGeography(const GeographyModel& rModel, PropertySet& rSeriesProp)
{
if (rModel.mosProjectionType.has_value())
rSeriesProp.setProperty(PROP_GeographyProjectionType, *rModel.mosProjectionType);
if (rModel.mosViewedRegionType.has_value())
rSeriesProp.setProperty(PROP_GeographyViewedRegionType, *rModel.mosViewedRegionType);
if (rModel.mosCultureLanguage.has_value())
rSeriesProp.setProperty(PROP_GeographyCultureLanguage, *rModel.mosCultureLanguage);
if (rModel.mosCultureRegion.has_value())
rSeriesProp.setProperty(PROP_GeographyCultureRegion, *rModel.mosCultureRegion);
if (rModel.mosAttribution.has_value())
rSeriesProp.setProperty(PROP_GeographyAttribution, *rModel.mosAttribution);
if (rModel.mxGeoCache.has_value())
{
const auto& rCache = *rModel.mxGeoCache;
if (rCache.mosProvider.has_value())
rSeriesProp.setProperty(PROP_GeoCacheProvider, *rCache.mosProvider);
if (rCache.mosBinary.has_value())
rSeriesProp.setProperty(PROP_GeoCacheBinary, *rCache.mosBinary);
if (rCache.mxClear.has_value())
rSeriesProp.setProperty(PROP_GeoCacheClearData,
geoClearToPropertyValues(*rCache.mxClear));
}
}
} // namespace oox::drawingml::chart
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
+10 -2
View File
@@ -22,6 +22,7 @@
#include <drawingml/shapepropertiescontext.hxx>
#include <drawingml/textbodycontext.hxx>
#include <drawingml/chart/datasourcecontext.hxx>
#include <drawingml/chart/geographycontext.hxx>
#include <drawingml/chart/seriesmodel.hxx>
#include <drawingml/chart/titlecontext.hxx>
#include <oox/core/xmlfilterbase.hxx>
@@ -860,8 +861,15 @@ ContextHandlerRef LayoutPropsContext::onCreateContext( sal_Int32 nElement, const
return new BinningContext( *this, rB );
}
case CX_TOKEN( geography ):
// TODO
return nullptr;
{
auto& rGeo = mrModel.mxGeography.emplace();
rGeo.mosProjectionType = rAttribs.getString( XML_projectionType );
rGeo.mosViewedRegionType = rAttribs.getString( XML_viewedRegionType );
rGeo.mosCultureLanguage = rAttribs.getString( XML_cultureLanguage );
rGeo.mosCultureRegion = rAttribs.getString( XML_cultureRegion );
rGeo.mosAttribution = rAttribs.getString( XML_attribution );
return new GeographyContext( *this, *mrModel.mxGeography );
}
case CX_TOKEN( statistics ):
mrModel.mosQuartileMethod = rAttribs.getString( XML_quartileMethod );
return nullptr;
@@ -40,6 +40,7 @@
#include <comphelper/sequence.hxx>
#include <osl/diagnose.h>
#include <drawingml/chart/datasourceconverter.hxx>
#include <drawingml/chart/geographyconverter.hxx>
#include <drawingml/chart/seriesmodel.hxx>
#include <drawingml/chart/titleconverter.hxx>
#include <drawingml/chart/typegroupconverter.hxx>
@@ -997,6 +998,12 @@ Reference< XDataSeries > SeriesConverter::createDataSeries( const TypeGroupConve
if (!rLPR->maSubtotalIndices.empty())
aSeriesProp.setProperty(PROP_SubtotalIndices,
comphelper::containerToSequence(rLPR->maSubtotalIndices));
if (rLPR->mxGeography.has_value())
{
aSeriesProp.setProperty(PROP_HasGeography, true);
convertGeography(*rLPR->mxGeography, aSeriesProp);
}
}
return xDataSeries;
}
+9 -1
View File
@@ -22,6 +22,7 @@
#include <oox/token/tokens.hxx>
#include <oox/core/xmlfilterbase.hxx>
#include <oox/export/chartexport.hxx>
#include <oox/export/chartgeographyexport.hxx>
#include <oox/export/shapes.hxx>
#include <oox/token/relationship.hxx>
#include <oox/export/utils.hxx>
@@ -4012,8 +4013,11 @@ void ChartExport::exportSeries_chartex( const Reference<chart2::XChartType>& xCh
uno::Any aIntervalClosed = xSeriesProp->getPropertyValue( u"IntervalClosed"_ustr);
const bool bHasIC = aIntervalClosed.hasValue();
bool bHasGeography = false;
xSeriesProp->getPropertyValue(u"HasGeography"_ustr) >>= bHasGeography;
bool bHasAny = bHasParentLL || bHasRegionLL || bHasVisibility
|| bHasQM || bHasSubtotals || bHasIC;
|| bHasQM || bHasSubtotals || bHasIC || bHasGeography;
if (bHasAny)
{
pFS->startElement(FSNS(XML_cx, XML_layoutPr));
@@ -4043,8 +4047,12 @@ void ChartExport::exportSeries_chartex( const Reference<chart2::XChartType>& xCh
XML_meanMarker, bHasMeanMarker ? ToPsz10(bMeanMarker) : nullptr,
XML_nonoutliers, bHasNonoutliers ? ToPsz10(bNonoutliers) : nullptr,
XML_outliers, bHasOutliers ? ToPsz10(bOutliers) : nullptr);
}
if (bHasGeography)
oox::drawingml::chart::exportGeography(xSeriesProp, pFS);
if (bHasIC)
{
sal_uInt32 nIntervalClosedChar = '\0';
+339
View File
@@ -0,0 +1,339 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <oox/export/chartgeographyexport.hxx>
#include <drawingml/chart/geographyconverter.hxx>
#include <drawingml/chart/geographymodel.hxx>
#include <oox/token/namespaces.hxx>
#include <oox/token/tokens.hxx>
// Code for exporting <cx:geography> content in a chartex chart, used for the
// regionMap chart type.
using namespace ::com::sun::star;
namespace oox::drawingml::chart
{
namespace
{
const char* toNullableStr(const std::optional<OUString>& rOpt, OString& rBuf)
{
if (!rOpt.has_value())
return nullptr;
rBuf = rOpt->toUtf8();
return rBuf.getStr();
}
void writeAddress(const GeoAddressModel& rAddr, const sax_fastparser::FSHelperPtr& pFS)
{
OString b1, b2, b3, b4, b5, b6, b7;
pFS->singleElement(
FSNS(XML_cx, XML_address), XML_address1, toNullableStr(rAddr.mosAddress1, b1),
XML_countryRegion, toNullableStr(rAddr.mosCountryRegion, b2), XML_adminDistrict1,
toNullableStr(rAddr.mosAdminDistrict1, b3), XML_adminDistrict2,
toNullableStr(rAddr.mosAdminDistrict2, b4), XML_postalCode,
toNullableStr(rAddr.mosPostalCode, b5), XML_locality, toNullableStr(rAddr.mosLocality, b6),
XML_isoCountryCode, toNullableStr(rAddr.mosIsoCountryCode, b7));
}
void writeLocResults(const std::vector<GeoLocationQueryResultModel>& rResults,
const sax_fastparser::FSHelperPtr& pFS)
{
if (rResults.empty())
return;
pFS->startElement(FSNS(XML_cx, XML_geoLocationQueryResults));
for (const auto& rR : rResults)
{
pFS->startElement(FSNS(XML_cx, XML_geoLocationQueryResult));
if (rR.mxQuery.has_value())
{
const auto& q = *rR.mxQuery;
OString b1, b2, b3, b4, b5;
pFS->singleElement(FSNS(XML_cx, XML_geoLocationQuery), XML_countryRegion,
toNullableStr(q.mosCountryRegion, b1), XML_adminDistrict1,
toNullableStr(q.mosAdminDistrict1, b2), XML_adminDistrict2,
toNullableStr(q.mosAdminDistrict2, b3), XML_postalCode,
toNullableStr(q.mosPostalCode, b4), XML_entityType,
toNullableStr(q.mosEntityType, b5));
}
if (!rR.maLocations.empty())
{
pFS->startElement(FSNS(XML_cx, XML_geoLocations));
for (const auto& rLoc : rR.maLocations)
{
OString b1, b2, b3, b4;
if (rLoc.mxAddress.has_value())
{
pFS->startElement(FSNS(XML_cx, XML_geoLocation), XML_latitude,
toNullableStr(rLoc.mosLatitude, b1), XML_longitude,
toNullableStr(rLoc.mosLongitude, b2), XML_entityName,
toNullableStr(rLoc.mosEntityName, b3), XML_entityType,
toNullableStr(rLoc.mosEntityType, b4));
writeAddress(*rLoc.mxAddress, pFS);
pFS->endElement(FSNS(XML_cx, XML_geoLocation));
}
else
{
pFS->singleElement(FSNS(XML_cx, XML_geoLocation), XML_latitude,
toNullableStr(rLoc.mosLatitude, b1), XML_longitude,
toNullableStr(rLoc.mosLongitude, b2), XML_entityName,
toNullableStr(rLoc.mosEntityName, b3), XML_entityType,
toNullableStr(rLoc.mosEntityType, b4));
}
}
pFS->endElement(FSNS(XML_cx, XML_geoLocations));
}
pFS->endElement(FSNS(XML_cx, XML_geoLocationQueryResult));
}
pFS->endElement(FSNS(XML_cx, XML_geoLocationQueryResults));
}
void writeDataResults(const std::vector<GeoDataEntityQueryResultModel>& rResults,
const sax_fastparser::FSHelperPtr& pFS)
{
if (rResults.empty())
return;
pFS->startElement(FSNS(XML_cx, XML_geoDataEntityQueryResults));
for (const auto& rR : rResults)
{
pFS->startElement(FSNS(XML_cx, XML_geoDataEntityQueryResult));
if (rR.mxQuery.has_value())
{
OString b1, b2;
pFS->singleElement(FSNS(XML_cx, XML_geoDataEntityQuery), XML_entityType,
toNullableStr(rR.mxQuery->mosEntityType, b1), XML_entityId,
toNullableStr(rR.mxQuery->mosEntityId, b2));
}
if (rR.mxData.has_value())
{
const auto& d = *rR.mxData;
OString b1, b2, b3, b4, b5, b6;
pFS->startElement(
FSNS(XML_cx, XML_geoData), XML_entityName, toNullableStr(d.mosEntityName, b1),
XML_entityId, toNullableStr(d.mosEntityId, b2), XML_east,
toNullableStr(d.mosEast, b3), XML_west, toNullableStr(d.mosWest, b4), XML_north,
toNullableStr(d.mosNorth, b5), XML_south, toNullableStr(d.mosSouth, b6));
if (!d.maPolygons.empty())
{
pFS->startElement(FSNS(XML_cx, XML_geoPolygons));
for (const auto& rP : d.maPolygons)
{
OString pb1, pb2, pb3;
pFS->singleElement(FSNS(XML_cx, XML_geoPolygon), XML_polygonId,
toNullableStr(rP.mosPolygonId, pb1), XML_numPoints,
toNullableStr(rP.mosNumPoints, pb2), XML_pcaRings,
toNullableStr(rP.mosPcaRings, pb3));
}
pFS->endElement(FSNS(XML_cx, XML_geoPolygons));
}
if (!d.maCopyrights.empty())
{
pFS->startElement(FSNS(XML_cx, XML_copyrights));
for (const auto& rC : d.maCopyrights)
{
pFS->startElement(FSNS(XML_cx, XML_copyright));
pFS->writeEscaped(rC.msText);
pFS->endElement(FSNS(XML_cx, XML_copyright));
}
pFS->endElement(FSNS(XML_cx, XML_copyrights));
}
pFS->endElement(FSNS(XML_cx, XML_geoData));
}
pFS->endElement(FSNS(XML_cx, XML_geoDataEntityQueryResult));
}
pFS->endElement(FSNS(XML_cx, XML_geoDataEntityQueryResults));
}
void writePtResults(const std::vector<GeoDataPointToEntityQueryResultModel>& rResults,
const sax_fastparser::FSHelperPtr& pFS)
{
if (rResults.empty())
return;
pFS->startElement(FSNS(XML_cx, XML_geoDataPointToEntityQueryResults));
for (const auto& rR : rResults)
{
pFS->startElement(FSNS(XML_cx, XML_geoDataPointToEntityQueryResult));
if (rR.mxPointQuery.has_value())
{
OString b1, b2, b3;
pFS->singleElement(FSNS(XML_cx, XML_geoDataPointQuery), XML_entityType,
toNullableStr(rR.mxPointQuery->mosEntityType, b1), XML_latitude,
toNullableStr(rR.mxPointQuery->mosLatitude, b2), XML_longitude,
toNullableStr(rR.mxPointQuery->mosLongitude, b3));
}
if (rR.mxEntityQuery.has_value())
{
OString b1, b2;
pFS->singleElement(FSNS(XML_cx, XML_geoDataPointToEntityQuery), XML_entityType,
toNullableStr(rR.mxEntityQuery->mosEntityType, b1), XML_entityId,
toNullableStr(rR.mxEntityQuery->mosEntityId, b2));
}
pFS->endElement(FSNS(XML_cx, XML_geoDataPointToEntityQueryResult));
}
pFS->endElement(FSNS(XML_cx, XML_geoDataPointToEntityQueryResults));
}
void writeChildResults(const std::vector<GeoChildEntitiesQueryResultModel>& rResults,
const sax_fastparser::FSHelperPtr& pFS)
{
if (rResults.empty())
return;
pFS->startElement(FSNS(XML_cx, XML_geoChildEntitiesQueryResults));
for (const auto& rR : rResults)
{
pFS->startElement(FSNS(XML_cx, XML_geoChildEntitiesQueryResult));
if (rR.mxQuery.has_value())
{
OString b1;
pFS->startElement(FSNS(XML_cx, XML_geoChildEntitiesQuery), XML_entityId,
toNullableStr(rR.mxQuery->mosEntityId, b1));
if (!rR.mxQuery->maEntityTypes.empty())
{
pFS->startElement(FSNS(XML_cx, XML_geoChildTypes));
for (const auto& rT : rR.mxQuery->maEntityTypes)
{
pFS->startElement(FSNS(XML_cx, XML_entityType));
pFS->writeEscaped(rT);
pFS->endElement(FSNS(XML_cx, XML_entityType));
}
pFS->endElement(FSNS(XML_cx, XML_geoChildTypes));
}
pFS->endElement(FSNS(XML_cx, XML_geoChildEntitiesQuery));
}
if (!rR.maEntities.empty())
{
pFS->startElement(FSNS(XML_cx, XML_geoChildEntities));
for (const auto& rE : rR.maEntities)
{
OString b1, b2, b3;
pFS->singleElement(FSNS(XML_cx, XML_geoHierarchyEntity), XML_entityName,
toNullableStr(rE.mosEntityName, b1), XML_entityId,
toNullableStr(rE.mosEntityId, b2), XML_entityType,
toNullableStr(rE.mosEntityType, b3));
}
pFS->endElement(FSNS(XML_cx, XML_geoChildEntities));
}
pFS->endElement(FSNS(XML_cx, XML_geoChildEntitiesQueryResult));
}
pFS->endElement(FSNS(XML_cx, XML_geoChildEntitiesQueryResults));
}
void writeParentResults(const std::vector<GeoParentEntitiesQueryResultModel>& rResults,
const sax_fastparser::FSHelperPtr& pFS)
{
if (rResults.empty())
return;
pFS->startElement(FSNS(XML_cx, XML_geoParentEntitiesQueryResults));
for (const auto& rR : rResults)
{
pFS->startElement(FSNS(XML_cx, XML_geoParentEntitiesQueryResult));
if (rR.mxQuery.has_value())
{
OString b1;
pFS->singleElement(FSNS(XML_cx, XML_geoParentEntitiesQuery), XML_entityId,
toNullableStr(rR.mxQuery->mosEntityId, b1));
}
if (rR.mxEntity.has_value())
{
OString b1, b2;
pFS->singleElement(FSNS(XML_cx, XML_geoEntity), XML_entityName,
toNullableStr(rR.mxEntity->mosEntityName, b1), XML_entityType,
toNullableStr(rR.mxEntity->mosEntityType, b2));
}
if (rR.mxParentEntity.has_value())
{
OString b1;
pFS->singleElement(FSNS(XML_cx, XML_geoParentEntity), XML_entityId,
toNullableStr(rR.mxParentEntity->mosEntityId, b1));
}
pFS->endElement(FSNS(XML_cx, XML_geoParentEntitiesQueryResult));
}
pFS->endElement(FSNS(XML_cx, XML_geoParentEntitiesQueryResults));
}
} // anonymous namespace
void exportGeography(const uno::Reference<beans::XPropertySet>& xSeriesProp,
const sax_fastparser::FSHelperPtr& pFS)
{
if (!xSeriesProp.is())
return;
OUString sProjectionType, sViewedRegionType, sCultureLanguage, sCultureRegion, sAttribution;
uno::Any aPT = xSeriesProp->getPropertyValue(u"GeographyProjectionType"_ustr);
uno::Any aVR = xSeriesProp->getPropertyValue(u"GeographyViewedRegionType"_ustr);
uno::Any aCL = xSeriesProp->getPropertyValue(u"GeographyCultureLanguage"_ustr);
uno::Any aCR = xSeriesProp->getPropertyValue(u"GeographyCultureRegion"_ustr);
uno::Any aAT = xSeriesProp->getPropertyValue(u"GeographyAttribution"_ustr);
bool bHasPT = (aPT >>= sProjectionType);
bool bHasVR = (aVR >>= sViewedRegionType);
bool bHasCL = (aCL >>= sCultureLanguage);
bool bHasCR = (aCR >>= sCultureRegion);
bool bHasAT = (aAT >>= sAttribution);
if (!bHasPT && !bHasVR && !bHasCL && !bHasCR && !bHasAT)
return;
pFS->startElement(FSNS(XML_cx, XML_geography), XML_projectionType,
bHasPT ? sProjectionType.toUtf8().getStr() : nullptr, XML_viewedRegionType,
bHasVR ? sViewedRegionType.toUtf8().getStr() : nullptr, XML_cultureLanguage,
bHasCL ? sCultureLanguage.toUtf8().getStr() : nullptr, XML_cultureRegion,
bHasCR ? sCultureRegion.toUtf8().getStr() : nullptr, XML_attribution,
bHasAT ? sAttribution.toUtf8().getStr() : nullptr);
// Handle the geoCache child element
OUString sProvider;
uno::Any aProvider = xSeriesProp->getPropertyValue(u"GeoCacheProvider"_ustr);
bool bHasProvider = (aProvider >>= sProvider);
OUString sBinary;
uno::Any aBinary = xSeriesProp->getPropertyValue(u"GeoCacheBinary"_ustr);
bool bHasBinary = (aBinary >>= sBinary);
uno::Sequence<beans::PropertyValue> aClearData;
uno::Any aClear = xSeriesProp->getPropertyValue(u"GeoCacheClearData"_ustr);
bool bHasClear = (aClear >>= aClearData) && aClearData.hasElements();
if (bHasProvider || bHasBinary || bHasClear)
{
pFS->startElement(FSNS(XML_cx, XML_geoCache), XML_provider,
bHasProvider ? sProvider.toUtf8().getStr() : nullptr);
if (bHasBinary)
{
pFS->startElement(FSNS(XML_cx, XML_binary));
pFS->writeEscaped(sBinary);
pFS->endElement(FSNS(XML_cx, XML_binary));
}
else if (bHasClear)
{
GeoClearModel aClearModel = geoClearFromPropertyValues(aClearData);
pFS->startElement(FSNS(XML_cx, XML_clear));
writeLocResults(aClearModel.maLocResults, pFS);
writeDataResults(aClearModel.maDataResults, pFS);
writePtResults(aClearModel.maPtResults, pFS);
writeChildResults(aClearModel.maChildResults, pFS);
writeParentResults(aClearModel.maParentResults, pFS);
pFS->endElement(FSNS(XML_cx, XML_clear));
}
pFS->endElement(FSNS(XML_cx, XML_geoCache));
}
pFS->endElement(FSNS(XML_cx, XML_geography));
}
} // namespace oox::drawingml::chart
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
+9
View File
@@ -235,6 +235,14 @@ FromWordArt
Function
GapwidthSequence
GenerateVbaEvents
GeoCacheBinary
GeoCacheClearData
GeoCacheProvider
GeographyAttribution
GeographyCultureLanguage
GeographyCultureRegion
GeographyProjectionType
GeographyViewedRegionType
Geometry3D
GlowEffect
GlowEffectRadius
@@ -253,6 +261,7 @@ HScroll
Handles
HasAutoShowInfo
HasColumnRowHeaders
HasGeography
HasHorizontalScrollBar
HasLayoutInfo
HasMainTitle
+56
View File
@@ -479,6 +479,8 @@ add
additionalCharacteristics
additive
addlxml
address
address1
addressBook
addressFieldName
adec
@@ -489,6 +491,8 @@ adjustColumnWidth
adjustLineHeightInTable
adjustRightInd
adjusthandles
adminDistrict1
adminDistrict2
administrators
advAuto
advClick
@@ -694,6 +698,7 @@ attr
attrName
attrNameLst
attribute
attribution
audio
audioCd
audioFile
@@ -884,6 +889,7 @@ bilevel
billions
binCount
binSize
binary
binning
birds
birdsFlight
@@ -1444,6 +1450,8 @@ coordorigin
coordsize
copies
copy
copyright
copyrights
coral
coreProperties
corner
@@ -1457,6 +1465,7 @@ countASubtotal
countBy
countNums
countSubtotal
countryRegion
couponCutoutDashes
couponCutoutDots
cover
@@ -1515,6 +1524,8 @@ ctrlPr
cube
cubicBezTo
culture
cultureLanguage
cultureRegion
cup
curly
current
@@ -2069,6 +2080,7 @@ eachPage
eachSect
earth1
earth2
east
eastAsia
eastAsiaTheme
eastAsianLayout
@@ -2161,6 +2173,9 @@ entr
entries
entry
entryMacro
entityId
entityName
entityType
envelopes
eol
eq
@@ -2523,6 +2538,33 @@ gear6
gear9
gems
general
geoCache
geoChildEntities
geoChildEntitiesQuery
geoChildEntitiesQueryResult
geoChildEntitiesQueryResults
geoChildTypes
geoData
geoDataEntityQuery
geoDataEntityQueryResult
geoDataEntityQueryResults
geoDataPointQuery
geoDataPointToEntityQuery
geoDataPointToEntityQueryResult
geoDataPointToEntityQueryResults
geoEntity
geoHierarchyEntity
geoLocation
geoLocationQuery
geoLocationQueryResult
geoLocationQueryResults
geoLocations
geoParentEntitiesQuery
geoParentEntitiesQueryResult
geoParentEntitiesQueryResults
geoParentEntity
geoPolygon
geoPolygons
geography
gfxdata
ghostCol
@@ -2949,6 +2991,7 @@ isLgl
isNarration
isPhoto
iscomment
isoCountryCode
isometricBottomDown
isometricBottomUp
isometricLeftDown
@@ -3056,6 +3099,7 @@ lat
latentStyles
latin
latinLnBrk
latitude
lavender
lavenderBlush
lawnGreen
@@ -3246,6 +3290,7 @@ local
localConnection
localRefresh
localSheetId
locality
location
lock
lockRevision
@@ -3260,6 +3305,7 @@ log
logBase
lon
long
longitude
longCurve
longFileNames
longText
@@ -3673,6 +3719,7 @@ normal
normalViewPr
normalizeH
normalizedString
north
northwest
notBeside
notBetween
@@ -3713,6 +3760,7 @@ numIdMacAtCleanup
numLit
numPicBullet
numPicBulletId
numPoints
numPr
numRef
numRestart
@@ -3977,6 +4025,7 @@ pattFill
pattern
patternFill
patternType
pcaRings
pct
pct10
pct12
@@ -4127,6 +4176,7 @@ points
polar
poly
polyline
polygonId
portrait
pos
posEven
@@ -4139,6 +4189,7 @@ positiveInteger
post
postSp
postageStamp
postalCode
powder
powderBlue
power
@@ -4203,6 +4254,7 @@ product
productSubtotal
progId
progress
projectionType
prompt
promptTitle
promptedSolutions
@@ -4217,6 +4269,7 @@ protectedRange
protectedRanges
protection
provid
provider
proxy
prst
prstClr
@@ -4945,6 +4998,7 @@ sourceObject
sourceRef
sourceSheetId
sourceType
south
southwest
sp
sp3d
@@ -5786,6 +5840,7 @@ view3D
viewMergedData
viewPr
viewpoint
viewedRegionType
viewpointorigin
vine
violet
@@ -5855,6 +5910,7 @@ wedgeEllipseCallout
wedgeRectCallout
wedgeRoundRectCallout
weight
west
wgp
wheat
wheel