filter/source/pdf/impdialog.cxx                       |   23 +
 filter/source/pdf/impdialog.hxx                       |    2 
 filter/source/pdf/pdfdialog.cxx                       |   24 +
 filter/source/pdf/pdfdialog.hxx                       |   13 
 include/LibreOfficeKit/LibreOfficeKitEnums.h          |   10 
 include/sfx2/viewsh.hxx                               |    6 
 include/svtools/genericasyncunodialog.hxx             |  124 ++++++++
 libreofficekit/source/gtk/lokdocview.cxx              |    1 
 offapi/com/sun/star/document/PDFDialog.idl            |    1 
 sfx2/inc/guisaveas.hxx                                |   32 ++
 sfx2/source/doc/guisaveas.cxx                         |  263 ++++++++++++------
 sfx2/source/doc/objserv.cxx                           |   15 -
 sfx2/source/view/ipclient.cxx                         |    3 
 vcl/jsdialog/enabled.cxx                              |    9 
 writerperfect/source/writer/EPUBExportDialog.cxx      |    5 
 writerperfect/source/writer/EPUBExportDialog.hxx      |    1 
 writerperfect/source/writer/EPUBExportUIComponent.cxx |   25 +
 writerperfect/source/writer/EPUBExportUIComponent.hxx |   14 
 18 files changed, 485 insertions(+), 86 deletions(-)

New commits:
commit a0966e44b389fe66f6ef79c6c84ff9bcca4947d3
Author:     Andras Timar <andras.ti...@collabora.com>
AuthorDate: Wed Dec 14 20:33:18 2022 +0100
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Mon Jan 23 19:00:51 2023 +0100

    lok: hide 'View PDF after export' checkbox in PDF export dialog
    
    Change-Id: I866e4765ba88ca6c93375c9fecd51f22b79ce72e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/144535
    Tested-by: Jenkins
    Reviewed-by: Andras Timar <andras.ti...@collabora.com>

diff --git a/filter/source/pdf/impdialog.cxx b/filter/source/pdf/impdialog.cxx
index 735e2e443333..2516342cde70 100644
--- a/filter/source/pdf/impdialog.cxx
+++ b/filter/source/pdf/impdialog.cxx
@@ -632,7 +632,15 @@ void 
ImpPDFTabGeneralPage::SetFilterConfigItem(ImpPDFTabDialog* pParent)
 
     mxCbExportNotes->set_active( pParent->mbExportNotes );
     mxCbExportNotesInMargin->set_active( pParent->mbExportNotesInMargin );
-    mxCbViewPDF->set_active( pParent->mbViewPDF);
+    if (comphelper::LibreOfficeKit::isActive())
+    {
+        mxCbViewPDF->hide();
+        mxCbViewPDF->set_active(false);
+    }
+    else
+    {
+       mxCbViewPDF->set_active(pParent->mbViewPDF);
+    }
 
     if ( mbIsPresentation )
     {
commit a44d2046d21ec61f9846f6a05bd396eedc0dae4f
Author:     Szymon Kłos <szymon.k...@collabora.com>
AuthorDate: Wed Dec 14 09:29:22 2022 +0100
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Mon Jan 23 19:00:40 2023 +0100

    lok: hide customization in EPUB export dialog
    
    Change-Id: I531aba2eb52e74904b6cba82add769d35a8a28c5
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/144150
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Andras Timar <andras.ti...@collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/144534
    Tested-by: Jenkins

diff --git a/writerperfect/source/writer/EPUBExportDialog.cxx 
b/writerperfect/source/writer/EPUBExportDialog.cxx
index 0bba77a1898b..ecea590ac831 100644
--- a/writerperfect/source/writer/EPUBExportDialog.cxx
+++ b/writerperfect/source/writer/EPUBExportDialog.cxx
@@ -14,6 +14,7 @@
 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
 #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
 #include <com/sun/star/ui/dialogs/XFolderPicker2.hpp>
+#include <comphelper/lok.hxx>
 #include <comphelper/sequenceashashmap.hxx>
 #include <sfx2/filedlghelper.hxx>
 #include <sfx2/opengrf.hxx>
@@ -92,6 +93,7 @@ EPUBExportDialog::EPUBExportDialog(weld::Window* pParent,
     , m_xInitialCreator(m_xBuilder->weld_entry("author"))
     , m_xLanguage(m_xBuilder->weld_entry("language"))
     , m_xDate(m_xBuilder->weld_entry("date"))
+    , m_xCustomizeFrame(m_xBuilder->weld_frame("customize"))
 
 {
     assert(PositionToVersion(m_xVersion->get_active()) == 
EPUBExportFilter::GetDefaultVersion());
@@ -154,6 +156,9 @@ EPUBExportDialog::EPUBExportDialog(weld::Window* pParent,
     }
 
     m_xOKButton->connect_clicked(LINK(this, EPUBExportDialog, OKClickHdl));
+
+    if (comphelper::LibreOfficeKit::isActive())
+        m_xCustomizeFrame->hide();
 }
 
 IMPL_LINK_NOARG(EPUBExportDialog, VersionSelectHdl, weld::ComboBox&, void)
diff --git a/writerperfect/source/writer/EPUBExportDialog.hxx 
b/writerperfect/source/writer/EPUBExportDialog.hxx
index 9e11d5351559..440c74d1176e 100644
--- a/writerperfect/source/writer/EPUBExportDialog.hxx
+++ b/writerperfect/source/writer/EPUBExportDialog.hxx
@@ -54,6 +54,7 @@ private:
     std::unique_ptr<weld::Entry> m_xInitialCreator;
     std::unique_ptr<weld::Entry> m_xLanguage;
     std::unique_ptr<weld::Entry> m_xDate;
+    std::unique_ptr<weld::Frame> m_xCustomizeFrame;
 };
 
 } // namespace writerperfect
commit 6b9f73a9cf1f7776589bdc896bf861e168f2083b
Author:     Szymon Kłos <szymon.k...@collabora.com>
AuthorDate: Wed Dec 14 09:18:11 2022 +0100
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Mon Jan 23 18:59:24 2023 +0100

    lok: hide signatures in PDF export dialog
    
    Change-Id: Idd67e7ffe4dffc89555d75773501908165cbdd7b
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/144149
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Andras Timar <andras.ti...@collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/144513
    Tested-by: Jenkins

diff --git a/filter/source/pdf/impdialog.cxx b/filter/source/pdf/impdialog.cxx
index 3d049737d220..735e2e443333 100644
--- a/filter/source/pdf/impdialog.cxx
+++ b/filter/source/pdf/impdialog.cxx
@@ -28,6 +28,7 @@
 #include <sfx2/objsh.hxx>
 #include <svx/AccessibilityCheckDialog.hxx>
 
+#include <comphelper/lok.hxx>
 #include <comphelper/propertyvalue.hxx>
 #include <comphelper/sequence.hxx>
 #include <comphelper/storagehelper.hxx>
