configure.ac                                     |    2 
 cui/source/options/optpath.cxx                   |    3 -
 include/sfx2/app.hxx                             |    3 -
 include/sfx2/sfxsids.hrc                         |    2 
 include/unotools/mediadescriptor.hxx             |    1 
 offapi/com/sun/star/document/MediaDescriptor.idl |    5 ++
 sfx2/inc/guisaveas.hxx                           |   12 ++---
 sfx2/source/appl/app.cxx                         |   43 --------------------
 sfx2/source/appl/appuno.cxx                      |   18 ++++++++
 sfx2/source/dialog/filedlghelper.cxx             |   24 ++++-------
 sfx2/source/dialog/filedlgimpl.hxx               |    1 
 sfx2/source/doc/guisaveas.cxx                    |   48 +++++++++++++++--------
 sfx2/source/doc/sfxbasemodel.cxx                 |    8 +++
 sfx2/source/inc/appdata.hxx                      |    1 
 sfx2/source/view/ipclient.cxx                    |    2 
 15 files changed, 85 insertions(+), 88 deletions(-)

New commits:
commit 6a89ff06fccbd7acf706b2bb50425bcd9cb986fd
Author:     Samuel Mehrbrodt <samuel.mehrbr...@allotropia.de>
AuthorDate: Mon May 12 09:49:51 2025 +0200
Commit:     Samuel Mehrbrodt <samuel.mehrbr...@allotropia.de>
CommitDate: Mon May 12 09:49:51 2025 +0200

    Release 24.2.13
    
    Change-Id: Id34c202244f87bac06d741e5819abf35415a61cd

diff --git a/configure.ac b/configure.ac
index 2479e4b246ca..81f369bbc856 100644
--- a/configure.ac
+++ b/configure.ac
@@ -9,7 +9,7 @@ dnl in order to create a configure script.
 # several non-alphanumeric characters, those are split off and used only for 
the
 # ABOUTBOXPRODUCTVERSIONSUFFIX in openoffice.lst. Why that is necessary, no 
idea.
 
