diff options
author | Mike Kaganski <mike.kaganski@collabora.com> | 2021-02-25 22:35:29 +0300 |
---|---|---|
committer | Mike Kaganski <mike.kaganski@collabora.com> | 2021-02-26 08:58:59 +0100 |
commit | 43e306ebe61ef5a849dcfd1e74b697be3b3fe716 (patch) | |
tree | a440ab92160dc800bea4b2a130d6a3e5f8d1b431 /fpicker/source/win32 | |
parent | df33714f0ecaf4d35011f2d2116e5e1a4ec75f1a (diff) |
Simplify VistaFilePickerImpl
Change-Id: I13ac92f8f28a1d912681239fee1780093f8be444
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111561
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
Diffstat (limited to 'fpicker/source/win32')
-rw-r--r-- | fpicker/source/win32/VistaFilePickerImpl.cxx | 215 | ||||
-rw-r--r-- | fpicker/source/win32/VistaFilePickerImpl.hxx | 27 |
2 files changed, 93 insertions, 149 deletions
diff --git a/fpicker/source/win32/VistaFilePickerImpl.cxx b/fpicker/source/win32/VistaFilePickerImpl.cxx index 0355e940c6f9..b0e733be88bc 100644 --- a/fpicker/source/win32/VistaFilePickerImpl.cxx +++ b/fpicker/source/win32/VistaFilePickerImpl.cxx @@ -27,6 +27,7 @@ #include <com/sun/star/awt/XSystemDependentWindowPeer.hpp> #include <com/sun/star/lang/SystemDependent.hpp> #include <comphelper/sequence.hxx> +#include <comphelper/windowserrorstring.hxx> #include <fpicker/strings.hrc> #include <fpsofficeResMgr.hxx> #include <osl/file.hxx> @@ -93,6 +94,59 @@ const GUID CLIENTID_FILEOPEN_PLAY = {0x32CFB147, 0xF5AE, 0x4F90, 0xA1 const GUID CLIENTID_FILEOPEN_LINK = {0x39AC4BAE, 0x7D2D, 0x46BC, 0xBE, 0x2E, 0xF8, 0x8C, 0xB5, 0x65, 0x5E, 0x6A}; +class TDialogImplBase +{ +public: + template <class ComPtrDialog> TDialogImplBase(ComPtrDialog&& iDialog) + { + HRESULT hResult = iDialog.create(); + if (FAILED(hResult)) + throw css::uno::RuntimeException(WindowsErrorStringFromHRESULT(hResult)); + hResult = iDialog.query(&m_iDialog); + if (FAILED(hResult)) + throw css::uno::RuntimeException(WindowsErrorStringFromHRESULT(hResult)); + } + + TFileDialog getComPtr() { return m_iDialog; }; + virtual ComPtr<IShellItemArray> getResult(bool bInExecute) + { + ComPtr<IShellItem> iItem; + if (bInExecute) + m_iDialog->GetCurrentSelection(&iItem); + else + m_iDialog->GetResult(&iItem); + void* iItems = nullptr; + SHCreateShellItemArrayFromShellItem(iItem, IID_IShellItemArray, &iItems); + return ComPtr<IShellItemArray>(reinterpret_cast<IShellItemArray*>(iItems)); + } + +private: + TFileDialog m_iDialog; +}; + +template <class ComPtrDialog> class TDialogImpl : public TDialogImplBase +{ +public: + TDialogImpl() : TDialogImplBase(ComPtrDialog()) {} +}; + +class TOpenDialogImpl : public TDialogImpl<TFileOpenDialog> +{ +public: + ComPtr<IShellItemArray> getResult(bool bInExecute) override + { + ComPtr<IShellItemArray> iItems; + TFileOpenDialog iDialog{ getComPtr() }; + if (FAILED(bInExecute ? iDialog->GetSelectedItems(&iItems) : iDialog->GetResults(&iItems))) + iItems = TDialogImplBase::getResult(bInExecute); + return iItems; + } +}; + +using TSaveDialogImpl = TDialogImpl<TFileSaveDialog>; +using TFolderPickerDialogImpl = TDialogImpl<TFolderPickerDialog>; + + static OUString lcl_getURLFromShellItem (IShellItem* pItem) { LPWSTR pStr = nullptr; @@ -179,11 +233,7 @@ static ::std::vector<COMDLG_FILTERSPEC> lcl_buildFilterList(CFilterContainer& rC VistaFilePickerImpl::VistaFilePickerImpl() - : m_iDialogOpen () - , m_iDialogSave () - , m_iFolderPicker() - , m_hLastResult () - , m_lFilters () + : m_lFilters () , m_iEventHandler(new VistaFilePickerEventHandler(this)) , m_bInExecute (false) , m_bWasExecuted (false) @@ -209,7 +259,7 @@ void VistaFilePickerImpl::before() // osl::Thread class initializes COm already in MTA mode because it's needed // by VCL and UNO so. There is no way to change that from outside... // but we need a STA environment... - m_hLastResult = o3tl::safeCoInitializeEx(COINIT_APARTMENTTHREADED, mnNbCallCoInitializeExForReinit); + o3tl::safeCoInitializeEx(COINIT_APARTMENTTHREADED, mnNbCallCoInitializeExForReinit); } @@ -433,37 +483,20 @@ void VistaFilePickerImpl::impl_sta_getCurrentFilter(const RequestRef& rRequest) } -void VistaFilePickerImpl::impl_sta_CreateDialog(const RequestRef& rRequest, PickerDialog eType, DWORD nOrFlags) +template <class TDialogImplClass> void VistaFilePickerImpl::impl_sta_CreateDialog() { // SYNCHRONIZED-> osl::ClearableMutexGuard aLock(m_aMutex); + m_pDialog.reset(new TDialogImplClass); +} - TFileDialog iDialog; - switch (eType) - { - case PickerDialog::FileOpen: - m_hLastResult = m_iDialogOpen.create(); - if (FAILED(m_hLastResult)) - return; - m_iDialogOpen.query(&iDialog); - break; - - case PickerDialog::FileSave: - m_hLastResult = m_iDialogSave.create(); - if (FAILED(m_hLastResult)) - return; - m_iDialogSave.query(&iDialog); - break; - - case PickerDialog::Folder: - m_hLastResult = m_iFolderPicker.create(); - if (FAILED(m_hLastResult)) - return; - m_iFolderPicker.query(&iDialog); - break; - } +void VistaFilePickerImpl::impl_sta_InitDialog(const RequestRef& rRequest, DWORD nOrFlags) +{ + // SYNCHRONIZED-> + osl::ClearableMutexGuard aLock(m_aMutex); + TFileDialog iDialog = impl_getBaseDialogInterface(); TFileDialogEvents iHandler = m_iEventHandler; aLock.clear(); @@ -509,30 +542,22 @@ void VistaFilePickerImpl::impl_sta_CreateDialog(const RequestRef& rRequest, Pick void VistaFilePickerImpl::impl_sta_CreateOpenDialog(const RequestRef& rRequest) { - DWORD nFlags = 0; - nFlags |= FOS_FILEMUSTEXIST; - nFlags |= FOS_OVERWRITEPROMPT; - - impl_sta_CreateDialog(rRequest, PickerDialog::FileOpen, nFlags); + impl_sta_CreateDialog<TOpenDialogImpl>(); + impl_sta_InitDialog(rRequest, FOS_FILEMUSTEXIST | FOS_OVERWRITEPROMPT); } void VistaFilePickerImpl::impl_sta_CreateSaveDialog(const RequestRef& rRequest) { - DWORD nFlags = 0; - nFlags |= FOS_FILEMUSTEXIST; - nFlags |= FOS_OVERWRITEPROMPT; - - impl_sta_CreateDialog(rRequest, PickerDialog::FileSave, nFlags); + impl_sta_CreateDialog<TSaveDialogImpl>(); + impl_sta_InitDialog(rRequest, FOS_FILEMUSTEXIST | FOS_OVERWRITEPROMPT); } void VistaFilePickerImpl::impl_sta_CreateFolderPicker(const RequestRef& rRequest) { - DWORD nFlags = 0; - nFlags |= FOS_PICKFOLDERS; - - impl_sta_CreateDialog(rRequest, PickerDialog::Folder, nFlags); + impl_sta_CreateDialog<TFolderPickerDialogImpl>(); + impl_sta_InitDialog(rRequest, FOS_PICKFOLDERS); } @@ -710,7 +735,7 @@ void VistaFilePickerImpl::impl_sta_SetMultiSelectionMode(const RequestRef& rRequ // <- SYNCHRONIZED DWORD nFlags = 0; - m_hLastResult = iDialog->GetOptions ( &nFlags ); + iDialog->GetOptions(&nFlags); if (bMultiSelection) nFlags |= FOS_ALLOWMULTISELECT; @@ -866,76 +891,31 @@ void VistaFilePickerImpl::impl_sta_getSelectedFiles(const RequestRef& rRequest) // SYNCHRONIZED-> osl::ClearableMutexGuard aLock(m_aMutex); - TFileOpenDialog iOpen = m_iDialogOpen; - TFileSaveDialog iSave = m_iDialogSave; - TFolderPickerDialog iPick = m_iFolderPicker; + std::shared_ptr<TDialogImplBase> pDialog(m_pDialog); bool bInExecute = m_bInExecute; aLock.clear(); // <- SYNCHRONIZED - // ask dialog for results - // Note : we must differ between single/multi selection ! - // Note further: we must react different if dialog is in execute or not .-( - ComPtr< IShellItem > iItem; - ComPtr< IShellItemArray > iItems; - HRESULT hResult = E_FAIL; - - if (iOpen.is()) - { - if (bInExecute) - hResult = iOpen->GetSelectedItems(&iItems); - else - { - hResult = iOpen->GetResults(&iItems); - if (FAILED(hResult)) - hResult = iOpen->GetResult(&iItem); - } - } - else if (iSave.is()) - { - if (bInExecute) - hResult = iSave->GetCurrentSelection(&iItem); - else - hResult = iSave->GetResult(&iItem); - } - else if (iPick.is()) - { - if (bInExecute) - hResult = iPick->GetCurrentSelection(&iItem); - else - { - hResult = iPick->GetResult(&iItem); - } - } + if (!pDialog) + return; - if (FAILED(hResult)) + // ask dialog for results + // we must react different if dialog is in execute or not .-( + ComPtr<IShellItemArray> iItems = pDialog->getResult(bInExecute); + if (!iItems) return; // convert and pack results std::vector< OUString > lFiles; - if (iItem.is()) + if (DWORD nCount; SUCCEEDED(iItems->GetCount(&nCount))) { - const OUString sURL = lcl_getURLFromShellItem(iItem); - if (sURL.getLength() > 0) - lFiles.push_back(sURL); - } - - if (iItems.is()) - { - DWORD nCount; - hResult = iItems->GetCount(&nCount); - if ( SUCCEEDED(hResult) ) + for (DWORD i = 0; i < nCount; ++i) { - for (DWORD i=0; i<nCount; ++i) + if (ComPtr<IShellItem> iItem; SUCCEEDED(iItems->GetItemAt(i, &iItem))) { - hResult = iItems->GetItemAt(i, &iItem); - if ( SUCCEEDED(hResult) ) - { - const OUString sURL = lcl_getURLFromShellItem(iItem); - if (sURL.getLength() > 0) - lFiles.push_back(sURL); - } + if (const OUString sURL = lcl_getURLFromShellItem(iItem); !sURL.isEmpty()) + lFiles.push_back(sURL); } } } @@ -952,9 +932,6 @@ void VistaFilePickerImpl::impl_sta_ShowDialogModal(const RequestRef& rRequest) ::osl::ResettableMutexGuard aLock(m_aMutex); TFileDialog iDialog = impl_getBaseDialogInterface(); - TFileOpenDialog iOpen = m_iDialogOpen; - TFileSaveDialog iSave = m_iDialogSave; - TFolderPickerDialog iPick = m_iFolderPicker; // it's important to know if we are showing the dialog. // Some dialog interface methods can't be called then or some @@ -1033,14 +1010,7 @@ void VistaFilePickerImpl::impl_sta_ShowDialogModal(const RequestRef& rRequest) try { // show dialog and wait for user decision - if (iOpen.is()) - hResult = iOpen->Show( hParentWindow ); // parent window needed - else - if (iSave.is()) - hResult = iSave->Show( hParentWindow ); // parent window needed - else - if (iPick.is()) - hResult = iPick->Show( hParentWindow ); // parent window needed + hResult = iDialog->Show(hParentWindow); // parent window needed } catch(...) {} @@ -1065,13 +1035,8 @@ TFileDialog VistaFilePickerImpl::impl_getBaseDialogInterface() // SYNCHRONIZED-> osl::MutexGuard aLock(m_aMutex); - - if (m_iDialogOpen.is()) - m_iDialogOpen.query(&iDialog); - if (m_iDialogSave.is()) - m_iDialogSave.query(&iDialog); - if (m_iFolderPicker.is()) - m_iFolderPicker.query(&iDialog); + if (m_pDialog) + iDialog = m_pDialog->getComPtr(); return iDialog; } @@ -1084,12 +1049,8 @@ TFileDialogCustomize VistaFilePickerImpl::impl_getCustomizeInterface() // SYNCHRONIZED-> osl::MutexGuard aLock(m_aMutex); - if (m_iDialogOpen.is()) - m_iDialogOpen.query(&iCustom); - else if (m_iDialogSave.is()) - m_iDialogSave.query(&iCustom); - else if (m_iFolderPicker.is()) - m_iFolderPicker.query(&iCustom); + if (m_pDialog) + m_pDialog->getComPtr().query(&iCustom); return iCustom; } diff --git a/fpicker/source/win32/VistaFilePickerImpl.hxx b/fpicker/source/win32/VistaFilePickerImpl.hxx index d60e3acbe020..1353c55e869a 100644 --- a/fpicker/source/win32/VistaFilePickerImpl.hxx +++ b/fpicker/source/win32/VistaFilePickerImpl.hxx @@ -82,6 +82,7 @@ const OUString PROP_CONTROL_ENABLE("control_enable" ); // [sal_Bool] true=ON const OUString PROP_PARENT_WINDOW("ParentWindow"); //[css::awt::XWindow] preferred parent window const OUString STRING_SEPARATOR("------------------------------------------" ); +class TDialogImplBase; /** native implementation of the file picker on Vista and upcoming windows versions. * This dialog uses COM internally. Further it marshall every request so it will @@ -278,30 +279,12 @@ class VistaFilePickerImpl : private ::cppu::BaseMutex void impl_SetDefaultExtension( const OUString& currentFilter ); private: - enum class PickerDialog - { - FileOpen, - FileSave, - Folder, - }; - - void impl_sta_CreateDialog(const RequestRef& rRequest, PickerDialog eType, DWORD nOrFlags); - - - /// COM object representing a file open dialog - TFileOpenDialog m_iDialogOpen; - - - /// COM object representing a file save dialog - TFileSaveDialog m_iDialogSave; - - - /// COM object representing a folder picker dialog - TFolderPickerDialog m_iFolderPicker; + template <class TDialogImplClass> void impl_sta_CreateDialog(); + void impl_sta_InitDialog(const RequestRef& rRequest, DWORD nOrFlags); - /// knows the return state of the last COM call - HRESULT m_hLastResult; + /// object representing a file dialog + std::shared_ptr<TDialogImplBase> m_pDialog; /// @todo document me |