@@ -250,7 +251,10 @@ ImpPDFTabDialog::ImpPDFTabDialog(weld::Window* pParent, 
const Sequence< Property
 
     // queue the tab pages for later creation (created when first shown)
     AddTabPage("general", ImpPDFTabGeneralPage::Create, nullptr );
-    AddTabPage("digitalsignatures", ImpPDFTabSigningPage::Create, nullptr);
+    if (comphelper::LibreOfficeKit::isActive())
+        m_xTabCtrl->remove_page("digitalsignatures");
+    else
+        AddTabPage("digitalsignatures", ImpPDFTabSigningPage::Create, nullptr);
     AddTabPage("security", ImpPDFTabSecurityPage::Create, nullptr);
     AddTabPage("links", ImpPDFTabLinksPage::Create, nullptr);
     AddTabPage("userinterface", ImpPDFTabViewerPage::Create, nullptr);
commit 12c44966a3156b975b6d6ac3c4dc4beba4469146
Author:     Szymon Kłos <szymon.k...@collabora.com>
AuthorDate: Wed Dec 14 17:36:10 2022 +0100
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Mon Jan 23 18:59:15 2023 +0100

    lok: remove undefined behaviour warning
    
    Change-Id: I74d015bdf2c30b85c8e9eb8271780c9999ea1f15
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/144169
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Andras Timar <andras.ti...@collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/144536
    Tested-by: Jenkins

diff --git a/include/svtools/genericasyncunodialog.hxx 
b/include/svtools/genericasyncunodialog.hxx
index 7168d08f4301..937f9778030d 100644
--- a/include/svtools/genericasyncunodialog.hxx
+++ b/include/svtools/genericasyncunodialog.hxx
@@ -57,14 +57,6 @@ protected:
     {
     }
 
-    virtual ~OGenericUnoAsyncDialog() override
-    {
-        SolarMutexGuard aSolarGuard;
-        ::osl::MutexGuard aGuard(m_aMutex);
-        if (m_xAsyncDialog)
-            destroyAsyncDialog();
-    }
-
 public:
     // XAsynchronousExecutableDialog
     void SAL_CALL setDialogTitle(const OUString& aTitle) override
commit 39dbdf2a0af624ab81d3f451194cdff0ba517a93
Author:     Szymon Kłos <szymon.k...@collabora.com>
AuthorDate: Mon Dec 12 15:27:26 2022 +0100
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Mon Jan 23 18:58:44 2023 +0100

    lok: export PDF/EPUB with extension
    
    Change-Id: Ib266814d88a4f121959cb21f40293d671f242448
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143989
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Andras Timar <andras.ti...@collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/144512
    Tested-by: Jenkins

diff --git a/sfx2/source/doc/guisaveas.cxx b/sfx2/source/doc/guisaveas.cxx
index d95d2bb2c289..c0f951d62206 100644
--- a/sfx2/source/doc/guisaveas.cxx
+++ b/sfx2/source/doc/guisaveas.cxx
@@ -1089,8 +1089,21 @@ bool ModelData_Impl::OutputFileDialog( sal_Int16 
nStoreMode,
 
     // get the path from the dialog
     INetURLObject aURL( pFileDlg->GetPath() );
-    // the path should be provided outside since it might be used for further 
calls to the dialog
-    aSuggestedName = 
aURL.GetLastName(INetURLObject::DecodeMechanism::WithCharset);
+
+    if (comphelper::LibreOfficeKit::isActive())
+    {
+        // keep name with extension
+        aSuggestedName = aRecommendedName;
+        OUString aExtension;
+        if (size_t nPos = aSuggestedName.lastIndexOf('.') + 1)
+            aExtension = aSuggestedName.copy(nPos, aSuggestedName.getLength() 
- nPos);
+        aURL.SetExtension(aExtension);
+    }
+    else
+    {
+        // the path should be provided outside since it might be used for 
further calls to the dialog
+        aSuggestedName = 
aURL.GetLastName(INetURLObject::DecodeMechanism::WithCharset);
+    }
     aSuggestedDir = pFileDlg->GetDisplayDirectory();
 
     // old filter options should be cleared in case different filter is used
commit 82d474a28ae3524740c38b3adcb0da3f2276075c
Author:     NickWingate <nick.wing...@collabora.com>
AuthorDate: Thu Sep 22 09:02:42 2022 +0100
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Mon Jan 23 18:58:34 2023 +0100

    Async PDFExport dialog and parent methods
    
    Filter dialogs are all called generically from
    guisaveas.cxx in GUIStoreModel()
    
    Signed-off-by: NickWingate <nick.wing...@collabora.com>
    Change-Id: Idfbe85c09f84d4a7cf3f00b9704d5af94868a051
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/140403
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Andras Timar <andras.ti...@collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/144511
    Tested-by: Jenkins

diff --git a/filter/source/pdf/impdialog.cxx b/filter/source/pdf/impdialog.cxx
index 159271f8a6f8..3d049737d220 100644
--- a/filter/source/pdf/impdialog.cxx
+++ b/filter/source/pdf/impdialog.cxx
@@ -541,6 +541,8 @@ ImpPDFTabGeneralPage::ImpPDFTabGeneralPage(weld::Container* 
pPage, weld::DialogC
 
 ImpPDFTabGeneralPage::~ImpPDFTabGeneralPage()
 {
+    if (mxPasswordUnusedWarnDialog)
+        mxPasswordUnusedWarnDialog->response(RET_CANCEL);
 }
 
 void ImpPDFTabGeneralPage::SetFilterConfigItem(ImpPDFTabDialog* pParent)
@@ -871,10 +873,11 @@ IMPL_LINK_NOARG(ImpPDFTabGeneralPage, 
TogglePDFVersionOrUniversalAccessibilityHa
         // if a password was set, inform the user that this will not be used
         if (pSecPage && pSecPage->hasPassword())
         {
-            std::unique_ptr<weld::MessageDialog> 
xBox(Application::CreateMessageDialog(m_xContainer.get(),
+            mxPasswordUnusedWarnDialog =
+                
std::shared_ptr<weld::MessageDialog>(Application::CreateMessageDialog(m_xContainer.get(),
                                                       VclMessageType::Warning, 
VclButtonsType::Ok,
                                                       
FilterResId(STR_WARN_PASSWORD_PDFA)));
-            xBox->run();
+            mxPasswordUnusedWarnDialog->runAsync(mxPasswordUnusedWarnDialog, 
[] (sal_uInt32){ });
         }
     }
     else
diff --git a/filter/source/pdf/impdialog.hxx b/filter/source/pdf/impdialog.hxx
index d509334abaf4..dd2a9a3add98 100644
--- a/filter/source/pdf/impdialog.hxx
+++ b/filter/source/pdf/impdialog.hxx
@@ -233,6 +233,8 @@ class ImpPDFTabGeneralPage : public SfxTabPage
 
     DECL_LINK(TogglePDFVersionOrUniversalAccessibilityHandle, 
weld::Toggleable&, void);
 
+    std::shared_ptr<weld::MessageDialog> mxPasswordUnusedWarnDialog;
+
 public:
 
     ImpPDFTabGeneralPage(weld::Container* pPage, weld::DialogController* 
pController, const SfxItemSet& rSet);
diff --git a/filter/source/pdf/pdfdialog.cxx b/filter/source/pdf/pdfdialog.cxx
index 7c3e5dda1956..c036fc747b2a 100644
--- a/filter/source/pdf/pdfdialog.cxx
+++ b/filter/source/pdf/pdfdialog.cxx
@@ -62,6 +62,13 @@ std::unique_ptr<weld::DialogController> 
PDFDialog::createDialog(const css::uno::
     return nullptr;
 }
 
+std::shared_ptr<SfxTabDialogController> PDFDialog::createAsyncDialog(const 
css::uno::Reference<css::awt::XWindow>& rParent)
+{
+    if( mxSrcDoc.is() )
+        return 
std::make_shared<ImpPDFTabDialog>(Application::GetFrameWeld(rParent), 
maFilterData, mxSrcDoc);
+    return nullptr;
+}
+
 void PDFDialog::executedDialog( sal_Int16 nExecutionResult )
 {
     if (nExecutionResult && m_xDialog)
@@ -69,6 +76,23 @@ void PDFDialog::executedDialog( sal_Int16 nExecutionResult )
     destroyDialog();
 }
 
+void PDFDialog::runAsync(const css::uno::Reference< 
css::ui::dialogs::XDialogClosedListener >& xListener)
+{
+    SfxTabDialogController::runAsync(m_xAsyncDialog, [this, 
xListener](sal_Int32 nResponse) {
+        executedAsyncDialog( m_xAsyncDialog, nResponse );
+        css::ui::dialogs::DialogClosedEvent aEvent;
+        aEvent.DialogResult = nResponse;
+        xListener->dialogClosed( aEvent );
+        destroyAsyncDialog();
+    });
+}
+
+void PDFDialog::executedAsyncDialog( std::shared_ptr<SfxTabDialogController> 
xAsyncDialog, sal_Int32 nExecutionResult )
+{
+    if (nExecutionResult && xAsyncDialog)
+        maFilterData = 
static_cast<ImpPDFTabDialog*>(xAsyncDialog.get())->GetFilterData();
+}
+
 Reference< XPropertySetInfo > SAL_CALL PDFDialog::getPropertySetInfo()
 {
     Reference< XPropertySetInfo >  xInfo( createPropertySetInfo( 
getInfoHelper() ) );
diff --git a/filter/source/pdf/pdfdialog.hxx b/filter/source/pdf/pdfdialog.hxx
index fcfd1d0976bd..2410192a2617 100644
--- a/filter/source/pdf/pdfdialog.hxx
+++ b/filter/source/pdf/pdfdialog.hxx
@@ -19,8 +19,6 @@
 
 #pragma once
 
-#include <svtools/genericunodialog.hxx>
-
 #include <comphelper/proparrhlp.hxx>
 #include <cppuhelper/implbase.hxx>
 
@@ -28,12 +26,16 @@
 #include <com/sun/star/document/XExporter.hpp>
 #include <com/sun/star/lang/XComponent.hpp>
 
+#include <sfx2/tabdlg.hxx>
+#include <svtools/genericasyncunodialog.hxx>
+
 using namespace ::com::sun::star::beans;
 using namespace ::com::sun::star::document;
 using namespace ::com::sun::star::lang;
 using namespace ::com::sun::star::uno;
 
-typedef ::cppu::ImplInheritanceHelper < ::svt::OGenericUnoDialog, 
XPropertyAccess, XExporter >  PDFDialog_Base;
+typedef ::cppu::ImplInheritanceHelper < 
::svt::OGenericUnoAsyncDialog<SfxTabDialogController>,
+                                        XPropertyAccess, XExporter >  
PDFDialog_Base;
 
 class PDFDialog final:
     public PDFDialog_Base,
@@ -54,6 +56,11 @@ private:
     virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
     virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override;
 
+    // OGenericUnoAsyncDialog
+    virtual std::shared_ptr<SfxTabDialogController> createAsyncDialog(const 
css::uno::Reference<css::awt::XWindow>& rParent) override;
+    virtual void runAsync(const css::uno::Reference< 
css::ui::dialogs::XDialogClosedListener >& xListener) override;
+    virtual void executedAsyncDialog(std::shared_ptr<SfxTabDialogController> 
xAsyncDialog, sal_Int32 nExecutionResult) override;
+
     // XPropertyAccess
     using OPropertySetHelper::getPropertyValues;
     virtual Sequence< PropertyValue > SAL_CALL getPropertyValues(  ) override;
diff --git a/include/LibreOfficeKit/LibreOfficeKitEnums.h 
b/include/LibreOfficeKit/LibreOfficeKitEnums.h
index 1e9821204c0b..38b3e5e62a40 100644
--- a/include/LibreOfficeKit/LibreOfficeKitEnums.h
+++ b/include/LibreOfficeKit/LibreOfficeKitEnums.h
@@ -899,6 +899,14 @@ typedef enum
      *      which is a representation of the pie segment.
      */
     LOK_CALLBACK_MEDIA_SHAPE = 58,
+
+    /**
+     * The document is available to download by the client.
+     *
+     * Payload example:
+     * "file:///tmp/hello-world.pdf"
+     */
+    LOK_CALLBACK_EXPORT_FILE = 59,
 }
 LibreOfficeKitCallbackType;
 
@@ -1045,6 +1053,8 @@ static inline const char* lokCallbackTypeToString(int 
nType)
         return "LOK_CALLBACK_FONTS_MISSING";
     case LOK_CALLBACK_MEDIA_SHAPE:
         return "LOK_CALLBACK_MEDIA_SHAPE";
+    case LOK_CALLBACK_EXPORT_FILE:
+        return "LOK_CALLBACK_EXPORT_FILE";
     }
 
     assert(!"Unknown LibreOfficeKitCallbackType type.");
diff --git a/include/sfx2/viewsh.hxx b/include/sfx2/viewsh.hxx
index 975076a1fd51..c57a6fab7046 100644
--- a/include/sfx2/viewsh.hxx
+++ b/include/sfx2/viewsh.hxx
@@ -56,6 +56,7 @@ class SfxPrinter;
 class NotifyEvent;
 class SfxInPlaceClient;
 class SfxLokCallbackInterface;
+class SfxStoringHelper;
 namespace rtl { class OStringBuffer; }
 namespace vcl { class PrinterController; }
 
@@ -173,6 +174,9 @@ friend class SfxPrinterController;
     /// Used to set the DocId at construction time. See SetCurrentDocId.
     static ViewShellDocId       mnCurrentDocId;
 
+    /// Used for async export
+    std::shared_ptr<SfxStoringHelper> m_xHelper;
+
 protected:
     virtual void                Activate(bool IsMDIActivate) override;
     virtual void                Deactivate(bool IsMDIActivate) override;
@@ -416,6 +420,8 @@ public:
     // Blocked Command view settings
     void setBlockedCommandList(const char* blockedCommandList);
     bool isBlockedCommand(OUString command);
+
+    void SetStoringHelper(std::shared_ptr<SfxStoringHelper> xHelper) { 
m_xHelper = xHelper; }
 };
 
 
diff --git a/include/svtools/genericasyncunodialog.hxx 
b/include/svtools/genericasyncunodialog.hxx
new file mode 100644
index 000000000000..7168d08f4301
--- /dev/null
+++ b/include/svtools/genericasyncunodialog.hxx
@@ -0,0 +1,132 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/ui/dialogs/XAsynchronousExecutableDialog.hpp>
+#include <sfx2/tabdlg.hxx>
+#include <svtools/genericunodialog.hxx>
+#include <vcl/svapp.hxx>
+
+using namespace css::uno;
+
+namespace svt
+{
+typedef cppu::ImplInheritanceHelper<::svt::OGenericUnoDialog,
+                                    
css::ui::dialogs::XAsynchronousExecutableDialog>
+    OGenericUnoAsyncDialogBase;
+
+/** abstract base class for implementing UNO objects representing asynchronous 
dialogs
+    */
+template <typename T> class OGenericUnoAsyncDialog : public 
OGenericUnoAsyncDialogBase
+{
+    class UnoAsyncDialogEntryGuard
+    {
+    public:
+        UnoAsyncDialogEntryGuard(OGenericUnoAsyncDialog<T>& _rDialog)
+            : m_aGuard(_rDialog.GetMutex())
+        {
+        }
+
+    private:
+        ::osl::MutexGuard m_aGuard;
+    };
+
+protected:
+    std::shared_ptr<T> m_xAsyncDialog;
+
+protected:
+    OGenericUnoAsyncDialog(const 
css::uno::Reference<css::uno::XComponentContext>& _rxContext)
+        : OGenericUnoAsyncDialogBase(_rxContext)
+    {
+    }
+
+    virtual ~OGenericUnoAsyncDialog() override
+    {
+        SolarMutexGuard aSolarGuard;
+        ::osl::MutexGuard aGuard(m_aMutex);
+        if (m_xAsyncDialog)
+            destroyAsyncDialog();
+    }
+
+public:
+    // XAsynchronousExecutableDialog
+    void SAL_CALL setDialogTitle(const OUString& aTitle) override
+    {
+        OGenericUnoDialog::setTitle(aTitle);
+    }
+
+    virtual void SAL_CALL startExecuteModal(
+        const css::uno::Reference<css::ui::dialogs::XDialogClosedListener>& 
xListener) override
+    {
+        SolarMutexGuard aSolarGuard;
+
+        {
+            UnoAsyncDialogEntryGuard aGuard(*this);
+
+            if (m_bExecuting)
+                throw RuntimeException("already executing the dialog 
(recursive call)", *this);
+
+            if (!m_xAsyncDialog)
+            {
+                m_xAsyncDialog = createAsyncDialog(m_xParent);
+                OSL_ENSURE(m_xAsyncDialog, 
"OGenericUnoAsyncDialog::startExecuteModal: "
+                                           "createAsyncDialog returned 
nonsense!");
+                if (!m_xAsyncDialog)
+                    return;
+
+                // do some initialisations
+                if (!m_bTitleAmbiguous)
+                    m_xAsyncDialog->set_title(m_sTitle);
+            }
+
+            m_bExecuting = true;
+        }
+
+        runAsync(xListener);
+    }
+
+protected:
+    virtual std::shared_ptr<T>
+    createAsyncDialog(const css::uno::Reference<css::awt::XWindow>& 
/*rParent*/)
+    {
+        return nullptr;
+    }
+
+    void destroyAsyncDialog()
+    {
+        SolarMutexGuard aSolarGuard;
+        if (m_xAsyncDialog)
+            m_xAsyncDialog.reset();
+    }
+
+    virtual void
+    runAsync(const 
css::uno::Reference<css::ui::dialogs::XDialogClosedListener>& /*xListener*/)
+    {
+    }
+
+    virtual void executedAsyncDialog(std::shared_ptr<T> /*xAsyncDialog*/,
+                                     sal_Int32 /*_nExecutionResult*/)
+    {
+    }
+};
+
+} // namespace svt
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/libreofficekit/source/gtk/lokdocview.cxx 
b/libreofficekit/source/gtk/lokdocview.cxx
index 4fc6fe0452c1..ff40e4929781 100644
--- a/libreofficekit/source/gtk/lokdocview.cxx
+++ b/libreofficekit/source/gtk/lokdocview.cxx
@@ -1485,6 +1485,7 @@ callback (gpointer pData)
     case LOK_CALLBACK_PRINT_RANGES:
     case LOK_CALLBACK_FONTS_MISSING:
     case LOK_CALLBACK_MEDIA_SHAPE:
+    case LOK_CALLBACK_EXPORT_FILE:
     {
         // TODO: Implement me
         break;
diff --git a/offapi/com/sun/star/document/PDFDialog.idl 
b/offapi/com/sun/star/document/PDFDialog.idl
index e92b57accd2d..007b30ebef22 100644
--- a/offapi/com/sun/star/document/PDFDialog.idl
+++ b/offapi/com/sun/star/document/PDFDialog.idl
@@ -36,6 +36,7 @@ service PDFDialog
         "officecfg/registry/schema/org/openoffice/Office/Common.xcs"
     */
 
+    interface ::com::sun::star::ui::dialogs::XAsynchronousExecutableDialog;
 };
 
 
diff --git a/sfx2/inc/guisaveas.hxx b/sfx2/inc/guisaveas.hxx
index c19f78e3fdf1..88a69711c8fd 100644
--- a/sfx2/inc/guisaveas.hxx
+++ b/sfx2/inc/guisaveas.hxx
@@ -31,8 +31,15 @@
 #include <com/sun/star/frame/XModel.hpp>
 #include <com/sun/star/frame/XModuleManager2.hpp>
 
+#include <comphelper/sequenceashashmap.hxx>
+
+#include <sfx2/bindings.hxx>
 #include <sfx2/signaturestate.hxx>
 
+#include <svtools/dialogclosedlistener.hxx>
+
+#include <tools/urlobj.hxx>
+
 
 namespace com::sun::star::document { class XDocumentProperties; }
 
@@ -48,10 +55,32 @@ private:
     css::uno::Reference< css::container::XContainerQuery > m_xFilterQuery;
     css::uno::Reference< css::frame::XModuleManager2 >     m_xModuleManager;
 
+    std::shared_ptr<ModelData_Impl> m_xModelData;
+    css::uno::Sequence< css::beans::PropertyValue > m_aArgsSequence;
+
     css::uno::Reference< css::container::XNameAccess > const & 
GetFilterConfiguration();
     css::uno::Reference< css::container::XContainerQuery > const & 
GetFilterQuery();
     css::uno::Reference< css::frame::XModuleManager2 > const & 
GetModuleManager();
 
+    bool m_xDialogUsed;
+    bool m_bRemote;
+    bool m_bPreselectPassword;
+    bool m_bDialogUsed;
+    bool m_bSetStandardName;
+    sal_Int16 m_nStoreMode;
+
+    DECL_LINK(FilterDialogClosedHdl, css::ui::dialogs::DialogClosedEvent*, 
void);
+
+    static bool 
FinishGUIStoreModel(::comphelper::SequenceAsHashMap::const_iterator& 
aFileNameIter,
+                             ModelData_Impl& aModelData, bool bRemote, 
sal_Int16 nStoreMode,
+                             css::uno::Sequence< css::beans::PropertyValue >& 
aFilterProps,
+                             bool bSetStandardName, bool bPreselectPassword, 
bool bDialogUsed,
+                             std::u16string_view aFilterFromMediaDescr, 
std::u16string_view aOldFilterName,
+                             css::uno::Sequence< css::beans::PropertyValue >& 
aArgsSequence,
+                             OUString aFilterName);
+
+    void CallFinishGUIStoreModel();
+
 public:
     SfxStoringHelper();
 
@@ -60,7 +89,8 @@ public:
                     std::u16string_view aSlotName,
                     css::uno::Sequence< css::beans::PropertyValue >& 
aArgsSequence,
                     bool bPreselectPassword,
-                    SignatureState nDocumentSignatureState );
+                    SignatureState nDocumentSignatureState,
+                    bool bIsAsync );
 
     static bool CheckFilterOptionsAppearance(
                     const css::uno::Reference< css::container::XNameAccess >& 
xFilterCFG,
diff --git a/sfx2/source/doc/guisaveas.cxx b/sfx2/source/doc/guisaveas.cxx
index 7cce6b515db4..d95d2bb2c289 100644
--- a/sfx2/source/doc/guisaveas.cxx
+++ b/sfx2/source/doc/guisaveas.cxx
@@ -18,6 +18,7 @@
  */
 
 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
+#include <com/sun/star/ui/dialogs/XAsynchronousExecutableDialog.hpp>
 #include <com/sun/star/ui/dialogs/XFilePicker3.hpp>
 #include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
 #include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp>
@@ -55,16 +56,20 @@
 #include <tools/debug.hxx>
 #include <comphelper/diagnose_ex.hxx>
 #include <tools/urlobj.hxx>
+#include <tools/json_writer.hxx>
+#include <tools/urlobj.hxx>
 #include <comphelper/processfactory.hxx>
 #include <comphelper/propertysequence.hxx>
 #include <comphelper/propertyvalue.hxx>
 #include <comphelper/sequenceashashmap.hxx>
 #include <comphelper/mimeconfighelper.hxx>
 #include <comphelper/lok.hxx>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
 #include <utility>
 #include <vcl/svapp.hxx>
 #include <vcl/weld.hxx>
 #include <o3tl/char16_t2wchar_t.hxx>
+#include <unotools/tempfile.hxx>
 
 #include <sfx2/sfxsids.hrc>
 #include <sfx2/strings.hrc>
@@ -72,6 +77,8 @@
 #include <sfx2/filedlghelper.hxx>
 #include <sfx2/app.hxx>
 #include <sfx2/sfxuno.hxx>
+#include <sfx2/viewsh.hxx>
+#include <sfx2/bindings.hxx>
 #include <alienwarn.hxx>
 
 #include <memory>
@@ -261,10 +268,15 @@ class ModelData_Impl
     std::unique_ptr<::comphelper::SequenceAsHashMap> m_pDocumentPropsHM;
     std::unique_ptr<::comphelper::SequenceAsHashMap> m_pModulePropsHM;
 
+    uno::Reference<beans::XPropertyAccess> m_xFilterProperties;
+    uno::Reference<ui::dialogs::XAsynchronousExecutableDialog> m_xFilterDialog;
+
     ::comphelper::SequenceAsHashMap m_aMediaDescrHM;
 
     bool m_bRecommendReadOnly;
 
+    DECL_LINK(OptionsDialogClosedHdl, css::ui::dialogs::DialogClosedEvent*, 
void);
+
 public:
     ModelData_Impl( SfxStoringHelper& aOwner,
                     uno::Reference< frame::XModel > xModel,
@@ -296,7 +308,7 @@ public:
     uno::Sequence< beans::PropertyValue > GetPreselectedFilter_Impl( sal_Int16 
nStoreMode );
     uno::Sequence< beans::PropertyValue > GetDocServiceDefaultFilter();
 
-    bool ExecuteFilterDialog_Impl( const OUString& aFilterName );
+    bool ExecuteFilterDialog_Impl( const OUString& aFilterName, bool bAsync );
 
     sal_Int8 CheckSaveAcceptable( sal_Int8 nCurStatus );
     sal_Int8 CheckStateForSave();
@@ -322,7 +334,6 @@ public:
     OUString GetRecommendedDir( const OUString& aSuggestedDir );
     OUString GetRecommendedName( const OUString& aSuggestedName,
                                         const OUString& aTypeName );
-
 };
 
 
@@ -343,6 +354,8 @@ ModelData_Impl::~ModelData_Impl()
     FreeDocumentProps();
     m_pDocumentPropsHM.reset();
     m_pModulePropsHM.reset();
+    if (m_xFilterProperties)
+        m_xFilterProperties.clear();
 }
 
 
@@ -535,7 +548,7 @@ uno::Sequence< beans::PropertyValue > 
ModelData_Impl::GetPreselectedFilter_Impl(
 }
 
 
-bool ModelData_Impl::ExecuteFilterDialog_Impl( const OUString& aFilterName )
+bool ModelData_Impl::ExecuteFilterDialog_Impl( const OUString& aFilterName, 
bool bIsAsync )
 {
     bool bDialogUsed = false;
 
@@ -557,15 +570,31 @@ bool ModelData_Impl::ExecuteFilterDialog_Impl( const 
OUString& aFilterName )
                         {"ParentWindow", 
uno::Any(SfxStoringHelper::GetModelXWindow(m_xModel))},
                     }));
 
-                    uno::Reference< ui::dialogs::XExecutableDialog > 
xFilterDialog(
-                                                
comphelper::getProcessServiceFactory()->createInstanceWithArguments(aServiceName,
 aDialogArgs), uno::UNO_QUERY );
-                    uno::Reference< beans::XPropertyAccess > 
xFilterProperties( xFilterDialog, uno::UNO_QUERY );
+                    uno::Reference< beans::XPropertyAccess > xFilterProperties;
+                    uno::Reference< ui::dialogs::XExecutableDialog > 
xFilterDialog;
+                    uno::Reference< ui::dialogs::XAsynchronousExecutableDialog 
> xAsyncFilterDialog;
+                    uno::Reference< document::XExporter > xExporter;
 
-                    if( xFilterDialog.is() && xFilterProperties.is() )
+                    if ( bIsAsync )
+                    {
+                        xAsyncFilterDialog = uno::Reference< 
ui::dialogs::XAsynchronousExecutableDialog >(
+                            
comphelper::getProcessServiceFactory()->createInstanceWithArguments( 
aServiceName, aDialogArgs ), uno::UNO_QUERY );
+                        OSL_ENSURE(xAsyncFilterDialog.is(), 
"ModelData_Impl::ExecuteFilterDialog_Impl: Dialog is not async!");
+                        xFilterProperties = uno::Reference< 
beans::XPropertyAccess >( xAsyncFilterDialog, uno::UNO_QUERY );
+                        xExporter = uno::Reference< document::XExporter >( 
xAsyncFilterDialog, uno::UNO_QUERY );
+                    }
+                    else
+                    {
+                        xFilterDialog = uno::Reference< 
ui::dialogs::XExecutableDialog >(
+                            
comphelper::getProcessServiceFactory()->createInstanceWithArguments( 
aServiceName, aDialogArgs ), uno::UNO_QUERY );
+                        xFilterProperties = uno::Reference< 
beans::XPropertyAccess >( xFilterDialog, uno::UNO_QUERY );
+                        xExporter = uno::Reference< document::XExporter >( 
xFilterDialog, uno::UNO_QUERY );
+                    }
+
+                    if ( xFilterProperties.is() && ( xFilterDialog.is() || 
xAsyncFilterDialog.is() ) )
                     {
                         bDialogUsed = true;
 
-                        uno::Reference< document::XExporter > xExporter( 
xFilterDialog, uno::UNO_QUERY );
                         if( xExporter.is() )
                             xExporter->setSourceDocument( GetModel() );
 
@@ -573,19 +602,32 @@ bool ModelData_Impl::ExecuteFilterDialog_Impl( const 
OUString& aFilterName )
                         GetMediaDescr() >> aPropsForDialog;
                         xFilterProperties->setPropertyValues( aPropsForDialog 
);
 
-                        if( !xFilterDialog->execute() )
+                        if ( bIsAsync )
                         {
-                            throw task::ErrorCodeIOException(
-                                ("ModelData_Impl::ExecuteFilterDialog_Impl:"
-                                 " ERRCODE_IO_ABORT"),
-                                uno::Reference< uno::XInterface >(),
-                                sal_uInt32(ERRCODE_IO_ABORT));
-                        }
+                            m_xFilterProperties = xFilterProperties;
+                            m_xFilterDialog = xAsyncFilterDialog;
+
+                            auto aDialogClosedListener = rtl::Reference(new 
svt::DialogClosedListener());
+                            aDialogClosedListener->SetDialogClosedLink( LINK( 
this, ModelData_Impl, OptionsDialogClosedHdl ) );
 
-                        const uno::Sequence< beans::PropertyValue > 
aPropsFromDialog =
-                                                                    
xFilterProperties->getPropertyValues();
-                        for ( const auto& rProp : aPropsFromDialog )
-                            GetMediaDescr()[rProp.Name] = rProp.Value;
+                            m_xFilterDialog->startExecuteModal( 
aDialogClosedListener );
+                        }
+                        else
+                        {
+                            if( !xFilterDialog->execute() )
+                            {
+                                throw task::ErrorCodeIOException(
+                                    
("ModelData_Impl::ExecuteFilterDialog_Impl:"
+                                    " ERRCODE_IO_ABORT"),
+                                    uno::Reference< uno::XInterface >(),
+                                    sal_uInt32(ERRCODE_IO_ABORT));
+                            }
+
+                            const uno::Sequence< beans::PropertyValue > 
aPropsFromDialog =
+                                                                        
xFilterProperties->getPropertyValues();
+                            for ( const auto& rProp : aPropsFromDialog )
+                                GetMediaDescr()[rProp.Name] = rProp.Value;
+                        }
                     }
                 }
             }