-AC_INIT([LibreOffice],[24.2.12.0],[],[],[http://documentfoundation.org/])
+AC_INIT([LibreOffice],[24.2.13.0],[],[],[http://documentfoundation.org/])
 
 dnl libnumbertext needs autoconf 2.68, but that can pick up autoconf268 just 
fine if it is installed
 dnl whereas aclocal (as run by autogen.sh) insists on using autoconf and fails 
hard
commit f5ac9d6cfd673878f63ba059bfda366323ec05f2
Author:     Samuel Mehrbrodt <samuel.mehrbr...@allotropia.de>
AuthorDate: Thu Apr 24 11:01:48 2025 +0200
Commit:     Samuel Mehrbrodt <samuel.mehrbr...@allotropia.de>
CommitDate: Mon May 12 08:52:43 2025 +0200

    tdf#165392 Save as should default to current document directory as well
    
    As done in 3fa39a4dadc8e2777185465a6f7c9968c8cf44d1 for Export,
    do the same for "Save as"/"Save a copy" as well.
    
    Change-Id: I5135cff0f74d6673fcfc7fa090ed752bea1d59cb
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/184542
    Reviewed-by: Samuel Mehrbrodt <samuel.mehrbr...@allotropia.de>
    Tested-by: Jenkins
    (cherry picked from commit 5683376d063569368bd7d3036ec6ce725134bb08)

diff --git a/offapi/com/sun/star/document/MediaDescriptor.idl 
b/offapi/com/sun/star/document/MediaDescriptor.idl
index e6f73d3afdcd..6cf7c8cc870c 100644
--- a/offapi/com/sun/star/document/MediaDescriptor.idl
+++ b/offapi/com/sun/star/document/MediaDescriptor.idl
@@ -449,7 +449,7 @@ service MediaDescriptor
      */
     [optional,property] string SuggestedSaveAsName;
 
-    /** Directory to be used when exporting (to PDF, epub, ...).
+    /** Directory to be used when saving (save as, save a copy) or exporting 
(to PDF, epub, ...).
         Defaults to the current document directory.
      */
     [optional,property] string ExportDirectory;
diff --git a/sfx2/source/doc/guisaveas.cxx b/sfx2/source/doc/guisaveas.cxx
index 2d557889fdc2..37560fc72cfb 100644
--- a/sfx2/source/doc/guisaveas.cxx
+++ b/sfx2/source/doc/guisaveas.cxx
@@ -936,15 +936,17 @@ bool ModelData_Impl::OutputFileDialog( sal_Int16 
nStoreMode,
     SfxFilterFlags nMust = getMustFlags( nStoreMode );
     SfxFilterFlags nDont = getDontFlags( nStoreMode );
     weld::Window* pFrameWin = SfxStoringHelper::GetModelWindow(m_xModel);
+
+    const OUString aBaseUrl = 
GetDocProps().getUnpackedValueOrDefault("DocumentBaseURL", OUString());
+    OUString aExportDir = 
GetDocProps().getUnpackedValueOrDefault("ExportDirectory", aBaseUrl);
+    INetURLObject aObj( aExportDir );
+    aObj.removeSegment();
+    aExportDir = aObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+    if (!aExportDir.isEmpty())
+        rStandardDir = aExportDir;
+
     if ( ( nStoreMode & EXPORT_REQUESTED ) && !( nStoreMode & 
WIDEEXPORT_REQUESTED ) )
     {
-        const OUString aBaseUrl = 
GetDocProps().getUnpackedValueOrDefault("DocumentBaseURL", OUString());
-        OUString aExportDir = 
GetDocProps().getUnpackedValueOrDefault("ExportDirectory", aBaseUrl);
-        INetURLObject aObj( aExportDir );
-        aObj.removeSegment();
-        aExportDir = aObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
-        if (!aExportDir.isEmpty())
-            rStandardDir = aExportDir;
         if ( ( nStoreMode & PDFEXPORT_REQUESTED ) && 
!aPreselectedFilterPropsHM.empty() )
         {
             // this is a PDF export
commit 2c357df2492fbc37d9ef0611c5d8e78e40786da0
Author:     Samuel Mehrbrodt <samuel.mehrbr...@allotropia.de>
AuthorDate: Fri Apr 11 18:21:37 2025 +0200
Commit:     Samuel Mehrbrodt <samuel.mehrbr...@allotropia.de>
CommitDate: Mon May 12 08:45:48 2025 +0200

    tdf#165917 Improve Export directory pre-selection
    
    When calling an Export dialog (PDF, epub, ...) the following
    folder will be preselected:
    
    For stored documents:
    * Current document directory
    * If another directory was chosen for the export,
      that directory will be preselected for subsequent exports
      (stored only during runtime - per document)
    
    For unstored documents:
    * The last used export directory is restored (last used in unsaved doc)
    
    Change-Id: I97595d164cf1d3604166c38aa2a5ed31be56f113
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/184062
    Reviewed-by: Samuel Mehrbrodt <samuel.mehrbr...@allotropia.de>
    Tested-by: Jenkins
    (cherry picked from commit 3fa39a4dadc8e2777185465a6f7c9968c8cf44d1)

diff --git a/cui/source/options/optpath.cxx b/cui/source/options/optpath.cxx
index 7832c260075b..9aed19f28c41 100644
--- a/cui/source/options/optpath.cxx
+++ b/cui/source/options/optpath.cxx
@@ -464,9 +464,6 @@ void SvxPathTabPage::ChangeCurrentEntry( const OUString& 
_rFolder )
         // will be used for the next open dialog.
         SvtViewOptions aDlgOpt( EViewType::Dialog, IODLG_CONFIGNAME );
         aDlgOpt.Delete();
-        // Reset also last used dir in the sfx application instance
-        SfxApplication *pSfxApp = SfxGetpApp();
-        pSfxApp->ResetLastDir();
     }
 }
 
diff --git a/include/sfx2/app.hxx b/include/sfx2/app.hxx
index 96bce367fd75..2dd8932b3dec 100644
--- a/include/sfx2/app.hxx
+++ b/include/sfx2/app.hxx
@@ -159,7 +159,6 @@ public:
     virtual void                Invalidate(sal_uInt16 nId = 0) override;
     void                        NotifyEvent(const SfxEventHint& rEvent, bool 
bSynchron = true );
     bool                        IsDowning() const;
-    void                        ResetLastDir();
 
     SAL_DLLPRIVATE SfxDispatcher* GetAppDispatcher_Impl();
     SAL_DLLPRIVATE SfxDispatcher* GetDispatcher_Impl();
@@ -198,8 +197,6 @@ public:
     SAL_DLLPRIVATE static void  OfaState_Impl(SfxItemSet &);
 
     SAL_DLLPRIVATE void         SetProgress_Impl(SfxProgress *);
-    SAL_DLLPRIVATE const OUString& GetLastDir_Impl() const;
-    SAL_DLLPRIVATE void         SetLastDir_Impl( const OUString & );
 
     SAL_DLLPRIVATE static void  Registrations_Impl();
     SAL_DLLPRIVATE SfxWorkWindow* GetWorkWindow_Impl(const SfxViewFrame 
*pFrame) const;
diff --git a/include/sfx2/sfxsids.hrc b/include/sfx2/sfxsids.hrc
index c5479d836855..26c335c5a112 100644
--- a/include/sfx2/sfxsids.hrc
+++ b/include/sfx2/sfxsids.hrc
@@ -301,7 +301,7 @@ class SvxZoomItem;
 #define FN_CHANGE_THEME                     (SID_SFX_START + 1745)
 #define FN_PARAM_NEW_THEME                  
TypedWhichId<SfxStringItem>(SID_SFX_START + 1746)
 #define SID_OPTIONS_PAGEID                  
TypedWhichId<SfxUInt16Item>(SID_SFX_START + 1747)
-
+#define SID_EXPORTDIRECTORY                 
TypedWhichId<SfxStringItem>(SID_SFX_START + 1748)
 //      SID_SFX_free_END                    (SID_SFX_START + 3999)
 
 #define SID_OPEN_NEW_VIEW                   
TypedWhichId<SfxBoolItem>(SID_SFX_START + 520)
diff --git a/include/unotools/mediadescriptor.hxx 
b/include/unotools/mediadescriptor.hxx
index 67ae2704246e..07d678d588a3 100644
--- a/include/unotools/mediadescriptor.hxx
+++ b/include/unotools/mediadescriptor.hxx
@@ -102,6 +102,7 @@ class UNOTOOLS_DLLPUBLIC MediaDescriptor : public 
comphelper::SequenceAsHashMap
         static constexpr OUString PROP_VIEWONLY = u"ViewOnly"_ustr;
         static constexpr OUString PROP_DOCUMENTBASEURL = 
u"DocumentBaseURL"_ustr;
         static constexpr OUString PROP_SUGGESTEDSAVEASNAME = 
u"SuggestedSaveAsName"_ustr;
+        static constexpr OUString PROP_EXPORTDIRECTORY = 
u"ExportDirectory"_ustr;
         static constexpr OUString PROP_AUTOSAVEEVENT = u"AutoSaveEvent"_ustr;
 
     // interface
diff --git a/offapi/com/sun/star/document/MediaDescriptor.idl 
b/offapi/com/sun/star/document/MediaDescriptor.idl
index 6d0982b5ee64..e6f73d3afdcd 100644
--- a/offapi/com/sun/star/document/MediaDescriptor.idl
+++ b/offapi/com/sun/star/document/MediaDescriptor.idl
@@ -449,6 +449,11 @@ service MediaDescriptor
      */
     [optional,property] string SuggestedSaveAsName;
 
+    /** Directory to be used when exporting (to PDF, epub, ...).
+        Defaults to the current document directory.
+     */
+    [optional,property] string ExportDirectory;
+
     /** name of the template instead of the URL
 
         <p>
diff --git a/sfx2/inc/guisaveas.hxx b/sfx2/inc/guisaveas.hxx
index a1f85bbc2248..dec5bfdf44c8 100644
--- a/sfx2/inc/guisaveas.hxx
+++ b/sfx2/inc/guisaveas.hxx
@@ -28,7 +28,7 @@
 #include <com/sun/star/beans/PropertyValue.hpp>
 #include <com/sun/star/container/XNameAccess.hpp>
 #include <com/sun/star/container/XContainerQuery.hpp>
-#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/frame/XModel2.hpp>
 #include <com/sun/star/frame/XModuleManager2.hpp>
 
 #include <comphelper/sequenceashashmap.hxx>
@@ -82,7 +82,7 @@ public:
     SfxStoringHelper();
 
     bool GUIStoreModel(
-                    const css::uno::Reference< css::frame::XModel >& xModel,
+                    const css::uno::Reference< css::frame::XModel2 >& xModel,
                     std::u16string_view aSlotName,
                     css::uno::Sequence< css::beans::PropertyValue >& 
aArgsSequence,
                     bool bPreselectPassword,
@@ -95,17 +95,17 @@ public:
 
 
     static void SetDocInfoState(
-        const css::uno::Reference< css::frame::XModel >& xModel,
+        const css::uno::Reference< css::frame::XModel2 >& xModel,
         const css::uno::Reference< css::document::XDocumentProperties>& 
i_xOldDocInfo );
 
     static bool WarnUnacceptableFormat(
-                                    const css::uno::Reference< 
css::frame::XModel >& xModel,
+                                    const css::uno::Reference< 
css::frame::XModel2 >& xModel,
                                     std::u16string_view aOldUIName,
                                     const OUString& aDefExtension,
                                     bool rDefaultIsAlien );
 
-    static css::uno::Reference<css::awt::XWindow> GetModelXWindow(const 
css::uno::Reference<css::frame::XModel>& rModel);
-    static weld::Window* GetModelWindow( const css::uno::Reference< 
css::frame::XModel >& xModel );
+    static css::uno::Reference<css::awt::XWindow> GetModelXWindow(const 
css::uno::Reference<css::frame::XModel2>& rModel);
+    static weld::Window* GetModelWindow( const css::uno::Reference< 
css::frame::XModel2 >& xModel );
 
 };
 
diff --git a/sfx2/source/appl/app.cxx b/sfx2/source/appl/app.cxx
index 6ae9810345e5..c38714946baa 100644
--- a/sfx2/source/appl/app.cxx
+++ b/sfx2/source/appl/app.cxx
@@ -182,49 +182,6 @@ SfxApplication::~SfxApplication()
 }
 
 
-const OUString& SfxApplication::GetLastDir_Impl() const
-
-/*  [Description]
-
-    Internal method by which the last set directory with the method
-    <SfxApplication::SetLastDir_Impl()> in SFX is returned.
-
-    This is usually the most recently addressed by the
-    SfxFileDialog directory.
-
-    [Cross-reference]
-    <SfxApplication::SetLastDir_Impl()>
-*/
-
-{
-    return pImpl->aLastDir;
-}
-
-void SfxApplication::SetLastDir_Impl
-(
-    const OUString&   rNewDir     /* Complete directory path as a string */
-)
-
-/*  [Description]
-
-    Internal Method, by which a directory path is set that was last addressed
-    (eg by the SfxFileDialog).
-
-    [Cross-reference]
-    <SfxApplication::GetLastDir_Impl()>
-*/
-
-{
-    pImpl->aLastDir = rNewDir;
-}
-
-
-void SfxApplication::ResetLastDir()
-{
-    pImpl->aLastDir.clear();
-}
-
-
 SfxDispatcher* SfxApplication::GetDispatcher_Impl()
 {
     return pImpl->pViewFrame ? pImpl->pViewFrame->GetDispatcher() : 
&*pImpl->pAppDispat;
diff --git a/sfx2/source/appl/appuno.cxx b/sfx2/source/appl/appuno.cxx
index 386cce711c7c..5f3b2eceb4d7 100644
--- a/sfx2/source/appl/appuno.cxx
+++ b/sfx2/source/appl/appuno.cxx
@@ -144,6 +144,7 @@ constexpr OUString sDenyList = u"DenyList"_ustr;
 constexpr OUString sModifyPasswordInfo = u"ModifyPasswordInfo"_ustr;
 constexpr OUString sSuggestedSaveAsDir = u"SuggestedSaveAsDir"_ustr;
 constexpr OUString sSuggestedSaveAsName = u"SuggestedSaveAsName"_ustr;
+constexpr OUString sExportDirectory = u"ExportDirectory"_ustr;
 constexpr OUString sEncryptionData = u"EncryptionData"_ustr;
 constexpr OUString sFailOnWarning = u"FailOnWarning"_ustr;
 constexpr OUString sDocumentService = u"DocumentService"_ustr;
@@ -812,6 +813,14 @@ void TransformParameters( sal_uInt16 nSlotId, const 
uno::Sequence<beans::Propert
                 if (bOK)
                     rSet.Put( SfxStringItem( SID_SUGGESTEDSAVEASNAME, sVal ) );
             }
+            else if ( aName == sExportDirectory )
+            {
+                OUString sVal;
+                bool bOK = ((rProp.Value >>= sVal) && !sVal.isEmpty());
+                DBG_ASSERT( bOK, "invalid type or value for ExportDirectoy" );
+                if (bOK)
+                    rSet.Put( SfxStringItem( SID_EXPORTDIRECTORY, sVal ) );
+            }
             else if (aName == sDocumentService)
             {
                 OUString aVal;
@@ -1088,6 +1097,8 @@ void TransformItems( sal_uInt16 nSlotId, const 
SfxItemSet& rSet, uno::Sequence<b
                 nAdditional++;
             if ( rSet.GetItemState( SID_SUGGESTEDSAVEASNAME ) == 
SfxItemState::SET )
                 nAdditional++;
+            if ( rSet.GetItemState( SID_EXPORTDIRECTORY ) == SfxItemState::SET 
)
+                nAdditional++;
             if ( rSet.GetItemState( SID_DOC_SERVICE ) == SfxItemState::SET )
                 nAdditional++;
             if (rSet.HasItem(SID_FILTER_PROVIDER))
@@ -1262,6 +1273,8 @@ void TransformItems( sal_uInt16 nSlotId, const 
SfxItemSet& rSet, uno::Sequence<b
                         continue;
                     if ( nId == SID_SUGGESTEDSAVEASNAME )
                         continue;
+                    if ( nId == SID_EXPORTDIRECTORY )
+                        continue;
                     if ( nId == SID_LOCK_CONTENT_EXTRACTION )
                         continue;
                     if ( nId == SID_LOCK_EXPORT )
@@ -1650,6 +1663,11 @@ void TransformItems( sal_uInt16 nSlotId, const 
SfxItemSet& rSet, uno::Sequence<b
             pValue[nActProp].Name = sSuggestedSaveAsName;
             pValue[nActProp++].Value <<= pItem->GetValue();
         }
+        if ( const SfxStringItem *pItem = rSet.GetItemIfSet( 
SID_EXPORTDIRECTORY, false) )
+        {
+            pValue[nActProp].Name = sExportDirectory;
+            pValue[nActProp++].Value <<= pItem->GetValue();
+        }
         if ( const SfxStringItem *pItem = rSet.GetItemIfSet( SID_DOC_SERVICE, 
false) )
         {
             pValue[nActProp].Name = sDocumentService;
diff --git a/sfx2/source/dialog/filedlghelper.cxx 
b/sfx2/source/dialog/filedlghelper.cxx
index 37301d4a7fae..aaa693aab7e1 100644
--- a/sfx2/source/dialog/filedlghelper.cxx
+++ b/sfx2/source/dialog/filedlghelper.cxx
@@ -900,7 +900,8 @@ FileDialogHelper_Impl::FileDialogHelper_Impl(
     const OUString& sStandardDir,
     const css::uno::Sequence< OUString >& rDenyList
     )
-    :maPreviewIdle("sfx2 FileDialogHelper_Impl maPreviewIdle")
+    :msStandardDir         ( sStandardDir )
+    ,maPreviewIdle("sfx2 FileDialogHelper_Impl maPreviewIdle")
     ,m_nDialogType          ( nDialogType )
     ,meContext              ( FileDialogHelper::UnknownContext )
 {
@@ -2150,16 +2151,11 @@ void FileDialogHelper_Impl::saveConfig()
             aDlgOpt.SetUserItem( USERITEM_NAME, Any( aUserData ) );
     }
 
-    // Store to config, if explicit context is set. Otherwise store in 
(global) runtime var.
-    if (meContext != FileDialogHelper::UnknownContext)
+    // Store to config, if explicit context is set (and default directory is 
not given)
+    if (meContext != FileDialogHelper::UnknownContext && 
msStandardDir.isEmpty())
     {
         SaveLastDirectory(FileDialogHelper::contextToString(meContext), 
getPath());
     }
-    else
-    {
-        SfxApplication *pSfxApp = SfxGetpApp();
-        pSfxApp->SetLastDir_Impl( getPath() );
-    }
 }
 
 OUString FileDialogHelper_Impl::getInitPath(std::u16string_view _rFallback,
@@ -2167,7 +2163,12 @@ OUString 
FileDialogHelper_Impl::getInitPath(std::u16string_view _rFallback,
 {
     OUString sPath;
     // Load from config, if explicit context is set. Otherwise load from 
(global) runtime var.
-    if (meContext != FileDialogHelper::UnknownContext)
+    if (meContext == FileDialogHelper::UnknownContext || 
!msStandardDir.isEmpty())
+    {
+        // For export, the default directory is passed on
+        sPath = msStandardDir;
+    }
+    else
     {
         OUString sContext = FileDialogHelper::contextToString(meContext);
         Reference<XNameAccess> 
set(officecfg::Office::Common::Misc::FilePickerLastDirectory::get());
@@ -2182,11 +2183,6 @@ OUString 
FileDialogHelper_Impl::getInitPath(std::u16string_view _rFallback,
         {
         }
     }
-    else
-    {
-        SfxApplication *pSfxApp = SfxGetpApp();
-        sPath = pSfxApp->GetLastDir_Impl();
-    }
 
     if ( sPath.isEmpty() )
         sPath = o3tl::getToken(_rFallback, _nFallbackToken, ' ' );
diff --git a/sfx2/source/dialog/filedlgimpl.hxx 
b/sfx2/source/dialog/filedlgimpl.hxx
index 07f1906ba3e8..259fc8f0ec73 100644
--- a/sfx2/source/dialog/filedlgimpl.hxx
+++ b/sfx2/source/dialog/filedlgimpl.hxx
@@ -61,6 +61,7 @@ namespace sfx2
         OUString             maCurFilter;
         OUString             maSelectFilter;
         OUString             maButtonLabel;
+        OUString             msStandardDir;
 
         Idle                        maPreviewIdle;
         Graphic                     maGraphic;
diff --git a/sfx2/source/doc/guisaveas.cxx b/sfx2/source/doc/guisaveas.cxx
index 9e06dca31dce..2d557889fdc2 100644
--- a/sfx2/source/doc/guisaveas.cxx
+++ b/sfx2/source/doc/guisaveas.cxx
@@ -55,6 +55,7 @@
 #include <svl/eitem.hxx>
 #include <tools/debug.hxx>
 #include <comphelper/diagnose_ex.hxx>
+#include <comphelper/namedvaluecollection.hxx>
 #include <tools/urlobj.hxx>
 #include <tools/json_writer.hxx>
 #include <tools/urlobj.hxx>
@@ -210,7 +211,7 @@ class DocumentSettingsGuard
 
     bool m_bRestoreSettings;
 public:
-    DocumentSettingsGuard( const uno::Reference< frame::XModel >& xModel, bool 
bReadOnly, bool bRestore )
+    DocumentSettingsGuard( const uno::Reference< frame::XModel2 >& xModel, 
bool bReadOnly, bool bRestore )
     : m_bPreserveReadOnly( false )
     , m_bReadOnlySupported( false )
     , m_bRestoreSettings( bRestore )
@@ -262,7 +263,7 @@ public:
 class ModelData_Impl
 {
     SfxStoringHelper* m_pOwner;
-    uno::Reference< frame::XModel > m_xModel;
+    uno::Reference< frame::XModel2 > m_xModel;
     uno::Reference< frame::XStorable > m_xStorable;
     uno::Reference< frame::XStorable2 > m_xStorable2;
 
@@ -281,14 +282,14 @@ class ModelData_Impl
 
 public:
     ModelData_Impl( SfxStoringHelper& aOwner,
-                    uno::Reference< frame::XModel > xModel,
+                    uno::Reference< frame::XModel2 > xModel,
                     const uno::Sequence< beans::PropertyValue >& aMediaDescr );
 
     ~ModelData_Impl();
 
     void FreeDocumentProps();
 
-    uno::Reference< frame::XModel > const & GetModel() const;
+    uno::Reference< frame::XModel2 > const & GetModel() const;
     uno::Reference< frame::XStorable > const & GetStorable();
     uno::Reference< frame::XStorable2 > const & GetStorable2();
 
@@ -326,7 +327,7 @@ public:
                                 bool bPreselectPassword,
                                 OUString& aSuggestedDir,
                                 sal_Int16 nDialog,
-                                const OUString& rStandardDir,
+                                OUString& rStandardDir,
                                 const css::uno::Sequence< OUString >& rDenyList
                                 );
 
@@ -340,7 +341,7 @@ public:
 
 
 ModelData_Impl::ModelData_Impl( SfxStoringHelper& aOwner,
-                                uno::Reference< frame::XModel > xModel,
+                                uno::Reference< frame::XModel2 > xModel,
                                 const uno::Sequence< beans::PropertyValue >& 
aMediaDescr )
 : m_pOwner( &aOwner )
 , m_xModel(std::move( xModel ))
@@ -367,7 +368,7 @@ void ModelData_Impl::FreeDocumentProps()
 }
 
 
-uno::Reference< frame::XModel > const & ModelData_Impl::GetModel() const
+uno::Reference< frame::XModel2 > const & ModelData_Impl::GetModel() const
 {
     if ( !m_xModel.is() )
         throw uno::RuntimeException();
@@ -375,7 +376,6 @@ uno::Reference< frame::XModel > const & 
ModelData_Impl::GetModel() const
     return m_xModel;
 }
 
-
 uno::Reference< frame::XStorable > const & ModelData_Impl::GetStorable()
 {
     if ( !m_xStorable.is() )
@@ -877,7 +877,7 @@ bool ModelData_Impl::OutputFileDialog( sal_Int16 nStoreMode,
                                             bool bPreselectPassword,
                                             OUString& aSuggestedDir,
                                             sal_Int16 nDialog,
-                                            const OUString& rStandardDir,
+                                            OUString& rStandardDir,
                                             const css::uno::Sequence< OUString 
>& rDenyList)
 {
     if ( nStoreMode == SAVEASREMOTE_REQUESTED )
@@ -938,6 +938,13 @@ bool ModelData_Impl::OutputFileDialog( sal_Int16 
nStoreMode,
     weld::Window* pFrameWin = SfxStoringHelper::GetModelWindow(m_xModel);
     if ( ( nStoreMode & EXPORT_REQUESTED ) && !( nStoreMode & 
WIDEEXPORT_REQUESTED ) )
     {
+        const OUString aBaseUrl = 
GetDocProps().getUnpackedValueOrDefault("DocumentBaseURL", OUString());
+        OUString aExportDir = 
GetDocProps().getUnpackedValueOrDefault("ExportDirectory", aBaseUrl);
+        INetURLObject aObj( aExportDir );
+        aObj.removeSegment();
+        aExportDir = aObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+        if (!aExportDir.isEmpty())
+            rStandardDir = aExportDir;
         if ( ( nStoreMode & PDFEXPORT_REQUESTED ) && 
!aPreselectedFilterPropsHM.empty() )
         {
             // this is a PDF export
@@ -968,7 +975,6 @@ bool ModelData_Impl::OutputFileDialog( sal_Int16 nStoreMode,
             eCtxt = sfx2::FileDialogHelper::WriterExport;
         else if ( aDocServiceName == "com.sun.star.sheet.SpreadsheetDocument" )
             eCtxt = sfx2::FileDialogHelper::CalcExport;
-
         if ( eCtxt != sfx2::FileDialogHelper::UnknownContext )
                pFileDlg->SetContext( eCtxt );
 
@@ -1190,6 +1196,16 @@ bool ModelData_Impl::OutputFileDialog( sal_Int16 
nStoreMode,
     GetMediaDescr()[OUString("URL")] <<= aURL.GetMainURL( 
INetURLObject::DecodeMechanism::NONE );
     GetMediaDescr()[sFilterNameString] <<= aFilterName;
 
+    // for Export - keep a runtime var for each document where the document 
was last exported to
+    if (GetStorable()->hasLocation() && (nStoreMode & EXPORT_REQUESTED))
+    {
+        uno::Sequence< beans::PropertyValue > descriptor{
+            beans::PropertyValue(u"ExportDirectory"_ustr,
+                -1, uno::Any(aURL.GetMainURL( 
INetURLObject::DecodeMechanism::NONE )), beans::PropertyState_DIRECT_VALUE),
+        };
+        GetModel()->setArgs(descriptor);
+    }
+
     return bUseFilterOptions;
 }
 
@@ -1399,7 +1415,7 @@ uno::Reference< css::frame::XModuleManager2 > const & 
SfxStoringHelper::GetModul
     return m_xModuleManager;
 }
 
-bool SfxStoringHelper::GUIStoreModel( const uno::Reference< frame::XModel >& 
xModel,
+bool SfxStoringHelper::GUIStoreModel( const uno::Reference< frame::XModel2 >& 
xModel,
                                             std::u16string_view aSlotName,
                                             uno::Sequence< 
beans::PropertyValue >& aArgsSequence,
                                             bool bPreselectPassword,
@@ -1885,7 +1901,7 @@ bool SfxStoringHelper::CheckFilterOptionsAppearance(
 
 // static
 void SfxStoringHelper::SetDocInfoState(
-        const uno::Reference< frame::XModel >& xModel,
+        const uno::Reference< frame::XModel2 >& xModel,
         const uno::Reference< document::XDocumentProperties>& i_xOldDocProps )
 {
     uno::Reference<document::XDocumentPropertiesSupplier> const
@@ -1960,7 +1976,7 @@ void SfxStoringHelper::SetDocInfoState(
 
 
 // static
-bool SfxStoringHelper::WarnUnacceptableFormat( const uno::Reference< 
frame::XModel >& xModel,
+bool SfxStoringHelper::WarnUnacceptableFormat( const uno::Reference< 
frame::XModel2 >& xModel,
                                                     std::u16string_view 
aOldUIName,
                                                     const OUString& 
aDefExtension,
                                                     bool bDefIsAlien )
@@ -1974,7 +1990,7 @@ bool SfxStoringHelper::WarnUnacceptableFormat( const 
uno::Reference< frame::XMod
     return aDlg.run() == RET_OK;
 }
 
-uno::Reference<awt::XWindow> SfxStoringHelper::GetModelXWindow(const 
uno::Reference<frame::XModel>& xModel)
+uno::Reference<awt::XWindow> SfxStoringHelper::GetModelXWindow(const 
uno::Reference<frame::XModel2>& xModel)
 {
     try {
         if ( xModel.is() )
@@ -1997,7 +2013,7 @@ uno::Reference<awt::XWindow> 
SfxStoringHelper::GetModelXWindow(const uno::Refere
     return uno::Reference<awt::XWindow>();
 }
 
-weld::Window* SfxStoringHelper::GetModelWindow( const uno::Reference< 
frame::XModel >& xModel )
+weld::Window* SfxStoringHelper::GetModelWindow( const uno::Reference< 
frame::XModel2 >& xModel )
 {
     weld::Window* pWin = nullptr;
 
diff --git a/sfx2/source/doc/sfxbasemodel.cxx b/sfx2/source/doc/sfxbasemodel.cxx
index 062c594f2c4f..8e7499e4f1dd 100644
--- a/sfx2/source/doc/sfxbasemodel.cxx
+++ b/sfx2/source/doc/sfxbasemodel.cxx
@@ -1137,6 +1137,14 @@ void SAL_CALL SfxBaseModel::setArgs(const 
Sequence<beans::PropertyValue>& aArgs)
                 ok = true;
             }
         }
+        else if (rArg.Name == "ExportDirectory")
+        {
+            if (rArg.Value >>= sValue)
+            {
+                pMedium->GetItemSet().Put(SfxStringItem(SID_EXPORTDIRECTORY, 
sValue));
+                ok = true;
+            }
+        }
         else if (rArg.Name == "LockContentExtraction")
         {
             if (rArg.Value >>= bValue)
diff --git a/sfx2/source/inc/appdata.hxx b/sfx2/source/inc/appdata.hxx
index 6362d05d093d..d23f2d5a720d 100644
--- a/sfx2/source/inc/appdata.hxx
+++ b/sfx2/source/inc/appdata.hxx
@@ -61,7 +61,6 @@ class SfxAppData_Impl
 {
 public:
     IndexBitSet                         aIndexBitSet;           // for 
counting noname documents
-    OUString                            aLastDir;               // for IO 
dialog
 
     // DDE stuff
     std::unique_ptr<DdeService>              pDdeService;
diff --git a/sfx2/source/view/ipclient.cxx b/sfx2/source/view/ipclient.cxx
index e6b9beb364ba..9ed57f1616d7 100644
--- a/sfx2/source/view/ipclient.cxx
+++ b/sfx2/source/view/ipclient.cxx
@@ -906,7 +906,7 @@ ErrCodeMsg SfxInPlaceClient::DoVerb(sal_Int32 nVerb)
         {
             svt::EmbeddedObjectRef::TryRunningState( m_xImp->m_xObject );
             // TODO/LATER: this special verb should disappear when outplace 
activation is completely available
-            uno::Reference< frame::XModel > xEmbModel( 
m_xImp->m_xObject->getComponent(), uno::UNO_QUERY );
+            uno::Reference< frame::XModel2 > xEmbModel( 
m_xImp->m_xObject->getComponent(), uno::UNO_QUERY );
             if ( xEmbModel.is() )
             {
                 bSaveCopyAs = true;

Reply via email to