sc/source/ui/attrdlg/scdlgfact.cxx | 5 + sc/source/ui/attrdlg/scdlgfact.hxx | 5 + sc/source/ui/inc/tabvwsh.hxx | 3 + sc/source/ui/view/tabvwshf.cxx | 109 +++++++++++++++++++++++-------------- vcl/source/window/dialog.cxx | 48 +++++++++++----- 5 files changed, 113 insertions(+), 57 deletions(-)
New commits: commit 208757f4d359260afe27633d589a0c25444bbb67 Author: Noel Grandin <noel.gran...@collabora.co.uk> AuthorDate: Wed Jan 24 12:57:17 2024 +0200 Commit: Noel Grandin <noel.gran...@collabora.co.uk> CommitDate: Mon Jan 29 11:35:21 2024 +0100 make set-tab-bg-col dialog async and adjust the logic in Dialog::EndDialog to cope with dialogs that can loop. Change-Id: I71c88d8fb0512e92e7890566143c762ec9650e28 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162511 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk> diff --git a/sc/source/ui/attrdlg/scdlgfact.cxx b/sc/source/ui/attrdlg/scdlgfact.cxx index 8cbd923ce63a..10c27561a2c2 100644 --- a/sc/source/ui/attrdlg/scdlgfact.cxx +++ b/sc/source/ui/attrdlg/scdlgfact.cxx @@ -350,6 +350,11 @@ short AbstractScTabBgColorDlg_Impl::Execute() return m_xDlg->run(); } +bool AbstractScTabBgColorDlg_Impl::StartExecuteAsync(VclAbstractDialog::AsyncContext &rCtx) +{ + return weld::DialogController::runAsync(m_xDlg, rCtx.maEndDialogFn); +} + short AbstractScImportOptionsDlg_Impl::Execute() { return m_xDlg->run(); diff --git a/sc/source/ui/attrdlg/scdlgfact.hxx b/sc/source/ui/attrdlg/scdlgfact.hxx index 7591b7338801..d490e6004df5 100644 --- a/sc/source/ui/attrdlg/scdlgfact.hxx +++ b/sc/source/ui/attrdlg/scdlgfact.hxx @@ -575,13 +575,14 @@ public: class AbstractScTabBgColorDlg_Impl : public AbstractScTabBgColorDlg { - std::unique_ptr<ScTabBgColorDlg> m_xDlg; + std::shared_ptr<ScTabBgColorDlg> m_xDlg; public: - explicit AbstractScTabBgColorDlg_Impl(std::unique_ptr<ScTabBgColorDlg> p) + explicit AbstractScTabBgColorDlg_Impl(std::shared_ptr<ScTabBgColorDlg> p) : m_xDlg(std::move(p)) { } virtual short Execute() override; + virtual bool StartExecuteAsync(VclAbstractDialog::AsyncContext &rCtx) override; virtual void GetSelectedColor( Color& rColor ) const override; // screenshotting diff --git a/sc/source/ui/inc/tabvwsh.hxx b/sc/source/ui/inc/tabvwsh.hxx index a5cafcb885d2..c7bd83ec1f55 100644 --- a/sc/source/ui/inc/tabvwsh.hxx +++ b/sc/source/ui/inc/tabvwsh.hxx @@ -43,6 +43,7 @@ class SvxNumberInfoItem; struct SfxChildWinInfo; class AbstractScInsertTableDlg; class AbstractScMoveTableDlg; +class AbstractScTabBgColorDlg; class ScArea; class ScAuditingShell; class ScDrawShell; @@ -460,6 +461,8 @@ private: void DoInsertTableFromDialog( SfxRequest& rReq, const VclPtr<AbstractScInsertTableDlg>& pDlg ); void ExecuteAppendOrRenameTable( SfxRequest& rReq ); void ExecuteSetTableBackgroundCol( SfxRequest& rReq ); + void ExecuteTableBackgroundDialog( const VclPtr<AbstractScTabBgColorDlg>& pDlg, const std::shared_ptr<SfxRequest>& xReq, Color aOldTabBgColor, sal_uInt16 nSlot ); + bool DoTableBackgroundDialog( sal_Int32 nResult, const VclPtr<AbstractScTabBgColorDlg>& pDlg, const std::shared_ptr<SfxRequest>& xReq, Color aOldTabBgColor, sal_uInt16 nSlot ); }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/view/tabvwshf.cxx b/sc/source/ui/view/tabvwshf.cxx index f302d83aaf24..fb66f62a5f67 100644 --- a/sc/source/ui/view/tabvwshf.cxx +++ b/sc/source/ui/view/tabvwshf.cxx @@ -1220,59 +1220,86 @@ void ScTabViewShell::ExecuteSetTableBackgroundCol(SfxRequest& rReq) } else { - sal_uInt16 nRet = RET_OK; /// temp - bool bDone = false; /// temp - Color aTabBgColor = rDoc.GetTabBgColor( nCurrentTab ); ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); - ScopedVclPtr<AbstractScTabBgColorDlg> pDlg(pFact->CreateScTabBgColorDlg( + VclPtr<AbstractScTabBgColorDlg> pDlg(pFact->CreateScTabBgColorDlg( GetFrameWeld(), ScResId(SCSTR_SET_TAB_BG_COLOR), ScResId(SCSTR_NO_TAB_BG_COLOR), aTabBgColor)); - while ( !bDone && nRet == RET_OK ) + + auto xRequest = std::make_shared<SfxRequest>(rReq); + rReq.Ignore(); // the 'old' request is not relevant any more + ExecuteTableBackgroundDialog(pDlg, xRequest, aTabBgColor, nSlot); + } +} + +void ScTabViewShell::ExecuteTableBackgroundDialog(const VclPtr<AbstractScTabBgColorDlg>& pDlg, + const std::shared_ptr<SfxRequest>& xReq, + Color aOldTabBgColor, sal_uInt16 nSlot) +{ + pDlg->StartExecuteAsync( + [this, pDlg, xReq, aOldTabBgColor, nSlot] (sal_Int32 nResult)->void { - nRet = pDlg->Execute(); - if( nRet == RET_OK ) + if (DoTableBackgroundDialog(nResult, pDlg, xReq, aOldTabBgColor, nSlot)) + ExecuteTableBackgroundDialog(pDlg, xReq, aOldTabBgColor, nSlot); + else + pDlg->disposeOnce(); + } + ); +} + +bool ScTabViewShell::DoTableBackgroundDialog(sal_Int32 nResult, const VclPtr<AbstractScTabBgColorDlg>& pDlg, + const std::shared_ptr<SfxRequest>& xReq, + Color aOldTabBgColor, sal_uInt16 nSlot) +{ + if (nResult != RET_OK) + return false; + + ScViewData& rViewData = GetViewData(); + ScDocument& rDoc = rViewData.GetDocument(); + ScMarkData& rMark = rViewData.GetMarkData(); + SCTAB nCurrentTab = rViewData.GetTabNo(); + SCTAB nTabSelCount = rMark.GetSelectCount(); + bool bDone = false; /// temp + Color aSelectedColor; + pDlg->GetSelectedColor(aSelectedColor); + std::unique_ptr<ScUndoTabColorInfo::List> + pTabColorList(new ScUndoTabColorInfo::List); + if ( nTabSelCount > 1 ) + { + for (const auto& rTab : rMark) + { + if ( !rDoc.IsTabProtected(rTab) ) { - Color aSelectedColor; - pDlg->GetSelectedColor(aSelectedColor); - std::unique_ptr<ScUndoTabColorInfo::List> - pTabColorList(new ScUndoTabColorInfo::List); - if ( nTabSelCount > 1 ) - { - for (const auto& rTab : rMark) - { - if ( !rDoc.IsTabProtected(rTab) ) - { - ScUndoTabColorInfo aTabColorInfo(rTab); - aTabColorInfo.maNewTabBgColor = aSelectedColor; - pTabColorList->push_back(aTabColorInfo); - } - } - bDone = SetTabBgColor( *pTabColorList ); - } - else - { - bDone = SetTabBgColor( aSelectedColor, nCurrentTab ); //ScViewFunc.SetTabBgColor - } + ScUndoTabColorInfo aTabColorInfo(rTab); + aTabColorInfo.maNewTabBgColor = aSelectedColor; + pTabColorList->push_back(aTabColorInfo); + } + } + bDone = SetTabBgColor( *pTabColorList ); + } + else + { + bDone = SetTabBgColor( aSelectedColor, nCurrentTab ); //ScViewFunc.SetTabBgColor + } - if ( bDone ) - { - rReq.AppendItem( SvxColorItem( aTabBgColor, nSlot ) ); - rReq.Done(); - } - else - { - if( rReq.IsAPI() ) - { + if ( bDone ) + { + xReq->AppendItem( SvxColorItem( aOldTabBgColor, nSlot ) ); + xReq->Done(); + } + else + { + if( xReq->IsAPI() ) + { #if HAVE_FEATURE_SCRIPTING - StarBASIC::Error( ERRCODE_BASIC_SETPROP_FAILED ); + StarBASIC::Error( ERRCODE_BASIC_SETPROP_FAILED ); #endif - } - } - } } } + + return !bDone; } + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/source/window/dialog.cxx b/vcl/source/window/dialog.cxx index 83a8e8babaf2..f395dd307411 100644 --- a/vcl/source/window/dialog.cxx +++ b/vcl/source/window/dialog.cxx @@ -1182,7 +1182,21 @@ void Dialog::EndDialog( tools::Long nResult ) // coverity[check_after_deref] - ImplEndExecuteModal might trigger destruction of mpDialogImpl if ( mpDialogImpl && mpDialogImpl->maEndCtx.isSet() ) { + // We have a special case with async-dialogs that re-execute themselves. + // In order to prevent overwriting state we need here, we need to extract + // all the state we need before before calling maEndDialogFn, because + // maEndDialogFn might itself call StartExecuteAsync and store new state. + std::shared_ptr<weld::DialogController> xOwnerDialogController = std::move(mpDialogImpl->maEndCtx.mxOwnerDialogController); + std::shared_ptr<weld::Dialog> xOwnerSelf = std::move(mpDialogImpl->maEndCtx.mxOwnerSelf); + auto xOwner = std::move(mpDialogImpl->maEndCtx.mxOwner); + if ( mpDialogImpl->mbStartedModal ) + { + mpDialogImpl->mbStartedModal = false; + mpDialogImpl->mnResult = -1; + } + mbInExecute = false; auto fn = std::move(mpDialogImpl->maEndCtx.maEndDialogFn); + // std::move leaves maEndDialogFn in a valid state with unspecified // value. For the SwSyncBtnDlg case gcc and msvc left maEndDialogFn // unset, but clang left maEndDialogFn at its original value, keeping @@ -1190,24 +1204,30 @@ void Dialog::EndDialog( tools::Long nResult ) // an inconsistent lifecycle for the dialog. Force it to be unset. mpDialogImpl->maEndCtx.maEndDialogFn = nullptr; fn(nResult); - } - - if ( mpDialogImpl && mpDialogImpl->mbStartedModal ) - { - mpDialogImpl->mbStartedModal = false; - mpDialogImpl->mnResult = -1; - } - mbInExecute = false; - if ( mpDialogImpl ) - { - // Destroy ourselves (if we have a context with VclPtr owner) - std::shared_ptr<weld::DialogController> xOwnerDialogController = std::move(mpDialogImpl->maEndCtx.mxOwnerDialogController); - std::shared_ptr<weld::Dialog> xOwnerSelf = std::move(mpDialogImpl->maEndCtx.mxOwnerSelf); - mpDialogImpl->maEndCtx.mxOwner.disposeAndClear(); + // Destroy ourselves, if we have a context with VclPtr owner, and + // we have not been re-executed. + if (!mpDialogImpl || !mpDialogImpl->maEndCtx.isSet()) + xOwner.disposeAndClear(); xOwnerDialogController.reset(); xOwnerSelf.reset(); } + else + { + if ( mpDialogImpl && mpDialogImpl->mbStartedModal ) + { + mpDialogImpl->mbStartedModal = false; + mpDialogImpl->mnResult = -1; + } + mbInExecute = false; + if ( mpDialogImpl) + { + // Destroy ourselves (if we have a context with VclPtr owner) + std::shared_ptr<weld::DialogController> xOwnerDialogController = std::move(mpDialogImpl->maEndCtx.mxOwnerDialogController); + std::shared_ptr<weld::Dialog> xOwnerSelf = std::move(mpDialogImpl->maEndCtx.mxOwnerSelf); + mpDialogImpl->maEndCtx.mxOwner.disposeAndClear(); + } + } } namespace vcl