diff --git a/bnc1039203.patch b/bnc1039203.patch new file mode 100644 index 0000000..429a291 --- /dev/null +++ b/bnc1039203.patch @@ -0,0 +1,605 @@ +From 377af664602f5df27df5fcfad5e50a0f59dca38c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Szymon=20K=C5=82os?= +Date: Fri, 2 Feb 2018 10:21:50 +0100 +Subject: [PATCH 1/4] tdf#115394 import custom slide transition time in PPTX +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +* custom values are imported correctly +* standard (fast, slow, medium) values are changed + to match values in the MSO + +Change-Id: I004242afbbf641fe414abc8df248a2844c104502 +Reviewed-on: https://gerrit.libreoffice.org/49139 +Tested-by: Jenkins +Reviewed-by: Szymon Kłos +--- + include/oox/ppt/slidetransition.hxx | 4 +++ + offapi/com/sun/star/presentation/DrawPage.idl | 9 +++++-- + oox/source/ppt/slidetransition.cxx | 22 ++++++++++++++--- + oox/source/ppt/slidetransitioncontext.cxx | 6 +++++ + oox/source/token/properties.txt | 1 + + sd/qa/unit/data/pptx/tdf115394.pptx | Bin 0 -> 31282 bytes + sd/qa/unit/import-tests.cxx | 34 ++++++++++++++++++++++++++ + sd/source/ui/inc/unoprnms.hxx | 1 + + sd/source/ui/unoidl/unopage.cxx | 2 +- + 9 files changed, 72 insertions(+), 7 deletions(-) + create mode 100644 sd/qa/unit/data/pptx/tdf115394.pptx + +diff --git a/include/oox/ppt/slidetransition.hxx b/include/oox/ppt/slidetransition.hxx +index 8986016f30aa..5a31b158334b 100644 +--- a/include/oox/ppt/slidetransition.hxx ++++ b/include/oox/ppt/slidetransition.hxx +@@ -43,7 +43,10 @@ namespace oox { namespace ppt { + void setSlideProperties( PropertyMap& props ); + void setTransitionFilterProperties( const css::uno::Reference< css::animations::XTransitionFilter > & xFilter ); + ++ /// Set one of standard values for slide transition duration + void setOoxTransitionSpeed( sal_Int32 nToken ); ++ /// Set slide transition time directly ++ void setOoxTransitionSpeed( double fDuration ); + void setMode( bool bMode ) + { mbMode = bMode; } + void setOoxAdvanceTime( sal_Int32 nAdvanceTime ) +@@ -66,6 +69,7 @@ namespace oox { namespace ppt { + ::sal_Int16 mnTransitionSubType; + bool mbTransitionDirectionNormal; + css::presentation::AnimationSpeed mnAnimationSpeed; ++ double mfTransitionDurationInSeconds; + bool mbMode; /**< http://api.libreoffice.org/docs/common/ref/com/sun/star/animations/XTransitionFilter.html Mode property */ + ::sal_Int32 mnAdvanceTime; + }; +diff --git a/offapi/com/sun/star/presentation/DrawPage.idl b/offapi/com/sun/star/presentation/DrawPage.idl +index 18e499e81420..0e070470ad25 100644 +--- a/offapi/com/sun/star/presentation/DrawPage.idl ++++ b/offapi/com/sun/star/presentation/DrawPage.idl +@@ -79,11 +79,11 @@ published service DrawPage + [property] short Layout; + + +- /** defines the speed of the fade-in effect of this page. ++ /** Defines the speed of the fade-in effect of this page. ++ @see TransitionSpeed + */ + [property] com::sun::star::presentation::AnimationSpeed Speed; + +- + /** defines if a header presentation shape from the master page is visible + on this page. + */ +@@ -142,6 +142,11 @@ published service DrawPage + */ + [optional, property] long DateTimeFormat; + ++ /** Specifies slide transition time in seconds. ++ @since LibreOffice 6.1 ++ @see Speed ++ */ ++ [property, optional] double TransitionDuration; + }; + + +diff --git a/oox/source/ppt/slidetransition.cxx b/oox/source/ppt/slidetransition.cxx +index e609e6709c2f..7c1555b7dc80 100644 +--- a/oox/source/ppt/slidetransition.cxx ++++ b/oox/source/ppt/slidetransition.cxx +@@ -45,6 +45,7 @@ namespace oox { namespace ppt { + , mnTransitionSubType( 0 ) + , mbTransitionDirectionNormal( true ) + , mnAnimationSpeed( AnimationSpeed_FAST ) ++ , mfTransitionDurationInSeconds( -1.0 ) + , mbMode( true ) + , mnAdvanceTime( -1 ) + { +@@ -56,6 +57,7 @@ namespace oox { namespace ppt { + , mnTransitionSubType( 0 ) + , mbTransitionDirectionNormal( true ) + , mnAnimationSpeed( AnimationSpeed_FAST ) ++ , mfTransitionDurationInSeconds( -1.0 ) + , mbMode( true ) + , mnAdvanceTime( -1 ) + { +@@ -76,6 +78,8 @@ namespace oox { namespace ppt { + aProps.setProperty( PROP_TransitionSubtype, mnTransitionSubType); + aProps.setProperty( PROP_TransitionDirection, mbTransitionDirectionNormal); + aProps.setProperty( PROP_Speed, mnAnimationSpeed); ++ if( mfTransitionDurationInSeconds >= 0.0 ) ++ aProps.setProperty( PROP_TransitionDuration, mfTransitionDurationInSeconds); + aProps.setProperty( PROP_TransitionFadeColor, sal_Int32(0)); + if( mnAdvanceTime != -1 ) { + aProps.setProperty( PROP_Duration, mnAdvanceTime/1000); +@@ -110,19 +114,21 @@ namespace oox { namespace ppt { + { + switch( nToken ) + { +- /* In case you want to use time values in second, +- * the speed values are located in the PPT97 importer +- * sd/source/filter/ppt/ppt97animations.cxx:664 +- * (void Ppt97Animation::UpdateCacheData() const) ++ /* the speed values are located in the PPT97 importer ++ * sd/source/filter/ppt/pptin.cxx:1783 ++ * (void ImplSdPPTImport::ImportPageEffect) + */ + case XML_fast: + mnAnimationSpeed = AnimationSpeed_FAST; ++ mfTransitionDurationInSeconds = 0.5; + break; + case XML_med: + mnAnimationSpeed = AnimationSpeed_MEDIUM; ++ mfTransitionDurationInSeconds = 0.75; + break; + case XML_slow: + mnAnimationSpeed = AnimationSpeed_SLOW; ++ mfTransitionDurationInSeconds = 1.0; + break; + default: + // should not happen. just ignore +@@ -130,6 +136,14 @@ namespace oox { namespace ppt { + } + } + ++ void SlideTransition::setOoxTransitionSpeed( double fDurationInSeconds ) ++ { ++ // for compatibility ++ mnAnimationSpeed = ( fDurationInSeconds <= 0.5 ) ? AnimationSpeed_FAST ++ : ( fDurationInSeconds >= 1.0 ) ? AnimationSpeed_SLOW : AnimationSpeed_MEDIUM; ++ mfTransitionDurationInSeconds = fDurationInSeconds; ++ } ++ + sal_Int16 SlideTransition::ooxToOdpEightDirections( ::sal_Int32 nOoxType ) + { + sal_Int16 nOdpDirection; +diff --git a/oox/source/ppt/slidetransitioncontext.cxx b/oox/source/ppt/slidetransitioncontext.cxx +index 64d6d5942ba3..7639df7c023b 100644 +--- a/oox/source/ppt/slidetransitioncontext.cxx ++++ b/oox/source/ppt/slidetransitioncontext.cxx +@@ -32,6 +32,7 @@ + #include + #include + #include ++#include + + using namespace ::com::sun::star; + using namespace ::oox::core; +@@ -50,6 +51,11 @@ SlideTransitionContext::SlideTransitionContext( FragmentHandler2 const & rParent + // ST_TransitionSpeed + maTransition.setOoxTransitionSpeed( rAttribs.getToken( XML_spd, XML_fast ) ); + ++ // p14:dur ++ sal_Int32 nDurationInMs = rAttribs.getInteger( P14_TOKEN( dur ), -1 ); ++ if( nDurationInMs > -1 ) ++ maTransition.setOoxTransitionSpeed( nDurationInMs / 1000.0 ); ++ + // TODO + rAttribs.getBool( XML_advClick, true ); + +diff --git a/oox/source/token/properties.txt b/oox/source/token/properties.txt +index e6bc79ff3d08..d5e945cc4342 100644 +--- a/oox/source/token/properties.txt ++++ b/oox/source/token/properties.txt +@@ -527,6 +527,7 @@ TopMargin + TotalsRow + Transformation + TransitionDirection ++TransitionDuration + TransitionFadeColor + TransitionSubtype + TransitionType +diff --git a/sd/source/ui/inc/unoprnms.hxx b/sd/source/ui/inc/unoprnms.hxx +index 3dd438f0ec28..1e5e3b910f3e 100644 +--- a/sd/source/ui/inc/unoprnms.hxx ++++ b/sd/source/ui/inc/unoprnms.hxx +@@ -33,6 +33,7 @@ + #define UNO_NAME_PAGE_NUMBER "Number" + #define UNO_NAME_PAGE_ORIENTATION "Orientation" + #define UNO_NAME_PAGE_SPEED "Speed" ++#define UNO_NAME_PAGE_TRANSITION_DURATION "TransitionDuration" + #define UNO_NAME_PAGE_WIDTH "Width" + #define UNO_NAME_PAGE_PREVIEW "Preview" + #define UNO_NAME_PAGE_PREVIEWBITMAP "PreviewBitmap" +diff --git a/sd/source/ui/unoidl/unopage.cxx b/sd/source/ui/unoidl/unopage.cxx +index 10f25204c810..532d10dbb569 100644 +--- a/sd/source/ui/unoidl/unopage.cxx ++++ b/sd/source/ui/unoidl/unopage.cxx +@@ -142,7 +142,7 @@ const SvxItemPropertySet* ImplGetDrawPagePropertySet( bool bImpress, PageKind eP + { OUString("TransitionSubtype"), WID_TRANSITION_SUBTYPE, ::cppu::UnoType::get(), 0, 0}, + { OUString("TransitionDirection"), WID_TRANSITION_DIRECTION, ::cppu::UnoType::get(), 0, 0}, + { OUString("TransitionFadeColor"), WID_TRANSITION_FADE_COLOR, ::cppu::UnoType::get(), 0, 0}, +- { OUString("TransitionDuration"), WID_TRANSITION_DURATION, ::cppu::UnoType::get(), 0, 0}, ++ { OUString(UNO_NAME_PAGE_TRANSITION_DURATION), WID_TRANSITION_DURATION, ::cppu::UnoType::get(), 0, 0}, + { OUString("LoopSound"), WID_LOOP_SOUND, cppu::UnoType::get(), 0, 0}, + { OUString("NavigationOrder"), WID_NAVORDER, cppu::UnoType::get(),0, 0}, + { OUString(), 0, css::uno::Type(), 0, 0 } +-- +2.13.6 + + +From 9719741507be6daa92e4af9ddfb3177fa51404ca Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Szymon=20K=C5=82os?= +Date: Mon, 5 Feb 2018 12:41:58 +0100 +Subject: [PATCH 2/4] tdf#115394 export custom transition time in PPTX +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Change-Id: Ib8f4cef713895029dc18f68a07baa4b65e4260c0 +Reviewed-on: https://gerrit.libreoffice.org/49245 +Tested-by: Jenkins +Reviewed-by: Szymon Kłos +--- + sd/qa/unit/export-tests-ooxml2.cxx | 36 ++++++++ + sd/source/filter/eppt/pptx-epptooxml.cxx | 150 ++++++++++++++++++++++--------- + 2 files changed, 145 insertions(+), 41 deletions(-) + +diff --git a/sd/source/filter/eppt/pptx-epptooxml.cxx b/sd/source/filter/eppt/pptx-epptooxml.cxx +index c5c3ca580101..9ba23b0ac016 100644 +--- a/sd/source/filter/eppt/pptx-epptooxml.cxx ++++ b/sd/source/filter/eppt/pptx-epptooxml.cxx +@@ -650,7 +650,42 @@ void PowerPointExport::WriteTransition(const FSHelperPtr& pFS) + sal_Int32 advanceTiming = -1; + sal_Int32 changeType = 0; + +- if (GETA(Speed)) ++ sal_Int32 nTransitionDuration = -1; ++ bool isTransitionDurationSet = false; ++ ++ // try to use TransitionDuration instead of old Speed property ++ if (GETA(TransitionDuration)) ++ { ++ double fTransitionDuration = -1.0; ++ mAny >>= fTransitionDuration; ++ if (fTransitionDuration >= 0) ++ { ++ nTransitionDuration = fTransitionDuration * 1000.0; ++ ++ // override values because in MS formats meaning of fast/medium/slow is different ++ if (nTransitionDuration <= 500) ++ { ++ // fast is default ++ speed = nullptr; ++ } ++ else if (nTransitionDuration >= 1000) ++ { ++ speed = "slow"; ++ } ++ else ++ { ++ speed = "med"; ++ } ++ ++ bool isStandardValue = nTransitionDuration == 500 ++ || nTransitionDuration == 750 ++ || nTransitionDuration == 1000; ++ ++ if(!isStandardValue) ++ isTransitionDurationSet = true; ++ } ++ } ++ else if (GETA(Speed)) + { + mAny >>= animationSpeed; + +@@ -670,50 +705,12 @@ void PowerPointExport::WriteTransition(const FSHelperPtr& pFS) + + if (GETA(Change)) + mAny >>= changeType; ++ bool isAdvanceTimingSet = advanceTiming != -1; + + // 1 means automatic, 2 half automatic - not sure what it means - at least I don't see it in UI + if (changeType == 1 && GETA(Duration)) + mAny >>= advanceTiming; + +- if (nTransition14 || pPresetTransition) +- { +- const char* pRequiresNS = nTransition14 ? "p14" : "p15"; +- +- pFS->startElement(FSNS(XML_mc, XML_AlternateContent), FSEND); +- pFS->startElement(FSNS(XML_mc, XML_Choice), XML_Requires, pRequiresNS, FSEND); +- +- +- pFS->startElementNS(XML_p, XML_transition, +- XML_spd, speed, +- XML_advTm, advanceTiming != -1 ? I32S(advanceTiming*1000) : nullptr, +- FSEND); +- +- if (nTransition14) +- { +- pFS->singleElementNS(XML_p14, nTransition14, +- XML_isInverted, pInverted, +- XML_dir, pDirection14, +- XML_pattern, pPattern, +- FSEND); +- } +- else if (pPresetTransition) +- { +- pFS->singleElementNS(XML_p15, XML_prstTrans, +- XML_prst, pPresetTransition, +- FSEND); +- } +- +- pFS->endElement(FSNS(XML_p, XML_transition)); +- +- pFS->endElement(FSNS(XML_mc, XML_Choice)); +- pFS->startElement(FSNS(XML_mc, XML_Fallback), FSEND); +- } +- +- pFS->startElementNS(XML_p, XML_transition, +- XML_spd, speed, +- XML_advTm, advanceTiming != -1 ? I32S(advanceTiming*1000) : nullptr, +- FSEND); +- + if (!bOOXmlSpecificTransition) + { + switch (nPPTTransitionType) +@@ -807,6 +804,77 @@ void PowerPointExport::WriteTransition(const FSHelperPtr& pFS) + } + } + ++ if (nTransition14 || pPresetTransition || isTransitionDurationSet) ++ { ++ const char* pRequiresNS = (nTransition14 || isTransitionDurationSet) ? "p14" : "p15"; ++ ++ pFS->startElement(FSNS(XML_mc, XML_AlternateContent), FSEND); ++ pFS->startElement(FSNS(XML_mc, XML_Choice), XML_Requires, pRequiresNS, FSEND); ++ ++ if(isTransitionDurationSet && isAdvanceTimingSet) ++ { ++ pFS->startElementNS(XML_p, XML_transition, ++ XML_spd, speed, ++ XML_advTm, I32S(advanceTiming * 1000), ++ FSNS(XML_p14, XML_dur), I32S(nTransitionDuration), ++ FSEND); ++ } ++ else if(isTransitionDurationSet) ++ { ++ pFS->startElementNS(XML_p, XML_transition, ++ XML_spd, speed, ++ FSNS(XML_p14, XML_dur), I32S(nTransitionDuration), ++ FSEND); ++ } ++ else if(isAdvanceTimingSet) ++ { ++ pFS->startElementNS(XML_p, XML_transition, ++ XML_spd, speed, ++ XML_advTm, I32S(advanceTiming * 1000), ++ FSEND); ++ } ++ else ++ { ++ pFS->startElementNS(XML_p, XML_transition, ++ XML_spd, speed, ++ FSEND); ++ } ++ ++ if (nTransition14) ++ { ++ pFS->singleElementNS(XML_p14, nTransition14, ++ XML_isInverted, pInverted, ++ XML_dir, pDirection14, ++ XML_pattern, pPattern, ++ FSEND); ++ } ++ else if (pPresetTransition) ++ { ++ pFS->singleElementNS(XML_p15, XML_prstTrans, ++ XML_prst, pPresetTransition, ++ FSEND); ++ } ++ else if (isTransitionDurationSet && nTransition) ++ { ++ pFS->singleElementNS(XML_p, nTransition, ++ XML_dir, pDirection, ++ XML_orient, pOrientation, ++ XML_spokes, pSpokes, ++ XML_thruBlk, pThruBlk, ++ FSEND); ++ } ++ ++ pFS->endElement(FSNS(XML_p, XML_transition)); ++ ++ pFS->endElement(FSNS(XML_mc, XML_Choice)); ++ pFS->startElement(FSNS(XML_mc, XML_Fallback), FSEND); ++ } ++ ++ pFS->startElementNS(XML_p, XML_transition, ++ XML_spd, speed, ++ XML_advTm, isAdvanceTimingSet ? I32S(advanceTiming * 1000) : nullptr, ++ FSEND); ++ + if (nTransition) + { + pFS->singleElementNS(XML_p, nTransition, +@@ -819,7 +887,7 @@ void PowerPointExport::WriteTransition(const FSHelperPtr& pFS) + + pFS->endElementNS(XML_p, XML_transition); + +- if (nTransition14 || pPresetTransition) ++ if (nTransition14 || pPresetTransition || isTransitionDurationSet) + { + pFS->endElement(FSNS(XML_mc, XML_Fallback)); + pFS->endElement(FSNS(XML_mc, XML_AlternateContent)); +-- +2.13.6 + + +From 41fe895bf25d6a0895cfd1ce78f3cbd1d3eb02b3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Szymon=20K=C5=82os?= +Date: Wed, 7 Feb 2018 12:22:52 +0100 +Subject: [PATCH 3/4] tdf#115394 export correct slide transition time in PPT +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Change-Id: Ie293dd4cc128c256e39d54fdcd83bb5e13484662 +Reviewed-on: https://gerrit.libreoffice.org/49345 +Tested-by: Jenkins +Reviewed-by: Szymon Kłos +--- + sd/qa/unit/data/ppt/tdf115394.ppt | Bin 0 -> 90112 bytes + sd/qa/unit/export-tests.cxx | 39 ++++++++++++++++++++++++++++++++++++++ + sd/qa/unit/import-tests.cxx | 25 ++++++++++++++++++++++++ + sd/source/filter/eppt/eppt.cxx | 26 ++++++++++++++++++++++--- + sd/source/filter/ppt/pptin.cxx | 6 +++--- + 5 files changed, 90 insertions(+), 6 deletions(-) + create mode 100644 sd/qa/unit/data/ppt/tdf115394.ppt + +diff --git a/sd/source/filter/eppt/eppt.cxx b/sd/source/filter/eppt/eppt.cxx +index 2b3f76a41ebf..a506a376c20f 100644 +--- a/sd/source/filter/eppt/eppt.cxx ++++ b/sd/source/filter/eppt/eppt.cxx +@@ -241,11 +241,31 @@ void PPTWriter::ImplWriteSlide( sal_uInt32 nPageNum, sal_uInt32 nMasterNum, sal_ + sal_Int32 nSlideTime = 0; // still has to !!! + sal_uInt8 nSpeed = 1; + +- if ( GetPropertyValue( aAny, mXPagePropSet, "Speed" ) ) ++ if ( GetPropertyValue( aAny, mXPagePropSet, "TransitionDuration" ) ) + { + css::presentation::AnimationSpeed aAs; +- aAny >>= aAs; +- nSpeed = (sal_uInt8)aAs; ++ double fTransitionDuration = -1.0; ++ aAny >>= fTransitionDuration; ++ ++ if (fTransitionDuration >= 0) ++ { ++ if (fTransitionDuration <= 0.5) ++ { ++ aAs = css::presentation::AnimationSpeed::AnimationSpeed_FAST; ++ } ++ else if (fTransitionDuration >= 1.0) ++ { ++ aAs = css::presentation::AnimationSpeed::AnimationSpeed_SLOW; ++ } ++ else ++ { ++ aAs = css::presentation::AnimationSpeed::AnimationSpeed_MEDIUM; ++ } ++ } ++ else ++ aAs = css::presentation::AnimationSpeed::AnimationSpeed_MEDIUM; ++ ++ nSpeed = static_cast(aAs); + } + sal_Int16 nTT = 0; + if ( GetPropertyValue( aAny, mXPagePropSet, "TransitionType" ) +diff --git a/sd/source/filter/ppt/pptin.cxx b/sd/source/filter/ppt/pptin.cxx +index 4215cd7b60a8..91a541135204 100644 +--- a/sd/source/filter/ppt/pptin.cxx ++++ b/sd/source/filter/ppt/pptin.cxx +@@ -1786,11 +1786,11 @@ void ImplSdPPTImport::ImportPageEffect( SdPage* pPage, const bool bNewAnimations + } + + if ( nSpeed == 0 ) +- pPage->setTransitionDuration( 3.0 ); // slow ++ pPage->setTransitionDuration( 1.0 ); // slow + else if ( nSpeed == 1 ) +- pPage->setTransitionDuration( 2.0 ); // medium ++ pPage->setTransitionDuration( 0.75 ); // medium + else if ( nSpeed == 2 ) +- pPage->setTransitionDuration( 1.0 ); // fast ++ pPage->setTransitionDuration( 0.5 ); // fast + + if ( nBuildFlags & 0x400 ) // slidechange by time + { // time to show (in Ticks) +-- +2.13.6 + + +From b49d7f142bf33a961b8a5ba1ba92e6dc85134940 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Szymon=20K=C5=82os?= +Date: Thu, 8 Feb 2018 23:21:38 +0100 +Subject: [PATCH 4/4] tdf#115394 correct transition in case of 0s +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Change-Id: I23d18acef0bd5db4a4ad6fc67d409e7ed5c93949 +Reviewed-on: https://gerrit.libreoffice.org/49462 +Tested-by: Jenkins +Reviewed-by: Szymon Kłos +--- + include/oox/ppt/slidetransitioncontext.hxx | 1 + + oox/source/ppt/slidetransitioncontext.cxx | 9 ++++++++- + sd/qa/unit/data/pptx/tdf115394-zero.pptx | Bin 0 -> 34352 bytes + sd/qa/unit/export-tests-ooxml2.cxx | 16 ++++++++++++++++ + sd/source/filter/eppt/pptx-epptooxml.cxx | 8 ++++---- + 5 files changed, 29 insertions(+), 5 deletions(-) + create mode 100644 sd/qa/unit/data/pptx/tdf115394-zero.pptx + +diff --git a/include/oox/ppt/slidetransitioncontext.hxx b/include/oox/ppt/slidetransitioncontext.hxx +index 3361fd07a5a5..f6b2e7a91d56 100644 +--- a/include/oox/ppt/slidetransitioncontext.hxx ++++ b/include/oox/ppt/slidetransitioncontext.hxx +@@ -47,6 +47,7 @@ namespace oox { namespace ppt { + private: + PropertyMap& maSlideProperties; + bool mbHasTransition; ++ bool mbHasTransitionDuration; + SlideTransition maTransition; + }; + +diff --git a/oox/source/ppt/slidetransitioncontext.cxx b/oox/source/ppt/slidetransitioncontext.cxx +index 7639df7c023b..94fc1c3862ae 100644 +--- a/oox/source/ppt/slidetransitioncontext.cxx ++++ b/oox/source/ppt/slidetransitioncontext.cxx +@@ -47,6 +47,7 @@ SlideTransitionContext::SlideTransitionContext( FragmentHandler2 const & rParent + : FragmentHandler2( rParent ) + , maSlideProperties( aProperties ) + , mbHasTransition( false ) ++, mbHasTransitionDuration( false ) + { + // ST_TransitionSpeed + maTransition.setOoxTransitionSpeed( rAttribs.getToken( XML_spd, XML_fast ) ); +@@ -54,7 +55,13 @@ SlideTransitionContext::SlideTransitionContext( FragmentHandler2 const & rParent + // p14:dur + sal_Int32 nDurationInMs = rAttribs.getInteger( P14_TOKEN( dur ), -1 ); + if( nDurationInMs > -1 ) ++ { ++ // In MSO 0 is visible as 0.01s ++ if( nDurationInMs == 0.0 ) ++ nDurationInMs = 10; + maTransition.setOoxTransitionSpeed( nDurationInMs / 1000.0 ); ++ mbHasTransitionDuration = true; ++ } + + // TODO + rAttribs.getBool( XML_advClick, true ); +@@ -182,7 +189,7 @@ void SlideTransitionContext::onEndElement() + { + if( isCurrentElement(PPT_TOKEN( transition )) ) + { +- if( mbHasTransition ) ++ if( mbHasTransition || mbHasTransitionDuration ) + { + maTransition.setSlideProperties( maSlideProperties ); + mbHasTransition = false; +diff --git a/sd/source/filter/eppt/pptx-epptooxml.cxx b/sd/source/filter/eppt/pptx-epptooxml.cxx +index 9ba23b0ac016..1ab1a7dc68ff 100644 +--- a/sd/source/filter/eppt/pptx-epptooxml.cxx ++++ b/sd/source/filter/eppt/pptx-epptooxml.cxx +@@ -641,10 +641,6 @@ void PowerPointExport::WriteTransition(const FSHelperPtr& pFS) + } + } + +- // check if we resolved what transition to export +- if (!nPPTTransitionType && !bOOXmlSpecificTransition) +- return; +- + AnimationSpeed animationSpeed = AnimationSpeed_MEDIUM; + const char* speed = nullptr; + sal_Int32 advanceTiming = -1; +@@ -703,6 +699,10 @@ void PowerPointExport::WriteTransition(const FSHelperPtr& pFS) + } + } + ++ // check if we resolved what transition to export or time is set ++ if (!nPPTTransitionType && !bOOXmlSpecificTransition && !isTransitionDurationSet) ++ return; ++ + if (GETA(Change)) + mAny >>= changeType; + bool isAdvanceTimingSet = advanceTiming != -1; +-- +2.13.6 + diff --git a/bnc1060128.patch b/bnc1060128.patch new file mode 100644 index 0000000..483cf7c --- /dev/null +++ b/bnc1060128.patch @@ -0,0 +1,1130 @@ +From 85753e0f2759960dd87f6ecf9245e764a9f9bf11 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Szymon=20K=C5=82os?= +Date: Thu, 4 Jan 2018 22:15:32 +0100 +Subject: [PATCH 1/2] tdf#114821 import complex data labels in bar chart +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +* import static text & fields: + VALUE, SERIESNAME, COLUMNNAME +* text is formatted +* DataPointCustomLabelField with field type + (DataPointCustomLabelFieldType) was introduced. +* text can have many portions & multiple lines +* unit tests for import data labels with formatting + +Not implemented: CELLREF field support which needs +importing some additional data from extLst + +Shows custom text as a label for data points. + +Change-Id: Iba8fd508eb16356b05586b93d7b8da32240d2b91 +Reviewed-on: https://gerrit.libreoffice.org/48243 +Tested-by: Jenkins +Reviewed-by: Szymon Kłos +--- + chart2/inc/unonames.hxx | 1 + + chart2/qa/extras/chart2import.cxx | 154 +++++++++++++++++++++ + chart2/qa/extras/data/pptx/tdf115107-2.pptx | Bin 0 -> 50519 bytes + chart2/qa/extras/data/pptx/tdf115107.pptx | Bin 0 -> 50726 bytes + chart2/source/chartcore.component | 1 + + chart2/source/model/main/DataPointProperties.cxx | 11 +- + chart2/source/model/main/DataPointProperties.hxx | 3 +- + chart2/source/model/main/FormattedString.cxx | 40 ++++++ + chart2/source/model/main/FormattedString.hxx | 16 ++- + chart2/source/view/charttypes/VSeriesPlotter.cxx | 126 +++++++++++++++-- + chart2/source/view/inc/AbstractShapeFactory.hxx | 7 + + chart2/source/view/inc/OpenglShapeFactory.hxx | 7 + + chart2/source/view/inc/ShapeFactory.hxx | 7 + + chart2/source/view/inc/VSeriesPlotter.hxx | 2 + + chart2/source/view/main/OpenglShapeFactory.cxx | 12 ++ + chart2/source/view/main/ShapeFactory.cxx | 94 +++++++++++++ + offapi/UnoApi_offapi.mk | 3 + + .../sun/star/chart2/DataPointCustomLabelField.idl | 26 ++++ + .../star/chart2/DataPointCustomLabelFieldType.idl | 33 +++++ + offapi/com/sun/star/chart2/DataPointProperties.idl | 8 ++ + .../sun/star/chart2/XDataPointCustomLabelField.idl | 43 ++++++ + oox/inc/drawingml/textfield.hxx | 2 + + oox/source/drawingml/chart/seriesconverter.cxx | 78 +++++++++++ + oox/source/token/properties.txt | 1 + + 24 files changed, 657 insertions(+), 18 deletions(-) + create mode 100644 chart2/qa/extras/data/pptx/tdf115107-2.pptx + create mode 100644 chart2/qa/extras/data/pptx/tdf115107.pptx + create mode 100644 offapi/com/sun/star/chart2/DataPointCustomLabelField.idl + create mode 100644 offapi/com/sun/star/chart2/DataPointCustomLabelFieldType.idl + create mode 100644 offapi/com/sun/star/chart2/XDataPointCustomLabelField.idl + +diff --git a/chart2/inc/unonames.hxx b/chart2/inc/unonames.hxx +index 867a155e14aa..44c3bf67d3cb 100644 +--- a/chart2/inc/unonames.hxx ++++ b/chart2/inc/unonames.hxx +@@ -29,6 +29,7 @@ + #define CHART_UNONAME_LABEL_BORDER_DASH "LabelBorderDash" + #define CHART_UNONAME_LABEL_BORDER_DASHNAME "LabelBorderDashName" + #define CHART_UNONAME_LABEL_BORDER_TRANS "LabelBorderTransparency" ++#define CHART_UNONAME_CUSTOM_LABEL_FIELDS "CustomLabelFields" + + #endif + +diff --git a/chart2/source/chartcore.component b/chart2/source/chartcore.component +index f7a1783eda68..45c87f93d633 100644 +--- a/chart2/source/chartcore.component ++++ b/chart2/source/chartcore.component +@@ -158,6 +158,7 @@ + constructor="com_sun_star_comp_chart_FormattedString_get_implementation"> + + ++ + + +diff --git a/chart2/source/model/main/DataPointProperties.cxx b/chart2/source/model/main/DataPointProperties.cxx +index 66e0b88d1f5a..dbc950c2195b 100644 +--- a/chart2/source/model/main/DataPointProperties.cxx ++++ b/chart2/source/model/main/DataPointProperties.cxx +@@ -30,7 +30,7 @@ + #include + #include + #include +- ++#include + #include + #include + #include +@@ -406,6 +406,12 @@ void DataPointProperties::AddPropertiesToVector( + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); ++ ++ rOutProperties.emplace_back( CHART_UNONAME_CUSTOM_LABEL_FIELDS, ++ PROP_DATAPOINT_CUSTOM_LABEL_FIELDS, ++ cppu::UnoType>>::get(), ++ beans::PropertyAttribute::BOUND ++ | beans::PropertyAttribute::MAYBEDEFAULT); + } + + void DataPointProperties::AddDefaultsToMap( +@@ -486,6 +492,9 @@ void DataPointProperties::AddDefaultsToMap( + PropertyHelper::setPropertyValueDefault(rOutMap, PROP_DATAPOINT_LABEL_BORDER_DASH, drawing::LineDash()); + PropertyHelper::setEmptyPropertyValueDefault(rOutMap, PROP_DATAPOINT_LABEL_BORDER_DASH_NAME); + PropertyHelper::setPropertyValueDefault(rOutMap, PROP_DATAPOINT_LABEL_BORDER_TRANS, 0); ++ ++ uno::Sequence> aFields(0); ++ PropertyHelper::setPropertyValueDefault(rOutMap, PROP_DATAPOINT_CUSTOM_LABEL_FIELDS, aFields); + } + + } // namespace chart +diff --git a/chart2/source/model/main/DataPointProperties.hxx b/chart2/source/model/main/DataPointProperties.hxx +index 3daf838e5da5..6490b5c8cfe5 100644 +--- a/chart2/source/model/main/DataPointProperties.hxx ++++ b/chart2/source/model/main/DataPointProperties.hxx +@@ -80,7 +80,8 @@ namespace DataPointProperties + PROP_DATAPOINT_LABEL_BORDER_WIDTH, + PROP_DATAPOINT_LABEL_BORDER_DASH, + PROP_DATAPOINT_LABEL_BORDER_DASH_NAME, +- PROP_DATAPOINT_LABEL_BORDER_TRANS ++ PROP_DATAPOINT_LABEL_BORDER_TRANS, ++ PROP_DATAPOINT_CUSTOM_LABEL_FIELDS + + // additionally some properites from ::chart::LineProperties + }; +diff --git a/chart2/source/model/main/FormattedString.cxx b/chart2/source/model/main/FormattedString.cxx +index 4f26acc95e3f..2dfcca2d35c5 100644 +--- a/chart2/source/model/main/FormattedString.cxx ++++ b/chart2/source/model/main/FormattedString.cxx +@@ -95,6 +95,8 @@ namespace chart + FormattedString::FormattedString() : + ::property::OPropertySet( m_aMutex ), + m_aString(), ++ m_aType(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT), ++ m_aGuid(), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) + {} + +@@ -103,6 +105,8 @@ FormattedString::FormattedString( const FormattedString & rOther ) : + impl::FormattedString_Base(), + ::property::OPropertySet( rOther, m_aMutex ), + m_aString( rOther.m_aString ), ++ m_aType(rOther.m_aType), ++ m_aGuid(rOther.m_aGuid), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) + {} + +@@ -133,6 +137,41 @@ void SAL_CALL FormattedString::setString( const OUString& String ) + + } + ++// ____ XDataPointCustomLabelField ____ ++css::chart2::DataPointCustomLabelFieldType SAL_CALL FormattedString::getFieldType() ++{ ++ MutexGuard aGuard(GetMutex()); ++ return m_aType; ++} ++ ++void SAL_CALL ++FormattedString::setFieldType(const css::chart2::DataPointCustomLabelFieldType Type) ++{ ++ { ++ MutexGuard aGuard(GetMutex()); ++ m_aType = Type; ++ } ++ //don't keep the mutex locked while calling out ++ fireModifyEvent(); ++} ++ ++OUString SAL_CALL FormattedString::getGuid() ++{ ++ MutexGuard aGuard( GetMutex()); ++ return m_aGuid; ++} ++ ++void SAL_CALL FormattedString::setGuid( const OUString& guid ) ++{ ++ { ++ MutexGuard aGuard( GetMutex()); ++ m_aGuid= guid; ++ } ++ //don't keep the mutex locked while calling out ++ fireModifyEvent(); ++ ++} ++ + // ____ XModifyBroadcaster ____ + void SAL_CALL FormattedString::addModifyListener( const uno::Reference< util::XModifyListener >& aListener ) + { +@@ -226,6 +265,7 @@ sal_Bool SAL_CALL FormattedString::supportsService( const OUString& rServiceName + css::uno::Sequence< OUString > SAL_CALL FormattedString::getSupportedServiceNames() + { + return { ++ "com.sun.star.chart2.DataPointCustomLabelField", + "com.sun.star.chart2.FormattedString", + "com.sun.star.beans.PropertySet" }; + } +diff --git a/chart2/source/model/main/FormattedString.hxx b/chart2/source/model/main/FormattedString.hxx +index 16c73372ebcc..aee7674081be 100644 +--- a/chart2/source/model/main/FormattedString.hxx ++++ b/chart2/source/model/main/FormattedString.hxx +@@ -26,6 +26,8 @@ + #include + #include + #include ++#include ++#include + #include + #include + +@@ -35,7 +37,7 @@ namespace chart + namespace impl + { + typedef ::cppu::WeakImplHelper< +- css::chart2::XFormattedString2, ++ css::chart2::XDataPointCustomLabelField, // inherits from XFormattedString2 + css::lang::XServiceInfo, + css::util::XCloneable, + css::util::XModifyBroadcaster, +@@ -82,6 +84,13 @@ private: + virtual OUString SAL_CALL getString() override; + virtual void SAL_CALL setString( const OUString& String ) override; + ++ // ____ XDataPointCustomLabelField ____ ++ virtual css::chart2::DataPointCustomLabelFieldType SAL_CALL getFieldType() override; ++ virtual void SAL_CALL ++ setFieldType( const css::chart2::DataPointCustomLabelFieldType FieldType ) override; ++ virtual OUString SAL_CALL getGuid() override; ++ void SAL_CALL setGuid( const OUString& guid ) override; ++ + // ____ OPropertySet ____ + virtual css::uno::Any GetDefaultValue( sal_Int32 nHandle ) const override; + +@@ -115,8 +124,13 @@ private: + + void fireModifyEvent(); + ++ // ____ XFormattedString ____ + OUString m_aString; + ++ // ____ XDataPointCustomLabelField ____ ++ css::chart2::DataPointCustomLabelFieldType m_aType; ++ OUString m_aGuid; ++ + css::uno::Reference< css::util::XModifyListener > m_xModifyEventForwarder; + }; + +diff --git a/chart2/source/view/charttypes/VSeriesPlotter.cxx b/chart2/source/view/charttypes/VSeriesPlotter.cxx +index af1544b22815..23cad6ada542 100644 +--- a/chart2/source/view/charttypes/VSeriesPlotter.cxx ++++ b/chart2/source/view/charttypes/VSeriesPlotter.cxx +@@ -56,6 +56,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -413,9 +414,21 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re + , sal_Int32 nTextWidth ) + { + uno::Reference< drawing::XShape > xTextShape; ++ Sequence> aCustomLabels; + + try + { ++ const uno::Reference< css::beans::XPropertySet >& xPropertySet( ++ rDataSeries.getPropertiesOfPoint( nPointIndex ) ); ++ if( xPropertySet.is() ) ++ { ++ uno::Any aAny = xPropertySet->getPropertyValue( CHART_UNONAME_CUSTOM_LABEL_FIELDS ); ++ if( aAny.hasValue() ) ++ { ++ aAny >>= aCustomLabels; ++ } ++ } ++ + awt::Point aScreenPosition2D(rScreenPosition2D); + if(eAlignment==LABEL_ALIGN_LEFT) + aScreenPosition2D.X -= nOffset; +@@ -495,26 +508,75 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re + } + + sal_Int32 nLineCountForSymbolsize = 0; +- Sequence< OUString > aTextList(3); ++ sal_uInt32 nTextListLength = 3; ++ sal_uInt32 nCustomLabelsCount = aCustomLabels.getLength(); ++ bool bUseCustomLabel = false; ++ Sequence< OUString > aTextList( nTextListLength ); ++ ++ bUseCustomLabel = nCustomLabelsCount > 0; ++ if( bUseCustomLabel ) + { +- if(pLabel->ShowCategoryName) ++ nTextListLength = ( nCustomLabelsCount > 3 ) ? nCustomLabelsCount : 3; ++ aSeparator = ""; ++ aTextList = Sequence< OUString >( nTextListLength ); ++ for( sal_uInt32 i = 0; i < nCustomLabelsCount; ++i ) + { +- if( m_pExplicitCategoriesProvider ) ++ switch( aCustomLabels[i]->getFieldType() ) + { +- Sequence< OUString > aCategories( m_pExplicitCategoriesProvider->getSimpleCategories() ); +- if( nPointIndex >= 0 && nPointIndex < aCategories.getLength() ) ++ case DataPointCustomLabelFieldType_VALUE: ++ { ++ aTextList[i] = getLabelTextForValue( rDataSeries, nPointIndex, fValue, false ); ++ break; ++ } ++ case DataPointCustomLabelFieldType_CATEGORYNAME: ++ { ++ aTextList[i] = getCategoryName( nPointIndex ); ++ break; ++ } ++ case DataPointCustomLabelFieldType_SERIESNAME: + { +- aTextList[0] = aCategories[nPointIndex]; ++ OUString aRole; ++ if ( m_xChartTypeModel ) ++ aRole = m_xChartTypeModel->getRoleOfSequenceForSeriesLabel(); ++ uno::Reference< XDataSeries > xSeries( rDataSeries.getModel() ); ++ aTextList[i] = DataSeriesHelper::getDataSeriesLabel( xSeries, aRole ); ++ break; + } ++ case DataPointCustomLabelFieldType_CELLREF: ++ { ++ // TODO: for now doesn't show placeholder ++ aTextList[i] = OUString(); ++ break; ++ } ++ case DataPointCustomLabelFieldType_TEXT: ++ { ++ aTextList[i] = aCustomLabels[i]->getString(); ++ break; ++ } ++ case DataPointCustomLabelFieldType_NEWLINE: ++ { ++ aTextList[i] = "\n"; ++ break; ++ } ++ default: ++ break; + } ++ aCustomLabels[i]->setString( aTextList[i] ); ++ } ++ } ++ else ++ { ++ if( pLabel->ShowCategoryName ) ++ { ++ aTextList[0] = getCategoryName( nPointIndex ); + } + +- if(pLabel->ShowNumber) ++ if( pLabel->ShowNumber ) + { + aTextList[1] = getLabelTextForValue(rDataSeries, nPointIndex, fValue, false); + } + +- if(pLabel->ShowNumberInPercent) ++ if( pLabel->ShowNumberInPercent ) + { + if(fSumValue==0.0) + fSumValue=1.0; +@@ -524,13 +586,13 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re + + aTextList[2] = getLabelTextForValue(rDataSeries, nPointIndex, fValue, true); + } ++ } + +- for( sal_Int32 nN = 0; nN < 3; ++nN) ++ for( sal_Int32 nN = 0; nN < aTextList.getLength(); ++nN ) ++ { ++ if( !aTextList[nN].isEmpty() ) + { +- if( !aTextList[nN].isEmpty() ) +- { +- ++nLineCountForSymbolsize; +- } ++ ++nLineCountForSymbolsize; + } + } + +@@ -549,7 +611,28 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re + // a multi-line label. + bool bMultiLineLabel = ( aSeparator == "\n" ); + +- if( bMultiLineLabel ) ++ if( bUseCustomLabel ) ++ { ++ Sequence< uno::Reference< XFormattedString > > aFormattedLabels( aCustomLabels.getLength() ); ++ for( int i = 0; i < aFormattedLabels.getLength(); i++ ) ++ { ++ uno::Reference< XFormattedString > xString( aCustomLabels[i], uno::UNO_QUERY ); ++ aFormattedLabels[i] = xString; ++ } ++ ++ // center the text ++ sal_uInt32 nProperties = pPropNames->getLength(); ++ pPropNames->realloc( nProperties + 1 ); ++ pPropValues->realloc( nProperties + 1 ); ++ (*pPropNames)[ nProperties ] = UNO_NAME_EDIT_PARA_ADJUST; ++ (*pPropValues)[ nProperties ] <<= style::ParagraphAdjust_CENTER; ++ ++ // create text shape ++ xTextShape = AbstractShapeFactory::getOrCreateShapeFactory( m_xShapeFactory )-> ++ createText( xTarget_, aFormattedLabels, *pPropNames, *pPropValues, ++ AbstractShapeFactory::makeTransformation( aScreenPosition2D ) ); ++ } ++ else if( bMultiLineLabel ) + { + // prepare properties for each paragraph + // we want to have the value and percent value centered respect +@@ -575,7 +658,7 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re + { + // join text list elements + OUStringBuffer aText; +- for( sal_Int32 nN = 0; nN < 3; ++nN) ++ for( sal_uInt32 nN = 0; nN < nTextListLength; ++nN) + { + if( !aTextList[nN].isEmpty() ) + { +@@ -2050,6 +2133,19 @@ VDataSeries* VSeriesPlotter::getFirstSeries() const + return nullptr; + } + ++OUString VSeriesPlotter::getCategoryName( sal_Int32 nPointIndex ) const ++{ ++ if (m_pExplicitCategoriesProvider) ++ { ++ Sequence< OUString > aCategories(m_pExplicitCategoriesProvider->getSimpleCategories()); ++ if (nPointIndex >= 0 && nPointIndex < aCategories.getLength()) ++ { ++ return aCategories[nPointIndex]; ++ } ++ } ++ return OUString(); ++} ++ + uno::Sequence< OUString > VSeriesPlotter::getSeriesNames() const + { + std::vector aRetVector; +diff --git a/chart2/source/view/inc/AbstractShapeFactory.hxx b/chart2/source/view/inc/AbstractShapeFactory.hxx +index 26512214341d..e281e6291ebf 100644 +--- a/chart2/source/view/inc/AbstractShapeFactory.hxx ++++ b/chart2/source/view/inc/AbstractShapeFactory.hxx +@@ -200,6 +200,13 @@ public: + , const css::uno::Any& rATransformation ) = 0; + + virtual css::uno::Reference< css::drawing::XShape > ++ createText(const css::uno::Reference< css::drawing::XShapes >& xTarget ++ , css::uno::Sequence< css::uno::Reference< css::chart2::XFormattedString > >& xFormattedString ++ , const tNameSequence& rPropNames ++ , const tAnySequence& rPropValues ++ , const css::uno::Any& rATransformation) = 0; ++ ++ virtual css::uno::Reference< css::drawing::XShape > + createText( const css::uno::Reference< css::drawing::XShapes >& xTarget2D, + const css::awt::Size& rSize, + const css::awt::Point& rPosition, +diff --git a/chart2/source/view/inc/OpenglShapeFactory.hxx b/chart2/source/view/inc/OpenglShapeFactory.hxx +index 01b2223cf59c..7963068ce79e 100644 +--- a/chart2/source/view/inc/OpenglShapeFactory.hxx ++++ b/chart2/source/view/inc/OpenglShapeFactory.hxx +@@ -151,6 +151,13 @@ public: + , const css::uno::Any& rATransformation ) override; + + virtual css::uno::Reference< css::drawing::XShape > ++ createText( const css::uno::Reference< css::drawing::XShapes >& xTarget ++ , css::uno::Sequence< css::uno::Reference< css::chart2::XFormattedString > >& xFormattedString ++ , const tNameSequence& rPropNames ++ , const tAnySequence& rPropValues ++ , const css::uno::Any& rATransformation ) override; ++ ++ virtual css::uno::Reference< css::drawing::XShape > + createText( const css::uno::Reference< css::drawing::XShapes >& xTarget2D, + const css::awt::Size& rSize, + const css::awt::Point& rPosition, +diff --git a/chart2/source/view/inc/ShapeFactory.hxx b/chart2/source/view/inc/ShapeFactory.hxx +index 02a75d3a0764..ec1080732142 100644 +--- a/chart2/source/view/inc/ShapeFactory.hxx ++++ b/chart2/source/view/inc/ShapeFactory.hxx +@@ -189,6 +189,13 @@ public: + , const css::uno::Any& rATransformation ) override; + + virtual css::uno::Reference< css::drawing::XShape > ++ createText(const css::uno::Reference< css::drawing::XShapes >& xTarget ++ , css::uno::Sequence< css::uno::Reference< css::chart2::XFormattedString > >& xFormattedString ++ , const tNameSequence& rPropNames ++ , const tAnySequence& rPropValues ++ , const css::uno::Any& rATransformation) override; ++ ++ virtual css::uno::Reference< css::drawing::XShape > + createText( const css::uno::Reference< css::drawing::XShapes >& xTarget2D, + const css::awt::Size& rSize, + const css::awt::Point& rPosition, +diff --git a/chart2/source/view/inc/VSeriesPlotter.hxx b/chart2/source/view/inc/VSeriesPlotter.hxx +index 54f3f7733d63..d8b1cf05eb2b 100644 +--- a/chart2/source/view/inc/VSeriesPlotter.hxx ++++ b/chart2/source/view/inc/VSeriesPlotter.hxx +@@ -389,6 +389,8 @@ protected: + + VDataSeries* getFirstSeries() const; + ++ OUString getCategoryName( sal_Int32 nPointIndex ) const; ++ + protected: + PlottingPositionHelper* m_pMainPosHelper; + +diff --git a/chart2/source/view/main/OpenglShapeFactory.cxx b/chart2/source/view/main/OpenglShapeFactory.cxx +index 9cb3318f7fa2..e6c4980b8017 100644 +--- a/chart2/source/view/main/OpenglShapeFactory.cxx ++++ b/chart2/source/view/main/OpenglShapeFactory.cxx +@@ -408,6 +408,18 @@ uno::Reference< drawing::XShape > + } + + uno::Reference< drawing::XShape > ++ OpenglShapeFactory::createText( const uno::Reference< drawing::XShapes >& xTarget ++ , uno::Sequence< uno::Reference< chart2::XFormattedString > >& rFormattedString ++ , const tNameSequence& rPropNames ++ , const tAnySequence& rPropValues ++ , const uno::Any& rATransformation ) ++{ ++ dummy::DummyText* pText = new dummy::DummyText( rFormattedString[0]->getString(), rPropNames, rPropValues, ++ rATransformation, xTarget, 0 ); ++ return pText; ++} ++ ++uno::Reference< drawing::XShape > + OpenglShapeFactory::createText( const uno::Reference< drawing::XShapes >& xTarget, + const awt::Size& , const awt::Point& rPos, + uno::Sequence< uno::Reference< chart2::XFormattedString > >& rFormattedString, +diff --git a/chart2/source/view/main/ShapeFactory.cxx b/chart2/source/view/main/ShapeFactory.cxx +index 3ed37f316225..2a72f969fa10 100644 +--- a/chart2/source/view/main/ShapeFactory.cxx ++++ b/chart2/source/view/main/ShapeFactory.cxx +@@ -2237,6 +2237,100 @@ uno::Reference< drawing::XShape > + } + + uno::Reference< drawing::XShape > ++ ShapeFactory::createText( const uno::Reference< drawing::XShapes >& xTarget ++ , uno::Sequence< uno::Reference< chart2::XFormattedString > >& xFormattedString ++ , const tNameSequence& rPropNames ++ , const tAnySequence& rPropValues ++ , const uno::Any& rATransformation ) ++{ ++ if( !xTarget.is() ) ++ return nullptr; ++ ++ if( !xFormattedString.hasElements() ) ++ return nullptr; ++ ++ sal_Int32 nNumberOfParagraphs = xFormattedString.getLength(); ++ ++ bool bNotEmpty = false; ++ for( sal_Int32 nN = 0; nN < nNumberOfParagraphs; ++nN ) ++ { ++ if( !xFormattedString[nN]->getString().isEmpty() ) ++ { ++ bNotEmpty = true; ++ break; ++ } ++ } ++ if( !bNotEmpty ) ++ return nullptr; ++ ++ //create shape and add to page ++ uno::Reference< drawing::XShape > xShape( ++ m_xShapeFactory->createInstance( ++ "com.sun.star.drawing.TextShape" ), uno::UNO_QUERY ); ++ xTarget->add(xShape); ++ ++ //set paragraph properties ++ bNotEmpty = false; ++ Reference< text::XText > xText( xShape, uno::UNO_QUERY ); ++ if( xText.is() ) ++ { ++ // the first cursor is used for appending the next paragraph, ++ // after a new string has been inserted the cursor is moved at the end ++ // of the inserted string ++ // the second cursor is used for selecting the paragraph and apply the ++ // passed text properties ++ Reference< text::XTextCursor > xInsertCursor = xText->createTextCursor(); ++ Reference< text::XTextCursor > xSelectionCursor = xText->createTextCursor(); ++ if( xInsertCursor.is() && xSelectionCursor.is() ) ++ { ++ uno::Reference< beans::XPropertySet > xSelectionProp( xSelectionCursor, uno::UNO_QUERY ); ++ if( xSelectionProp.is() ) ++ { ++ for( sal_Int32 nN = 0; nN < nNumberOfParagraphs; ++nN ) ++ { ++ if( !xFormattedString[nN]->getString().isEmpty() ) ++ { ++ xInsertCursor->gotoEnd( false ); ++ xSelectionCursor->gotoEnd( false ); ++ xText->insertString( xInsertCursor, xFormattedString[nN]->getString(), false ); ++ bNotEmpty = true; ++ xSelectionCursor->gotoEnd( true ); // select current paragraph ++ uno::Reference< beans::XPropertySet > xStringProperties( xFormattedString[nN], uno::UNO_QUERY ); ++ PropertyMapper::setMappedProperties( xSelectionProp, xStringProperties, ++ PropertyMapper::getPropertyNameMapForTextShapeProperties() ); ++ } ++ } ++ } ++ } ++ } ++ ++ if( !bNotEmpty ) ++ return nullptr; ++ ++ uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY ); ++ if( xProp.is() ) ++ { ++ //set whole text shape properties ++ PropertyMapper::setMultiProperties( rPropNames, rPropValues, xProp ); ++ ++ if( rATransformation.hasValue() ) ++ { ++ //set position matrix ++ //the matrix needs to be set at the end behind autogrow and such position influencing properties ++ try ++ { ++ xProp->setPropertyValue( "Transformation", rATransformation ); ++ } ++ catch( const uno::Exception& e ) ++ { ++ SAL_WARN("chart2", "Exception caught. " << e ); ++ } ++ } ++ } ++ return xShape; ++} ++ ++uno::Reference< drawing::XShape > + ShapeFactory::createText( const uno::Reference< drawing::XShapes >& xTarget, + const awt::Size& rSize, + const awt::Point& rPos, +diff --git a/offapi/UnoApi_offapi.mk b/offapi/UnoApi_offapi.mk +index 472771a5c15d..b50864a25880 100644 +--- a/offapi/UnoApi_offapi.mk ++++ b/offapi/UnoApi_offapi.mk +@@ -69,6 +69,8 @@ $(eval $(call gb_UnoApi_add_idlfiles_nohdl,offapi,com/sun/star/awt/tree,\ + $(eval $(call gb_UnoApi_add_idlfiles_nohdl,offapi,com/sun/star/chart2,\ + CartesianCoordinateSystem2d \ + CartesianCoordinateSystem3d \ ++ DataPointCustomLabelField \ ++ DataPointCustomLabelFieldType \ + ExponentialRegressionCurve \ + ExponentialScaling \ + FormattedString \ +@@ -2024,6 +2026,7 @@ $(eval $(call gb_UnoApi_add_idlfiles,offapi,com/sun/star/chart2,\ + XCoordinateSystem \ + XCoordinateSystemContainer \ + XDataInterpreter \ ++ XDataPointCustomLabelField \ + XDataSeries \ + XDataSeriesContainer \ + XDefaultSizeTransmitter \ +diff --git a/offapi/com/sun/star/chart2/DataPointCustomLabelField.idl b/offapi/com/sun/star/chart2/DataPointCustomLabelField.idl +new file mode 100644 +index 000000000000..cebe1c3273f3 +--- /dev/null ++++ b/offapi/com/sun/star/chart2/DataPointCustomLabelField.idl +@@ -0,0 +1,26 @@ ++/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ ++/* ++ * 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/. ++ */ ++ ++#ifndef com_sun_star_chart2_DataPointCustomLabelField_idl ++#define com_sun_star_chart2_DataPointCustomLabelField_idl ++ ++#include ++ ++module com { module sun { module star { module chart2 { ++ ++/** ++ @since LibreOffice 6.1 ++*/ ++service DataPointCustomLabelField : XDataPointCustomLabelField; ++ ++}; }; }; }; ++ ++#endif ++ ++/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ +\ No newline at end of file +diff --git a/offapi/com/sun/star/chart2/DataPointCustomLabelFieldType.idl b/offapi/com/sun/star/chart2/DataPointCustomLabelFieldType.idl +new file mode 100644 +index 000000000000..0b7f925342a6 +--- /dev/null ++++ b/offapi/com/sun/star/chart2/DataPointCustomLabelFieldType.idl +@@ -0,0 +1,33 @@ ++/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ ++/* ++ * 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/. ++ */ ++ ++#ifndef com_sun_star_chart2_DataPointCustomLabelFieldType_idl ++#define com_sun_star_chart2_DataPointCustomLabelFieldType_idl ++ ++module com { module sun { module star { module chart2 { ++ ++/** The Field type enumeration for custom data point labels. ++ ++ @since LibreOffice 6.1 ++ */ ++enum DataPointCustomLabelFieldType ++{ ++ TEXT, ++ VALUE, ++ SERIESNAME, ++ CATEGORYNAME, ++ CELLREF, ++ NEWLINE ++}; ++ ++}; }; }; }; ++ ++#endif ++ ++/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ +\ No newline at end of file +diff --git a/offapi/com/sun/star/chart2/DataPointProperties.idl b/offapi/com/sun/star/chart2/DataPointProperties.idl +index 31bd0a42696c..df5cf071ee90 100644 +--- a/offapi/com/sun/star/chart2/DataPointProperties.idl ++++ b/offapi/com/sun/star/chart2/DataPointProperties.idl +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include + + module com + { +@@ -258,6 +259,13 @@ service DataPointProperties + + [property] DataPointLabel Label; + ++ /** specifies a text with possible fields that is used as a data point label, ++ if set then Label property is ignored ++ ++ @since LibreOffice 6.1 ++ */ ++ [optional, property] sequence CustomLabelFields; ++ + /** specifies a string that is used to separate the parts of a data label (caption) + */ + [optional, property] string LabelSeparator; +diff --git a/offapi/com/sun/star/chart2/XDataPointCustomLabelField.idl b/offapi/com/sun/star/chart2/XDataPointCustomLabelField.idl +new file mode 100644 +index 000000000000..a6a1b0151c94 +--- /dev/null ++++ b/offapi/com/sun/star/chart2/XDataPointCustomLabelField.idl +@@ -0,0 +1,43 @@ ++/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ ++/* ++ * 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/. ++ */ ++#ifndef com_sun_star_chart2_DataPointCustomLabelField_idl ++#define com_sun_star_chart2_DataPointCustomLabelField_idl ++ ++#include ++#include ++ ++module com { module sun { module star { module chart2 { ++ ++/** ++ Provides interface for DataPointCustomLabelField service. ++ ++ @since LibreOffice 6.1 ++*/ ++interface XDataPointCustomLabelField : XFormattedString2 ++{ ++ DataPointCustomLabelFieldType getFieldType(); ++ ++ void setFieldType( [in] DataPointCustomLabelFieldType fieldType ); ++ ++ string getGuid(); ++ ++ void setGuid( [in] string guid ); ++ ++}; ++ ++ ++ ++} ; // chart2 ++} ; // com ++} ; // sun ++} ; // star ++ ++#endif ++ ++/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ +diff --git a/oox/inc/drawingml/textfield.hxx b/oox/inc/drawingml/textfield.hxx +index 9f5bf9cf27af..7cc15a04fce4 100644 +--- a/oox/inc/drawingml/textfield.hxx ++++ b/oox/inc/drawingml/textfield.hxx +@@ -38,7 +38,9 @@ public: + const TextParagraphProperties& getTextParagraphProperties() const { return maTextParagraphProperties; } + + void setType( const OUString& sType ) { msType = sType; } ++ const OUString& getType() const { return msType; } + void setUuid( const OUString & sUuid ) { msUuid = sUuid; } ++ const OUString& getUuid() const { return msUuid; } + + virtual sal_Int32 insertAt( + const ::oox::core::XmlFilterBase& rFilterBase, +diff --git a/oox/source/drawingml/chart/seriesconverter.cxx b/oox/source/drawingml/chart/seriesconverter.cxx +index 6eceb213ea04..1a5c2ba8d96d 100644 +--- a/oox/source/drawingml/chart/seriesconverter.cxx ++++ b/oox/source/drawingml/chart/seriesconverter.cxx +@@ -22,11 +22,16 @@ + #include + #include + #include ++#include ++#include ++#include + #include + #include + #include + #include + #include ++#include ++#include + #include + #include + #include +@@ -41,6 +46,10 @@ + #include + #include + #include ++#include ++#include ++#include ++#include + + namespace oox { + namespace drawingml { +@@ -200,6 +209,20 @@ void importBorderProperties( PropertySet& rPropSet, Shape& rShape, const Graphic + rPropSet.setProperty(PROP_LabelBorderColor, uno::makeAny(nColor)); + } + ++DataPointCustomLabelFieldType lcl_ConvertFieldNameToFieldEnum( const OUString& rField ) ++{ ++ if (rField == "VALUE") ++ return DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_VALUE; ++ else if (rField == "SERIESNAME") ++ return DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_SERIESNAME; ++ else if (rField == "CATEGORYNAME") ++ return DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_CATEGORYNAME; ++ else if (rField == "CELLREF") ++ return DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_CELLREF; ++ else ++ return DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT; ++} ++ + } // namespace + + DataLabelConverter::DataLabelConverter( const ConverterRoot& rParent, DataLabelModel& rModel ) : +@@ -247,6 +270,61 @@ void DataLabelConverter::convertFromModel( const Reference< XDataSeries >& rxDat + + if (mrModel.mxShapeProp) + importBorderProperties(aPropSet, *mrModel.mxShapeProp, getFilter().getGraphicHelper()); ++ ++ if( mrModel.mxText && mrModel.mxText->mxTextBody && mrModel.mxText->mxTextBody->getParagraphs().size() ) ++ { ++ css::uno::Reference< XComponentContext > xContext = getComponentContext(); ++ uno::Sequence< css::uno::Reference< XDataPointCustomLabelField > > aSequence; ++ ++ auto& rParagraphs = mrModel.mxText->mxTextBody->getParagraphs(); ++ ++ int nSequenceSize = 0; ++ for( auto& pParagraph : rParagraphs ) ++ nSequenceSize += pParagraph->getRuns().size(); ++ ++ int nParagraphs = rParagraphs.size(); ++ if( nParagraphs > 1 ) ++ nSequenceSize += nParagraphs - 1; ++ ++ aSequence.realloc( nSequenceSize ); ++ ++ int nPos = 0; ++ for( auto& pParagraph : rParagraphs ) ++ { ++ for( auto& pRun : pParagraph->getRuns() ) ++ { ++ css::uno::Reference< XDataPointCustomLabelField > xCustomLabel = DataPointCustomLabelField::create( xContext ); ++ ++ // Store properties ++ oox::PropertySet aPropertySet( xCustomLabel ); ++ pRun->getTextCharacterProperties().pushToPropSet( aPropertySet, getFilter() ); ++ ++ TextField* pField = nullptr; ++ if( ( pField = dynamic_cast< TextField* >( pRun.get() ) ) ) ++ { ++ xCustomLabel->setString( pField->getText() ); ++ xCustomLabel->setFieldType( lcl_ConvertFieldNameToFieldEnum( pField->getType() ) ); ++ xCustomLabel->setGuid( pField->getUuid() ); ++ } ++ else if( pRun.get() ) ++ { ++ xCustomLabel->setString( pRun->getText() ); ++ xCustomLabel->setFieldType( DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT ); ++ } ++ aSequence[ nPos++ ] = xCustomLabel; ++ } ++ ++ if( nParagraphs > 1 && nPos < nSequenceSize ) ++ { ++ css::uno::Reference< XDataPointCustomLabelField > xCustomLabel = DataPointCustomLabelField::create( xContext ); ++ xCustomLabel->setFieldType( DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_NEWLINE ); ++ xCustomLabel->setString("\n"); ++ aSequence[ nPos++ ] = xCustomLabel; ++ } ++ } ++ ++ aPropSet.setProperty( PROP_CustomLabelFields, makeAny( aSequence ) ); ++ } + } + catch( Exception& ) + { +diff --git a/oox/source/token/properties.txt b/oox/source/token/properties.txt +index e6bc79ff3d08..1c700894a112 100644 +--- a/oox/source/token/properties.txt ++++ b/oox/source/token/properties.txt +@@ -278,6 +278,7 @@ LabelBorderWidth + LabelPlacement + LabelPosition + LabelSeparator ++CustomLabelFields + LayoutInfo + LeftBorder + LeftBorderDistance +-- +2.13.6 + + +From 12415c5d82817b4d056d205b6afc940872b83682 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Szymon=20K=C5=82os?= +Date: Sat, 27 Jan 2018 20:29:38 +0100 +Subject: [PATCH 2/2] tdf#114821 export complex data labels in charts +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Change-Id: I9b0893dfde4efc10bb05e6e17b7128b016efeb71 +Reviewed-on: https://gerrit.libreoffice.org/48788 +Tested-by: Jenkins +Reviewed-by: Szymon Kłos +--- + chart2/qa/extras/chart2export.cxx | 159 ++++++++++++++++++++++++++++++++++++++ + oox/source/export/chartexport.cxx | 107 ++++++++++++++++++++++++- + 2 files changed, 262 insertions(+), 4 deletions(-) + +diff --git a/oox/source/export/chartexport.cxx b/oox/source/export/chartexport.cxx +index 128a166c6c4a..63375d6c2fca 100644 +--- a/oox/source/export/chartexport.cxx ++++ b/oox/source/export/chartexport.cxx +@@ -60,6 +60,8 @@ + #include + #include + #include ++#include ++#include + #include + #include + #include +@@ -2866,17 +2868,111 @@ const char* toOOXMLPlacement( sal_Int32 nPlacement ) + return "outEnd"; + } + +-void writeLabelProperties( +- const FSHelperPtr& pFS, const uno::Reference& xPropSet, const LabelPlacementParam& rLabelParam ) ++OUString getFieldTypeString( const chart2::DataPointCustomLabelFieldType aType ) ++{ ++ switch (aType) ++ { ++ case chart2::DataPointCustomLabelFieldType_CATEGORYNAME: ++ return OUString("CATEGORYNAME"); ++ ++ case chart2::DataPointCustomLabelFieldType_SERIESNAME: ++ return OUString("SERIESNAME"); ++ ++ case chart2::DataPointCustomLabelFieldType_VALUE: ++ return OUString("VALUE"); ++ ++ case chart2::DataPointCustomLabelFieldType_CELLREF: ++ return OUString("CELLREF"); ++ ++ default: ++ break; ++ } ++ return OUString(); ++} ++ ++void writeRunProperties( ChartExport* pChartExport, Reference& xPropertySet ) ++{ ++ bool bDummy = false; ++ sal_Int32 nDummy; ++ pChartExport->WriteRunProperties(xPropertySet, false, XML_rPr, true, bDummy, nDummy); ++} ++ ++void writeCustomLabel( const FSHelperPtr& pFS, ChartExport* pChartExport, ++ const Sequence>& rCustomLabelFields ) ++{ ++ pFS->startElement(FSNS(XML_c, XML_tx), FSEND); ++ pFS->startElement(FSNS(XML_c, XML_rich), FSEND); ++ ++ // TODO: body properties? ++ pFS->singleElement(FSNS(XML_a, XML_bodyPr), FSEND); ++ ++ OUString sFieldType; ++ bool bNewParagraph; ++ pFS->startElement(FSNS(XML_a, XML_p), FSEND); ++ ++ for (auto& rField : rCustomLabelFields) ++ { ++ Reference xPropertySet(rField, UNO_QUERY); ++ chart2::DataPointCustomLabelFieldType aType = rField->getFieldType(); ++ sFieldType.clear(); ++ bNewParagraph = false; ++ ++ if (aType == chart2::DataPointCustomLabelFieldType_NEWLINE) ++ bNewParagraph = true; ++ else if (aType != chart2::DataPointCustomLabelFieldType_TEXT) ++ sFieldType = getFieldTypeString(aType); ++ ++ if (bNewParagraph) ++ { ++ pFS->endElement(FSNS(XML_a, XML_p)); ++ pFS->startElement(FSNS(XML_a, XML_p), FSEND); ++ continue; ++ } ++ ++ if (sFieldType.isEmpty()) ++ { ++ // Normal text run ++ pFS->startElement(FSNS(XML_a, XML_r), FSEND); ++ writeRunProperties(pChartExport, xPropertySet); ++ ++ pFS->startElement(FSNS(XML_a, XML_t), FSEND); ++ pFS->writeEscaped(rField->getString()); ++ pFS->endElement(FSNS(XML_a, XML_t)); ++ ++ pFS->endElement(FSNS(XML_a, XML_r)); ++ } ++ else ++ { ++ // Field ++ pFS->startElement(FSNS(XML_a, XML_fld), XML_id, USS(rField->getGuid()), XML_type, USS(sFieldType), FSEND); ++ writeRunProperties(pChartExport, xPropertySet); ++ ++ pFS->startElement(FSNS(XML_a, XML_t), FSEND); ++ pFS->writeEscaped(rField->getString()); ++ pFS->endElement(FSNS(XML_a, XML_t)); ++ ++ pFS->endElement(FSNS(XML_a, XML_fld)); ++ } ++ } ++ ++ pFS->endElement(FSNS(XML_a, XML_p)); ++ pFS->endElement(FSNS(XML_c, XML_rich)); ++ pFS->endElement(FSNS(XML_c, XML_tx)); ++} ++ ++void writeLabelProperties( const FSHelperPtr& pFS, ChartExport* pChartExport, ++ const uno::Reference& xPropSet, const LabelPlacementParam& rLabelParam ) + { + if (!xPropSet.is()) + return; + + chart2::DataPointLabel aLabel; ++ Sequence> aCustomLabelFields; + sal_Int32 nLabelBorderWidth = 0; + sal_Int32 nLabelBorderColor = 0x00FFFFFF; + + xPropSet->getPropertyValue("Label") >>= aLabel; ++ xPropSet->getPropertyValue("CustomLabelFields") >>= aCustomLabelFields; + xPropSet->getPropertyValue("LabelBorderWidth") >>= nLabelBorderWidth; + xPropSet->getPropertyValue("LabelBorderColor") >>= nLabelBorderColor; + +@@ -2897,6 +2993,9 @@ void writeLabelProperties( + pFS->endElement(FSNS(XML_c, XML_spPr)); + } + ++ if (aCustomLabelFields.getLength() > 0) ++ writeCustomLabel(pFS, pChartExport, aCustomLabelFields); ++ + if (rLabelParam.mbExport) + { + sal_Int32 nLabelPlacement = rLabelParam.meDefault; +@@ -2992,12 +3091,12 @@ void ChartExport::exportDataLabels( + // Individual label property that overwrites the baseline. + pFS->startElement(FSNS(XML_c, XML_dLbl), FSEND); + pFS->singleElement(FSNS(XML_c, XML_idx), XML_val, I32S(nIdx), FSEND); +- writeLabelProperties(pFS, xLabelPropSet, aParam); ++ writeLabelProperties(pFS, this, xLabelPropSet, aParam); + pFS->endElement(FSNS(XML_c, XML_dLbl)); + } + + // Baseline label properties for all labels. +- writeLabelProperties(pFS, xPropSet, aParam); ++ writeLabelProperties(pFS, this, xPropSet, aParam); + + pFS->singleElement(FSNS(XML_c, XML_showLeaderLines), + XML_val, "0", +-- +2.13.6 + diff --git a/bnc1081079.patch b/bnc1081079.patch new file mode 100644 index 0000000..88c7a10 --- /dev/null +++ b/bnc1081079.patch @@ -0,0 +1,29 @@ +diff --git a/oox/source/export/chartexport.cxx b/oox/source/export/chartexport.cxx +index 128a166c..4e789f9 100644 +--- a/oox/source/export/chartexport.cxx ++++ b/oox/source/export/chartexport.cxx +@@ -2930,6 +2930,24 @@ + FSHelperPtr pFS = GetFS(); + pFS->startElement(FSNS(XML_c, XML_dLbls), FSEND); + ++ bool bLinkedNumFmt = true; ++ if (GetProperty(xPropSet, "LinkNumberFormatToSource")) ++ mAny >>= bLinkedNumFmt; ++ ++ if (GetProperty(xPropSet, "NumberFormat")) ++ { ++ sal_Int32 nKey = 0; ++ mAny >>= nKey; ++ ++ OUString aNumberFormatString = getNumberFormatCode(nKey); ++ OString sNumberFormatString = OUStringToOString(aNumberFormatString, RTL_TEXTENCODING_UTF8); ++ ++ pFS->singleElement(FSNS(XML_c, XML_numFmt), ++ XML_formatCode, sNumberFormatString.getStr(), ++ XML_sourceLinked, bLinkedNumFmt ? "1" : "0", ++ FSEND); ++ } ++ + uno::Sequence aAttrLabelIndices; + xPropSet->getPropertyValue("AttributedDataPoints") >>= aAttrLabelIndices; + diff --git a/bnc955545.patch b/bnc955545.patch new file mode 100644 index 0000000..9cc7737 --- /dev/null +++ b/bnc955545.patch @@ -0,0 +1,309 @@ +commit d2437852097ba042dd5445800505bb7942006759 +Author: Miklos Vajna +Date: Wed Feb 21 17:27:53 2018 +0100 + + tdf#115873 sd navigator: allow selecting but not focusing on objects + + There were also two cases here: + + - changing the selection with the keyboard or single-click only updated + the selection in the navigator + - pressing enter or double-click also selected the shape in the main + window and gave the focus away + + Introduce a 3rd case for single-click: update the shape selection but + doesn't give the focus away. This way double-click is not needed to sync + navigator -> main doc selection but keyboard navigation should still + work. + + An additional trick is to make sure that the current shell is the draw + shell (and not the slide sorter) after navigation, so follow-up + operations work with the selected object and not with the whole slide. + + Finally, a third related problem was that the selection jumped back to + the item of the slide after clicking on a shape in the navigator. The + reason for this was the navigator list was constantly cleared and + re-filled in SdNavigatorWin::InitTreeLB(), as + SdPageObjsTLB::IsEqualToDoc() returned false (even if the list was up to + date) in case of shapes which had children but no name. Fix this by + using the same SdrIterMode::Flat iteration mode that + SdPageObjsTLB::AddShapeList() does, so the fill and the equality check + of the navigator iterates the same way. + + Conflicts: + sd/qa/unit/tiledrendering/tiledrendering.cxx + + (cherry picked from commit f3c68cdf8f6a0273c62b493552f78af0138a44e8) + + Change-Id: I0bfc3e8b49f7ef01d5797a68284616dcd2a81c5d + Reviewed-on: https://gerrit.libreoffice.org/50158 + Tested-by: Jenkins + Reviewed-by: Andras Timar + +diff --git a/sd/source/ui/dlg/navigatr.cxx b/sd/source/ui/dlg/navigatr.cxx +index 4552f262c7a1..53526c95473b 100644 +--- a/sd/source/ui/dlg/navigatr.cxx ++++ b/sd/source/ui/dlg/navigatr.cxx +@@ -54,6 +54,7 @@ + #include + #include + #include ++#include + + namespace { + static const sal_uInt16 nShowNamedShapesFilter=1; +@@ -215,6 +216,11 @@ NavigatorDragType SdNavigatorWin::GetNavigatorDragType() + return eDT; + } + ++VclPtr SdNavigatorWin::GetObjects() ++{ ++ return maTlbObjects; ++} ++ + IMPL_LINK_NOARG(SdNavigatorWin, SelectToolboxHdl, ToolBox *, void) + { + sal_uInt16 nId = maToolbox->GetCurItemId(); +@@ -337,6 +343,27 @@ IMPL_LINK_NOARG(SdNavigatorWin, ClickObjectHdl, SvTreeListBox*, bool) + if ( pShellWnd ) + pShellWnd->GrabFocus(); + } ++ ++ // We navigated to an object, but the current shell may be ++ // still the slide sorter. Explicitly try to grab the draw ++ // shell focus, so follow-up operations work with the object ++ // and not with the whole slide. ++ sd::DrawDocShell* pDocShell = pInfo->mpDocShell; ++ if (pDocShell) ++ { ++ sd::ViewShell* pViewShell = pDocShell->GetViewShell(); ++ if (pViewShell) ++ { ++ vcl::Window* pWindow = pViewShell->GetActiveWindow(); ++ if (pWindow) ++ pWindow->GrabFocus(); ++ } ++ } ++ ++ if (!maTlbObjects->IsNavigationGrabsFocus()) ++ // This is the case when keyboard navigation inside the ++ // navigator should continue to work. ++ maTlbObjects->GrabFocus(); + } + } + } +diff --git a/sd/source/ui/dlg/sdtreelb.cxx b/sd/source/ui/dlg/sdtreelb.cxx +index 7667c66db132..d9d193e445c0 100644 +--- a/sd/source/ui/dlg/sdtreelb.cxx ++++ b/sd/source/ui/dlg/sdtreelb.cxx +@@ -58,6 +58,7 @@ + #include + #include + #include ++#include + + + using namespace com::sun::star; +@@ -205,6 +206,8 @@ SdPageObjsTLB::SdPageObjsTLB( vcl::Window* pParentWin, WinBits nStyle ) + , mbSaveTreeItemState ( false ) + , mbShowAllShapes ( false ) + , mbShowAllPages ( false ) ++, mbSelectionHandlerNavigates(false) ++, mbNavigationGrabsFocus(true) + { + // add lines to Tree-ListBox + SetStyle( GetStyle() | WB_TABSTOP | WB_BORDER | WB_HASLINES | +@@ -626,6 +629,52 @@ void SdPageObjsTLB::SetShowAllShapes ( + } + } + ++bool SdPageObjsTLB::IsEqualToShapeList(SvTreeListEntry*& pEntry, const SdrObjList& rList, ++ const OUString& rListName) ++{ ++ if (!pEntry) ++ return false; ++ OUString aName = GetEntryText(pEntry); ++ ++ if (rListName != aName) ++ return false; ++ ++ pEntry = Next(pEntry); ++ ++ SdrObjListIter aIter(rList, ++ !rList.HasObjectNavigationOrder() /* use navigation order, if available */, ++ SdrIterMode::Flat); ++ ++ while (aIter.IsMore()) ++ { ++ SdrObject* pObj = aIter.Next(); ++ ++ const OUString aObjectName(GetObjectName(pObj)); ++ ++ if (!aObjectName.isEmpty()) ++ { ++ if (!pEntry) ++ return false; ++ ++ aName = GetEntryText(pEntry); ++ ++ if (aObjectName != aName) ++ return false; ++ ++ if (pObj->IsGroupObject()) ++ { ++ bool bRet = IsEqualToShapeList(pEntry, *pObj->GetSubList(), aObjectName); ++ if (!bRet) ++ return false; ++ } ++ else ++ pEntry = Next(pEntry); ++ } ++ } ++ ++ return true; ++} ++ + /** + * Checks if the pages (PageKind::Standard) of a doc and the objects on the pages + * are identical to the TreeLB. +@@ -640,9 +689,7 @@ bool SdPageObjsTLB::IsEqualToDoc( const SdDrawDocument* pInDoc ) + if( !mpDoc ) + return false; + +- SdrObject* pObj = nullptr; + SvTreeListEntry* pEntry = First(); +- OUString aName; + + // compare all pages including the objects + sal_uInt16 nPage = 0; +@@ -653,39 +700,9 @@ bool SdPageObjsTLB::IsEqualToDoc( const SdDrawDocument* pInDoc ) + const SdPage* pPage = static_cast( mpDoc->GetPage( nPage ) ); + if( pPage->GetPageKind() == PageKind::Standard ) + { +- if( !pEntry ) ++ bool bRet = IsEqualToShapeList(pEntry, *pPage, pPage->GetName()); ++ if (!bRet) + return false; +- aName = GetEntryText( pEntry ); +- +- if( pPage->GetName() != aName ) +- return false; +- +- pEntry = Next( pEntry ); +- +- SdrObjListIter aIter( +- *pPage, +- !pPage->HasObjectNavigationOrder() /* use navigation order, if available */, +- SdrIterMode::DeepWithGroups ); +- +- while( aIter.IsMore() ) +- { +- pObj = aIter.Next(); +- +- const OUString aObjectName( GetObjectName( pObj ) ); +- +- if( !aObjectName.isEmpty() ) +- { +- if( !pEntry ) +- return false; +- +- aName = GetEntryText( pEntry ); +- +- if( aObjectName != aName ) +- return false; +- +- pEntry = Next( pEntry ); +- } +- } + } + nPage++; + } +@@ -895,6 +912,9 @@ void SdPageObjsTLB::SelectHdl() + } + + SvTreeListBox::SelectHdl(); ++ ++ if (mbSelectionHandlerNavigates) ++ DoubleClickHdl(); + } + + /** +@@ -939,6 +959,16 @@ void SdPageObjsTLB::KeyInput( const KeyEvent& rKEvt ) + SvTreeListBox::KeyInput( rKEvt ); + } + ++void SdPageObjsTLB::MouseButtonDown(const MouseEvent& rMEvt) ++{ ++ mbSelectionHandlerNavigates = rMEvt.GetClicks() == 1; ++ comphelper::ScopeGuard aNavigationGuard([this]() { this->mbSelectionHandlerNavigates = false; }); ++ mbNavigationGrabsFocus = rMEvt.GetClicks() != 1; ++ comphelper::ScopeGuard aGrabGuard([this]() { this->mbNavigationGrabsFocus = true; }); ++ ++ SvTreeListBox::MouseButtonDown(rMEvt); ++} ++ + /** + * StartDrag-Request + */ +diff --git a/sd/source/ui/inc/navigatr.hxx b/sd/source/ui/inc/navigatr.hxx +index cd487a249058..a9501c5236a4 100644 +--- a/sd/source/ui/inc/navigatr.hxx ++++ b/sd/source/ui/inc/navigatr.hxx +@@ -76,7 +76,7 @@ private: + ::sd::DrawDocShell* mpDocShell; + }; + +-class SdNavigatorWin : public PanelLayout ++class SD_DLLPUBLIC SdNavigatorWin : public PanelLayout + { + public: + typedef ::std::function UpdateRequestFunctor; +@@ -101,6 +101,7 @@ public: + bool InsertFile(const OUString& rFileName); + + NavigatorDragType GetNavigatorDragType(); ++ VclPtr GetObjects(); + + protected: + virtual bool EventNotify(NotifyEvent& rNEvt) override; +diff --git a/sd/source/ui/inc/sdtreelb.hxx b/sd/source/ui/inc/sdtreelb.hxx +index 6f9887ecd40e..b358e376672b 100644 +--- a/sd/source/ui/inc/sdtreelb.hxx ++++ b/sd/source/ui/inc/sdtreelb.hxx +@@ -195,6 +195,7 @@ public: + OUString GetEntryLongDescription( SvTreeListEntry* pEntry ) const override; + virtual void SelectHdl() override; + virtual void KeyInput( const KeyEvent& rKEvt ) override; ++ void MouseButtonDown(const MouseEvent& rMEvt) override; + + void SetViewFrame( SfxViewFrame* pViewFrame ); + +@@ -202,7 +203,11 @@ public: + void Fill( const SdDrawDocument*, SfxMedium* pSfxMedium, const OUString& rDocName ); + void SetShowAllShapes (const bool bShowAllShapes, const bool bFill); + bool GetShowAllShapes() const { return mbShowAllShapes;} ++ bool IsNavigationGrabsFocus() const { return mbNavigationGrabsFocus; } + bool IsEqualToDoc( const SdDrawDocument* pInDoc ); ++ /// Visits rList recursively and tries to advance pEntry accordingly. ++ bool IsEqualToShapeList(SvTreeListEntry*& pEntry, const SdrObjList& rList, ++ const OUString& rListName); + bool HasSelectedChildren( const OUString& rName ); + bool SelectEntry( const OUString& rName ); + OUString GetSelectedEntry(); +@@ -247,6 +252,16 @@ private: + /** This flag controls whether to show all pages. + */ + bool mbShowAllPages; ++ /** ++ * If changing the selection should also result in navigating to the ++ * relevant shape. ++ */ ++ bool mbSelectionHandlerNavigates; ++ /** ++ * If navigation should not only select the relevant shape but also change ++ * focus to it. ++ */ ++ bool mbNavigationGrabsFocus; + + /** Return when the current transferable may be dropped at the + given list box entry. diff --git a/libreoffice.changes b/libreoffice.changes index 5bd25d2..4c60a11 100644 --- a/libreoffice.changes +++ b/libreoffice.changes @@ -1,9 +1,40 @@ +------------------------------------------------------------------- +Mon Mar 5 15:47:27 UTC 2018 - andras.timar@collabora.com + +- Remove upstreamed patches + * bnc1061210.patch + * bnc954772.patch + ------------------------------------------------------------------- Mon Mar 5 10:24:22 UTC 2018 - tchvatal@suse.com - Version update to 6.0.2.1 release: * second bugfix release closing around 80 TDF issues +------------------------------------------------------------------- +Wed Feb 28 08:02:05 UTC 2018 - andras.timar@collabora.com + +- LO-L3: Saving PPTX chart changes $12K to 12,345 format + * bnc1081079.patch + +------------------------------------------------------------------- +Thu Feb 22 11:10:32 UTC 2018 - andras.timar@collabora.com + +- LO-L3: Cutting object (Rectangle) in Navigator cuts the whole slide instead + * bnc955545.patch + +------------------------------------------------------------------- +Wed Feb 21 10:27:05 UTC 2018 - andras.timar@collabora.com + +- LO-L3: Wrong transition time + * bnc1039203.patch +- LO-L3: Slide with chart has some strange (too large?) elements (PPTX) + * bnc1060128.patch +- LO-L3: Table(s) from DOCX show wrong position/color/...? + * bnc1061210.patch +- LO-L3: Copy and Paste in Table ignores formatting completely + * bnc954772.patch + ------------------------------------------------------------------- Tue Feb 20 14:03:07 UTC 2018 - tchvatal@suse.com diff --git a/libreoffice.spec b/libreoffice.spec index 14cef07..5091f80 100644 --- a/libreoffice.spec +++ b/libreoffice.spec @@ -92,6 +92,14 @@ Patch3: mediawiki-no-broken-help.diff Patch4: kde5-configure-checks.patch Patch5: 0001-Use-PYTHON_FOR_BUILD-instead-of-calling-python-direc.patch Patch6: orcus-0.13.3.patch +# LO-L3: Wrong transition time +Patch7: bnc1039203.patch +# LO-L3: Slide with chart has some strange (too large?) elements (PPTX) +Patch8: bnc1060128.patch +# LO-L3: Cutting object (Rectangle) in Navigator cuts the whole slide instead +Patch11: bnc955545.patch +# LO-L3: Saving PPTX chart changes $12K to 12,345 format +Patch12: bnc1081079.patch Patch500: boost_string_fixes.patch # try to save space by using hardlinks Patch990: install-with-hardlinks.diff @@ -886,6 +894,10 @@ Provides additional %{langname} translations and resources for %{project}. \ %patch4 -p1 %patch5 -p1 %patch6 -p1 +%patch7 -p1 +%patch8 -p1 +%patch11 -p1 +%patch12 -p1 %patch990 -p1 # Disable some of the failing tests (some are random) @@ -1042,7 +1054,7 @@ make build-nocheck %check # Run tests only on 64b intel as they are resource hogs %ifarch x86_64 -make +make %endif %install