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

Reply via email to