diff options
2098 files changed, 21135 insertions, 10264 deletions
diff --git a/RepositoryExternal.mk b/RepositoryExternal.mk index e63ab24dba27..4854a20aa050 100644 --- a/RepositoryExternal.mk +++ b/RepositoryExternal.mk @@ -3105,7 +3105,7 @@ endef # gb_LinkTarget__use_postgresql endif # !SYSTEM_POSTGRESQL -ifeq ($(ENABLE_KF5),TRUE) +ifneq (,$(filter TRUE,$(ENABLE_KF5) $(ENABLE_GTK3_KDE5))) define gb_LinkTarget__use_kf5 $(call gb_LinkTarget_set_include,$(1),\ @@ -3133,7 +3133,7 @@ endif # ENABLE_KF5 -ifeq ($(ENABLE_QT5),TRUE) +ifneq (,$(filter TRUE,$(ENABLE_QT5) $(ENABLE_GTK3_KDE5))) define gb_LinkTarget__use_qt5 $(call gb_LinkTarget_set_include,$(1),\ diff --git a/avmedia/inc/mediacontrol.hxx b/avmedia/inc/mediacontrol.hxx index 33c063fc9dad..6b004626ff83 100644 --- a/avmedia/inc/mediacontrol.hxx +++ b/avmedia/inc/mediacontrol.hxx @@ -66,7 +66,6 @@ private: MediaItem maItem; bool mbLocked; MediaControlStyle meControlStyle; - double mfTime; }; } diff --git a/avmedia/source/framework/MediaControlBase.cxx b/avmedia/source/framework/MediaControlBase.cxx index c572bed7d0e6..dc83204d4228 100644 --- a/avmedia/source/framework/MediaControlBase.cxx +++ b/avmedia/source/framework/MediaControlBase.cxx @@ -133,6 +133,28 @@ void MediaControlBase::InitializeWidgets() mxTimeSlider->set_tooltip_text( AvmResId( AVMEDIA_STR_POSITION )); } +void MediaControlBase::UpdatePlayState(const MediaItem& rMediaItem) +{ + if (rMediaItem.getState() == MediaState::Play) + { + mxPlayToolBox->set_item_active("play", true); + mxPlayToolBox->set_item_active("pause", false); + mxPlayToolBox->set_item_active("stop", false); + } + else if( rMediaItem.getState() == MediaState::Pause ) + { + mxPlayToolBox->set_item_active("play", false); + mxPlayToolBox->set_item_active("pause", true); + mxPlayToolBox->set_item_active("stop", false); + } + else + { + mxPlayToolBox->set_item_active("play", false); + mxPlayToolBox->set_item_active("pause", false); + mxPlayToolBox->set_item_active("stop", true); + } +} + void MediaControlBase::UpdateToolBoxes(const MediaItem& rMediaItem) { const bool bValidURL = !rMediaItem.getURL().isEmpty(); @@ -150,24 +172,7 @@ void MediaControlBase::UpdateToolBoxes(const MediaItem& rMediaItem) { mxPlayToolBox->set_sensitive(true); mxMuteToolBox->set_sensitive(true); - if( rMediaItem.getState() == MediaState::Play ) - { - mxPlayToolBox->set_item_active("play", true); - mxPlayToolBox->set_item_active("pause", false); - mxPlayToolBox->set_item_active("stop", false); - } - else if( rMediaItem.getState() == MediaState::Pause ) - { - mxPlayToolBox->set_item_active("play", false); - mxPlayToolBox->set_item_active("pause", true); - mxPlayToolBox->set_item_active("stop", false); - } - else - { - mxPlayToolBox->set_item_active("play", false); - mxPlayToolBox->set_item_active("pause", false); - mxPlayToolBox->set_item_active("stop", true); - } + UpdatePlayState(rMediaItem); mxPlayToolBox->set_item_active("loop", rMediaItem.isLoop()); mxMuteToolBox->set_item_active("mute", rMediaItem.isMute()); if (!mbCurrentlySettingZoom) @@ -226,15 +231,21 @@ void MediaControlBase::SelectPlayToolBoxItem( MediaItem& aExecItem, MediaItem co aExecItem.setTime( 0.0 ); else aExecItem.setTime( aItem.getTime() ); + + UpdatePlayState(aExecItem); } else if (rId == "pause") { aExecItem.setState( MediaState::Pause ); + + UpdatePlayState(aExecItem); } else if (rId == "stop") { aExecItem.setState( MediaState::Stop ); aExecItem.setTime( 0.0 ); + + UpdatePlayState(aExecItem); } else if (rId == "mute") { diff --git a/avmedia/source/framework/mediacontrol.cxx b/avmedia/source/framework/mediacontrol.cxx index 55286145bb39..4c8026a88804 100644 --- a/avmedia/source/framework/mediacontrol.cxx +++ b/avmedia/source/framework/mediacontrol.cxx @@ -39,8 +39,7 @@ MediaControl::MediaControl( vcl::Window* pParent, MediaControlStyle eControlStyl maChangeTimeIdle( "avmedia MediaControl Change Time Idle" ), maItem( 0, AVMediaSetMask::ALL ), mbLocked( false ), - meControlStyle( eControlStyle ), - mfTime(0.0) + meControlStyle( eControlStyle ) { mxPlayToolBox = m_xBuilder->weld_toolbar("playtoolbox"); mxTimeSlider = m_xBuilder->weld_scale("timeslider"); @@ -116,11 +115,11 @@ void MediaControl::UpdateURLField(MediaItem const & tempItem) void MediaControl::setState( const MediaItem& rItem ) { - double fTime = rItem.getTime(); - if( !mbLocked && fTime != mfTime) + if (mbLocked) + return; + bool bChanged = maItem.merge(rItem); + if (bChanged) { - mfTime = fTime; - maItem.merge( rItem ); if( rItem.getURL().isEmpty() && meControlStyle == MediaControlStyle::SingleLine ) mxPlayToolBox->set_sensitive(false); UpdateToolBoxes( maItem ); diff --git a/avmedia/source/framework/mediaitem.cxx b/avmedia/source/framework/mediaitem.cxx index 127ad8af243f..0a53cf5d4d39 100644 --- a/avmedia/source/framework/mediaitem.cxx +++ b/avmedia/source/framework/mediaitem.cxx @@ -178,187 +178,201 @@ bool MediaItem::PutValue( const css::uno::Any& rVal, sal_uInt8 ) return bRet; } - -void MediaItem::merge( const MediaItem& rMediaItem ) +bool MediaItem::merge(const MediaItem& rMediaItem) { + bool bChanged = false; + const AVMediaSetMask nMaskSet = rMediaItem.getMaskSet(); if( AVMediaSetMask::URL & nMaskSet ) - setURL( rMediaItem.getURL(), rMediaItem.getTempURL(), rMediaItem.getReferer() ); + bChanged |= setURL(rMediaItem.getURL(), rMediaItem.getTempURL(), rMediaItem.getReferer()); if( AVMediaSetMask::MIME_TYPE & nMaskSet ) - setMimeType( rMediaItem.getMimeType() ); + bChanged |= setMimeType(rMediaItem.getMimeType()); if (nMaskSet & AVMediaSetMask::GRAPHIC) - setGraphic(rMediaItem.getGraphic()); + bChanged |= setGraphic(rMediaItem.getGraphic()); if( AVMediaSetMask::STATE & nMaskSet ) - setState( rMediaItem.getState() ); + bChanged |= setState( rMediaItem.getState() ); if( AVMediaSetMask::DURATION & nMaskSet ) - setDuration( rMediaItem.getDuration() ); + bChanged |= setDuration(rMediaItem.getDuration()); if( AVMediaSetMask::TIME & nMaskSet ) - setTime( rMediaItem.getTime() ); + bChanged |= setTime(rMediaItem.getTime()); if( AVMediaSetMask::LOOP & nMaskSet ) - setLoop( rMediaItem.isLoop() ); + bChanged |= setLoop(rMediaItem.isLoop()); if( AVMediaSetMask::MUTE & nMaskSet ) - setMute( rMediaItem.isMute() ); + bChanged |= setMute(rMediaItem.isMute()); if( AVMediaSetMask::VOLUMEDB & nMaskSet ) - setVolumeDB( rMediaItem.getVolumeDB() ); + bChanged |= setVolumeDB(rMediaItem.getVolumeDB()); if( AVMediaSetMask::ZOOM & nMaskSet ) - setZoom( rMediaItem.getZoom() ); -} + bChanged |= setZoom(rMediaItem.getZoom()); + return bChanged; +} AVMediaSetMask MediaItem::getMaskSet() const { return m_pImpl->m_nMaskSet; } - -void MediaItem::setURL( const OUString& rURL, const OUString& rTempURL, const OUString& rReferer ) +bool MediaItem::setURL(const OUString& rURL, const OUString& rTempURL, const OUString& rReferer) { m_pImpl->m_nMaskSet |= AVMediaSetMask::URL; - m_pImpl->m_URL = rURL; - m_pImpl->m_TempFileURL = rTempURL; - m_pImpl->m_Referer = rReferer; + bool bChanged = rURL != m_pImpl->m_URL || rTempURL != m_pImpl->m_TempFileURL || rReferer != m_pImpl->m_Referer; + if (bChanged) + { + m_pImpl->m_URL = rURL; + m_pImpl->m_TempFileURL = rTempURL; + m_pImpl->m_Referer = rReferer; + } + return bChanged; } - const OUString& MediaItem::getURL() const { return m_pImpl->m_URL; } - const OUString& MediaItem::getTempURL() const { return m_pImpl->m_TempFileURL; } - const OUString& MediaItem::getReferer() const { return m_pImpl->m_Referer; } - -void MediaItem::setMimeType( const OUString& rMimeType ) +bool MediaItem::setMimeType(const OUString& rMimeType) { m_pImpl->m_nMaskSet |= AVMediaSetMask::MIME_TYPE; - m_pImpl->m_sMimeType = rMimeType; + bool bChanged = rMimeType != m_pImpl->m_sMimeType; + if (bChanged) + m_pImpl->m_sMimeType = rMimeType; + return bChanged; } - OUString MediaItem::getMimeType() const { return !m_pImpl->m_sMimeType.isEmpty() ? m_pImpl->m_sMimeType : AVMEDIA_MIMETYPE_COMMON; } -void MediaItem::setGraphic(const Graphic& rGraphic) +bool MediaItem::setGraphic(const Graphic& rGraphic) { m_pImpl->m_nMaskSet |= AVMediaSetMask::GRAPHIC; - m_pImpl->m_aGraphic = rGraphic; + bool bChanged = rGraphic != m_pImpl->m_aGraphic; + if (bChanged) + m_pImpl->m_aGraphic = rGraphic; + return bChanged; } const Graphic & MediaItem::getGraphic() const { return m_pImpl->m_aGraphic; } -void MediaItem::setState( MediaState eState ) +bool MediaItem::setState(MediaState eState) { - m_pImpl->m_eState = eState; m_pImpl->m_nMaskSet |= AVMediaSetMask::STATE; + bool bChanged = eState != m_pImpl->m_eState; + if (bChanged) + m_pImpl->m_eState = eState; + return bChanged; } - MediaState MediaItem::getState() const { return m_pImpl->m_eState; } - -void MediaItem::setDuration( double fDuration ) +bool MediaItem::setDuration(double fDuration) { - m_pImpl->m_fDuration = fDuration; m_pImpl->m_nMaskSet |= AVMediaSetMask::DURATION; + bool bChanged = fDuration != m_pImpl->m_fDuration; + if (bChanged) + m_pImpl->m_fDuration = fDuration; + return bChanged; } - double MediaItem::getDuration() const { return m_pImpl->m_fDuration; } - -void MediaItem::setTime( double fTime ) +bool MediaItem::setTime(double fTime) { - m_pImpl->m_fTime = fTime; m_pImpl->m_nMaskSet |= AVMediaSetMask::TIME; + bool bChanged = fTime != m_pImpl->m_fTime; + if (bChanged) + m_pImpl->m_fTime = fTime; + return bChanged; } - double MediaItem::getTime() const { return m_pImpl->m_fTime; } - -void MediaItem::setLoop( bool bLoop ) +bool MediaItem::setLoop(bool bLoop) { - m_pImpl->m_bLoop = bLoop; m_pImpl->m_nMaskSet |= AVMediaSetMask::LOOP; + bool bChanged = bLoop != m_pImpl->m_bLoop; + if (bChanged) + m_pImpl->m_bLoop = bLoop; + return bChanged; } - bool MediaItem::isLoop() const { return m_pImpl->m_bLoop; } - -void MediaItem::setMute( bool bMute ) +bool MediaItem::setMute(bool bMute) { - m_pImpl->m_bMute = bMute; m_pImpl->m_nMaskSet |= AVMediaSetMask::MUTE; + bool bChanged = bMute != m_pImpl->m_bMute; + if (bChanged) + m_pImpl->m_bMute = bMute; + return bChanged; } - bool MediaItem::isMute() const { return m_pImpl->m_bMute; } - -void MediaItem::setVolumeDB( sal_Int16 nDB ) +bool MediaItem::setVolumeDB(sal_Int16 nDB) { - m_pImpl->m_nVolumeDB = nDB; m_pImpl->m_nMaskSet |= AVMediaSetMask::VOLUMEDB; + bool bChanged = nDB != m_pImpl->m_nVolumeDB; + if (bChanged) + m_pImpl->m_nVolumeDB = nDB; + return bChanged; } - sal_Int16 MediaItem::getVolumeDB() const { return m_pImpl->m_nVolumeDB; } - -void MediaItem::setZoom( css::media::ZoomLevel eZoom ) +bool MediaItem::setZoom(css::media::ZoomLevel eZoom) { - m_pImpl->m_eZoom = eZoom; m_pImpl->m_nMaskSet |= AVMediaSetMask::ZOOM; + bool bChanged = eZoom != m_pImpl->m_eZoom; + if (bChanged) + m_pImpl->m_eZoom = eZoom; + return bChanged; } - css::media::ZoomLevel MediaItem::getZoom() const { return m_pImpl->m_eZoom; } - OUString GetFilename(OUString const& rSourceURL) { uno::Reference<uri::XUriReferenceFactory> const xUriFactory( diff --git a/avmedia/source/gstreamer/gstplayer.cxx b/avmedia/source/gstreamer/gstplayer.cxx index f25ec5c6bb0c..397fe8809d93 100644 --- a/avmedia/source/gstreamer/gstplayer.cxx +++ b/avmedia/source/gstreamer/gstplayer.cxx @@ -284,7 +284,6 @@ Player::Player() : mbUseGtkSink( false ), mbFakeVideo (false ), mnUnmutedVolume( 0 ), - mbPlayPending ( false ), mbMuted( false ), mbLooping( false ), mbInitialized( false ), @@ -384,7 +383,6 @@ void Player::processMessage( GstMessage *message ) switch( GST_MESSAGE_TYPE( message ) ) { case GST_MESSAGE_EOS: gst_element_set_state( mpPlaybin, GST_STATE_READY ); - mbPlayPending = false; if (mbLooping) start(); break; @@ -400,9 +398,6 @@ void Player::processMessage( GstMessage *message ) { gst_video_overlay_expose(mpXOverlay); } - - if (mbPlayPending) - mbPlayPending = ((newstate == GST_STATE_READY) || (newstate == GST_STATE_PAUSED)); } break; default: @@ -531,7 +526,6 @@ void Player::preparePlaybin( std::u16string_view rURL, GstElement *pSink ) if (mpPlaybin != nullptr) { gst_element_set_state( mpPlaybin, GST_STATE_NULL ); - mbPlayPending = false; g_object_unref( mpPlaybin ); } @@ -596,7 +590,6 @@ bool Player::create( const OUString& rURL ) preparePlaybin( rURL, gst_element_factory_make( "fakesink", nullptr ) ); gst_element_set_state( mpPlaybin, GST_STATE_PAUSED ); - mbPlayPending = false; bRet = true; } @@ -609,7 +602,6 @@ bool Player::create( const OUString& rURL ) return bRet; } - void SAL_CALL Player::start() { ::osl::MutexGuard aGuard(m_aMutex); @@ -618,11 +610,9 @@ void SAL_CALL Player::start() if( mbInitialized && mpPlaybin != nullptr ) { gst_element_set_state( mpPlaybin, GST_STATE_PLAYING ); - mbPlayPending = true; } } - void SAL_CALL Player::stop() { ::osl::MutexGuard aGuard(m_aMutex); @@ -631,21 +621,19 @@ void SAL_CALL Player::stop() if( mpPlaybin ) gst_element_set_state( mpPlaybin, GST_STATE_PAUSED ); - mbPlayPending = false; SAL_INFO( "avmedia.gstreamer", AVVERSION "stop " << mpPlaybin ); } - sal_Bool SAL_CALL Player::isPlaying() { ::osl::MutexGuard aGuard(m_aMutex); - bool bRet = mbPlayPending; + bool bRet = false; - // return whether the pipeline is in PLAYING STATE or not - if( !mbPlayPending && mbInitialized && mpPlaybin ) + // return whether the pipeline target is PLAYING STATE or not + if (mbInitialized && mpPlaybin) { - bRet = GST_STATE( mpPlaybin ) == GST_STATE_PLAYING; + bRet = GST_STATE_TARGET(mpPlaybin) == GST_STATE_PLAYING; } SAL_INFO( "avmedia.gstreamer", AVVERSION "isPlaying " << bRet ); @@ -653,7 +641,6 @@ sal_Bool SAL_CALL Player::isPlaying() return bRet; } - double SAL_CALL Player::getDuration() { ::osl::MutexGuard aGuard(m_aMutex); diff --git a/avmedia/source/gstreamer/gstplayer.hxx b/avmedia/source/gstreamer/gstplayer.hxx index a82dac3f2b39..2694ac00ce7e 100644 --- a/avmedia/source/gstreamer/gstplayer.hxx +++ b/avmedia/source/gstreamer/gstplayer.hxx @@ -86,7 +86,6 @@ private: bool mbFakeVideo; gdouble mnUnmutedVolume; - bool mbPlayPending; bool mbMuted; bool mbLooping; bool mbInitialized; diff --git a/avmedia/source/viewer/mediawindow.cxx b/avmedia/source/viewer/mediawindow.cxx index 4ff32f636eb6..0b1ca1b9c11a 100644 --- a/avmedia/source/viewer/mediawindow.cxx +++ b/avmedia/source/viewer/mediawindow.cxx @@ -352,10 +352,10 @@ uno::Reference< media::XPlayer > MediaWindow::createPlayer( const OUString& rURL return priv::MediaWindowImpl::createPlayer( rURL, rReferer, pMimeType ); } - uno::Reference< graphic::XGraphic > MediaWindow::grabFrame( const OUString& rURL, const OUString& rReferer, - const OUString& sMimeType ) + const OUString& sMimeType, + const uno::Reference<graphic::XGraphic>& rGraphic) { uno::Reference< media::XPlayer > xPlayer( createPlayer( rURL, rReferer, &sMimeType ) ); uno::Reference< graphic::XGraphic > xRet; @@ -394,7 +394,11 @@ uno::Reference< graphic::XGraphic > MediaWindow::grabFrame( const OUString& rURL } if (xGraphic) + { + if (rGraphic) + xGraphic.reset(new Graphic(rGraphic)); xRet = xGraphic->GetXGraphic(); + } return xRet; } diff --git a/basctl/source/basicide/baside3.cxx b/basctl/source/basicide/baside3.cxx index 920e82da3d0a..7b7e5db43b89 100644 --- a/basctl/source/basicide/baside3.cxx +++ b/basctl/source/basicide/baside3.cxx @@ -851,7 +851,7 @@ bool implImportDialog(weld::Window* pWin, const ScriptDocument& rDocument, const xFP->appendFilter( IDEResId(RID_STR_FILTER_ALLFILES), FilterMask_All ); xFP->setCurrentFilter( aDialogStr ); - if( aDlg.Execute() != ERRCODE_NONE ) + if( aDlg.Execute() == ERRCODE_NONE ) { Sequence< OUString > aPaths = xFP->getSelectedFiles(); diff --git a/basctl/source/basicide/moduldlg.cxx b/basctl/source/basicide/moduldlg.cxx index 2e3c8c2530d1..0471b2b2eefe 100644 --- a/basctl/source/basicide/moduldlg.cxx +++ b/basctl/source/basicide/moduldlg.cxx @@ -246,6 +246,10 @@ private: if (!pSource) return DND_ACTION_NONE; + // tdf#145722 only return a DND_ACTION_MOVE possibility if that + // is requested as an option + const bool bCheckForMove = rEvt.mnAction & DND_ACTION_MOVE; + sal_Int8 nMode = DND_ACTION_NONE; std::unique_ptr<weld::TreeIter> xEntry(pSource->make_iterator()); @@ -255,28 +259,31 @@ private: if (nDepth >= 2) { nMode = DND_ACTION_COPY; - EntryDescriptor aDesc = m_rTreeView.GetEntryDescriptor(xEntry.get()); - const ScriptDocument& aDocument( aDesc.GetDocument() ); - const OUString& aLibName( aDesc.GetLibName() ); - // allow MOVE mode only for libraries, which are not readonly - Reference< script::XLibraryContainer2 > xModLibContainer( aDocument.getLibraryContainer( E_SCRIPTS ), UNO_QUERY ); - Reference< script::XLibraryContainer2 > xDlgLibContainer( aDocument.getLibraryContainer( E_DIALOGS ), UNO_QUERY ); - if ( !( ( xModLibContainer.is() && xModLibContainer->hasByName( aLibName ) && xModLibContainer->isLibraryReadOnly( aLibName ) ) || - ( xDlgLibContainer.is() && xDlgLibContainer->hasByName( aLibName ) && xDlgLibContainer->isLibraryReadOnly( aLibName ) ) ) ) + if (bCheckForMove) { - // Only allow copy for localized libraries - bool bAllowMove = true; - if ( xDlgLibContainer.is() && xDlgLibContainer->hasByName( aLibName ) ) + EntryDescriptor aDesc = m_rTreeView.GetEntryDescriptor(xEntry.get()); + const ScriptDocument& aDocument( aDesc.GetDocument() ); + const OUString& aLibName( aDesc.GetLibName() ); + // allow MOVE mode only for libraries, which are not readonly + Reference< script::XLibraryContainer2 > xModLibContainer( aDocument.getLibraryContainer( E_SCRIPTS ), UNO_QUERY ); + Reference< script::XLibraryContainer2 > xDlgLibContainer( aDocument.getLibraryContainer( E_DIALOGS ), UNO_QUERY ); + if ( !( ( xModLibContainer.is() && xModLibContainer->hasByName( aLibName ) && xModLibContainer->isLibraryReadOnly( aLibName ) ) || + ( xDlgLibContainer.is() && xDlgLibContainer->hasByName( aLibName ) && xDlgLibContainer->isLibraryReadOnly( aLibName ) ) ) ) { - // Get StringResourceManager - Reference< container::XNameContainer > xDialogLib( aDocument.getLibrary( E_DIALOGS, aLibName, true ) ); - Reference< XStringResourceManager > xSourceMgr = - LocalizationMgr::getStringResourceFromDialogLibrary( xDialogLib ); - if( xSourceMgr.is() ) - bAllowMove = ( xSourceMgr->getLocales().getLength() == 0 ); + // Only allow copy for localized libraries + bool bAllowMove = true; + if ( xDlgLibContainer.is() && xDlgLibContainer->hasByName( aLibName ) ) + { + // Get StringResourceManager + Reference< container::XNameContainer > xDialogLib( aDocument.getLibrary( E_DIALOGS, aLibName, true ) ); + Reference< XStringResourceManager > xSourceMgr = + LocalizationMgr::getStringResourceFromDialogLibrary( xDialogLib ); + if( xSourceMgr.is() ) + bAllowMove = ( xSourceMgr->getLocales().getLength() == 0 ); + } + if( bAllowMove ) + nMode |= DND_ACTION_MOVE; } - if( bAllowMove ) - nMode |= DND_ACTION_MOVE; } } } @@ -496,6 +503,13 @@ private: OUString sText(m_rTreeView.get_text(*xSelected)); OUString sId(m_rTreeView.get_id(*xSelected)); + /// if copying then clone the userdata + if (Entry* pEntry = bMove ? nullptr : reinterpret_cast<Entry*>(sId.toUInt64())) + { + assert(pEntry->GetType() != OBJ_TYPE_DOCUMENT); + std::unique_ptr<Entry> xNewUserData(std::make_unique<Entry>(*pEntry)); + sId = OUString::number(reinterpret_cast<sal_uInt64>(xNewUserData.release())); + } std::unique_ptr<weld::TreeIter> xRet(m_rTreeView.make_iterator()); m_rTreeView.get_widget().insert(xNewParent.get(), nNewChildPos, &sText, &sId, nullptr, nullptr, false, xRet.get()); if (eType == OBJ_TYPE_MODULE) @@ -562,6 +576,9 @@ ObjectPage::ObjectPage(weld::Container* pParent, const OString &rName, BrowseMod } m_xDropTarget.reset(new SbTreeListBoxDropTarget(*m_xBasicBox)); + // tdf#145722 explicitly claim COPY and MOVE are options + rtl::Reference<TransferDataContainer> xHelper(new TransferDataContainer); + m_xBasicBox->get_widget().enable_drag_source(xHelper, DND_ACTION_COPYMOVE); m_xBasicBox->connect_editing(LINK(this, ObjectPage, EditingEntryHdl), LINK(this, ObjectPage, EditedEntryHdl)); diff --git a/basic/qa/basic_coverage/test_cdbl_method.bas b/basic/qa/basic_coverage/test_cdbl_method.bas index 1c7837fcaa4b..e44c23456ff1 100644 --- a/basic/qa/basic_coverage/test_cdbl_method.bas +++ b/basic/qa/basic_coverage/test_cdbl_method.bas @@ -1,18 +1,30 @@ -' -' 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/. -' +'
+' 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/.
+'
+
+Option Explicit
-Option Explicit +Function doUnitTest() As String
+ TestUtil.TestInit
+ verify_testCdbl
+ doUnitTest = TestUtil.GetResult()
+End Function +
+Sub verify_testCdbl + On Error GoTo errorHandler -Function doUnitTest as String ' CDBL - If (CDbl("100") <> 100) Then - doUnitTest = "FAIL" - Else - doUnitTest = "OK" - End If -End Function + TestUtil.AssertEqual(CDbl("100"), 100, "CDbl(""100"")") + + ' tdf#146672 - skip spaces and tabs at the end of the scanned string + TestUtil.AssertEqual(CDbl("28.8 "), 28.8, "CDbl(""28.8 "")")
+ TestUtil.AssertEqual(CDbl("28.8 "), 28.8, "CDbl(""28.8 "")")
+
+ Exit Sub +errorHandler: + TestUtil.ReportErrorHandler("verify_testCdbl", Err, Error$, Erl) +End Sub diff --git a/basic/qa/basic_coverage/test_declare_from_dll.bas b/basic/qa/basic_coverage/test_declare_from_dll.bas new file mode 100644 index 000000000000..7bdd1b170492 --- /dev/null +++ b/basic/qa/basic_coverage/test_declare_from_dll.bas @@ -0,0 +1,36 @@ +' +' 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/. +' + +Option Explicit + +' We link to shlwapi in many places, so safe to rely on it here +Declare Function PathFindExtensionA Lib "Shlwapi" (ByVal pszPath As String) As String + +Function doUnitTest() As String + TestUtil.TestInit + verify_testPathFindExtensionA + doUnitTest = TestUtil.GetResult() +End Function + +Sub verify_testPathFindExtensionA() + On Error GoTo errorHandler + + ' Only test on Windows + If (GetGUIType() <> 1) Then + TestUtil.Assert(True) ' The test passed + Exit Sub + End If + + ' Without the fix for tdf#147364 in place, the next call would crash in 64-bit version with + ' *** Exception 0xc0000005 occurred *** + TestUtil.AssertEqual(PathFindExtensionA("filename.ext"), ".ext", "PathFindExtensionA(""filename.ext"")") + + Exit Sub +errorHandler: + TestUtil.ReportErrorHandler("verify_testPathFindExtensionA", Err, Error$, Erl) +End Sub diff --git a/basic/qa/basic_coverage/test_non_ascii_names.bas b/basic/qa/basic_coverage/test_non_ascii_names.bas new file mode 100644 index 000000000000..a9ef0f159da2 --- /dev/null +++ b/basic/qa/basic_coverage/test_non_ascii_names.bas @@ -0,0 +1,28 @@ +' +' 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/. +' + +Option Explicit + +Function doUnitTest as String + [Prüfung] + doUnitTest = TestUtil.GetResult() +End Function + +Function [Функция]([😁]) + [Функция] = [😁] & " and some text" +End Function + +Sub [Prüfung] + On Error GoTo errorHandler + + TestUtil.AssertEqual([Функция]("Smiley"), "Smiley and some text", "[Функция](""Smiley"")") + + Exit Sub +errorHandler: + TestUtil.ReportErrorHandler("Prüfung", Err, Error$, Erl) +End Sub diff --git a/basic/qa/basic_coverage/test_tdf132388_ReplacePerformance.bas b/basic/qa/basic_coverage/test_tdf132388_ReplacePerformance.bas new file mode 100644 index 000000000000..531cdec5c622 --- /dev/null +++ b/basic/qa/basic_coverage/test_tdf132388_ReplacePerformance.bas @@ -0,0 +1,28 @@ +' +' 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/. +' + +Function doUnitTest as String + TestUtil.TestInit + TestReplacePerformance() + doUnitTest = TestUtil.GetResult() +End Function + +Sub TestReplacePerformance() + On Error GoTo errorHandler + ' Assume the normal case to be much faster than 60 s even on slow boxes, and the test string + ' is long enough to cause serious performance regressions make it perform much longer + n = 10000000 + s = Space(n) + t = Now + s = Replace(s, " ", "*", 1, -1, 1) + t = Now - t + TestUtil.Assert(t <= TimeSerial(0, 1, 0), "TestReplacePerformance", Format(t, """t = ""[s]"" s""")) + Exit Sub +errorHandler: + TestUtil.ReportErrorHandler("TestReplacePerformance", Err, Error$, Erl) +End Sub diff --git a/basic/qa/basic_coverage/test_tdf147089_idiv.bas b/basic/qa/basic_coverage/test_tdf147089_idiv.bas new file mode 100644 index 000000000000..3d5e2271140c --- /dev/null +++ b/basic/qa/basic_coverage/test_tdf147089_idiv.bas @@ -0,0 +1,30 @@ +'
+' 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/.
+'
+
+Option Explicit
+ +Function doUnitTest() As String
+ TestUtil.TestInit
+ verify_testIDiv
+ doUnitTest = TestUtil.GetResult()
+End Function +
+Sub verify_testIDiv + On Error GoTo errorHandler
+
+ ' tdf#147089 - IDIV operands are rounded to Integer values before the operation is performed
+ TestUtil.AssertEqual(8.4 \ 2, 4, "8.4 \ 2")
+ TestUtil.AssertEqual(9.9 \ 2, 5, "9.9 \ 2")
+ TestUtil.AssertEqual(20 \ 4.9, 4, "20 \ 4.9")
+ TestUtil.AssertEqual(20 \ 4.4, 5, "20 \ 4.4")
+ TestUtil.AssertEqual(16.4 \ 5.9, 2, "16.4 \ 5.9")
+
+ Exit Sub +errorHandler: + TestUtil.ReportErrorHandler("verify_testIDiv", Err, Error$, Erl) +End Sub diff --git a/basic/qa/cppunit/test_vba.cxx b/basic/qa/cppunit/test_vba.cxx index 818ba1c5f4c0..7cb64558ffa6 100644 --- a/basic/qa/cppunit/test_vba.cxx +++ b/basic/qa/cppunit/test_vba.cxx @@ -134,6 +134,7 @@ void VBATest::testMiscVBAFunctions() "string.vb", "strreverse.vb", "switch.vb", + "tdf147089_idiv.vb", "timeserial.vb", "timevalue.vb", "trim.vb", diff --git a/basic/qa/vba_tests/cdbl.vb b/basic/qa/vba_tests/cdbl.vb index f29271f082d6..8a7d09cd5a2e 100644 --- a/basic/qa/vba_tests/cdbl.vb +++ b/basic/qa/vba_tests/cdbl.vb @@ -23,6 +23,11 @@ Sub verify_testCdbl() TestUtil.AssertEqual(CDbl(0.005 * 0.01), 0.00005, "CDbl(0.005 * 0.01)") TestUtil.AssertEqual(CDbl("20"), 20, "CDbl(""20"")") + + ' tdf#146672 - skip spaces and tabs at the end of the scanned string + TestUtil.AssertEqual(CDbl("28.8 "), 28.8, "CDbl(""28.8 "")") + TestUtil.AssertEqual(CDbl("28.8 "), 28.8, "CDbl(""28.8 "")") + Exit Sub errorHandler: TestUtil.ReportErrorHandler("verify_testCdbl", Err, Error$, Erl) diff --git a/basic/qa/vba_tests/tdf147089_idiv.vb b/basic/qa/vba_tests/tdf147089_idiv.vb new file mode 100644 index 000000000000..515f1e00cf63 --- /dev/null +++ b/basic/qa/vba_tests/tdf147089_idiv.vb @@ -0,0 +1,31 @@ +'
+' 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/.
+'
+
+Option VBASupport 1
+Option Explicit
+ +Function doUnitTest() As String
+ TestUtil.TestInit
+ verify_testIDiv
+ doUnitTest = TestUtil.GetResult()
+End Function +
+Sub verify_testIDiv + On Error GoTo errorHandler
+
+ ' tdf#147089 - IDIV operands are rounded to Integer values before the operation is performed
+ TestUtil.AssertEqual(8.4 \ 2, 4, "8.4 \ 2")
+ TestUtil.AssertEqual(9.9 \ 2, 5, "9.9 \ 2")
+ TestUtil.AssertEqual(20 \ 4.9, 4, "20 \ 4.9")
+ TestUtil.AssertEqual(20 \ 4.4, 5, "20 \ 4.4")
+ TestUtil.AssertEqual(16.4 \ 5.9, 2, "16.4 \ 5.9")
+
+ Exit Sub +errorHandler: + TestUtil.ReportErrorHandler("verify_testIDiv", Err, Error$, Erl) +End Sub diff --git a/basic/source/classes/sbxmod.cxx b/basic/source/classes/sbxmod.cxx index cdd05c0c1f14..689ea383816f 100644 --- a/basic/source/classes/sbxmod.cxx +++ b/basic/source/classes/sbxmod.cxx @@ -2062,6 +2062,12 @@ ErrCode SbMethod::Call( SbxValue* pRet, SbxVariable* pCaller ) if( bInvalid && !pMod_->Compile() ) StarBASIC::Error( ERRCODE_BASIC_BAD_PROP_VALUE ); + // tdf#143582 - clear return value of the method before calling it + const SbxFlagBits nSavFlags = GetFlags(); + SetFlag(SbxFlagBits::ReadWrite | SbxFlagBits::NoBroadcast); + Clear(); + SetFlags(nSavFlags); + Get( aVals ); if ( pRet ) pRet->Put( aVals ); diff --git a/basic/source/comp/exprnode.cxx b/basic/source/comp/exprnode.cxx index 17bdbca25258..a5fd8dde3cfc 100644 --- a/basic/source/comp/exprnode.cxx +++ b/basic/source/comp/exprnode.cxx @@ -296,8 +296,8 @@ void SbiExprNode::FoldConstantsBinaryNode(SbiParser* pParser) { double nl = pLeft->nVal; double nr = pRight->nVal; - // tdf#141201 - round MOD literals to Integer values - if (eTok == MOD) + // tdf#141201, tdf#147089 - round MOD/IDIV literals to Integer values + if (eTok == MOD || eTok == IDIV) { nl = rtl::math::round(nl); nr = rtl::math::round(nr); diff --git a/basic/source/inc/rtlproto.hxx b/basic/source/inc/rtlproto.hxx index 7347ead45dc1..ff089d6b0dbd 100644 --- a/basic/source/inc/rtlproto.hxx +++ b/basic/source/inc/rtlproto.hxx @@ -233,6 +233,7 @@ extern void SbRtl_IsUnoStruct(StarBASIC * pBasic, SbxArray & rPar, bool bWrite); extern void SbRtl_FileDateTime(StarBASIC * pBasic, SbxArray & rPar, bool bWrite); extern void SbRtl_Format(StarBASIC * pBasic, SbxArray & rPar, bool bWrite); extern void SbRtl_FormatNumber(StarBASIC* pBasic, SbxArray& rPar, bool bWrite); +extern void SbRtl_FormatPercent(StarBASIC* pBasic, SbxArray& rPar, bool bWrite); extern void SbRtl_GetAttr(StarBASIC * pBasic, SbxArray & rPar, bool bWrite); extern void SbRtl_Randomize(StarBASIC * pBasic, SbxArray & rPar, bool bWrite); // JSM extern void SbRtl_Round(StarBASIC * pBasic, SbxArray & rPar, bool bWrite); diff --git a/basic/source/runtime/dllmgr-x64.cxx b/basic/source/runtime/dllmgr-x64.cxx index dad4bea8794a..b2ddbb890da1 100644 --- a/basic/source/runtime/dllmgr-x64.cxx +++ b/basic/source/runtime/dllmgr-x64.cxx @@ -512,8 +512,6 @@ ErrCode call( // We fake all calls as being to a varargs function, // as this means any floating-point argument among the first four // ones will end up in a XMM register where the callee expects it. - sal_Int32 (*proc_i)(double d, ...) = reinterpret_cast<sal_Int32 (*)(double, ...)>(proc.proc); - double (*proc_d)(double d, ...) = reinterpret_cast<double (*)(double, ...)>(proc.proc); sal_Int64 iRetVal = 0; double dRetVal = 0.0; @@ -527,55 +525,21 @@ ErrCode call( case SbxBOOL: case SbxBYTE: { - auto const st = stack.data(); - iRetVal = - proc_i(*reinterpret_cast<double *>(st + 0), - *reinterpret_cast<double *>(st + 1*8), - *reinterpret_cast<double *>(st + 2*8), - *reinterpret_cast<double *>(st + 3*8), - *reinterpret_cast<sal_uInt64 *>(st + 4*8), - *reinterpret_cast<sal_uInt64 *>(st + 5*8), - *reinterpret_cast<sal_uInt64 *>(st + 6*8), - *reinterpret_cast<sal_uInt64 *>(st + 7*8), - *reinterpret_cast<sal_uInt64 *>(st + 8*8), - *reinterpret_cast<sal_uInt64 *>(st + 9*8), - *reinterpret_cast<sal_uInt64 *>(st + 10*8), - *reinterpret_cast<sal_uInt64 *>(st + 11*8), - *reinterpret_cast<sal_uInt64 *>(st + 12*8), - *reinterpret_cast<sal_uInt64 *>(st + 13*8), - *reinterpret_cast<sal_uInt64 *>(st + 14*8), - *reinterpret_cast<sal_uInt64 *>(st + 15*8), - *reinterpret_cast<sal_uInt64 *>(st + 16*8), - *reinterpret_cast<sal_uInt64 *>(st + 17*8), - *reinterpret_cast<sal_uInt64 *>(st + 18*8), - *reinterpret_cast<sal_uInt64 *>(st + 19*8)); + auto p = reinterpret_cast<sal_Int64 (*)(...)>(proc.proc); + auto const st = reinterpret_cast<double *>(stack.data()); + iRetVal + = p(st[0], st[1], st[2], st[3], st[4], st[5], st[6], st[7], st[8], st[9], st[10], + st[11], st[12], st[13], st[14], st[15], st[16], st[17], st[18], st[19]); break; } case SbxSINGLE: case SbxDOUBLE: { - auto const st = stack.data(); - dRetVal = - proc_d(*reinterpret_cast<double *>(st + 0), - *reinterpret_cast<double *>(st + 1*8), - *reinterpret_cast<double *>(st + 2*8), - *reinterpret_cast<double *>(st + 3*8), - *reinterpret_cast<sal_uInt64 *>(st + 4*8), - *reinterpret_cast<sal_uInt64 *>(st + 5*8), - *reinterpret_cast<sal_uInt64 *>(st + 6*8), - *reinterpret_cast<sal_uInt64 *>(st + 7*8), - *reinterpret_cast<sal_uInt64 *>(st + 8*8), - *reinterpret_cast<sal_uInt64 *>(st + 9*8), - *reinterpret_cast<sal_uInt64 *>(st + 10*8), - *reinterpret_cast<sal_uInt64 *>(st + 11*8), - *reinterpret_cast<sal_uInt64 *>(st + 12*8), - *reinterpret_cast<sal_uInt64 *>(st + 13*8), - *reinterpret_cast<sal_uInt64 *>(st + 14*8), - *reinterpret_cast<sal_uInt64 *>(st + 15*8), - *reinterpret_cast<sal_uInt64 *>(st + 16*8), - *reinterpret_cast<sal_uInt64 *>(st + 17*8), - *reinterpret_cast<sal_uInt64 *>(st + 18*8), - *reinterpret_cast<sal_uInt64 *>(st + 19*8)); + auto p = reinterpret_cast<double (*)(...)>(proc.proc); + auto const st = reinterpret_cast<double*>(stack.data()); + dRetVal + = p(st[0], st[1], st[2], st[3], st[4], st[5], st[6], st[7], st[8], st[9], st[10], + st[11], st[12], st[13], st[14], st[15], st[16], st[17], st[18], st[19]); break; } default: diff --git a/basic/source/runtime/methods.cxx b/basic/source/runtime/methods.cxx index 7e9a1adcccd7..851584b6db79 100644 --- a/basic/source/runtime/methods.cxx +++ b/basic/source/runtime/methods.cxx @@ -68,7 +68,7 @@ #include <o3tl/char16_t2wchar_t.hxx> // include search util -#include <com/sun/star/util/SearchFlags.hpp> +#include <com/sun/star/i18n/Transliteration.hpp> #include <com/sun/star/util/SearchAlgorithms2.hpp> #include <i18nutil/searchopt.hxx> #include <unotools/textsearch.hxx> @@ -1267,6 +1267,7 @@ void SbRtl_Replace(StarBASIC *, SbxArray & rPar, bool) return; } } + --lStartPos; // Make it 0-based sal_Int32 lCount = -1; if (nArgCount >= 5) @@ -1302,40 +1303,52 @@ void SbRtl_Replace(StarBASIC *, SbxArray & rPar, bool) } const OUString aExpStr = rPar.Get(1)->GetOUString(); - const OUString aFindStr = rPar.Get(2)->GetOUString(); + OUString aFindStr = rPar.Get(2)->GetOUString(); const OUString aReplaceStr = rPar.Get(3)->GetOUString(); - const sal_Int32 nExpStrLen = aExpStr.getLength(); - const sal_Int32 nFindStrLen = aFindStr.getLength(); - // tdf#142487 - use utl::TextSearch in order to implement the replace algorithm - i18nutil::SearchOptions2 aSearchOptions; - aSearchOptions.searchString = aFindStr; - aSearchOptions.AlgorithmType2 = util::SearchAlgorithms2::ABSOLUTE; + OUString aSrcStr(aExpStr); + sal_Int32 nPrevPos = std::min(lStartPos, aSrcStr.getLength()); + css::uno::Sequence<sal_Int32> aOffset; if (bCaseInsensitive) - aSearchOptions.transliterateFlags |= TransliterationFlags::IGNORE_CASE; - utl::TextSearch textSearch(aSearchOptions); + { + // tdf#132389: case-insensitive operation for non-ASCII characters + // tdf#142487: use css::i18n::Transliteration to correctly handle ß -> ss expansion + // tdf#132388: We can't use utl::TextSearch (css::i18n::XTextSearch), because each call to + // css::i18n::XTextSearch::SearchForward transliterates input string, making + // performance of repeated calls unacceptable + auto xTrans = css::i18n::Transliteration::create(comphelper::getProcessComponentContext()); + xTrans->loadModule(css::i18n::TransliterationModules_IGNORE_CASE, {}); + aFindStr = xTrans->transliterate(aFindStr, 0, aFindStr.getLength(), aOffset); + aSrcStr = xTrans->transliterate(aSrcStr, nPrevPos, aSrcStr.getLength() - nPrevPos, aOffset); + nPrevPos = std::distance(aOffset.begin(), + std::lower_bound(aOffset.begin(), aOffset.end(), nPrevPos)); + } + + auto getExpStrPos = [aOffset, nExpLen = aExpStr.getLength()](sal_Int32 nSrcStrPos) -> sal_Int32 + { + assert(!aOffset.hasElements() || aOffset.getLength() >= nSrcStrPos); + if (!aOffset.hasElements()) + return nSrcStrPos; + return aOffset.getLength() > nSrcStrPos ? aOffset[nSrcStrPos] : nExpLen; + }; // Note: the result starts from lStartPos, removing everything to the left. See i#94895. - sal_Int32 nPrevPos = std::min(lStartPos - 1, nExpStrLen); - OUStringBuffer sResult(nExpStrLen - nPrevPos); + OUStringBuffer sResult(aSrcStr.getLength() - nPrevPos); sal_Int32 nCounts = 0; while (lCount == -1 || lCount > nCounts) { - sal_Int32 nStartPos = nPrevPos; - sal_Int32 aEndPos = aExpStr.getLength(); - if (textSearch.SearchForward(aExpStr, &nStartPos, &aEndPos)) - { - sResult.append(aExpStr.getStr() + nPrevPos, nStartPos - nPrevPos); - sResult.append(aReplaceStr); - nPrevPos = nStartPos + nFindStrLen; - nCounts++; - } - else - { + sal_Int32 nPos = aSrcStr.indexOf(aFindStr, nPrevPos); + if (nPos < 0) break; - } + + lStartPos = getExpStrPos(nPrevPos); + sResult.append(aExpStr.getStr() + lStartPos, getExpStrPos(nPos) - lStartPos); + sResult.append(aReplaceStr); + nPrevPos = nPos + aFindStr.getLength(); + nCounts++; } - sResult.append(aExpStr.getStr() + nPrevPos, nExpStrLen - nPrevPos); + lStartPos = getExpStrPos(nPrevPos); + sResult.append(aExpStr.getStr() + lStartPos, aExpStr.getLength() - lStartPos); rPar.Get(0)->PutString(sResult.makeStringAndClear()); } @@ -3324,8 +3337,7 @@ void SbRtl_Format(StarBASIC *, SbxArray & rPar, bool) } } -// https://msdn.microsoft.com/en-us/vba/language-reference-vba/articles/formatnumber-function -void SbRtl_FormatNumber(StarBASIC*, SbxArray& rPar, bool) +static void lcl_FormatNumberPercent(SbxArray& rPar, bool isPercent) { const sal_uInt32 nArgCount = rPar.Count(); if (nArgCount < 2 || nArgCount > 6) @@ -3408,6 +3420,8 @@ void SbRtl_FormatNumber(StarBASIC*, SbxArray& rPar, bool) } double fVal = rPar.Get(1)->GetDouble(); + if (isPercent) + fVal *= 100; const bool bNegative = fVal < 0; if (bNegative) fVal = fabs(fVal); // Always work with non-negatives, to easily handle leading zero @@ -3449,6 +3463,20 @@ void SbRtl_FormatNumber(StarBASIC*, SbxArray& rPar, bool) } rPar.Get(0)->PutString(aResult); + if (isPercent) + aResult += "%"; +} + +// https://docs.microsoft.com/en-us/office/vba/Language/Reference/User-Interface-Help/formatnumber-function +void SbRtl_FormatNumber(StarBASIC*, SbxArray& rPar, bool) +{ + return lcl_FormatNumberPercent(rPar, false); +} + +// https://docs.microsoft.com/en-us/office/vba/Language/Reference/User-Interface-Help/formatpercent-function +void SbRtl_FormatPercent(StarBASIC*, SbxArray& rPar, bool) +{ + return lcl_FormatNumberPercent(rPar, true); } namespace { diff --git a/basic/source/runtime/methods1.cxx b/basic/source/runtime/methods1.cxx index 117e84d73000..7e2d0c771a37 100644 --- a/basic/source/runtime/methods1.cxx +++ b/basic/source/runtime/methods1.cxx @@ -120,7 +120,7 @@ void SbRtl_CallByName(StarBASIC *, SbxArray & rPar, bool) return; } - // 2. parameter is ProcedureName + // 2. parameter is ProcName OUString aNameStr = rPar.Get(2)->GetOUString(); // 3. parameter is CallType diff --git a/basic/source/runtime/stdobj.cxx b/basic/source/runtime/stdobj.cxx index 4adda6efafec..810f53ad4912 100644 --- a/basic/source/runtime/stdobj.cxx +++ b/basic/source/runtime/stdobj.cxx @@ -141,7 +141,7 @@ constexpr Method aMethods[] = { { u"CallByName", SbxVARIANT, 3 | FUNCTION_, SbRtl_CallByName }, arg(u"Object", SbxOBJECT), - arg(u"ProcedureName", SbxSTRING), + arg(u"ProcName", SbxSTRING), arg(u"CallType", SbxINTEGER), { u"CBool", SbxBOOL, 1 | FUNCTION_, SbRtl_CBool }, @@ -401,6 +401,13 @@ constexpr Method aMethods[] = { arg(u"useParensForNegativeNumbers", SbxINTEGER, OPT_), // vbTriState arg(u"groupDigits", SbxINTEGER, OPT_), // vbTriState +{ u"FormatPercent", SbxSTRING, 5 | FUNCTION_ | COMPATONLY_, SbRtl_FormatPercent }, + arg(u"expression", SbxDOUBLE), + arg(u"numDigitsAfterDecimal", SbxINTEGER, OPT_), + arg(u"includeLeadingDigit", SbxINTEGER, OPT_), // vbTriState + arg(u"useParensForNegativeNumbers", SbxINTEGER, OPT_), // vbTriState + arg(u"groupDigits", SbxINTEGER, OPT_), // vbTriState + { u"Frac", SbxDOUBLE, 1 | FUNCTION_, SbRtl_Frac }, arg(u"number", SbxDOUBLE), diff --git a/basic/source/sbx/sbxscan.cxx b/basic/source/sbx/sbxscan.cxx index a496a51d6ccb..5fb56ba1d8fd 100644 --- a/basic/source/sbx/sbxscan.cxx +++ b/basic/source/sbx/sbxscan.cxx @@ -268,6 +268,9 @@ ErrCode ImpScan( const OUString& rWSrc, double& nVal, SbxDataType& rType, return ERRCODE_BASIC_CONVERSION; } #endif + // tdf#146672 - skip whitespaces and tabs at the end of the scanned string + while (*p == ' ' || *p == '\t') + p++; if( pLen ) *pLen = static_cast<sal_uInt16>( p - pStart ); if( !bRes ) diff --git a/basic/source/sbx/sbxvar.cxx b/basic/source/sbx/sbxvar.cxx index b8be36ec2735..6097d25eb995 100644 --- a/basic/source/sbx/sbxvar.cxx +++ b/basic/source/sbx/sbxvar.cxx @@ -281,7 +281,10 @@ SbxVariable& SbxVariable::operator=( const SbxVariable& r ) { SbxValue::operator=( r ); // tdf#144353 - copy information about a missing parameter. See SbiRuntime::SetIsMissing. - if (r.pInfo && !dynamic_cast<const SbxMethod*>(&r)) + // We cannot unconditionally assign the data about a variable because we would overwrite + // the information about parameters (name, type, flags, and ids). For instance, in the case + // where a method will be initialized with a literal. + if (!pInfo) pInfo = r.pInfo; m_aDeclareClassName = r.m_aDeclareClassName; m_xComListener = r.m_xComListener; diff --git a/bin/check-elf-dynamic-objects b/bin/check-elf-dynamic-objects index 523a892e4259..712856d1104c 100755 --- a/bin/check-elf-dynamic-objects +++ b/bin/check-elf-dynamic-objects @@ -88,7 +88,7 @@ programfiles=$(echo ${files} | grep -o '/program/[^/]* ' | xargs -n 1 basename) # of maintaining ABI stability # allow extending the allowlist using the environment variable to be able to work # on the installer stuff without the need for a baseline setup -globalallowlist="ld-linux-x86-64.so.2 ld-linux.so.2 libc.so.6 libm.so.6 libdl.so.2 libpthread.so.0 librt.so.1 libutil.so.1 libnsl.so.1 libcrypt.so.1 libgcc_s.so.1 libstdc++.so.6 libz.so.1 libfontconfig.so.1 libfreetype.so.6 libxml2.so.2 libxslt.so.1 libexslt.so.0 ${LO_ELFCHECK_ALLOWLIST-}" +globalallowlist="ld-linux-x86-64.so.2 ld-linux.so.2 libc.so.6 libm.so.6 libdl.so.2 libpthread.so.0 librt.so.1 libutil.so.1 libnsl.so.1 libcrypt.so.1 libgcc_s.so.1 libstdc++.so.6 libz.so.1 libfontconfig.so.1 libfreetype.so.6 libxml2.so.2 libxslt.so.1 libexslt.so.0 libnspr4.so libnss3.so libnssutil3.so libplc4.so libplds4.so libsmime3.so libssl3.so ${LO_ELFCHECK_ALLOWLIST-}" x11allowlist="libX11.so.6 libX11-xcb.so.1 libXext.so.6 libSM.so.6 libICE.so.6 libXinerama.so.1 libXrender.so.1 libXrandr.so.2 libcairo.so.2" openglallowlist="libGL.so.1" gobjectallowlist="libgobject-2.0.so.0 libglib-2.0.so.0" diff --git a/canvas/source/vcl/canvashelper_texturefill.cxx b/canvas/source/vcl/canvashelper_texturefill.cxx index 33f4f5c5318c..fa8b97395cfe 100644 --- a/canvas/source/vcl/canvashelper_texturefill.cxx +++ b/canvas/source/vcl/canvashelper_texturefill.cxx @@ -154,6 +154,12 @@ namespace vclcanvas // 2 colors and 2 stops (at 0 and 1) is a linear gradient: if( rColors.size() == 2 && rValues.maStops.size() == 2 && rValues.maStops[0] == 0 && rValues.maStops[1] == 1) { + // tdf#144073: Note that the code below adjusts the gradient area this way. + // No, I have no idea why. + aLeftTop -= 2.0*nDiagonalLength*aDirection; + aLeftBottom -= 2.0*nDiagonalLength*aDirection; + aRightTop += 2.0*nDiagonalLength*aDirection; + aRightBottom += 2.0*nDiagonalLength*aDirection; Gradient vclGradient( GradientStyle::Linear, rColors[ 0 ], rColors[ 1 ] ); ::tools::Polygon aTempPoly( static_cast<sal_uInt16>(5) ); aTempPoly[0] = ::Point( ::basegfx::fround( aLeftTop.getX() ), @@ -173,6 +179,12 @@ namespace vclcanvas && rValues.maStops.size() == 3 && rValues.maStops[0] == 0 && rValues.maStops[1] == 0.5 && rValues.maStops[2] == 1) { + // tdf#144073: Note that the code below adjusts the gradient area this way. + // No, I have no idea why. + aLeftTop -= 2.0*nDiagonalLength*aDirection; + aLeftBottom -= 2.0*nDiagonalLength*aDirection; + aRightTop += 2.0*nDiagonalLength*aDirection; + aRightBottom += 2.0*nDiagonalLength*aDirection; Gradient vclGradient( GradientStyle::Axial, rColors[ 1 ], rColors[ 0 ] ); ::tools::Polygon aTempPoly( static_cast<sal_uInt16>(5) ); aTempPoly[0] = ::Point( ::basegfx::fround( aLeftTop.getX() ), diff --git a/chart2/Library_chartcore.mk b/chart2/Library_chartcore.mk index 73945d783d3a..dd13d9b7b860 100644 --- a/chart2/Library_chartcore.mk +++ b/chart2/Library_chartcore.mk @@ -61,6 +61,7 @@ $(eval $(call gb_Library_use_libraries,chartcore,\ ucbhelper \ utl \ vcl \ + xo \ )) $(eval $(call gb_Library_set_componentfile,chartcore,chart2/source/chartcore)) diff --git a/chart2/qa/extras/chart2import.cxx b/chart2/qa/extras/chart2import.cxx index e908cfc57a71..f22f09a5d936 100644 --- a/chart2/qa/extras/chart2import.cxx +++ b/chart2/qa/extras/chart2import.cxx @@ -53,6 +53,7 @@ public: void testDOCXChartSeries(); void testDOCXChartEmptySeries(); void testTdf81396(); + void testPPTXChartErrorBars(); void testDOCXChartValuesSize(); void testPPTXChartSeries(); void testPPTXSparseChartSeries(); @@ -126,20 +127,16 @@ public: void testTdf90510(); // Pie chart label placement settings(XLS) void testTdf109858(); // Pie chart label placement settings(XLSX) void testTdf130105(); - void testTdf111173(); void testTdf122226(); - void testInternalDataProvider(); - void testTdf115107(); // import complex data point labels void testTdf115107_2(); // import complex data point labels in cobo charts with multiple data series - void testTdf116163(); - void testTdf48041(); - void testTdf121205(); + void testFixedSizeBarChartVeryLongLabel(); + void testAutomaticSizeBarChartVeryLongLabel(); CPPUNIT_TEST_SUITE(Chart2ImportTest); CPPUNIT_TEST(Fdo60083); @@ -154,6 +151,7 @@ public: CPPUNIT_TEST(testDOCXChartSeries); CPPUNIT_TEST(testDOCXChartEmptySeries); CPPUNIT_TEST(testTdf81396); + CPPUNIT_TEST(testPPTXChartErrorBars); CPPUNIT_TEST(testDOCXChartValuesSize); CPPUNIT_TEST(testPPTChartSeries); CPPUNIT_TEST(testPPTXChartSeries); @@ -216,17 +214,14 @@ public: CPPUNIT_TEST(testTdf130105); CPPUNIT_TEST(testTdf111173); CPPUNIT_TEST(testTdf122226); - CPPUNIT_TEST(testInternalDataProvider); - CPPUNIT_TEST(testTdf115107); CPPUNIT_TEST(testTdf115107_2); - CPPUNIT_TEST(testTdf116163); - CPPUNIT_TEST(testTdf48041); - CPPUNIT_TEST(testTdf121205); + CPPUNIT_TEST(testFixedSizeBarChartVeryLongLabel); + CPPUNIT_TEST(testAutomaticSizeBarChartVeryLongLabel); CPPUNIT_TEST_SUITE_END(); }; @@ -491,6 +486,19 @@ void Chart2ImportTest::testTdf81396() CPPUNIT_ASSERT_EQUAL(105.210801910481, aDataSeriesYValues[0][0]); } +void Chart2ImportTest::testPPTXChartErrorBars() +{ + load(u"/chart2/qa/extras/data/pptx/", "tdf127720.pptx"); + Reference<chart2::XChartDocument> xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc.is()); + + uno::Reference< chart::XChartDataArray > xDataArray(xChartDoc->getDataProvider(), UNO_QUERY_THROW); + Sequence<OUString> aColumnDesc = xDataArray->getColumnDescriptions(); + // Number of columns = 4 (Y-values, X-values and positive/negative error bars). + // Without the fix there would only be 2 columns (no error range). + CPPUNIT_ASSERT_EQUAL_MESSAGE("There must be 4 columns and descriptions", static_cast<sal_Int32>(4), aColumnDesc.getLength()); +} + void Chart2ImportTest::testDOCXChartValuesSize() { load( u"/chart2/qa/extras/data/docx/", "bubblechart.docx" ); @@ -2106,6 +2114,146 @@ void Chart2ImportTest::testTdf121205() CPPUNIT_ASSERT_EQUAL(OUString("Firstline\nSecondline\nThirdline"), aTitle); } +void Chart2ImportTest::testFixedSizeBarChartVeryLongLabel() +{ + // Bar chart area size is fixed (not automatic) so we can't resize + // the chart area to let the label break into multiple lines. In this + // case the best course of action is to just crop the label text. This + // test checks that the rendered text is actually cropped. + + load(u"/chart2/qa/extras/data/odp/", "BarChartVeryLongLabel.odp"); + + // Select shape 0 which has fixed size chart + Reference<chart2::XChartDocument> xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc.is()); + + Reference<chart2::XAxis> xHAxis = getAxisFromDoc(xChartDoc, 0, 0, 0); + CPPUNIT_ASSERT(xHAxis.is()); + + chart2::ScaleData aScaleData = xHAxis->getScaleData(); + CPPUNIT_ASSERT(aScaleData.Categories.is()); + + Reference<chart2::data::XLabeledDataSequence> xLabeledDataSequence = aScaleData.Categories; + CPPUNIT_ASSERT(xLabeledDataSequence.is()); + + Reference<chart2::data::XDataSequence> xDataSequence = xLabeledDataSequence->getValues(); + CPPUNIT_ASSERT(xDataSequence.is()); + + Reference<chart2::data::XTextualDataSequence> xTextualDataSequence(xDataSequence, uno::UNO_QUERY); + CPPUNIT_ASSERT(xTextualDataSequence.is()); + + std::vector<OUString> aCategories; + const Sequence<OUString> aTextData(xTextualDataSequence->getTextualData()); + ::std::copy(aTextData.begin(), aTextData.end(), + ::std::back_inserter(aCategories)); + + // Check that we have a very very long label text + CPPUNIT_ASSERT_EQUAL(OUString("Very very very very very very very very very very very loooooooooooong label"), aCategories[0]); + + // Check visible text + uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, uno::UNO_QUERY); + uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage(); + uno::Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xShapes.is()); + + uno::Reference<drawing::XShape> xXAxis = getShapeByName(xShapes, "CID/D=0:CS=0:Axis=0,0", + // Axis occurs twice in chart xshape representation so need to get the one related to labels + [](const uno::Reference<drawing::XShape>& rXShape) -> bool + { + uno::Reference<drawing::XShapes> xAxisShapes(rXShape, uno::UNO_QUERY); + CPPUNIT_ASSERT(xAxisShapes.is()); + uno::Reference<drawing::XShape> xChildShape(xAxisShapes->getByIndex(0), uno::UNO_QUERY); + uno::Reference< drawing::XShapeDescriptor > xShapeDescriptor(xChildShape, uno::UNO_QUERY_THROW); + return (xShapeDescriptor->getShapeType() == "com.sun.star.drawing.TextShape"); + }); + CPPUNIT_ASSERT(xXAxis.is()); + + uno::Reference<container::XIndexAccess> xIndexAccess(xXAxis, UNO_QUERY_THROW); + + // Check text is actually cropped + uno::Reference<text::XTextRange> xLabel(xIndexAccess->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(OUString("Very very very very very very..."), xLabel->getString()); + + uno::Reference<drawing::XShape> xChartWall = getShapeByName(xShapes, "CID/DiagramWall="); + CPPUNIT_ASSERT(xChartWall.is()); + + // The text shape width should be smaller than the chart wall + CPPUNIT_ASSERT_EQUAL(sal_Int32(5085), xChartWall->getSize().Width); + CPPUNIT_ASSERT_EQUAL(sal_Int32(7113), xChartWall->getSize().Height); + + CPPUNIT_ASSERT_EQUAL(sal_Int32(4870), xXAxis->getSize().Width); + CPPUNIT_ASSERT_EQUAL(sal_Int32(398), xXAxis->getSize().Height); +} + +void Chart2ImportTest::testAutomaticSizeBarChartVeryLongLabel() +{ + // Bar chart area size is automatic so we expect the label to be broken + // into multiple lines. + + load(u"/chart2/qa/extras/data/odp/", "BarChartVeryLongLabel.odp"); + + // Select shape 1, which has an automatic sized chart + Reference<chart2::XChartDocument> xChartDoc(getChartDocFromDrawImpress(0, 1), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc.is()); + + Reference<chart2::XAxis> xHAxis = getAxisFromDoc(xChartDoc, 0, 0, 0); + CPPUNIT_ASSERT(xHAxis.is()); + + chart2::ScaleData aScaleData = xHAxis->getScaleData(); + CPPUNIT_ASSERT(aScaleData.Categories.is()); + + Reference<chart2::data::XLabeledDataSequence> xLabeledDataSequence = aScaleData.Categories; + CPPUNIT_ASSERT(xLabeledDataSequence.is()); + + Reference<chart2::data::XDataSequence> xDataSequence = xLabeledDataSequence->getValues(); + CPPUNIT_ASSERT(xDataSequence.is()); + + Reference<chart2::data::XTextualDataSequence> xTextualDataSequence(xDataSequence, uno::UNO_QUERY); + CPPUNIT_ASSERT(xTextualDataSequence.is()); + + std::vector<OUString> aCategories; + const Sequence<OUString> aTextData(xTextualDataSequence->getTextualData()); + ::std::copy(aTextData.begin(), aTextData.end(), + ::std::back_inserter(aCategories)); + + // Check that we have a very very long label text + CPPUNIT_ASSERT_EQUAL(OUString("Very very very very very very very very very very very loooooooooooong label"), aCategories[0]); + + // Check visible text + uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, uno::UNO_QUERY); + uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage(); + uno::Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xShapes.is()); + + uno::Reference<drawing::XShape> xXAxis = getShapeByName(xShapes, "CID/D=0:CS=0:Axis=0,0", + // Axis occurs twice in chart xshape representation so need to get the one related to labels + [](const uno::Reference<drawing::XShape>& rXShape) -> bool + { + uno::Reference<drawing::XShapes> xAxisShapes(rXShape, uno::UNO_QUERY); + CPPUNIT_ASSERT(xAxisShapes.is()); + uno::Reference<drawing::XShape> xChildShape(xAxisShapes->getByIndex(0), uno::UNO_QUERY); + uno::Reference< drawing::XShapeDescriptor > xShapeDescriptor(xChildShape, uno::UNO_QUERY_THROW); + return (xShapeDescriptor->getShapeType() == "com.sun.star.drawing.TextShape"); + }); + CPPUNIT_ASSERT(xXAxis.is()); + + uno::Reference<container::XIndexAccess> xIndexAccess(xXAxis, UNO_QUERY_THROW); + + // Check text is unmodified + uno::Reference<text::XTextRange> xLabel(xIndexAccess->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(OUString("Very very very very very very very very very very very loooooooooooong label"), xLabel->getString()); + + uno::Reference<drawing::XShape> xChartWall = getShapeByName(xShapes, "CID/DiagramWall="); + CPPUNIT_ASSERT(xChartWall.is()); + + // The text shape width should be smaller than the chart wall + CPPUNIT_ASSERT_EQUAL(sal_Int32(5761), xChartWall->getSize().Width); + CPPUNIT_ASSERT_EQUAL(sal_Int32(7200), xChartWall->getSize().Height); + + CPPUNIT_ASSERT_EQUAL(sal_Int32(5320), xXAxis->getSize().Width); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1192), xXAxis->getSize().Height); +} + CPPUNIT_TEST_SUITE_REGISTRATION(Chart2ImportTest); CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/chart2/qa/extras/chart2import2.cxx b/chart2/qa/extras/chart2import2.cxx index 0693a1e64184..95ee2428b47d 100644 --- a/chart2/qa/extras/chart2import2.cxx +++ b/chart2/qa/extras/chart2import2.cxx @@ -75,6 +75,7 @@ public: void testTdfCustomShapePos(); void testTdf121281(); void testTdf139658(); + void testTdf146066(); CPPUNIT_TEST_SUITE(Chart2ImportTest2); @@ -114,6 +115,7 @@ public: CPPUNIT_TEST(testTdfCustomShapePos); CPPUNIT_TEST(testTdf121281); CPPUNIT_TEST(testTdf139658); + CPPUNIT_TEST(testTdf146066); CPPUNIT_TEST_SUITE_END(); }; @@ -874,6 +876,52 @@ void Chart2ImportTest2::testTdf139658() CPPUNIT_ASSERT_EQUAL(OUString("category\"3"), aCategories[2]); } +void Chart2ImportTest2::testTdf146066() +{ + load(u"/chart2/qa/extras/data/ods/", "tdf146066.ods"); + Reference<chart::XChartDocument> xChartDoc(getChartDocFromSheet(0, mxComponent), + UNO_QUERY_THROW); + uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, uno::UNO_QUERY); + uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage(); + uno::Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xShapes.is()); + + uno::Reference<drawing::XShape> xYAxisShape = getShapeByName( + xShapes, "CID/D=0:CS=0:Axis=1,0", // Y Axis + // Axis occurs twice in chart xshape representation so need to get the one related to labels + [](const uno::Reference<drawing::XShape>& rXShape) -> bool { + uno::Reference<drawing::XShapes> xAxisShapes(rXShape, uno::UNO_QUERY); + CPPUNIT_ASSERT(xAxisShapes.is()); + uno::Reference<drawing::XShape> xChildShape(xAxisShapes->getByIndex(0), uno::UNO_QUERY); + uno::Reference<drawing::XShapeDescriptor> xShapeDescriptor(xChildShape, + uno::UNO_QUERY_THROW); + return (xShapeDescriptor->getShapeType() == "com.sun.star.drawing.TextShape"); + }); + CPPUNIT_ASSERT(xYAxisShape.is()); + + // Check label count + uno::Reference<container::XIndexAccess> xIndexAccess(xYAxisShape, UNO_QUERY_THROW); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(8), xIndexAccess->getCount()); + + // Check text + uno::Reference<text::XTextRange> xLabel0(xIndexAccess->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(OUString("0"), xLabel0->getString()); + uno::Reference<text::XTextRange> xLabel1(xIndexAccess->getByIndex(1), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(OUString("5"), xLabel1->getString()); + uno::Reference<text::XTextRange> xLabel2(xIndexAccess->getByIndex(2), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(OUString("10"), xLabel2->getString()); + uno::Reference<text::XTextRange> xLabel3(xIndexAccess->getByIndex(3), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(OUString("15"), xLabel3->getString()); + uno::Reference<text::XTextRange> xLabel4(xIndexAccess->getByIndex(4), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(OUString("20"), xLabel4->getString()); + uno::Reference<text::XTextRange> xLabel5(xIndexAccess->getByIndex(5), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(OUString("25"), xLabel5->getString()); + uno::Reference<text::XTextRange> xLabel6(xIndexAccess->getByIndex(6), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(OUString("30"), xLabel6->getString()); + uno::Reference<text::XTextRange> xLabel7(xIndexAccess->getByIndex(7), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(OUString("35"), xLabel7->getString()); +} + CPPUNIT_TEST_SUITE_REGISTRATION(Chart2ImportTest2); CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/chart2/qa/extras/data/odp/BarChartVeryLongLabel.odp b/chart2/qa/extras/data/odp/BarChartVeryLongLabel.odp Binary files differnew file mode 100644 index 000000000000..c627af79e4d5 --- /dev/null +++ b/chart2/qa/extras/data/odp/BarChartVeryLongLabel.odp diff --git a/chart2/qa/extras/data/ods/tdf146066.ods b/chart2/qa/extras/data/ods/tdf146066.ods Binary files differnew file mode 100644 index 000000000000..03abe9ae68ca --- /dev/null +++ b/chart2/qa/extras/data/ods/tdf146066.ods diff --git a/chart2/qa/extras/data/pptx/tdf127720.pptx b/chart2/qa/extras/data/pptx/tdf127720.pptx Binary files differnew file mode 100644 index 000000000000..b10a4c5ab4ed --- /dev/null +++ b/chart2/qa/extras/data/pptx/tdf127720.pptx diff --git a/chart2/source/controller/dialogs/res_LegendPosition.cxx b/chart2/source/controller/dialogs/res_LegendPosition.cxx index 5ad9fe1ac63d..97318f59aeb3 100644 --- a/chart2/source/controller/dialogs/res_LegendPosition.cxx +++ b/chart2/source/controller/dialogs/res_LegendPosition.cxx @@ -85,7 +85,7 @@ void LegendPositionResources::writeToResources( const uno::Reference< frame::XMo xProp->getPropertyValue( "Show" ) >>= bShowLegend; if (m_xCbxShow) m_xCbxShow->set_active( bShowLegend ); - PositionEnableHdl(*m_xCbxShow); + PositionEnable(); //position chart2::LegendPosition ePos; @@ -160,6 +160,11 @@ void LegendPositionResources::writeToModel( const css::uno::Reference< frame::XM IMPL_LINK_NOARG(LegendPositionResources, PositionEnableHdl, weld::Toggleable&, void) { + PositionEnable(); +} + +void LegendPositionResources::PositionEnable() +{ bool bEnable = !m_xCbxShow || m_xCbxShow->get_active(); m_xRbtLeft->set_sensitive( bEnable ); diff --git a/chart2/source/controller/dialogs/tp_Scale.cxx b/chart2/source/controller/dialogs/tp_Scale.cxx index 6c7effde6707..3bb247a7075b 100644 --- a/chart2/source/controller/dialogs/tp_Scale.cxx +++ b/chart2/source/controller/dialogs/tp_Scale.cxx @@ -26,6 +26,7 @@ #include <svx/svxids.hrc> #include <osl/diagnose.h> +#include <sfx2/dialoghelper.hxx> #include <svx/chrtitem.hxx> #include <svl/eitem.hxx> #include <svl/intitem.hxx> @@ -558,6 +559,12 @@ void ScaleTabPage::SetNumFormat() nFmt = pNumFormatter->GetStandardFormat( SvNumFormatType::TIME, pFormat->GetLanguage() ); else nFmt = pNumFormatter->GetStandardFormat( SvNumFormatType::TIME ); + + // tdf#141625 give enough space to see full date+time + int nWidestTime(m_xFmtFldMin->get_pixel_size(getWidestDateTime(Application::GetSettings().GetLocaleDataWrapper(), true)).Width()); + int nWidthChars = std::ceil(nWidestTime / m_xFmtFldMin->get_approximate_digit_width()) + 1; + m_xFmtFldMin->set_width_chars(nWidthChars); + m_xFmtFldMax->set_width_chars(nWidthChars); } if( m_nAxisType == chart2::AxisType::DATE && ( eType != SvNumFormatType::DATE && eType != SvNumFormatType::DATETIME) ) diff --git a/chart2/source/controller/inc/res_LegendPosition.hxx b/chart2/source/controller/inc/res_LegendPosition.hxx index 87b96ab558fc..d1de5010e20a 100644 --- a/chart2/source/controller/inc/res_LegendPosition.hxx +++ b/chart2/source/controller/inc/res_LegendPosition.hxx @@ -55,6 +55,7 @@ public: private: void impl_setRadioButtonToggleHdl(); + void PositionEnable(); private: css::uno::Reference< css::uno::XComponentContext> m_xCC; diff --git a/chart2/source/controller/main/ChartWindow.cxx b/chart2/source/controller/main/ChartWindow.cxx index 9f1ff9342c98..f90bd046ac65 100644 --- a/chart2/source/controller/main/ChartWindow.cxx +++ b/chart2/source/controller/main/ChartWindow.cxx @@ -204,7 +204,6 @@ void ChartWindow::RequestHelp( const HelpEvent& rHEvt ) if( ( rHEvt.GetMode() & HelpEventMode::QUICK ) && m_pWindowController ) { -// Point aLogicHitPos = PixelToLogic( rHEvt.GetMousePosPixel()); // old chart: GetPointerPosPixel() Point aLogicHitPos = PixelToLogic( GetPointerPosPixel()); OUString aQuickHelpText; awt::Rectangle aHelpRect; @@ -213,12 +212,14 @@ void ChartWindow::RequestHelp( const HelpEvent& rHEvt ) if( bHelpHandled ) { + tools::Rectangle aPixelRect(LogicToPixel(lcl_AWTRectToVCLRect(aHelpRect))); + tools::Rectangle aScreenRect(OutputToScreenPixel(aPixelRect.TopLeft()), + OutputToScreenPixel(aPixelRect.BottomRight())); + if( bIsBalloonHelp ) - Help::ShowBalloon( - this, rHEvt.GetMousePosPixel(), lcl_AWTRectToVCLRect( aHelpRect ), aQuickHelpText ); + Help::ShowBalloon(this, rHEvt.GetMousePosPixel(), aScreenRect, aQuickHelpText); else - Help::ShowQuickHelp( - this, lcl_AWTRectToVCLRect( aHelpRect ), aQuickHelpText ); + Help::ShowQuickHelp(this, aScreenRect, aQuickHelpText); |