summaryrefslogtreecommitdiff
path: root/sfx2/source/dialog/filedlghelper.cxx
diff options
context:
space:
mode:
authorSamuel Mehrbrodt <samuel.mehrbrodt@allotropia.de>2021-07-08 05:50:25 +0200
committerSamuel Mehrbrodt <samuel.mehrbrodt@allotropia.de>2021-07-12 14:31:20 +0200
commitd157c1bd70d630a58db33910d550bb8dee9fe62e (patch)
tree6a7d4a63cc524fcbbdcdfd8c4271fcbb7cd3c983 /sfx2/source/dialog/filedlghelper.cxx
parentc62bb20032cef7479e9293e84a8d57a2c74399d0 (diff)
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>
Diffstat (limited to 'sfx2/source/dialog/filedlghelper.cxx')
-rw-r--r--sfx2/source/dialog/filedlghelper.cxx246
1 files changed, 215 insertions, 31 deletions
diff --git a/sfx2/source/dialog/filedlghelper.cxx b/sfx2/source/dialog/filedlghelper.cxx
index c388b909a3a4..abbdc48ae73d 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,43 +2114,67 @@ void FileDialogHelper_Impl::saveConfig()
aDlgOpt.SetUserItem( USERITEM_NAME, makeAny( aUserData ) );
}
- SfxApplication *pSfxApp = SfxGetpApp();
- pSfxApp->SetLastDir_Impl( getPath() );
+ // 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();
+ pSfxApp->SetLastDir_Impl( getPath() );
+ }
}
-namespace
+OUString FileDialogHelper_Impl::getInitPath(const OUString& _rFallback,
+ const sal_Int32 _nFallbackToken)
{
- OUString 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();
- OUString sPath = pSfxApp->GetLastDir_Impl();
+ sPath = pSfxApp->GetLastDir_Impl();
+ }
- if ( sPath.isEmpty() )
- sPath = _rFallback.getToken( _nFallbackToken, ' ' );
+ if ( sPath.isEmpty() )
+ sPath = _rFallback.getToken( _nFallbackToken, ' ' );
- // check if the path points to a valid (accessible) directory
- bool bValid = false;
- if ( !sPath.isEmpty() )
+ // 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
{
- 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& ) {}
+ ::ucbhelper::Content aContent( sPathCheck,
+ utl::UCBContentHelper::getDefaultCommandEnvironment(),
+ comphelper::getProcessComponentContext() );
+ bValid = aContent.isFolder();
}
-
- if ( !bValid )
- sPath.clear();
-
- return sPath;
+ catch( const Exception& ) {}
}
+ if ( !bValid )
+ sPath.clear();
+ return sPath;
}
void FileDialogHelper_Impl::loadConfig()
@@ -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();