tdf#126665 Remember last used file picker directory

This introduces internal tracking of last used directories.
Each caller of the file picker can pass a "context". The selected
directory will then be saved & restored when opening the file picker
with the same context again.

After ffa636ba74b04b3258ec9a696bc4eac33581fa24 , the Windows file picker
no longer tracks the last used directory itself.
This is a replacement and an improvement at the same time, since there is not
one global last used directory, but one per context.

Change-Id: I10650cfb9359922690954fa65c89b4e47477e2c5
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/118597
Tested-by: Jenkins
Reviewed-by: Heiko Tietze <heiko.tietze@documentfoundation.org>
Reviewed-by: Samuel Mehrbrodt <samuel.mehrbrodt@allotropia.de>
diff --git a/avmedia/source/viewer/mediawindow.cxx b/avmedia/source/viewer/mediawindow.cxx
index 0807de0..4ff32f6 100644
--- a/avmedia/source/viewer/mediawindow.cxx
+++ b/avmedia/source/viewer/mediawindow.cxx
@@ -215,6 +215,7 @@ bool MediaWindow::executeMediaURLDialog(weld::Window* pParent, OUString& rURL, b
    static const char               aSeparator[] = ";";
    OUStringBuffer                  aAllTypes;

    aDlg.SetContext(sfx2::FileDialogHelper::InsertMedia);
    aDlg.SetTitle( AvmResId( o_pbLink != nullptr
                ? AVMEDIA_STR_INSERTMEDIA_DLG : AVMEDIA_STR_OPENMEDIA_DLG ) );

diff --git a/basctl/source/basicide/moduldl2.cxx b/basctl/source/basicide/moduldl2.cxx
index 44796f0..17e937e 100644
--- a/basctl/source/basicide/moduldl2.cxx
+++ b/basctl/source/basicide/moduldl2.cxx
@@ -549,6 +549,7 @@ void LibPage::InsertLib()
    Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
    // file open dialog
    sfx2::FileDialogHelper aDlg(ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE, FileDialogFlags::NONE, m_pDialog->getDialog());
    aDlg.SetContext(sfx2::FileDialogHelper::BasicInsertLib);
    const Reference <XFilePicker3>& xFP = aDlg.GetFilePicker();

    xFP->setTitle(IDEResId(RID_STR_APPENDLIBS));
@@ -568,16 +569,6 @@ void LibPage::InsertLib()
              ";*.sti;*.otp"             // presentation template
              ";*.sxm;*.odf" );          // formula

    // set display directory and filter
    OUString aPath(GetExtraData()->GetAddLibPath());
    if ( !aPath.isEmpty() )
        xFP->setDisplayDirectory( aPath );
    else
    {
        // macro path from configuration management
        xFP->setDisplayDirectory( SvtPathOptions().GetWorkPath() );
    }

    OUString aLastFilter(GetExtraData()->GetAddLibFilter());
    if ( !aLastFilter.isEmpty() )
        xFP->setCurrentFilter( aLastFilter );