@@ -611,6 +653,34 @@ bool ModelData_Impl::ExecuteFilterDialog_Impl( const 
OUString& aFilterName )
     return bDialogUsed;
 }
 
+void SfxStoringHelper::CallFinishGUIStoreModel()
+{
+    ::comphelper::SequenceAsHashMap::const_iterator aFileNameIter = 
m_xModelData->GetMediaDescr().find( OUString("URL") );
+    uno::Sequence< beans::PropertyValue > aFilterProps = 
m_xModelData->GetPreselectedFilter_Impl( m_nStoreMode );
+    const OUString aFilterFromMediaDescr = 
m_xModelData->GetMediaDescr().getUnpackedValueOrDefault( aFilterNameString, 
OUString() );
+    const OUString aOldFilterName = 
m_xModelData->GetDocProps().getUnpackedValueOrDefault( aFilterNameString, 
OUString() );
+    ::comphelper::SequenceAsHashMap aFilterPropsHM( aFilterProps );
+    OUString aFilterName = aFilterPropsHM.getUnpackedValueOrDefault( "Name", 
OUString() );
+
+    SfxStoringHelper::FinishGUIStoreModel(aFileNameIter, *m_xModelData, 
m_bRemote, m_nStoreMode, aFilterProps,
+                                          m_bSetStandardName, 
m_bPreselectPassword, m_bDialogUsed,
+                                          aFilterFromMediaDescr, 
aOldFilterName, m_aArgsSequence, aFilterName);
+
+    if (SfxViewShell::Current())
+        SfxViewShell::Current()->SetStoringHelper(nullptr);
+}
+
+IMPL_LINK( ModelData_Impl, OptionsDialogClosedHdl, 
css::ui::dialogs::DialogClosedEvent*, pEvt, void )
+{
+    if (pEvt->DialogResult == RET_OK && m_xFilterProperties)
+    {
+        const uno::Sequence< beans::PropertyValue > aPropsFromDialog = 
m_xFilterProperties->getPropertyValues();
+        for ( const auto& rProp : aPropsFromDialog )
+            GetMediaDescr()[rProp.Name] = rProp.Value;
+
+        m_pOwner->CallFinishGUIStoreModel();
+    }
+}
 
 sal_Int8 ModelData_Impl::CheckSaveAcceptable( sal_Int8 nCurStatus )
 {
@@ -994,12 +1064,18 @@ bool ModelData_Impl::OutputFileDialog( sal_Int16 
nStoreMode,
 
     // aFilterName is a pure output parameter, pDialogParams is an in/out 
parameter
     OUString aFilterName;
-    if ( pFileDlg->Execute( pDialogParams, aFilterName ) != ERRCODE_NONE )
+    // in LOK case we don't show File Picker so it will fail, but execute to 
do other preparations
+    if ( pFileDlg->Execute( pDialogParams, aFilterName ) != ERRCODE_NONE
+        && !comphelper::LibreOfficeKit::isActive() )
     {
         throw task::ErrorCodeIOException(
             "ModelData_Impl::OutputFileDialog: ERRCODE_IO_ABORT",
             uno::Reference< uno::XInterface >(), sal_uInt32(ERRCODE_IO_ABORT));
     }
+    else if (comphelper::LibreOfficeKit::isActive())
+    {
+        aFilterName = aPreselectedFilterPropsHM.getUnpackedValueOrDefault( 
"Name", OUString() );
+    }
 
     // the following two arguments can not be converted in MediaDescriptor,
     // so they should be removed from the ItemSet after retrieving
@@ -1022,9 +1098,6 @@ bool ModelData_Impl::OutputFileDialog( sal_Int16 
nStoreMode,
     const OUString aFilterFromMediaDescr = 
GetMediaDescr().getUnpackedValueOrDefault( sFilterNameString, OUString() );
     const OUString aOldFilterName = GetDocProps().getUnpackedValueOrDefault( 
sFilterNameString, OUString() );
 
-    const OUString sFilterOptionsString(aFilterOptionsString);
-    const OUString sFilterDataString(aFilterDataString);
-
     if ( aFilterName == aFilterFromMediaDescr )
     {
         // preserve current settings if any
@@ -1034,32 +1107,32 @@ bool ModelData_Impl::OutputFileDialog( sal_Int16 
nStoreMode,
         if ( aFilterFromMediaDescr == aOldFilterName )
         {
             ::comphelper::SequenceAsHashMap::const_iterator aIter =
-                                        GetDocProps().find( 
sFilterOptionsString );
+                                        GetDocProps().find( 
aFilterOptionsString );
             if ( aIter != GetDocProps().end()
-              && GetMediaDescr().find( sFilterOptionsString ) == 
GetMediaDescr().end() )
+              && GetMediaDescr().find( aFilterOptionsString ) == 
GetMediaDescr().end() )
                 GetMediaDescr()[aIter->first] = aIter->second;
 
-            aIter = GetDocProps().find( sFilterDataString );
+            aIter = GetDocProps().find( aFilterDataString );
             if ( aIter != GetDocProps().end()
-              && GetMediaDescr().find( sFilterDataString ) == 
GetMediaDescr().end() )
+              && GetMediaDescr().find( aFilterDataString ) == 
GetMediaDescr().end() )
                 GetMediaDescr()[aIter->first] = aIter->second;
         }
     }
     else
     {
-        GetMediaDescr().erase( sFilterDataString );
-        GetMediaDescr().erase( sFilterOptionsString );
+        GetMediaDescr().erase( aFilterDataString );
+        GetMediaDescr().erase( aFilterOptionsString );
 
         if ( aFilterName == aOldFilterName )
         {
             // merge filter option of the document filter
 
             ::comphelper::SequenceAsHashMap::const_iterator aIter =
-                                GetDocProps().find( sFilterOptionsString );
+                                GetDocProps().find( aFilterOptionsString );
             if ( aIter != GetDocProps().end() )
                 GetMediaDescr()[aIter->first] = aIter->second;
 
-            aIter = GetDocProps().find( sFilterDataString );
+            aIter = GetDocProps().find( aFilterDataString );
             if ( aIter != GetDocProps().end() )
                 GetMediaDescr()[aIter->first] = aIter->second;
         }
@@ -1083,8 +1156,8 @@ bool ModelData_Impl::OutputFileDialog( sal_Int16 
nStoreMode,
                 aVal >>= bUseFilterOptions;
                 if ( !bUseFilterOptions )
                     bUseFilterOptions =
-                      ( GetMediaDescr().find( sFilterDataString ) == 
GetMediaDescr().end()
-                      && GetMediaDescr().find( sFilterOptionsString ) == 
GetMediaDescr().end() );
+                      ( GetMediaDescr().find( aFilterDataString ) == 
GetMediaDescr().end()
+                      && GetMediaDescr().find( aFilterOptionsString ) == 
GetMediaDescr().end() );
             }
             catch( const lang::IllegalArgumentException& )
             {}
@@ -1309,24 +1382,26 @@ bool SfxStoringHelper::GUIStoreModel( const 
uno::Reference< frame::XModel >& xMo
                                             std::u16string_view aSlotName,
                                             uno::Sequence< 
beans::PropertyValue >& aArgsSequence,
                                             bool bPreselectPassword,
-                                            SignatureState 
nDocumentSignatureState )
+                                            SignatureState 
nDocumentSignatureState,
+                                            bool bIsAsync)
 {
-    ModelData_Impl aModelData( *this, xModel, aArgsSequence );
-
-    bool bDialogUsed = false;
+    m_xModelData = std::make_shared<ModelData_Impl>( *this, xModel, 
aArgsSequence );
+    m_aArgsSequence = aArgsSequence;
+    ModelData_Impl& aModelData = *m_xModelData;
 
-    INetURLObject aURL;
+    m_bDialogUsed = false;
 
-    bool bSetStandardName = false; // can be set only for SaveAs
+    m_bSetStandardName = false; // can be set only for SaveAs
+    m_bPreselectPassword = bPreselectPassword;
 
     // parse the slot name
-    bool bRemote = false;
-    sal_Int16 nStoreMode = getStoreModeFromSlotName( aSlotName );
+    m_bRemote = false;
+    m_nStoreMode = getStoreModeFromSlotName( aSlotName );
 
-    if ( nStoreMode == SAVEASREMOTE_REQUESTED )
+    if ( m_nStoreMode == SAVEASREMOTE_REQUESTED )
     {
-        nStoreMode = SAVEAS_REQUESTED;
-        bRemote = true;
+        m_nStoreMode = SAVEAS_REQUESTED;
+        m_bRemote = true;
     }
 
     sal_Int8 nStatusSave = STATUS_NO_ACTION;
@@ -1338,10 +1413,10 @@ bool SfxStoringHelper::GUIStoreModel( const 
uno::Reference< frame::XModel >& xMo
         bool bSaveACopy = false;
         aSaveACopyIter->second >>= bSaveACopy;
         if ( bSaveACopy )
-            nStoreMode = EXPORT_REQUESTED | SAVEACOPY_REQUESTED | 
WIDEEXPORT_REQUESTED;
+            m_nStoreMode = EXPORT_REQUESTED | SAVEACOPY_REQUESTED | 
WIDEEXPORT_REQUESTED;
     }
     // handle the special cases
-    if ( nStoreMode & SAVEAS_REQUESTED )
+    if ( m_nStoreMode & SAVEAS_REQUESTED )
     {
         ::comphelper::SequenceAsHashMap::const_iterator aSaveToIter =
                         aModelData.GetMediaDescr().find( OUString("SaveTo") );
@@ -1350,16 +1425,16 @@ bool SfxStoringHelper::GUIStoreModel( const 
uno::Reference< frame::XModel >& xMo
             bool bWideExport = false;
             aSaveToIter->second >>= bWideExport;
             if ( bWideExport )
-                nStoreMode = EXPORT_REQUESTED | WIDEEXPORT_REQUESTED;
+                m_nStoreMode = EXPORT_REQUESTED | WIDEEXPORT_REQUESTED;
         }
 
         // if saving is not acceptable the warning must be shown even in case 
of SaveAs operation
-        if ( ( nStoreMode & SAVEAS_REQUESTED ) && 
aModelData.CheckSaveAcceptable( STATUS_SAVEAS ) == STATUS_NO_ACTION )
+        if ( ( m_nStoreMode & SAVEAS_REQUESTED ) && 
aModelData.CheckSaveAcceptable( STATUS_SAVEAS ) == STATUS_NO_ACTION )
             throw task::ErrorCodeIOException(
                 "SfxStoringHelper::GUIStoreModel: ERRCODE_IO_ABORT",
                 uno::Reference< uno::XInterface >(), 
sal_uInt32(ERRCODE_IO_ABORT));
     }
-    else if ( nStoreMode & SAVE_REQUESTED )
+    else if ( m_nStoreMode & SAVE_REQUESTED )
     {
         // if saving is not acceptable by the configuration the warning must 
be shown
         nStatusSave = aModelData.CheckSaveAcceptable( STATUS_SAVE );
@@ -1383,13 +1458,13 @@ bool SfxStoringHelper::GUIStoreModel( const 
uno::Reference< frame::XModel >& xMo
         else if ( nStatusSave != STATUS_SAVE )
         {
             // this should be a usual SaveAs operation
-            nStoreMode = SAVEAS_REQUESTED;
+            m_nStoreMode = SAVEAS_REQUESTED;
             if ( nStatusSave == STATUS_SAVEAS_STANDARDNAME )
-                bSetStandardName = true;
+                m_bSetStandardName = true;
         }
     }
 
-    if (!comphelper::LibreOfficeKit::isActive() && !( nStoreMode & 
EXPORT_REQUESTED ) )
+    if (!comphelper::LibreOfficeKit::isActive() && !( m_nStoreMode & 
EXPORT_REQUESTED ) )
     {
         // if it is no export, warn user that the signature will be removed
         if (  SignatureState::OK == nDocumentSignatureState
@@ -1409,7 +1484,7 @@ bool SfxStoringHelper::GUIStoreModel( const 
uno::Reference< frame::XModel >& xMo
         }
     }
 
-    if ( nStoreMode & SAVE_REQUESTED && nStatusSave == STATUS_SAVE )
+    if ( m_nStoreMode & SAVE_REQUESTED && nStatusSave == STATUS_SAVE )
     {
         // Document properties can contain streams that should be freed before 
storing
         aModelData.FreeDocumentProps();
@@ -1436,7 +1511,7 @@ bool SfxStoringHelper::GUIStoreModel( const 
uno::Reference< frame::XModel >& xMo
     }
 
     // preselect a filter for the storing process
-    uno::Sequence< beans::PropertyValue > aFilterProps = 
aModelData.GetPreselectedFilter_Impl( nStoreMode );
+    uno::Sequence< beans::PropertyValue > aFilterProps = 
aModelData.GetPreselectedFilter_Impl( m_nStoreMode );
 
     DBG_ASSERT( aFilterProps.hasElements(), "No filter for storing!\n" );
     if ( !aFilterProps.hasElements() )
@@ -1447,33 +1522,50 @@ bool SfxStoringHelper::GUIStoreModel( const 
uno::Reference< frame::XModel >& xMo
     ::comphelper::SequenceAsHashMap aFilterPropsHM( aFilterProps );
     OUString aFilterName = aFilterPropsHM.getUnpackedValueOrDefault( "Name", 
OUString() );
 
-    const OUString sFilterNameString(aFilterNameString);
+    const OUString aFilterFromMediaDescr = 
aModelData.GetMediaDescr().getUnpackedValueOrDefault( aFilterNameString, 
OUString() );
+    const OUString aOldFilterName = 
aModelData.GetDocProps().getUnpackedValueOrDefault( aFilterNameString, 
OUString() );
 
-    const OUString aFilterFromMediaDescr = 
aModelData.GetMediaDescr().getUnpackedValueOrDefault( sFilterNameString, 
OUString() );
-    const OUString aOldFilterName = 
aModelData.GetDocProps().getUnpackedValueOrDefault( sFilterNameString, 
OUString() );
-
-    bool bUseFilterOptions = false;
     ::comphelper::SequenceAsHashMap::const_iterator aFileNameIter = 
aModelData.GetMediaDescr().find( OUString("URL") );
 
-    const OUString sFilterOptionsString(aFilterOptionsString);
-    const OUString sFilterDataString(aFilterDataString);
-
-    bool bPDFOptions = (nStoreMode & PDFEXPORT_REQUESTED) && !(nStoreMode & 
PDFDIRECTEXPORT_REQUESTED);
-    bool bEPUBOptions = (nStoreMode & EPUBEXPORT_REQUESTED) && !(nStoreMode & 
EPUBDIRECTEXPORT_REQUESTED);
-    if ( ( nStoreMode & EXPORT_REQUESTED ) && (bPDFOptions || bEPUBOptions) )
+    bool bPDFOptions = (m_nStoreMode & PDFEXPORT_REQUESTED) && !(m_nStoreMode 
& PDFDIRECTEXPORT_REQUESTED);
+    bool bEPUBOptions = (m_nStoreMode & EPUBEXPORT_REQUESTED) && 
!(m_nStoreMode & EPUBDIRECTEXPORT_REQUESTED);
+    if ( ( m_nStoreMode & EXPORT_REQUESTED ) && (bPDFOptions || bEPUBOptions) )
     {
         // this is PDF or EPUB export, the filter options dialog should be 
shown before the export
-        aModelData.GetMediaDescr()[sFilterNameString] <<= aFilterName;
+        aModelData.GetMediaDescr()[aFilterNameString] <<= aFilterName;
         if ( aModelData.GetMediaDescr().find( "FilterFlags" ) == 
aModelData.GetMediaDescr().end()
-          && aModelData.GetMediaDescr().find( sFilterOptionsString ) == 
aModelData.GetMediaDescr().end()
-          && aModelData.GetMediaDescr().find( sFilterDataString ) == 
aModelData.GetMediaDescr().end() )
+          && aModelData.GetMediaDescr().find( aFilterOptionsString ) == 
aModelData.GetMediaDescr().end()
+          && aModelData.GetMediaDescr().find( aFilterDataString ) == 
aModelData.GetMediaDescr().end() )
         {
             // execute filter options dialog since no options are set in the 
media descriptor
-            if ( aModelData.ExecuteFilterDialog_Impl( aFilterName ) )
-                bDialogUsed = true;
+            if ( aModelData.ExecuteFilterDialog_Impl( aFilterName, bIsAsync ) )
+                m_bDialogUsed = true;
         }
     }
 
+    if (bIsAsync)
+        return false;
+
+    return SfxStoringHelper::FinishGUIStoreModel(aFileNameIter, aModelData, 
m_bRemote, m_nStoreMode, aFilterProps,
+                                                 m_bSetStandardName, 
m_bPreselectPassword, m_bDialogUsed,
+                                                 aFilterFromMediaDescr, 
aOldFilterName, aArgsSequence, aFilterName);
+}
+
+bool 
SfxStoringHelper::FinishGUIStoreModel(::comphelper::SequenceAsHashMap::const_iterator&
 aFileNameIter,
+                                          ModelData_Impl& aModelData, bool 
bRemote, sal_Int16 nStoreMode,
+                                          uno::Sequence< beans::PropertyValue 
>& aFilterProps,
+                                          bool bSetStandardName, bool 
bPreselectPassword, bool bDialogUsed,
+                                          std::u16string_view 
aFilterFromMediaDescr,
+                                          std::u16string_view aOldFilterName,
+                                          uno::Sequence< beans::PropertyValue 
>& aArgsSequence,
+                                          OUString aFilterName)
+{
+    const OUString sFilterNameString(aFilterNameString);
+    const OUString sFilterOptionsString(aFilterOptionsString);
+    const OUString sFilterDataString(aFilterDataString);
+    bool bUseFilterOptions = false;
+    INetURLObject aURL;
+
     if ( aFileNameIter == aModelData.GetMediaDescr().end() )
     {
         sal_Int16 nDialog = SFX2_IMPL_DIALOG_CONFIG;
@@ -1605,7 +1697,7 @@ bool SfxStoringHelper::GUIStoreModel( const 
uno::Reference< frame::XModel >& xMo
         && ( ( nStoreMode & EXPORT_REQUESTED ) || bUseFilterOptions ) )
     {
         // execute filter options dialog
-        if ( aModelData.ExecuteFilterDialog_Impl( aFilterName ) )
+        if ( aModelData.ExecuteFilterDialog_Impl( aFilterName, false ) )
         {
             bDialogUsed = true;
             // check if the file is a pdf or not and change the storing mode 
at convenience
@@ -1681,7 +1773,7 @@ bool SfxStoringHelper::GUIStoreModel( const 
uno::Reference< frame::XModel >& xMo
     }
 
     // Launch PDF viewer
-    if ( nStoreMode & PDFEXPORT_REQUESTED )
+    if ( nStoreMode & PDFEXPORT_REQUESTED && 
!comphelper::LibreOfficeKit::isActive() )
     {
         FilterConfigItem aItem(u"Office.Common/Filter/PDF/Export/");
         bool aViewPDF = aItem.ReadBool( "ViewPDFAfterExport", false );
@@ -1693,6 +1785,16 @@ bool SfxStoringHelper::GUIStoreModel( const 
uno::Reference< frame::XModel >& xMo
         }
     }
 
+    if ( comphelper::LibreOfficeKit::isActive() )
+    {
+        if ( SfxViewShell* pShell = SfxViewShell::Current() )
+        {
+            OUString sURL = aURL.GetMainURL( 
INetURLObject::DecodeMechanism::NONE );
+            pShell->libreOfficeKitViewCallback( LOK_CALLBACK_EXPORT_FILE,
+                OUStringToOString(sURL, RTL_TEXTENCODING_UTF8).getStr() );
+        }
+    }
+
     return bDialogUsed;
 }
 
diff --git a/sfx2/source/doc/objserv.cxx b/sfx2/source/doc/objserv.cxx
index f0bc6172ab1d..35716406cd80 100644
--- a/sfx2/source/doc/objserv.cxx
+++ b/sfx2/source/doc/objserv.cxx
@@ -590,6 +590,7 @@ void SfxObjectShell::ExecFile_Impl(SfxRequest &rReq)
 
     bool bIsPDFExport = false;
     bool bIsAutoRedact = false;
+    bool bIsAsync = false;
     std::vector<std::pair<RedactionTarget, OUString>> aRedactionTargets;
     switch(nId)
     {
@@ -896,6 +897,11 @@ void SfxObjectShell::ExecFile_Impl(SfxRequest &rReq)
         case SID_SAVEASREMOTE:
         case SID_SAVEDOC:
         {
+            // so far only pdf and epub support Async interface
+            if (comphelper::LibreOfficeKit::isActive() && rReq.GetCallMode() 
== SfxCallMode::ASYNCHRON
+                && (nId == SID_EXPORTDOCASEPUB || nId == SID_EXPORTDOCASPDF))
+                bIsAsync = true;
+
             // derived class may decide to abort this
             if( !QuerySlotExecutable( nId ) )
             {
@@ -1014,7 +1020,9 @@ void SfxObjectShell::ExecFile_Impl(SfxRequest &rReq)
                 if ( !pSlot )
                     throw uno::Exception("no slot", nullptr);
 
-                SfxStoringHelper aHelper;
+                std::shared_ptr<SfxStoringHelper> xHelper = 
std::make_shared<SfxStoringHelper>();
+                if (bIsAsync && SfxViewShell::Current())
+                    SfxViewShell::Current()->SetStoringHelper(xHelper);
 
                 if ( QueryHiddenInformation( bIsPDFExport ? 
HiddenWarningFact::WhenCreatingPDF : HiddenWarningFact::WhenSaving, nullptr ) 
!= RET_YES )
                 {
@@ -1036,11 +1044,12 @@ void SfxObjectShell::ExecFile_Impl(SfxRequest &rReq)
                     ExecuteSlot(aRequest);
                 }
 
-                aHelper.GUIStoreModel( GetModel(),
+                xHelper->GUIStoreModel( GetModel(),
                                        OUString::createFromAscii( 
pSlot->GetUnoName() ),
                                        aDispatchArgs,
                                        bPreselectPassword,
-                                       GetDocumentSignatureState() );
+                                       GetDocumentSignatureState(),
+                                       bIsAsync );
 
                 if (bMailPrepareExport)
                 {
diff --git a/sfx2/source/view/ipclient.cxx b/sfx2/source/view/ipclient.cxx
index 03ed38a78f3b..fd52355f3ed5 100644
--- a/sfx2/source/view/ipclient.cxx
+++ b/sfx2/source/view/ipclient.cxx
@@ -922,7 +922,8 @@ ErrCode SfxInPlaceClient::DoVerb(sal_Int32 nVerb)
                                             u"SaveAs",
                                             aDispatchArgs,
                                             false,
-                                            SignatureState::NOSIGNATURES );
+                                            SignatureState::NOSIGNATURES,
+                                            false );
                 }
                 catch( const task::ErrorCodeIOException& aErrorEx )
                 {
diff --git a/vcl/jsdialog/enabled.cxx b/vcl/jsdialog/enabled.cxx
index 370b691cf4ce..ce39de02c082 100644
--- a/vcl/jsdialog/enabled.cxx
+++ b/vcl/jsdialog/enabled.cxx
@@ -98,6 +98,15 @@ bool isBuilderEnabled(std::u16string_view rUIFile, bool 
bMobile)
         || rUIFile == u"xmlsec/ui/certpage.ui"
         || rUIFile == u"xmlsec/ui/digitalsignaturesdialog.ui"
         || rUIFile == u"xmlsec/ui/viewcertdialog.ui"
+        || rUIFile == u"filter/ui/pdfoptionsdialog.ui"
+        || rUIFile == u"filter/ui/pdfgeneralpage.ui"
+        || rUIFile == u"filter/ui/pdfviewpage.ui"
+        || rUIFile == u"filter/ui/pdfuserinterfacepage.ui"
+        || rUIFile == u"filter/ui/pdfsecuritypage.ui"
+        || rUIFile == u"filter/ui/pdflinkspage.ui"
+        || rUIFile == u"filter/ui/warnpdfdialog.ui"
+        || rUIFile == u"filter/ui/pdfsignpage.ui"
+        || rUIFile == u"writerperfect/ui/exportepub.ui"
         )
     {
         return true;
commit 56ecc91017367c0c34e0ca24139853db1319746f
Author:     Szymon Kłos <szymon.k...@collabora.com>
AuthorDate: Fri Dec 9 13:53:47 2022 +0100
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Mon Jan 23 18:58:23 2023 +0100

    Make EPUB Export dialog async
    
    (cherry picked from commit 9461b0e1385b87d2490bf9402729fb9e912395e9)
    
    Change-Id: Iead5b4ff6064395fd5abbcdea73db38415dbb37c
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/144514
    Tested-by: Jenkins
    Reviewed-by: Andras Timar <andras.ti...@collabora.com>

diff --git a/writerperfect/source/writer/EPUBExportUIComponent.cxx 
b/writerperfect/source/writer/EPUBExportUIComponent.cxx
index e8d618b99cf6..0e392ffe00ec 100644
--- a/writerperfect/source/writer/EPUBExportUIComponent.cxx
+++ b/writerperfect/source/writer/EPUBExportUIComponent.cxx
@@ -90,6 +90,31 @@ void SAL_CALL EPUBExportUIComponent::setSourceDocument(
     mxSourceDocument = xDocument;
 }
 
+void SAL_CALL EPUBExportUIComponent::setDialogTitle(const OUString& aTitle) { 
setTitle(aTitle); }
+
+void SAL_CALL EPUBExportUIComponent::startExecuteModal(
+    const css::uno::Reference<css::ui::dialogs::XDialogClosedListener>& 
xListener)
+{
+    SolarMutexGuard aSolarGuard;
+
+    if (!mxAsyncDialog)
+    {
+        if (mxSourceDocument.is())
+            mxAsyncDialog
+                = 
std::make_shared<EPUBExportDialog>(Application::GetFrameWeld(mxDialogParent),
+                                                     maFilterData, mxContext, 
mxSourceDocument);
+
+        if (!mxAsyncDialog)
+            return;
+    }
+
+    weld::DialogController::runAsync(mxAsyncDialog, [xListener](sal_Int32 
nResponse) {
+        css::ui::dialogs::DialogClosedEvent aEvent;
+        aEvent.DialogResult = nResponse;
+        xListener->dialogClosed(aEvent);
+    });
+}
+
 extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
 com_sun_star_comp_Writer_EPUBExportUIComponent_get_implementation(
     uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/)
diff --git a/writerperfect/source/writer/EPUBExportUIComponent.hxx 
b/writerperfect/source/writer/EPUBExportUIComponent.hxx
index 71fcc0ace168..b453a4e88096 100644
--- a/writerperfect/source/writer/EPUBExportUIComponent.hxx
+++ b/writerperfect/source/writer/EPUBExportUIComponent.hxx
@@ -12,6 +12,7 @@
 #include <com/sun/star/beans/XPropertyAccess.hpp>
 #include <com/sun/star/lang/XServiceInfo.hpp>
 #include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/ui/dialogs/XAsynchronousExecutableDialog.hpp>
 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
 #include <com/sun/star/document/XExporter.hpp>
 #include <com/sun/star/awt/XWindow.hpp>
@@ -19,6 +20,11 @@
 #include <comphelper/sequenceashashmap.hxx>
 #include <cppuhelper/implbase.hxx>
 
+namespace weld
+{
+class DialogController;
+}
+
 namespace com::sun::star::uno
 {
 class XComponentContext;
@@ -30,6 +36,7 @@ namespace writerperfect
 class EPUBExportUIComponent
     : public cppu::WeakImplHelper<css::beans::XPropertyAccess, 
css::lang::XInitialization,
                                   css::lang::XServiceInfo, 
css::ui::dialogs::XExecutableDialog,
+                                  
css::ui::dialogs::XAsynchronousExecutableDialog,
                                   css::document::XExporter>
 {
 public:
@@ -49,6 +56,12 @@ public:
     void SAL_CALL setTitle(const OUString& rTitle) override;
     sal_Int16 SAL_CALL execute() override;
 
+    // XAsynchronousExecutableDialog
+    void SAL_CALL setDialogTitle(const OUString& aTitle) override;
+
+    void SAL_CALL startExecuteModal(
+        const css::uno::Reference<css::ui::dialogs::XDialogClosedListener>& 
xListener) override;
+
     // XExporter
     void SAL_CALL
     setSourceDocument(const css::uno::Reference<css::lang::XComponent>& 
xDocument) override;
@@ -65,6 +78,7 @@ private:
     css::uno::Reference<css::uno::XComponentContext> mxContext;
     css::uno::Reference<css::lang::XComponent> mxSourceDocument;
     css::uno::Reference<css::awt::XWindow> mxDialogParent;
+    std::shared_ptr<weld::DialogController> mxAsyncDialog;
 };
 
 } // namespace writerperfect

Reply via email to