@@ -1005,6 +996,7 @@ void LibPage::ExportAsPackage( const OUString& aLibName )
{
    // file open dialog
    sfx2::FileDialogHelper aDlg(ui::dialogs::TemplateDescription::FILESAVE_SIMPLE, FileDialogFlags::NONE, m_pDialog->getDialog());
    aDlg.SetContext(sfx2::FileDialogHelper::BasicExportPackage);
    const Reference <XFilePicker3>& xFP = aDlg.GetFilePicker();

    Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
@@ -1017,17 +1009,6 @@ void LibPage::ExportAsPackage( const OUString& aLibName )
    OUString aTitle(IDEResId(RID_STR_PACKAGE_BUNDLE));
    xFP->appendFilter( aTitle, "*.oxt" ); // library files

    // set display directory and filter
    OUString aPath = GetExtraData()->GetAddLibPath();
    if ( !aPath.isEmpty() )
    {
        xFP->setDisplayDirectory( aPath );
    }
    else
    {
        // macro path from configuration management
        xFP->setDisplayDirectory( SvtPathOptions().GetWorkPath() );
    }
    xFP->setCurrentFilter( aTitle );

    if ( xFP->execute() != RET_OK )
diff --git a/cui/source/customize/acccfg.cxx b/cui/source/customize/acccfg.cxx
index 7a7965c..d850da8 100644
--- a/cui/source/customize/acccfg.cxx
+++ b/cui/source/customize/acccfg.cxx
@@ -1463,6 +1463,7 @@ void SfxAcceleratorConfigPage::StartFileDialog(StartFileDialogType nType, const 
    m_pFileDlg->AddFilter(aFilterAllStr, FILEDIALOG_FILTER_ALL);
    m_pFileDlg->AddFilter(aFilterCfgStr, "*.cfg");
    m_pFileDlg->SetCurrentFilter(aFilterCfgStr);
    m_pFileDlg->SetContext(sfx2::FileDialogHelper::AcceleratorConfig);

    Link<sfx2::FileDialogHelper*, void> aDlgClosedLink
        = bSave ? LINK(this, SfxAcceleratorConfigPage, SaveHdl)
diff --git a/cui/source/customize/cfg.cxx b/cui/source/customize/cfg.cxx
index 25f9730..57f6a46 100644
--- a/cui/source/customize/cfg.cxx
+++ b/cui/source/customize/cfg.cxx
@@ -2874,6 +2874,7 @@ IMPL_LINK_NOARG(SvxIconSelectorDialog, ImportHdl, weld::Button&, void)
    sfx2::FileDialogHelper aImportDialog(
        css::ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW,
        FileDialogFlags::Graphic | FileDialogFlags::MultiSelection, m_xDialog.get());
    aImportDialog.SetContext(sfx2::FileDialogHelper::IconImport);

    // disable the link checkbox in the dialog
    uno::Reference< css::ui::dialogs::XFilePickerControlAccess >
diff --git a/cui/source/dialogs/SignSignatureLineDialog.cxx b/cui/source/dialogs/SignSignatureLineDialog.cxx
index 286f115..7af20b3 100644
--- a/cui/source/dialogs/SignSignatureLineDialog.cxx
+++ b/cui/source/dialogs/SignSignatureLineDialog.cxx
@@ -124,6 +124,7 @@ IMPL_LINK_NOARG(SignSignatureLineDialog, loadImage, weld::Button&, void)
    Reference<XComponentContext> xContext = comphelper::getProcessComponentContext();
    sfx2::FileDialogHelper aHelper(TemplateDescription::FILEOPEN_PREVIEW, FileDialogFlags::NONE,
                                   m_xDialog.get());
    aHelper.SetContext(sfx2::FileDialogHelper::SignatureLine);
    Reference<XFilePicker3> xFilePicker = aHelper.GetFilePicker();
    if (!xFilePicker->execute())
        return;
diff --git a/cui/source/dialogs/insdlg.cxx b/cui/source/dialogs/insdlg.cxx
index 29c8d7c..7e411d3 100644
--- a/cui/source/dialogs/insdlg.cxx
+++ b/cui/source/dialogs/insdlg.cxx
@@ -85,6 +85,7 @@ IMPL_LINK_NOARG(SvInsertOleDlg, DoubleClickHdl, weld::TreeView&, bool)
IMPL_LINK_NOARG(SvInsertOleDlg, BrowseHdl, weld::Button&, void)
{
    sfx2::FileDialogHelper aHelper(ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE, FileDialogFlags::NONE, m_xDialog.get());
    aHelper.SetContext(sfx2::FileDialogHelper::InsertOLE);
    const Reference< XFilePicker3 >& xFilePicker = aHelper.GetFilePicker();

    // add filter
diff --git a/cui/source/dialogs/screenshotannotationdlg.cxx b/cui/source/dialogs/screenshotannotationdlg.cxx
index 4f02452..4a93d7b 100644
--- a/cui/source/dialogs/screenshotannotationdlg.cxx
+++ b/cui/source/dialogs/screenshotannotationdlg.cxx
@@ -282,6 +282,7 @@ IMPL_LINK_NOARG(ScreenshotAnnotationDlg_Impl, saveButtonHandler, weld::Button&, 

    auto xFileDlg = std::make_unique<sfx2::FileDialogHelper>(ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION,
                                                             FileDialogFlags::NONE, mpParentWindow);
    xFileDlg->SetContext(sfx2::FileDialogHelper::ScreenshotAnnotation);

    const uno::Reference< ui::dialogs::XFilePicker3 > xFilePicker = xFileDlg->GetFilePicker();

diff --git a/cui/source/options/optjava.cxx b/cui/source/options/optjava.cxx
index a21c5b2..85cd529 100644
--- a/cui/source/options/optjava.cxx
+++ b/cui/source/options/optjava.cxx
@@ -780,15 +780,15 @@ IMPL_LINK_NOARG(SvxJavaClassPathDlg, AddArchiveHdl_Impl, weld::Button&, void)
    sfx2::FileDialogHelper aDlg(TemplateDescription::FILEOPEN_SIMPLE, FileDialogFlags::NONE, m_xDialog.get());
    aDlg.SetTitle( CuiResId( RID_SVXSTR_ARCHIVE_TITLE ) );
    aDlg.AddFilter( CuiResId( RID_SVXSTR_ARCHIVE_HEADLINE ), "*.jar;*.zip" );
    aDlg.SetContext(sfx2::FileDialogHelper::JavaClassPath);
    OUString sFolder;
    if (m_xPathList->count_selected_rows() > 0)
    {
        osl::FileBase::getFileURLFromSystemPath(m_xPathList->get_selected_text(), sFolder);
            // best effort
    }
    if (sFolder.isEmpty())
         sFolder = SvtPathOptions().GetWorkPath();
    aDlg.SetDisplayDirectory( sFolder );
    if (!sFolder.isEmpty())
        aDlg.SetDisplayDirectory( sFolder );
    if ( aDlg.Execute() == ERRCODE_NONE )
    {
        OUString sURL = aDlg.GetPath();
diff --git a/cui/source/tabpages/numpages.cxx b/cui/source/tabpages/numpages.cxx
index 47542d1..8db9b0e 100644
--- a/cui/source/tabpages/numpages.cxx
+++ b/cui/source/tabpages/numpages.cxx
@@ -910,6 +910,7 @@ IMPL_LINK_NOARG(SvxBitmapPickTabPage, DoubleClickHdl_Impl, ValueSet*, void)
IMPL_LINK_NOARG(SvxBitmapPickTabPage, ClickAddBrowseHdl_Impl, weld::Button&, void)
{
    sfx2::FileDialogHelper aFileDialog(0, FileDialogFlags::NONE, GetFrameWeld());
    aFileDialog.SetContext(sfx2::FileDialogHelper::BulletsAddImage);
    aFileDialog.SetTitle(CuiResId(RID_SVXSTR_ADD_IMAGE));
    if ( aFileDialog.Execute() != ERRCODE_NONE )
        return;
diff --git a/dbaccess/source/ui/app/AppController.cxx b/dbaccess/source/ui/app/AppController.cxx
index d2fd90d..b704fdc 100644
--- a/dbaccess/source/ui/app/AppController.cxx
+++ b/dbaccess/source/ui/app/AppController.cxx
@@ -1078,13 +1078,13 @@ void OApplicationController::Execute(sal_uInt16 _nId, const Sequence< PropertyVa
                    OUString sUrl;
                    if ( m_xModel.is() )
                        sUrl = m_xModel->getURL();
                    if ( sUrl.isEmpty() )
                        sUrl = SvtPathOptions().GetWorkPath();

                    ::sfx2::FileDialogHelper aFileDlg(
                        ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION,
                        FileDialogFlags::NONE, getFrameWeld());
                    aFileDlg.SetDisplayDirectory( sUrl );
                    aFileDlg.SetContext(sfx2::FileDialogHelper::BaseSaveAs);
                    if (!sUrl.isEmpty())
                        aFileDlg.SetDisplayDirectory( sUrl );

                    std::shared_ptr<const SfxFilter> pFilter = getStandardDatabaseFilter();
                    if ( pFilter )
diff --git a/dbaccess/source/ui/dlg/dbwizsetup.cxx b/dbaccess/source/ui/dlg/dbwizsetup.cxx
index 1d9f89c..7707408f 100644
--- a/dbaccess/source/ui/dlg/dbwizsetup.cxx
+++ b/dbaccess/source/ui/dlg/dbwizsetup.cxx
@@ -772,15 +772,14 @@ bool ODbTypeWizDialogSetup::SaveDatabaseDocument()
        ::sfx2::FileDialogHelper aFileDlg(
                ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION,
                FileDialogFlags::NONE, m_xAssistant.get());
        aFileDlg.SetContext(sfx2::FileDialogHelper::BaseSaveAs);
        std::shared_ptr<const SfxFilter> pFilter = getStandardDatabaseFilter();
        if ( pFilter )
        {
            INetURLObject aWorkURL( m_sWorkPath );
            aFileDlg.SetDisplayFolder( aWorkURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ));

            OUString sDefaultName = DBA_RES( STR_DATABASEDEFAULTNAME );
            OUString sExtension = pFilter->GetDefaultExtension();
            sDefaultName += sExtension.replaceAt( 0, 1, OUString() );
            INetURLObject aWorkURL( m_sWorkPath );
            aWorkURL.Append( sDefaultName );
            sDefaultName = createUniqueFileName( aWorkURL );
            aFileDlg.SetFileName( sDefaultName );
diff --git a/dbaccess/source/ui/dlg/generalpage.cxx b/dbaccess/source/ui/dlg/generalpage.cxx
index da41b89..27eb77d 100644
--- a/dbaccess/source/ui/dlg/generalpage.cxx
+++ b/dbaccess/source/ui/dlg/generalpage.cxx
@@ -664,6 +664,7 @@ namespace dbaui
        ::sfx2::FileDialogHelper aFileDlg(
                ui::dialogs::TemplateDescription::FILEOPEN_READONLY_VERSION,
                FileDialogFlags::NONE, "sdatabase", SfxFilterFlags::NONE, SfxFilterFlags::NONE, GetFrameWeld());
        aFileDlg.SetContext(sfx2::FileDialogHelper::BaseDataSource);
        std::shared_ptr<const SfxFilter> pFilter = getStandardDatabaseFilter();
        if ( pFilter )
        {
diff --git a/desktop/source/deployment/gui/dp_gui_dialog2.cxx b/desktop/source/deployment/gui/dp_gui_dialog2.cxx
index 8b3f5099..2941d42 100644
--- a/desktop/source/deployment/gui/dp_gui_dialog2.cxx
+++ b/desktop/source/deployment/gui/dp_gui_dialog2.cxx
@@ -613,12 +613,10 @@ bool ExtMgrDialog::acceptLicense( const uno::Reference< deployment::XPackage > &
uno::Sequence< OUString > ExtMgrDialog::raiseAddPicker()
{
    sfx2::FileDialogHelper aDlgHelper(ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE, FileDialogFlags::NONE, m_xDialog.get());
    aDlgHelper.SetContext(sfx2::FileDialogHelper::ExtensionManager);
    const uno::Reference<ui::dialogs::XFilePicker3>& xFilePicker = aDlgHelper.GetFilePicker();
    xFilePicker->setTitle( m_sAddPackages );

    if ( !m_sLastFolderURL.isEmpty() )
        xFilePicker->setDisplayDirectory( m_sLastFolderURL );

    // collect and set filter list:
    typedef std::map< OUString, OUString > t_string2string;
    t_string2string title2filter;
@@ -673,7 +671,6 @@ uno::Sequence< OUString > ExtMgrDialog::raiseAddPicker()
    if ( xFilePicker->execute() != ui::dialogs::ExecutableDialogResults::OK )
        return uno::Sequence<OUString>(); // cancelled

    m_sLastFolderURL = xFilePicker->getDisplayDirectory();
    uno::Sequence< OUString > files( xFilePicker->getSelectedFiles() );
    OSL_ASSERT( files.hasElements() );
    return files;
diff --git a/desktop/source/deployment/gui/dp_gui_dialog2.hxx b/desktop/source/deployment/gui/dp_gui_dialog2.hxx
index 70e7626..921b6f0 100644
--- a/desktop/source/deployment/gui/dp_gui_dialog2.hxx
+++ b/desktop/source/deployment/gui/dp_gui_dialog2.hxx
@@ -91,7 +91,6 @@ class ExtMgrDialog : public weld::GenericDialogController
{
    const OUString       m_sAddPackages;
    OUString             m_sProgressText;
    OUString             m_sLastFolderURL;
    ::osl::Mutex         m_aMutex;
    bool                 m_bHasProgress;
    bool                 m_bProgressChanged;
diff --git a/extensions/source/propctrlr/formcomponenthandler.cxx b/extensions/source/propctrlr/formcomponenthandler.cxx
index 5631014..3b02a1c 100644
--- a/extensions/source/propctrlr/formcomponenthandler.cxx
+++ b/extensions/source/propctrlr/formcomponenthandler.cxx
@@ -2749,7 +2749,7 @@ namespace pcr
        ::sfx2::FileDialogHelper aFileDlg(
                ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW,
                FileDialogFlags::Graphic, pWin);

        aFileDlg.SetContext(sfx2::FileDialogHelper::FormsInsertImage);
        aFileDlg.SetTitle(aStrTrans);
        // non-linked images ( e.g. those located in the document
        // stream ) only if document is available
diff --git a/filter/source/xsltdialog/xmlfiltersettingsdialog.cxx b/filter/source/xsltdialog/xmlfiltersettingsdialog.cxx
index aa12803..a31eba9 100644
--- a/filter/source/xsltdialog/xmlfiltersettingsdialog.cxx
+++ b/filter/source/xsltdialog/xmlfiltersettingsdialog.cxx
@@ -847,6 +847,7 @@ void XMLFilterSettingsDialog::onSave()
    ::sfx2::FileDialogHelper aDlg(
        css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION,
        FileDialogFlags::NONE, m_xDialog.get());
    aDlg.SetContext(sfx2::FileDialogHelper::XMLFilterSettings);

    OUString aExtensions( "*.jar" );
    OUString aFilterName = XsltResId(STR_FILTER_PACKAGE) +
@@ -892,6 +893,7 @@ void XMLFilterSettingsDialog::onOpen()
    ::sfx2::FileDialogHelper aDlg(
    css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE,
    FileDialogFlags::NONE, m_xDialog.get());
    aDlg.SetContext(sfx2::FileDialogHelper::XMLFilterSettings);

    OUString aExtensions( "*.jar" );
    OUString aFilterName = XsltResId(STR_FILTER_PACKAGE) +
diff --git a/forms/source/component/ImageControl.cxx b/forms/source/component/ImageControl.cxx
index 857c25a..f072f59 100644
--- a/forms/source/component/ImageControl.cxx
+++ b/forms/source/component/ImageControl.cxx
@@ -774,6 +774,7 @@ bool OImageControlControl::implInsertGraphics()
        Reference< XWindow > xWindow( static_cast< ::cppu::OWeakObject* >( this ), UNO_QUERY );
        ::sfx2::FileDialogHelper aDialog(TemplateDescription::FILEOPEN_LINK_PREVIEW, FileDialogFlags::Graphic,
                                         Application::GetFrameWeld(xWindow));
        aDialog.SetContext(sfx2::FileDialogHelper::FormsInsertImage);
        aDialog.SetTitle( sTitle );

        Reference< XFilePickerControlAccess > xController( aDialog.GetFilePicker(), UNO_QUERY_THROW );
diff --git a/include/sfx2/filedlghelper.hxx b/include/sfx2/filedlghelper.hxx
index 4985b7b..2c85c6b 100644
--- a/include/sfx2/filedlghelper.hxx
+++ b/include/sfx2/filedlghelper.hxx
@@ -77,14 +77,64 @@ class FileDialogHelper_Impl;
class SFX2_DLLPUBLIC FileDialogHelper
{
public:
    enum Context                        // context where the FileDialogHelper is used
    // context where the FileDialogHelper is used
    enum Context
    {
        UNKNOWN_CONTEXT,                // unknown context
        SW_INSERT_GRAPHIC,              // insert graphic in writer
        SD_EXPORT,                      // export in draw
        SI_EXPORT,                      // export in impress
        SW_EXPORT                       // export in writer
        UnknownContext,
        AcceleratorConfig,
        AutoRedact,
        BaseDataSource,
        BaseSaveAs,
        BasicExportPackage,
        BasicInsertLib,
        BulletsAddImage,
        ExtensionManager,
        CalcDataProvider,
        CalcDataStream,
        CalcExport,
        CalcSaveAs,
        CalcXMLSource,
        DrawExport,
        DrawImpressInsertFile,
        DrawImpressOpenSound,
        DrawSaveAs,
        ExportImage,
        FormsAddInstance,
        FormsInsertImage,
        IconImport,
        ImpressClickAction,
        ImpressExport,
        ImpressPhotoDialog,
        ImpressSaveAs,
        LinkClientOLE,
        LinkClientFile,
        ImageMap,
        InsertDoc,
        InsertImage,
        InsertMedia,
        InsertOLE,
        JavaClassPath,
        ReportInsertImage,
        ScreenshotAnnotation,
        SignatureLine,
        TemplateImport,
        WriterCreateAddressList,
        WriterInsertDoc,
        WriterInsertImage,
        WriterInsertScript,
        WriterExport,
        WriterImportAutotext,
        WriterInsertHyperlink,
        WriterLoadTemplate,
        WriterMailMerge,
        WriterMailMergeSaveAs,
        WriterNewHTMLGlobalDoc,
        WriterRegisterDataSource,
        WriterSaveAs,
        WriterSaveHTML,
        XMLFilterSettings
    };
    static OUString contextToString(Context context);

private:
    Link<FileDialogHelper*,void>  m_aDialogClosedLink;
@@ -216,6 +266,8 @@ public:
    void                    CreateMatcher( const OUString& rName );

    /** sets the context of the dialog and trigger necessary actions e.g. loading config, setting help id
        This will also store the last used directory for this context, so that the last directory
        gets preselected on next filepicker launch (with the same context)
        @param _eNewContext
            New context for the dialog.
    */
diff --git a/officecfg/registry/data/org/openoffice/Office/Impress.xcu b/officecfg/registry/data/org/openoffice/Office/Impress.xcu
index b832397..112a89e 100644
--- a/officecfg/registry/data/org/openoffice/Office/Impress.xcu
+++ b/officecfg/registry/data/org/openoffice/Office/Impress.xcu
@@ -200,9 +200,4 @@
      <value>$(work)</value>
    </prop>
  </node>
  <node oor:name="Sound" oor:op="fuse">
    <prop oor:name="Path">
      <value>$(work)</value>
    </prop>
  </node>
</oor:component-data>
diff --git a/officecfg/registry/schema/org/openoffice/Office/Common.xcs b/officecfg/registry/schema/org/openoffice/Office/Common.xcs
index 56954ea..b5cc818 100644
--- a/officecfg/registry/schema/org/openoffice/Office/Common.xcs
+++ b/officecfg/registry/schema/org/openoffice/Office/Common.xcs
@@ -844,6 +844,16 @@
        <value/>
      </prop>
    </group>
    <group oor:name="LastDirectory">
      <info>
        <desc>Stores the last selected directory for the filepicker for different contexts.</desc>
      </info>
      <prop oor:name="LastPath" oor:type="xs:string" oor:nillable="false">
        <info>
          <desc>The last used path for this context (context is the name of the parent node)</desc>
        </info>
      </prop>
    </group>
  </templates>
  <component>
    <group oor:name="VCL">
@@ -5898,6 +5908,11 @@
          <desc>URL of the last used service in the remote file picker.</desc>
        </info>
      </prop>
      <set oor:name="FilePickerLastDirectory" oor:node-type="LastDirectory">
        <info>
          <desc>Contains the last used directory for the filepicker for various contexts</desc>
        </info>
      </set>
      <prop oor:name="CmisServersUrls" oor:type="oor:string-list" oor:nillable="false">
        <info>
          <desc>List of sample URLs of the CMIS servers in the place edition dialog.</desc>
diff --git a/officecfg/registry/schema/org/openoffice/Office/Impress.xcs b/officecfg/registry/schema/org/openoffice/Office/Impress.xcs
index d8edf33..83d43c3 100644
--- a/officecfg/registry/schema/org/openoffice/Office/Impress.xcs
+++ b/officecfg/registry/schema/org/openoffice/Office/Impress.xcs
@@ -1644,19 +1644,5 @@
        <value>$(work)</value>
      </prop>
    </group>
    <group oor:name="Sound">
      <info>
        <desc>Contains configuration items for Sound related functions.</desc>
      </info>
      <prop oor:name="Path" oor:type="xs:string" oor:nillable="false">
        <info>
          <desc>
            Access path, where sounds were loaded last time.
            The default is work directory.
          </desc>
        </info>
        <value>$(work)</value>
      </prop>
    </group>
  </component>
</oor:component-schema>
diff --git a/reportdesign/source/ui/report/ReportController.cxx b/reportdesign/source/ui/report/ReportController.cxx
index 762d1ba..e50c5e2 100644
--- a/reportdesign/source/ui/report/ReportController.cxx
+++ b/reportdesign/source/ui/report/ReportController.cxx
@@ -2997,6 +2997,7 @@ void OReportController::insertGraphic()
    {
        uno::Reference< report::XSection> xSection = getDesignView()->getCurrentSection();
        ::sfx2::FileDialogHelper aDialog(ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW, FileDialogFlags::Graphic, getFrameWeld());
        aDialog.SetContext(sfx2::FileDialogHelper::ReportInsertImage);
        aDialog.SetTitle( sTitle );

        uno::Reference< ui::dialogs::XFilePickerControlAccess > xController(aDialog.GetFilePicker(), UNO_QUERY_THROW);
diff --git a/sc/source/ui/miscdlgs/dataproviderdlg.cxx b/sc/source/ui/miscdlgs/dataproviderdlg.cxx
index 40186b6..8ad7dd2 100644
--- a/sc/source/ui/miscdlgs/dataproviderdlg.cxx
+++ b/sc/source/ui/miscdlgs/dataproviderdlg.cxx
@@ -785,6 +785,7 @@ IMPL_LINK_NOARG(ScDataProviderDlg, ApplyBtnHdl, weld::Button&, void)
IMPL_LINK_NOARG(ScDataProviderDlg, BrowseBtnHdl, weld::Button&, void)
{
    sfx2::FileDialogHelper aFileDialog(0, FileDialogFlags::NONE, m_xDialog.get());
    aFileDialog.SetContext(sfx2::FileDialogHelper::CalcDataProvider);
    if (aFileDialog.Execute() != ERRCODE_NONE)
        return;

diff --git a/sc/source/ui/miscdlgs/datastreamdlg.cxx b/sc/source/ui/miscdlgs/datastreamdlg.cxx
index a713b97..cd03a3e 100644
--- a/sc/source/ui/miscdlgs/datastreamdlg.cxx
+++ b/sc/source/ui/miscdlgs/datastreamdlg.cxx
@@ -51,6 +51,7 @@ DataStreamDlg::~DataStreamDlg() {}
IMPL_LINK_NOARG(DataStreamDlg, BrowseHdl, weld::Button&, void)
{
    sfx2::FileDialogHelper aFileDialog(0, FileDialogFlags::NONE, m_xDialog.get());
    aFileDialog.SetContext(sfx2::FileDialogHelper::CalcDataStream);
    if (aFileDialog.Execute() != ERRCODE_NONE)
        return;

diff --git a/sc/source/ui/xmlsource/xmlsourcedlg.cxx b/sc/source/ui/xmlsource/xmlsourcedlg.cxx
index edc8ca3..0bbfa9d 100644
--- a/sc/source/ui/xmlsource/xmlsourcedlg.cxx
+++ b/sc/source/ui/xmlsource/xmlsourcedlg.cxx
@@ -163,21 +163,16 @@ void ScXMLSourceDlg::SelectSourceFile()
{
    sfx2::FileDialogHelper aDlgHelper(ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE,
                                      FileDialogFlags::NONE, m_xDialog.get());
    aDlgHelper.SetContext(sfx2::FileDialogHelper::CalcXMLSource);

    uno::Reference<ui::dialogs::XFilePicker3> xFilePicker = aDlgHelper.GetFilePicker();

    if (maSrcPath.isEmpty())
        // Use default path.
        xFilePicker->setDisplayDirectory(SvtPathOptions().GetWorkPath());
    else
    {
        // Use the directory of current source file.
        INetURLObject aURL(maSrcPath);
        aURL.removeSegment();
        aURL.removeFinalSlash();
        OUString aPath = aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE);
        xFilePicker->setDisplayDirectory(aPath);
    }
    // Use the directory of current source file.
    INetURLObject aURL(maSrcPath);
    aURL.removeSegment();
    aURL.removeFinalSlash();
    OUString aPath = aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE);
    xFilePicker->setDisplayDirectory(aPath);

    if (xFilePicker->execute() != ui::dialogs::ExecutableDialogResults::OK)
        // File picker dialog cancelled.
diff --git a/sd/source/ui/dlg/PhotoAlbumDialog.cxx b/sd/source/ui/dlg/PhotoAlbumDialog.cxx
index 14e43dd..9c00afe 100644
--- a/sd/source/ui/dlg/PhotoAlbumDialog.cxx
+++ b/sd/source/ui/dlg/PhotoAlbumDialog.cxx
@@ -20,7 +20,6 @@

#include <unotools/pathoptions.hxx>
#include <unotools/ucbstreamhelper.hxx>
#include <officecfg/Office/Impress.hxx>
#include <vcl/graphicfilter.hxx>
#include <vcl/svapp.hxx>
#include <vcl/weld.hxx>
@@ -500,35 +499,16 @@ IMPL_LINK_NOARG(SdPhotoAlbumDialog, FileHdl, weld::Button&, void)
    ::sfx2::FileDialogHelper aDlg(
        css::ui::dialogs::TemplateDescription::FILEOPEN_PREVIEW,
        FileDialogFlags::Graphic | FileDialogFlags::MultiSelection, m_xDialog.get());
    // Read configuration
    OUString sUrl(officecfg::Office::Impress::Pictures::Path::get());

    INetURLObject aFile( SvtPathOptions().GetUserConfigPath() );
    if (!sUrl.isEmpty())
        aDlg.SetDisplayDirectory(sUrl);
    else
        aDlg.SetDisplayDirectory( aFile.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
    aDlg.SetContext(sfx2::FileDialogHelper::ImpressPhotoDialog);

    if ( aDlg.Execute() == ERRCODE_NONE )
    {
        const Sequence< OUString > aFilesArr = aDlg.GetSelectedFiles();
        if( aFilesArr.hasElements() )
        for ( const auto& rFile : aFilesArr )
        {
            sUrl = aDlg.GetDisplayDirectory();
            // Write out configuration
            {
                std::shared_ptr< comphelper::ConfigurationChanges > batch(
                    comphelper::ConfigurationChanges::create());
                officecfg::Office::Impress::Pictures::Path::set(sUrl, batch);
                batch->commit();
            }

            for ( const auto& rFile : aFilesArr )
            {
                // Store full path, show filename only. Use INetURLObject to display spaces in filename correctly
                INetURLObject aUrl(rFile);
                m_xImagesLst->append(aUrl.GetMainURL(INetURLObject::DecodeMechanism::NONE), aUrl.GetLastName(INetURLObject::DecodeMechanism::WithCharset), "");
            }
            // Store full path, show filename only. Use INetURLObject to display spaces in filename correctly
            INetURLObject aUrl(rFile);
            m_xImagesLst->append(aUrl.GetMainURL(INetURLObject::DecodeMechanism::NONE), aUrl.GetLastName(INetURLObject::DecodeMechanism::WithCharset), "");
        }
    }
    EnableDisableButtons();
diff --git a/sd/source/ui/dlg/filedlg.cxx b/sd/source/ui/dlg/filedlg.cxx
index 05c4243..a545f6d 100644
--- a/sd/source/ui/dlg/filedlg.cxx
+++ b/sd/source/ui/dlg/filedlg.cxx
@@ -34,7 +34,6 @@
#include <filedlg.hxx>
#include <sdresid.hxx>
#include <strings.hrc>
#include <officecfg/Office/Impress.hxx>

// -----------      SdFileDialog_Imp        ---------------------------

@@ -214,6 +213,7 @@ SdOpenSoundFileDialog::SdOpenSoundFileDialog(weld::Window *pParent)
{
    OUString aDescr = SdResId(STR_ALL_FILES);
    mpImpl->AddFilter( aDescr, "*.*");
    mpImpl->SetContext(sfx2::FileDialogHelper::DrawImpressOpenSound);

    // setup filter
#if defined UNX
@@ -233,9 +233,6 @@ SdOpenSoundFileDialog::SdOpenSoundFileDialog(weld::Window *pParent)
    aDescr = SdResId(STR_MIDI_FILE);
    mpImpl->AddFilter( aDescr, "*.mid" );
#endif

    // Restore last selected path
    mpImpl->SetDisplayDirectory(officecfg::Office::Impress::Sound::Path::get());
}

SdOpenSoundFileDialog::~SdOpenSoundFileDialog()
@@ -249,12 +246,6 @@ ErrCode SdOpenSoundFileDialog::Execute()

OUString SdOpenSoundFileDialog::GetPath() const
{
    // Save last selected path
    std::shared_ptr<comphelper::ConfigurationChanges> batch(
        comphelper::ConfigurationChanges::create());
    officecfg::Office::Impress::Sound::Path::set(mpImpl->GetPath(), batch);
    batch->commit();

    return mpImpl->GetPath();
}

diff --git a/sd/source/ui/dlg/tpaction.cxx b/sd/source/ui/dlg/tpaction.cxx
index 63fd24c..4cd0cf6 100644
--- a/sd/source/ui/dlg/tpaction.cxx
+++ b/sd/source/ui/dlg/tpaction.cxx
@@ -401,11 +401,7 @@ void SdTPAction::OpenFileDialog()
            sfx2::FileDialogHelper aFileDialog(
                ui::dialogs::TemplateDescription::FILEOPEN_READONLY_VERSION,
                FileDialogFlags::NONE, GetFrameWeld());

            if (bDocument && aFile.isEmpty())
                aFile = SvtPathOptions().GetWorkPath();

            aFileDialog.SetDisplayDirectory( aFile );
            aFileDialog.SetContext(sfx2::FileDialogHelper::ImpressClickAction);

            // The following is a workaround for #i4306#:
            // The addition of the implicitly existing "all files"
diff --git a/sd/source/ui/func/fuinsfil.cxx b/sd/source/ui/func/fuinsfil.cxx
index ff890df..aec950b 100644
--- a/sd/source/ui/func/fuinsfil.cxx
+++ b/sd/source/ui/func/fuinsfil.cxx
@@ -133,6 +133,7 @@ void FuInsertFile::DoExecute( SfxRequest& rReq )
        sfx2::FileDialogHelper      aFileDialog(
                ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE,
                FileDialogFlags::Insert, mpWindow ? mpWindow->GetFrameWeld() : nullptr);
        aFileDialog.SetContext(sfx2::FileDialogHelper::DrawImpressInsertFile);
        Reference< XFilePicker >    xFilePicker( aFileDialog.GetFilePicker() );
        Reference< XFilterManager > xFilterManager( xFilePicker, UNO_QUERY );
        OUString aOwnCont;
diff --git a/sfx2/source/appl/fileobj.cxx b/sfx2/source/appl/fileobj.cxx
index ebfe57e..f58ffe0 100644
--- a/sfx2/source/appl/fileobj.cxx
+++ b/sfx2/source/appl/fileobj.cxx
@@ -292,6 +292,7 @@ void SvFileObject::Edit(weld::Window* pParent, sfx2::SvBaseLink* pLink, const Li

            ::sfx2::FileDialogHelper & rFileDlg =
                pLink->GetInsertFileDialog( OUString() );
            rFileDlg.SetContext(sfx2::FileDialogHelper::LinkClientOLE);
            rFileDlg.StartExecuteModal(
                    LINK( this, SvFileObject, DialogClosedHdl ) );
        }
@@ -308,6 +309,7 @@ void SvFileObject::Edit(weld::Window* pParent, sfx2::SvBaseLink* pLink, const Li

            ::sfx2::FileDialogHelper & rFileDlg =
                pLink->GetInsertFileDialog(sFactory);
            rFileDlg.SetContext(sfx2::FileDialogHelper::LinkClientFile);
            rFileDlg.StartExecuteModal(
                    LINK( this, SvFileObject, DialogClosedHdl ) );
        }
diff --git a/sfx2/source/appl/opengrf.cxx b/sfx2/source/appl/opengrf.cxx
index fd54798..71e46fd 100644
--- a/sfx2/source/appl/opengrf.cxx
+++ b/sfx2/source/appl/opengrf.cxx
@@ -91,6 +91,7 @@ SvxOpenGraphicDialog::SvxOpenGraphicDialog(const OUString& rTitle, weld::Window*
    : mpImpl(new SvxOpenGrf_Impl(pPreferredParent, nDialogType))
{
    mpImpl->aFileDlg.SetTitle(rTitle);
    mpImpl->aFileDlg.SetContext(sfx2::FileDialogHelper::InsertImage);
}

SvxOpenGraphicDialog::~SvxOpenGraphicDialog()
diff --git a/sfx2/source/dialog/filedlghelper.cxx b/sfx2/source/dialog/filedlghelper.cxx
index c388b90..abbdc48 100644
--- a/sfx2/source/dialog/filedlghelper.cxx
+++ b/sfx2/source/dialog/filedlghelper.cxx
@@ -38,12 +38,16 @@
#include <com/sun/star/ui/dialogs/XFilePicker3.hpp>
#include <com/sun/star/ui/dialogs/XAsynchronousExecutableDialog.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/lang/XSingleServiceFactory.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/beans/NamedValue.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/embed/ElementModes.hpp>
#include <com/sun/star/container/XEnumeration.hpp>
#include <com/sun/star/container/XContainerQuery.hpp>
#include <com/sun/star/container/XNameAccess.hpp>
#include <com/sun/star/container/XNameContainer.hpp>
#include <com/sun/star/task/InteractionHandler.hpp>
#include <com/sun/star/task/XInteractionRequest.hpp>
#include <com/sun/star/util/RevisionTag.hpp>
@@ -88,6 +92,7 @@
#include <sal/log.hxx>
#include <comphelper/sequence.hxx>
#include <tools/diagnose_ex.h>
#include <officecfg/Office/Common.hxx>

#ifdef UNX
#include <errno.h>
@@ -133,9 +138,9 @@ static std::optional<OUString> GetLastFilterConfigId( FileDialogHelper::Context 

    switch( _eContext )
    {
        case FileDialogHelper::SD_EXPORT: return aSD_EXPORT_IDENTIFIER;
        case FileDialogHelper::SI_EXPORT: return aSI_EXPORT_IDENTIFIER;
        case FileDialogHelper::SW_EXPORT: return aSW_EXPORT_IDENTIFIER;
        case FileDialogHelper::DrawExport: return aSD_EXPORT_IDENTIFIER;
        case FileDialogHelper::ImpressExport: return aSI_EXPORT_IDENTIFIER;
        case FileDialogHelper::WriterExport: return aSW_EXPORT_IDENTIFIER;
        default: break;
    }

@@ -851,7 +856,7 @@ FileDialogHelper_Impl::FileDialogHelper_Impl(
    const css::uno::Sequence< OUString >& rDenyList
    )
    :m_nDialogType          ( nDialogType )
    ,meContext              ( FileDialogHelper::UNKNOWN_CONTEXT )
    ,meContext              ( FileDialogHelper::UnknownContext )
{
    const char* pServiceName=nullptr;
    switch (nDialog)
@@ -1979,6 +1984,46 @@ static void SetToken( OUString& rOrigStr, sal_Int32 nToken, sal_Unicode cTok, co
        rOrigStr = rOrigStr.replaceAt( nFirstChar, i-nFirstChar, rStr );
}

namespace
{
void SaveLastDirectory(OUString const& sContext, OUString const& sDirectory)
{
    if (sContext.isEmpty())
        return;

    std::shared_ptr<comphelper::ConfigurationChanges> batch(
        comphelper::ConfigurationChanges::create());
    Reference<container::XNameContainer> set(
        officecfg::Office::Common::Misc::FilePickerLastDirectory::get(batch));

    bool found;
    Any v;
    try
    {
        v = set->getByName(sContext);
        found = true;
    }
    catch (container::NoSuchElementException&)
    {
        found = false;
    }
    if (found)
    {
        Reference<XPropertySet> el(v.get<Reference<XPropertySet>>(), UNO_SET_THROW);
        el->setPropertyValue("LastPath", makeAny(sDirectory));
    }
    else
    {
        Reference<XPropertySet> el(
            (Reference<lang::XSingleServiceFactory>(set, UNO_QUERY_THROW)->createInstance()),
            UNO_QUERY_THROW);
        el->setPropertyValue("LastPath", makeAny(sDirectory));
        Any v2(makeAny(el));
        set->insertByName(sContext, v2);
    }
    batch->commit();
}
}

void FileDialogHelper_Impl::saveConfig()
{
@@ -2069,45 +2114,69 @@ void FileDialogHelper_Impl::saveConfig()
            aDlgOpt.SetUserItem( USERITEM_NAME, makeAny( aUserData ) );
    }

    SfxApplication *pSfxApp = SfxGetpApp();
    pSfxApp->SetLastDir_Impl( getPath() );
}

namespace
{
    OUString getInitPath( const OUString& _rFallback, const sal_Int32 _nFallbackToken )
    // Store to config, if explicit context is set. Otherwise store in (global) runtime var.
    if (meContext != FileDialogHelper::UnknownContext)
    {
        SaveLastDirectory(FileDialogHelper::contextToString(meContext), getPath());
    }
    else
    {
        SfxApplication *pSfxApp = SfxGetpApp();
        OUString sPath = pSfxApp->GetLastDir_Impl();

        if ( sPath.isEmpty() )
            sPath = _rFallback.getToken( _nFallbackToken, ' ' );

        // check if the path points to a valid (accessible) directory
        bool bValid = false;
        if ( !sPath.isEmpty() )
        {
            OUString sPathCheck( sPath );
            if ( sPathCheck[ sPathCheck.getLength() - 1 ] != '/' )
                sPathCheck += "/";
            sPathCheck += ".";
            try
            {
                ::ucbhelper::Content aContent( sPathCheck,
                                               utl::UCBContentHelper::getDefaultCommandEnvironment(),
                                               comphelper::getProcessComponentContext() );
                bValid = aContent.isFolder();
            }
            catch( const Exception& ) {}
        }

        if ( !bValid )
            sPath.clear();

        return sPath;
        pSfxApp->SetLastDir_Impl( getPath() );
    }
}

OUString FileDialogHelper_Impl::getInitPath(const OUString& _rFallback,
                                            const sal_Int32 _nFallbackToken)
{
    OUString sPath;
    // Load from config, if explicit context is set. Otherwise load from (global) runtime var.
    if (meContext != FileDialogHelper::UnknownContext)
    {
        OUString sContext = FileDialogHelper::contextToString(meContext);
        Reference<XNameAccess> set(officecfg::Office::Common::Misc::FilePickerLastDirectory::get());
        Any v;
        try
        {
            v = set->getByName(sContext);
            Reference<XPropertySet> el(v.get<Reference<XPropertySet>>(), UNO_SET_THROW);
            sPath = el->getPropertyValue("LastPath").get<OUString>();
        }
        catch (NoSuchElementException&)
        {
        }
    }
    else
    {
        SfxApplication *pSfxApp = SfxGetpApp();
        sPath = pSfxApp->GetLastDir_Impl();
    }

    if ( sPath.isEmpty() )
        sPath = _rFallback.getToken( _nFallbackToken, ' ' );

    // check if the path points to a valid (accessible) directory
    bool bValid = false;
    if ( !sPath.isEmpty() )
    {
        OUString sPathCheck( sPath );
        if ( sPathCheck[ sPathCheck.getLength() - 1 ] != '/' )
            sPathCheck += "/";
        sPathCheck += ".";
        try
        {
            ::ucbhelper::Content aContent( sPathCheck,
                                            utl::UCBContentHelper::getDefaultCommandEnvironment(),
                                            comphelper::getProcessComponentContext() );
            bValid = aContent.isFolder();
        }
        catch( const Exception& ) {}
    }
    if ( !bValid )
        sPath.clear();
    return sPath;
}

void FileDialogHelper_Impl::loadConfig()
{
    uno::Reference < XFilePickerControlAccess > xDlg( mxFileDlg, UNO_QUERY );
@@ -2375,6 +2444,121 @@ void FileDialogHelper::SetContext( Context _eNewContext )
    mpImpl->SetContext( _eNewContext );
}

OUString FileDialogHelper::contextToString(Context context)
{
    // These strings are used in the configuration, to store the last used directory for each context.
    // Please don't change them.
    switch(context) {
        case AcceleratorConfig:
            return "AcceleratorConfig";
        case AutoRedact:
            return "AutoRedact";
        case BaseDataSource:
            return "BaseDataSource";
        case BaseSaveAs:
            return "BaseSaveAs";
        case BasicExportPackage:
            return "BasicExportPackage";
        case BasicInsertLib:
            return "BasicInsertLib";
        case BulletsAddImage:
            return "BulletsAddImage";
        case CalcDataProvider:
            return "CalcDataProvider";
        case CalcDataStream:
            return "CalcDataStream";
        case CalcExport:
            return "CalcExport";
        case CalcSaveAs:
            return "CalcSaveAs";
        case CalcXMLSource:
            return "CalcXMLSource";
        case ExportImage:
            return "ExportImage";
        case ExtensionManager:
            return "ExtensionManager";
        case FormsAddInstance:
            return "FormsAddInstance";
        case FormsInsertImage:
            return "FormsInsertImage";
        case LinkClientOLE:
            return "LinkClientOLE";
        case LinkClientFile:
            return "LinkClientFile";
        case DrawImpressInsertFile:
            return "DrawImpressInsertFile";
        case DrawImpressOpenSound:
            return "DrawImpressOpenSound";
        case DrawExport:
            return "DrawExport";
        case DrawSaveAs:
            return "DrawSaveAs";
        case IconImport:
            return "IconImport";
        case ImpressClickAction:
            return "ImpressClickAction";
        case ImpressExport:
            return "ImpressExport";
        case ImpressPhotoDialog:
            return "ImpressPhotoDialog";
        case ImpressSaveAs:
            return "ImpressSaveAs";
        case ImageMap:
            return "ImageMap";
        case InsertDoc:
            return "InsertDoc";
        case InsertImage:
            return "InsertImage";
        case InsertOLE:
            return "InsertOLE";
        case InsertMedia:
            return "InsertMedia";
        case JavaClassPath:
            return "JavaClassPath";
        case ReportInsertImage:
            return "ReportInsertImage";
        case ScreenshotAnnotation:
            return "ScreenshotAnnotation";
        case SignatureLine:
            return "SignatureLine";
        case TemplateImport:
            return "TemplateImport";
        case WriterCreateAddressList:
            return "WriterCreateAddressList";
        case WriterExport:
            return "WriterExport";
        case WriterImportAutotext:
            return "WriterImportAutotext";
        case WriterInsertDoc:
            return "WriterInsertDoc";
        case WriterInsertHyperlink:
            return "WriterInsertHyperlink";
        case WriterInsertImage:
            return "WriterInsertImage";
        case WriterInsertScript:
            return "WriterInsertScript";
        case WriterLoadTemplate:
            return "WriterLoadTemplate";
        case WriterMailMerge:
            return "WriterMailMerge";
        case WriterMailMergeSaveAs:
            return "WriterMailMergeSaveAs";
        case WriterNewHTMLGlobalDoc:
            return "WriterNewHTMLGlobalDoc";
        case WriterRegisterDataSource:
            return "WriterRegisterDataSource";
        case WriterSaveAs:
            return "WriterSaveAs";
        case WriterSaveHTML:
            return "WriterSaveHTML";
        case XMLFilterSettings:
            return "XMLFilterSettings";
        case UnknownContext:
        default:
            return "";
    }
}

IMPL_LINK_NOARG(FileDialogHelper, ExecuteSystemFilePicker, void*, void)
{
    m_nError = mpImpl->execute();
diff --git a/sfx2/source/dialog/filedlgimpl.hxx b/sfx2/source/dialog/filedlgimpl.hxx
index f8a75f0..96f87bc 100644
--- a/sfx2/source/dialog/filedlgimpl.hxx
+++ b/sfx2/source/dialog/filedlgimpl.hxx
@@ -57,6 +57,7 @@ namespace sfx2
        ::std::vector< OUString > mlLastURLs;

        OUString             maPath;
        OUString             maLastPath;
        OUString             maFileName;
        OUString             maCurFilter;
        OUString             maSelectFilter;
@@ -204,6 +205,7 @@ namespace sfx2
        OUString                getFilterWithExtension( std::u16string_view rFilter ) const;

        void                    SetContext( FileDialogHelper::Context _eNewContext );
        OUString                getInitPath( const OUString& _rFallback, const sal_Int32 _nFallbackToken );

        bool             isSystemFilePicker() const { return mbSystemPicker; }
        bool             isPasswordEnabled() const { return mbIsPwdEnabled; }
diff --git a/sfx2/source/doc/autoredactdialog.cxx b/sfx2/source/doc/autoredactdialog.cxx
index eaa9047..0ccc622 100644
--- a/sfx2/source/doc/autoredactdialog.cxx
+++ b/sfx2/source/doc/autoredactdialog.cxx
@@ -492,6 +492,7 @@ void SfxAutoRedactDialog::StartFileDialog(StartFileDialogType nType, const OUStr
    Link<sfx2::FileDialogHelper*, void> aDlgClosedLink
        = bSave ? LINK(this, SfxAutoRedactDialog, SaveHdl)
                : LINK(this, SfxAutoRedactDialog, LoadHdl);
    m_pFileDlg->SetContext(sfx2::FileDialogHelper::AutoRedact);
    m_pFileDlg->StartExecuteModal(aDlgClosedLink);
}

diff --git a/sfx2/source/doc/docinsert.cxx b/sfx2/source/doc/docinsert.cxx
index 1cff140..f9b757b 100644
--- a/sfx2/source/doc/docinsert.cxx
+++ b/sfx2/source/doc/docinsert.cxx
@@ -97,6 +97,7 @@ void DocumentInserter::StartExecuteModal( const Link<sfx2::FileDialogHelper*,voi
                ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE,
                m_nDlgFlags, m_sDocFactory, SfxFilterFlags::NONE, SfxFilterFlags::NONE, m_pParent ) );
    }
    m_pFileDlg->SetContext(FileDialogHelper::InsertDoc);
    m_pFileDlg->StartExecuteModal( LINK( this, DocumentInserter, DialogClosedHdl ) );
}

diff --git a/sfx2/source/doc/guisaveas.cxx b/sfx2/source/doc/guisaveas.cxx
index 84a4edd..9f1aeba 100644
--- a/sfx2/source/doc/guisaveas.cxx
+++ b/sfx2/source/doc/guisaveas.cxx
@@ -881,15 +881,17 @@ bool ModelData_Impl::OutputFileDialog( sal_Int16 nStoreMode,
            pFileDlg.reset(new sfx2::FileDialogHelper( aDialogMode, aDialogFlags, aDocServiceName, nDialog, nMust, nDont, rStandardDir, rDenyList, pFrameWin ));
        }

        sfx2::FileDialogHelper::Context eCtxt = sfx2::FileDialogHelper::UNKNOWN_CONTEXT;
        sfx2::FileDialogHelper::Context eCtxt = sfx2::FileDialogHelper::UnknownContext;
        if ( aDocServiceName == "com.sun.star.drawing.DrawingDocument" )
            eCtxt = sfx2::FileDialogHelper::SD_EXPORT;
            eCtxt = sfx2::FileDialogHelper::DrawExport;
        else if ( aDocServiceName == "com.sun.star.presentation.PresentationDocument" )
            eCtxt = sfx2::FileDialogHelper::SI_EXPORT;
            eCtxt = sfx2::FileDialogHelper::ImpressExport;
        else if ( aDocServiceName == "com.sun.star.text.TextDocument" )
            eCtxt = sfx2::FileDialogHelper::SW_EXPORT;
            eCtxt = sfx2::FileDialogHelper::WriterExport;
        else if ( aDocServiceName == "com.sun.star.sheet.SpreadsheetDocument" )
            eCtxt = sfx2::FileDialogHelper::CalcExport;

        if ( eCtxt != sfx2::FileDialogHelper::UNKNOWN_CONTEXT )
        if ( eCtxt != sfx2::FileDialogHelper::UnknownContext )
               pFileDlg->SetContext( eCtxt );

        pFileDlg->CreateMatcher( aDocServiceName );
@@ -905,10 +907,23 @@ bool ModelData_Impl::OutputFileDialog( sal_Int16 nStoreMode,
    }
    else
    {
        // This is the normal dialog
        // This is the normal save as dialog
        pFileDlg.reset(new sfx2::FileDialogHelper( aDialogMode, aDialogFlags, aDocServiceName, nDialog,
            nMust, nDont, rStandardDir, rDenyList, pFrameWin ));
        pFileDlg->CreateMatcher( aDocServiceName );

        sfx2::FileDialogHelper::Context eCtxt = sfx2::FileDialogHelper::UnknownContext;
        if ( aDocServiceName == "com.sun.star.drawing.DrawingDocument" )
            eCtxt = sfx2::FileDialogHelper::DrawSaveAs;
        else if ( aDocServiceName == "com.sun.star.presentation.PresentationDocument" )
            eCtxt = sfx2::FileDialogHelper::ImpressSaveAs;
        else if ( aDocServiceName == "com.sun.star.text.TextDocument" )
            eCtxt = sfx2::FileDialogHelper::WriterSaveAs;
        else if ( aDocServiceName == "com.sun.star.sheet.SpreadsheetDocument" )
            eCtxt = sfx2::FileDialogHelper::CalcSaveAs;

        if ( eCtxt != sfx2::FileDialogHelper::UnknownContext )
               pFileDlg->SetContext( eCtxt );
    }

    OUString aAdjustToType;
@@ -1173,7 +1188,7 @@ OUString ModelData_Impl::GetRecommendedDir( const OUString& aSuggestedDir )
            }

            if ( aLocation.HasError() )
                aLocation = INetURLObject( SvtPathOptions().GetWorkPath() );
                aLocation = INetURLObject();
        }

        OUString sLocationURL( aLocation.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
@@ -1196,7 +1211,7 @@ OUString ModelData_Impl::GetRecommendedDir( const OUString& aSuggestedDir )
#endif
        // Suggest somewhere other than the system's temp directory
        if( bIsInTempPath )
            aLocation = INetURLObject( SvtPathOptions().GetWorkPath() );
            aLocation = INetURLObject();

        aLocation.setFinalSlash();
        if ( !aLocation.HasError() )
@@ -1205,7 +1220,7 @@ OUString ModelData_Impl::GetRecommendedDir( const OUString& aSuggestedDir )
        return OUString();
    }

    return INetURLObject( SvtPathOptions().GetWorkPath() ).GetMainURL( INetURLObject::DecodeMechanism::NONE );
    return OUString();
}


diff --git a/sfx2/source/doc/templatedlg.cxx b/sfx2/source/doc/templatedlg.cxx
index b7390e2..e1a5f4b 100644
--- a/sfx2/source/doc/templatedlg.cxx
+++ b/sfx2/source/doc/templatedlg.cxx
@@ -957,6 +957,7 @@ void SfxTemplateManagerDlg::OnTemplateImportCategory(std::u16string_view sCatego
{
    sfx2::FileDialogHelper aFileDlg(css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE,
                                    FileDialogFlags::MultiSelection, m_xDialog.get());
    aFileDlg.SetContext(sfx2::FileDialogHelper::TemplateImport);

    // add "All" filter
    aFileDlg.AddFilter( SfxResId(STR_SFX_FILTERNAME_ALL),
diff --git a/svx/source/core/graphichelper.cxx b/svx/source/core/graphichelper.cxx
index 997644b..de29e0b 100644
--- a/svx/source/core/graphichelper.cxx
+++ b/svx/source/core/graphichelper.cxx
@@ -227,7 +227,7 @@ OUString GraphicHelper::ExportGraphic(weld::Window* pParent, const Graphic& rGra
    aPath.SetSmartURL( sGraphicsPath );

    // fish out the graphic's name

    aDialogHelper.SetContext(FileDialogHelper::ExportImage);
    aDialogHelper.SetTitle( SvxResId(RID_SVXSTR_EXPORT_GRAPHIC_TITLE));
    aDialogHelper.SetDisplayDirectory( aPath.GetMainURL(INetURLObject::DecodeMechanism::ToIUri) );
    INetURLObject aURL;
diff --git a/svx/source/dialog/imapdlg.cxx b/svx/source/dialog/imapdlg.cxx
index ea30dfe..ccc07ac 100644
--- a/svx/source/dialog/imapdlg.cxx
+++ b/svx/source/dialog/imapdlg.cxx
@@ -373,7 +373,7 @@ void SvxIMapDlg::DoOpen()
    aDlg.AddFilter( IMAP_BINARY_FILTER, IMAP_BINARY_TYPE );

    aDlg.SetCurrentFilter( aFilter );
    aDlg.SetDisplayDirectory( SvtPathOptions().GetWorkPath() );
    aDlg.SetContext(sfx2::FileDialogHelper::ImageMap);

    if( aDlg.Execute() != ERRCODE_NONE )
        return;
@@ -416,7 +416,7 @@ bool SvxIMapDlg::DoSave()
    aDlg.AddFilter( aBinFilter, IMAP_BINARY_TYPE );

    aDlg.SetCurrentFilter( aCERNFilter );
    aDlg.SetDisplayDirectory( SvtPathOptions().GetWorkPath() );
    aDlg.SetContext(sfx2::FileDialogHelper::ImageMap);

    if( aDlg.Execute() == ERRCODE_NONE )
    {
diff --git a/svx/source/form/datanavi.cxx b/svx/source/form/datanavi.cxx
index 1e1d366..2c32b13 100644
--- a/svx/source/form/datanavi.cxx
+++ b/svx/source/form/datanavi.cxx
@@ -3069,13 +3069,12 @@ namespace svxform
        ::sfx2::FileDialogHelper aDlg(
            css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE,
            FileDialogFlags::NONE, m_xDialog.get());
        INetURLObject aFile( SvtPathOptions().GetWorkPath() );
        aDlg.SetContext(sfx2::FileDialogHelper::FormsAddInstance);

        aDlg.AddFilter( m_sAllFilterName, FILEDIALOG_FILTER_ALL );
        OUString sFilterName( "XML" );
        aDlg.AddFilter( sFilterName, "*.xml" );
        aDlg.SetCurrentFilter( sFilterName );
        aDlg.SetDisplayDirectory( aFile.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );

        if (aDlg.Execute() == ERRCODE_NONE)
            m_xURLED->set_entry_text(aDlg.GetPath());
diff --git a/sw/source/ui/chrdlg/chardlg.cxx b/sw/source/ui/chrdlg/chardlg.cxx
index f81bfa7..ab59691 100644
--- a/sw/source/ui/chrdlg/chardlg.cxx
+++ b/sw/source/ui/chrdlg/chardlg.cxx
@@ -294,6 +294,7 @@ IMPL_LINK_NOARG(SwCharURLPage, InsertFileHdl, weld::Button&, void)
{
    FileDialogHelper aDlgHelper(TemplateDescription::FILEOPEN_SIMPLE,
                                FileDialogFlags::NONE, GetFrameWeld());
    aDlgHelper.SetContext(FileDialogHelper::WriterInsertHyperlink);
    if( aDlgHelper.Execute() == ERRCODE_NONE )
    {
        const Reference<XFilePicker3>& xFP = aDlgHelper.GetFilePicker();
diff --git a/sw/source/ui/dbui/createaddresslistdialog.cxx b/sw/source/ui/dbui/createaddresslistdialog.cxx
index 068a834..36803bc 100644
--- a/sw/source/ui/dbui/createaddresslistdialog.cxx
+++ b/sw/source/ui/dbui/createaddresslistdialog.cxx
@@ -420,10 +420,8 @@ IMPL_LINK_NOARG(SwCreateAddressListDialog, OkHdl_Impl, weld::Button&, void)
    {
        sfx2::FileDialogHelper aDlgHelper(TemplateDescription::FILESAVE_SIMPLE,
                                          FileDialogFlags::NONE, m_xDialog.get());
        aDlgHelper.SetContext(sfx2::FileDialogHelper::WriterCreateAddressList);
        uno::Reference < XFilePicker3 > xFP = aDlgHelper.GetFilePicker();

        const OUString sPath( SvtPathOptions().SubstituteVariable("$(userurl)/database") );
        aDlgHelper.SetDisplayDirectory( sPath );
        xFP->appendFilter( m_sAddressListFilterName, "*.csv" );
        xFP->setCurrentFilter( m_sAddressListFilterName ) ;

diff --git a/sw/source/ui/dbui/mmdocselectpage.cxx b/sw/source/ui/dbui/mmdocselectpage.cxx
index cfed29e..7e92af1 100644
--- a/sw/source/ui/dbui/mmdocselectpage.cxx
+++ b/sw/source/ui/dbui/mmdocselectpage.cxx
@@ -133,10 +133,9 @@ IMPL_LINK(SwMailMergeDocSelectPage, FileSelectHdl, weld::Button&, rButton, void)
    {
        sfx2::FileDialogHelper aDlgHelper(TemplateDescription::FILEOPEN_SIMPLE,
                                          FileDialogFlags::NONE, m_pWizard->getDialog());
        aDlgHelper.SetContext(sfx2::FileDialogHelper::WriterMailMerge);
        Reference < XFilePicker3 > xFP = aDlgHelper.GetFilePicker();

        xFP->setDisplayDirectory( SvtPathOptions().GetWorkPath() );

        SfxObjectFactory &rFact = m_pWizard->GetSwView()->GetDocShell()->GetFactory();
        SfxFilterMatcher aMatcher( rFact.GetFactoryName() );
        SfxFilterMatcherIter aIter( aMatcher );
diff --git a/sw/source/ui/fldui/javaedit.cxx b/sw/source/ui/fldui/javaedit.cxx
index 15f2544..b13c982 100644
--- a/sw/source/ui/fldui/javaedit.cxx
+++ b/sw/source/ui/fldui/javaedit.cxx
@@ -231,7 +231,7 @@ IMPL_LINK_NOARG( SwJavaEditDialog, InsertFileHdl, weld::Button&, void )
            ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE,
            FileDialogFlags::Insert, "swriter", SfxFilterFlags::NONE, SfxFilterFlags::NONE, m_xDialog.get()));
    }

    m_pFileDlg->SetContext(sfx2::FileDialogHelper::WriterInsertScript);
    m_pFileDlg->StartExecuteModal( LINK( this, SwJavaEditDialog, DlgClosedHdl ) );
}

diff --git a/sw/source/ui/misc/glossary.cxx b/sw/source/ui/misc/glossary.cxx
index 75da931..e16564a 100644
--- a/sw/source/ui/misc/glossary.cxx
+++ b/sw/source/ui/misc/glossary.cxx
@@ -563,11 +563,9 @@ IMPL_LINK(SwGlossaryDlg, MenuHdl, const OString&, rItemIdent, void)
        // call the FileOpenDialog do find WinWord - Files with templates
        FileDialogHelper aDlgHelper(TemplateDescription::FILEOPEN_SIMPLE,
                                    FileDialogFlags::NONE, m_xDialog.get());
        aDlgHelper.SetContext(FileDialogHelper::WriterImportAutotext);
        uno::Reference < XFilePicker3 > xFP = aDlgHelper.GetFilePicker();

        SvtPathOptions aPathOpt;
        xFP->setDisplayDirectory(aPathOpt.GetWorkPath() );

        SfxFilterMatcher aMatcher( SwDocShell::Factory().GetFactoryName() );
        SfxFilterMatcherIter aIter( aMatcher );
        std::shared_ptr<const SfxFilter> pFilter = aIter.First();
diff --git a/sw/source/uibase/app/docsh2.cxx b/sw/source/uibase/app/docsh2.cxx
index 30b31f9..4fa73d0 100644
--- a/sw/source/uibase/app/docsh2.cxx
+++ b/sw/source/uibase/app/docsh2.cxx
@@ -546,7 +546,6 @@ void SwDocShell::Execute(SfxRequest& rReq)

                if ( aFileName.isEmpty() )
                {
                    SvtPathOptions aPathOpt;
                    SfxNewFileDialog aNewFileDlg(GetView()->GetFrameWeld(), SfxNewFileDialogMode::LoadTemplate);
                    aNewFileDlg.SetTemplateFlags(nFlags);

@@ -555,10 +554,9 @@ void SwDocShell::Execute(SfxRequest& rReq)
                    {
                        FileDialogHelper aDlgHelper(TemplateDescription::FILEOPEN_SIMPLE,
                                                    FileDialogFlags::NONE, GetView()->GetFrameWeld());
                        aDlgHelper.SetContext(FileDialogHelper::WriterLoadTemplate);
                        uno::Reference < XFilePicker3 > xFP = aDlgHelper.GetFilePicker();

                        xFP->setDisplayDirectory( aPathOpt.GetWorkPath() );

                        SfxObjectFactory &rFact = GetFactory();
                        SfxFilterMatcher aMatcher( rFact.GetFactoryName() );
                        SfxFilterMatcherIter aIter( aMatcher );
@@ -671,6 +669,7 @@ void SwDocShell::Execute(SfxRequest& rReq)
                        FileDialogHelper aDlgHelper(TemplateDescription::FILESAVE_AUTOEXTENSION,
                                                    FileDialogFlags::NONE,
                                                    GetView()->GetFrameWeld());
                        aDlgHelper.SetContext(FileDialogHelper::WriterSaveHTML);
                        aDlgHelper.AddFilter( pHtmlFlt->GetFilterName(), pHtmlFlt->GetDefaultExtension() );
                        aDlgHelper.SetCurrentFilter( pHtmlFlt->GetFilterName() );
                        if( ERRCODE_NONE != aDlgHelper.Execute())
@@ -926,6 +925,7 @@ void SwDocShell::Execute(SfxRequest& rReq)

                    FileDialogHelper aDlgHelper(TemplateDescription::FILESAVE_AUTOEXTENSION_TEMPLATE, FileDialogFlags::NONE,
                                                GetView()->GetFrameWeld());
                    aDlgHelper.SetContext(FileDialogHelper::WriterNewHTMLGlobalDoc);

                    const sal_Int16 nControlIds[] = {
                        CommonFilePickerElementIds::PUSHBUTTON_OK,
diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index 9aad1ea..132743c 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -2780,11 +2780,9 @@ OUString ConstructVndSunStarPkgUrl(const OUString& rMainURL, std::u16string_view
OUString SwDBManager::LoadAndRegisterDataSource(weld::Window* pParent, SwDocShell* pDocShell)
{
    sfx2::FileDialogHelper aDlgHelper(ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE, FileDialogFlags::NONE, pParent);
    aDlgHelper.SetContext(sfx2::FileDialogHelper::WriterRegisterDataSource);
    uno::Reference < ui::dialogs::XFilePicker3 > xFP = aDlgHelper.GetFilePicker();

    OUString sHomePath(SvtPathOptions().GetWorkPath());
    aDlgHelper.SetDisplayDirectory( sHomePath );

    OUString sFilterAll(SwResId(STR_FILTER_ALL));
    OUString sFilterAllData(SwResId(STR_FILTER_ALL_DATA));
    OUString sFilterSXB(SwResId(STR_FILTER_SXB));
diff --git a/sw/source/uibase/dbui/mailmergehelper.cxx b/sw/source/uibase/dbui/mailmergehelper.cxx
index 17abf70..4f420bb 100644
--- a/sw/source/uibase/dbui/mailmergehelper.cxx
+++ b/sw/source/uibase/dbui/mailmergehelper.cxx
@@ -59,6 +59,7 @@ OUString CallSaveAsDialog(weld::Window* pParent, OUString& rFilter)
    ::sfx2::FileDialogHelper aDialog( ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION,
                FileDialogFlags::NONE,
                SwDocShell::Factory().GetFactoryName(), SfxFilterFlags::NONE, SfxFilterFlags::NONE, pParent);
    aDialog.SetContext(sfx2::FileDialogHelper::WriterMailMergeSaveAs);

    if (aDialog.Execute()!=ERRCODE_NONE)
    {
diff --git a/sw/source/uibase/uiview/srcview.cxx b/sw/source/uibase/uiview/srcview.cxx
index 1754dd1..1a7816c 100644
--- a/sw/source/uibase/uiview/srcview.cxx
+++ b/sw/source/uibase/uiview/srcview.cxx
@@ -268,7 +268,6 @@ void SwSrcView::Execute(SfxRequest& rReq)
        case SID_SAVEACOPY:
        case SID_SAVEASDOC:
        {
            SvtPathOptions aPathOpt;
            // filesave dialog with autoextension
            FileDialogHelper aDlgHelper(
                TemplateDescription::FILESAVE_AUTOEXTENSION,
@@ -295,7 +294,6 @@ void SwSrcView::Execute(SfxRequest& rReq)
                xFP->setCurrentFilter( sHtml ) ;
            }

            xFP->setDisplayDirectory( aPathOpt.GetWorkPath() );
            if( aDlgHelper.Execute() == ERRCODE_NONE)
            {
                SfxMedium aMedium( xFP->getSelectedFiles().getConstArray()[0],
diff --git a/sw/source/uibase/uiview/view2.cxx b/sw/source/uibase/uiview/view2.cxx
index 0e96945..461b915 100644
--- a/sw/source/uibase/uiview/view2.cxx
+++ b/sw/source/uibase/uiview/view2.cxx
@@ -311,7 +311,7 @@ bool SwView::InsertGraphicDlg( SfxRequest& rReq )
        ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE,
        FileDialogFlags::Graphic, GetFrameWeld()));
    pFileDlg->SetTitle(SwResId(STR_INSERT_GRAPHIC ));
    pFileDlg->SetContext( FileDialogHelper::SW_INSERT_GRAPHIC );
    pFileDlg->SetContext( FileDialogHelper::WriterInsertImage );

    uno::Reference < XFilePicker3 > xFP = pFileDlg->GetFilePicker();
    uno::Reference < XFilePickerControlAccess > xCtrlAcc(xFP, UNO_QUERY);