| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_fpicker.hxx" |
| |
| //------------------------------------------------------------------------ |
| // includes |
| //------------------------------------------------------------------------ |
| |
| #include "VistaFilePickerEventHandler.hxx" |
| #include "asyncrequests.hxx" |
| |
| #include <com/sun/star/lang/XMultiServiceFactory.hpp> |
| #include <com/sun/star/embed/XStorage.hpp> |
| #include <com/sun/star/document/XDocumentRevisionListPersistence.hpp> |
| #include <com/sun/star/util/RevisionTag.hpp> |
| #include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp> |
| #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp> |
| |
| #include <comphelper/processfactory.hxx> |
| #include <comphelper/storagehelper.hxx> |
| //#include <tools/urlobj.hxx> |
| //#include <unotools/ucbhelper.hxx> |
| |
| #include <osl/file.hxx> |
| |
| //------------------------------------------------------------------------ |
| // namespace directives |
| //------------------------------------------------------------------------ |
| |
| namespace css = ::com::sun::star; |
| |
| namespace fpicker{ |
| namespace win32{ |
| namespace vista{ |
| |
| //------------------------------------------------------------------------ |
| // defines |
| //------------------------------------------------------------------------ |
| |
| //----------------------------------------------------------------------------------------- |
| VistaFilePickerEventHandler::VistaFilePickerEventHandler(IVistaFilePickerInternalNotify* pInternalNotify) |
| : m_nRefCount (0 ) |
| , m_nListenerHandle (0 ) |
| , m_pDialog ( ) |
| , m_lListener (m_aMutex) |
| , m_pInternalNotify (pInternalNotify) |
| { |
| } |
| |
| //----------------------------------------------------------------------------------------- |
| VistaFilePickerEventHandler::~VistaFilePickerEventHandler() |
| { |
| } |
| |
| //----------------------------------------------------------------------------------------- |
| HRESULT STDMETHODCALLTYPE VistaFilePickerEventHandler::QueryInterface(REFIID rIID , |
| void** ppObject) |
| { |
| *ppObject=NULL; |
| |
| if ( rIID == IID_IUnknown ) |
| *ppObject = (IUnknown*)(IFileDialogEvents*)this; |
| |
| if ( rIID == IID_IFileDialogEvents ) |
| *ppObject = (IFileDialogEvents*)this; |
| |
| if ( rIID == IID_IFileDialogControlEvents ) |
| *ppObject = (IFileDialogControlEvents*)this; |
| |
| if ( *ppObject != NULL ) |
| { |
| ((IUnknown*)*ppObject)->AddRef(); |
| return S_OK; |
| } |
| |
| return E_NOINTERFACE; |
| } |
| |
| //----------------------------------------------------------------------------------------- |
| ULONG STDMETHODCALLTYPE VistaFilePickerEventHandler::AddRef() |
| { |
| return osl_incrementInterlockedCount(&m_nRefCount); |
| } |
| |
| //----------------------------------------------------------------------------------------- |
| ULONG STDMETHODCALLTYPE VistaFilePickerEventHandler::Release() |
| { |
| ULONG nReturn = --m_nRefCount; |
| if ( m_nRefCount == 0 ) |
| delete this; |
| |
| return nReturn; |
| } |
| |
| //----------------------------------------------------------------------------------------- |
| STDMETHODIMP VistaFilePickerEventHandler::OnFileOk(IFileDialog* /*pDialog*/) |
| { |
| return E_NOTIMPL; |
| } |
| |
| //----------------------------------------------------------------------------------------- |
| STDMETHODIMP VistaFilePickerEventHandler::OnFolderChanging(IFileDialog* /*pDialog*/, |
| IShellItem* /*pFolder*/) |
| { |
| return E_NOTIMPL; |
| } |
| |
| //----------------------------------------------------------------------------------------- |
| STDMETHODIMP VistaFilePickerEventHandler::OnFolderChange(IFileDialog* /*pDialog*/) |
| { |
| impl_sendEvent(E_DIRECTORY_CHANGED, 0); |
| return S_OK; |
| } |
| |
| //----------------------------------------------------------------------------- |
| ::rtl::OUString lcl_getURLFromShellItem2 (IShellItem* pItem) |
| { |
| LPOLESTR pStr = NULL; |
| ::rtl::OUString sURL; |
| |
| SIGDN eConversion = SIGDN_FILESYSPATH; |
| HRESULT hr = pItem->GetDisplayName ( eConversion, &pStr ); |
| |
| if ( FAILED(hr) ) |
| { |
| eConversion = SIGDN_URL; |
| hr = pItem->GetDisplayName ( eConversion, &pStr ); |
| |
| if ( FAILED(hr) ) |
| return ::rtl::OUString(); |
| |
| sURL = ::rtl::OUString(reinterpret_cast<sal_Unicode*>(pStr)); |
| } |
| else |
| { |
| ::osl::FileBase::getFileURLFromSystemPath( reinterpret_cast<sal_Unicode*>(pStr), sURL ); |
| } |
| |
| CoTaskMemFree (pStr); |
| return sURL; |
| } |
| |
| //----------------------------------------------------------------------------------------- |
| void lcl_updateVersionListDirectly(IFileDialog* pDialog) |
| { |
| static const ::rtl::OUString SERVICENAME_REVISIONPERSISTENCE = ::rtl::OUString::createFromAscii("com.sun.star.document.DocumentRevisionListPersistence"); |
| static const ::sal_Int16 CONTROL_VERSIONLIST = css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_VERSION; |
| |
| TFileDialog iDialog (pDialog); |
| TFileOpenDialog iOpen ; |
| TFileDialogCustomize iCustomize; |
| |
| #ifdef __MINGW32__ |
| iDialog->QueryInterface(IID_IFileOpenDialog, (void**)(&iOpen)); |
| iDialog->QueryInterface(IID_IFileDialogCustomize, (void**)(&iCustomize)); |
| #else |
| iDialog.query(&iOpen ); |
| iDialog.query(&iCustomize); |
| #endif |
| |
| // make sure version list match to the current selection always ... |
| // at least an empty version list will be better then the wrong one .-) |
| iCustomize->RemoveAllControlItems(CONTROL_VERSIONLIST); |
| |
| HRESULT hResult = E_FAIL; |
| ComPtr< IShellItemArray > iItems; |
| ComPtr< IShellItem > iItem; |
| |
| if (iOpen.is()) |
| { |
| hResult = iOpen->GetSelectedItems(&iItems); |
| if (FAILED(hResult)) |
| return; |
| |
| DWORD nCount; |
| hResult = iItems->GetCount(&nCount); |
| if ( FAILED(hResult) ) |
| return; |
| |
| // we can show one version list only within control |
| if (nCount != 1) |
| return; |
| |
| hResult = iItems->GetItemAt(0, &iItem); |
| } |
| else |
| if (iDialog.is()) |
| hResult = iDialog->GetCurrentSelection(&iItem); |
| |
| if ( FAILED(hResult) ) |
| return; |
| |
| const ::rtl::OUString sURL = lcl_getURLFromShellItem2(iItem); |
| if (sURL.getLength() < 1) |
| return; |
| /* |
| INetURLObject aURL(sURL); |
| if (aURL.GetProtocol() != INET_PROT_FILE) |
| return; |
| |
| ::rtl::OUString sMain = aURL.GetMainURL(INetURLObject::NO_DECODE); |
| if ( ! ::utl::UCBContentHelper::IsDocument(sURL)) |
| return; |
| */ |
| try |
| { |
| css::uno::Reference< css::embed::XStorage > xStorage = ::comphelper::OStorageHelper::GetStorageFromURL(sURL, css::embed::ElementModes::READ); |
| if ( ! xStorage.is() ) |
| return; |
| |
| css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory(); |
| css::uno::Reference< css::document::XDocumentRevisionListPersistence > xReader (xSMGR->createInstance(SERVICENAME_REVISIONPERSISTENCE), css::uno::UNO_QUERY_THROW); |
| css::uno::Sequence< css::util::RevisionTag > lVersions = xReader->load(xStorage); |
| |
| for (::sal_Int32 i=0; i<lVersions.getLength(); ++i) |
| { |
| const css::util::RevisionTag& aTag = lVersions[i]; |
| iCustomize->AddControlItem(CONTROL_VERSIONLIST, i, reinterpret_cast<LPCTSTR>(aTag.Identifier.getStr())); |
| } |
| iCustomize->SetSelectedControlItem(CONTROL_VERSIONLIST, 0); |
| } |
| catch(const css::uno::Exception&) |
| {} |
| } |
| |
| //----------------------------------------------------------------------------------------- |
| STDMETHODIMP VistaFilePickerEventHandler::OnSelectionChange(IFileDialog* /*pDialog*/) |
| { |
| impl_sendEvent(E_FILE_SELECTION_CHANGED, 0); |
| //lcl_updateVersionListDirectly(pDialog); |
| return S_OK; |
| } |
| |
| //----------------------------------------------------------------------------------------- |
| STDMETHODIMP VistaFilePickerEventHandler::OnShareViolation(IFileDialog* /*pDialog*/ , |
| |
| IShellItem* /*pItem*/ , |
| |
| FDE_SHAREVIOLATION_RESPONSE* /*pResponse*/) |
| { |
| impl_sendEvent(E_CONTROL_STATE_CHANGED, css::ui::dialogs::CommonFilePickerElementIds::LISTBOX_FILTER); |
| return S_OK; |
| } |
| |
| //----------------------------------------------------------------------------------------- |
| STDMETHODIMP VistaFilePickerEventHandler::OnTypeChange(IFileDialog* pDialog) |
| { |
| UINT nFileTypeIndex; |
| HRESULT hResult = pDialog->GetFileTypeIndex( &nFileTypeIndex ); |
| |
| if ( hResult == S_OK ) |
| { |
| if ( m_pInternalNotify->onFileTypeChanged( nFileTypeIndex )) |
| impl_sendEvent(E_CONTROL_STATE_CHANGED, css::ui::dialogs::CommonFilePickerElementIds::LISTBOX_FILTER); |
| } |
| |
| return S_OK; |
| } |
| |
| //----------------------------------------------------------------------------------------- |
| STDMETHODIMP VistaFilePickerEventHandler::OnOverwrite(IFileDialog* /*pDialog*/ , |
| IShellItem* /*pItem*/ , |
| FDE_OVERWRITE_RESPONSE* /*pResponse*/) |
| { |
| return E_NOTIMPL; |
| } |
| |
| //----------------------------------------------------------------------------------------- |
| STDMETHODIMP VistaFilePickerEventHandler::OnItemSelected(IFileDialogCustomize* /*pCustomize*/, |
| |
| DWORD nIDCtl , |
| |
| DWORD /*nIDItem*/ ) |
| { |
| |
| impl_sendEvent(E_CONTROL_STATE_CHANGED, static_cast<sal_Int16>( nIDCtl )); |
| return S_OK; |
| } |
| |
| //----------------------------------------------------------------------------------------- |
| STDMETHODIMP VistaFilePickerEventHandler::OnButtonClicked(IFileDialogCustomize* /*pCustomize*/, |
| DWORD nIDCtl ) |
| { |
| |
| impl_sendEvent(E_CONTROL_STATE_CHANGED, static_cast<sal_Int16>( nIDCtl)); |
| return S_OK; |
| } |
| |
| //----------------------------------------------------------------------------------------- |
| STDMETHODIMP VistaFilePickerEventHandler::OnCheckButtonToggled(IFileDialogCustomize* /*pCustomize*/, |
| DWORD nIDCtl , |
| BOOL bChecked ) |
| { |
| if (nIDCtl == css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION) |
| m_pInternalNotify->onAutoExtensionChanged(bChecked); |
| |
| impl_sendEvent(E_CONTROL_STATE_CHANGED, static_cast<sal_Int16>( nIDCtl)); |
| |
| return S_OK; |
| } |
| |
| //----------------------------------------------------------------------------------------- |
| STDMETHODIMP VistaFilePickerEventHandler::OnControlActivating(IFileDialogCustomize* /*pCustomize*/, |
| DWORD nIDCtl ) |
| { |
| impl_sendEvent(E_CONTROL_STATE_CHANGED, static_cast<sal_Int16>( nIDCtl)); |
| return S_OK; |
| } |
| |
| //----------------------------------------------------------------------------------------- |
| void SAL_CALL VistaFilePickerEventHandler::addFilePickerListener( const css::uno::Reference< css::ui::dialogs::XFilePickerListener >& xListener ) |
| throw( css::uno::RuntimeException ) |
| { |
| m_lListener.addInterface(::getCppuType( (const css::uno::Reference< css::ui::dialogs::XFilePickerListener >*)NULL ), xListener); |
| } |
| |
| //----------------------------------------------------------------------------------------- |
| void SAL_CALL VistaFilePickerEventHandler::removeFilePickerListener( const css::uno::Reference< css::ui::dialogs::XFilePickerListener >& xListener ) |
| throw( css::uno::RuntimeException ) |
| { |
| m_lListener.removeInterface(::getCppuType( (const css::uno::Reference< css::ui::dialogs::XFilePickerListener >*)NULL ), xListener); |
| } |
| |
| //----------------------------------------------------------------------------------------- |
| void VistaFilePickerEventHandler::startListening( const TFileDialog& pBroadcaster ) |
| { |
| static const sal_Bool STARTUP_SUSPENDED = sal_True; |
| static const sal_Bool STARTUP_WORKING = sal_False; |
| |
| if (m_pDialog.is()) |
| return; |
| |
| m_pDialog = pBroadcaster; |
| m_pDialog->Advise(this, &m_nListenerHandle); |
| } |
| |
| //----------------------------------------------------------------------------------------- |
| void VistaFilePickerEventHandler::stopListening() |
| { |
| if (m_pDialog.is()) |
| { |
| m_pDialog->Unadvise(m_nListenerHandle); |
| m_pDialog.release(); |
| } |
| } |
| |
| static const ::rtl::OUString PROP_CONTROL_ID = ::rtl::OUString::createFromAscii("control_id"); |
| static const ::rtl::OUString PROP_PICKER_LISTENER = ::rtl::OUString::createFromAscii("picker_listener"); |
| |
| //----------------------------------------------------------------------------------------- |
| class AsyncPickerEvents : public RequestHandler |
| { |
| public: |
| |
| AsyncPickerEvents() |
| {} |
| |
| virtual ~AsyncPickerEvents() |
| {} |
| |
| virtual void before() |
| {} |
| |
| virtual void doRequest(const RequestRef& rRequest) |
| { |
| const ::sal_Int32 nEventID = rRequest->getRequest(); |
| const ::sal_Int16 nControlID = rRequest->getArgumentOrDefault(PROP_CONTROL_ID, (::sal_Int16)0); |
| const css::uno::Reference< css::ui::dialogs::XFilePickerListener > xListener = rRequest->getArgumentOrDefault(PROP_PICKER_LISTENER, css::uno::Reference< css::ui::dialogs::XFilePickerListener >()); |
| |
| if ( ! xListener.is()) |
| return; |
| |
| css::ui::dialogs::FilePickerEvent aEvent; |
| aEvent.ElementId = nControlID; |
| |
| switch (nEventID) |
| { |
| case VistaFilePickerEventHandler::E_FILE_SELECTION_CHANGED : |
| xListener->fileSelectionChanged(aEvent); |
| break; |
| |
| case VistaFilePickerEventHandler::E_DIRECTORY_CHANGED : |
| xListener->directoryChanged(aEvent); |
| break; |
| |
| case VistaFilePickerEventHandler::E_HELP_REQUESTED : |
| xListener->helpRequested(aEvent); |
| break; |
| |
| case VistaFilePickerEventHandler::E_CONTROL_STATE_CHANGED : |
| xListener->controlStateChanged(aEvent); |
| break; |
| |
| case VistaFilePickerEventHandler::E_DIALOG_SIZE_CHANGED : |
| xListener->dialogSizeChanged(); |
| break; |
| |
| // no default here. Let compiler detect changes on enum set ! |
| } |
| } |
| |
| virtual void after() |
| {} |
| }; |
| |
| //----------------------------------------------------------------------------------------- |
| void VistaFilePickerEventHandler::impl_sendEvent( EEventType eEventType, |
| ::sal_Int16 nControlID) |
| { |
| static AsyncRequests aNotify(RequestHandlerRef(new AsyncPickerEvents())); |
| |
| ::cppu::OInterfaceContainerHelper* pContainer = m_lListener.getContainer( ::getCppuType( ( const css::uno::Reference< css::ui::dialogs::XFilePickerListener >*) NULL ) ); |
| if ( ! pContainer) |
| return; |
| |
| ::cppu::OInterfaceIteratorHelper pIterator(*pContainer); |
| while (pIterator.hasMoreElements()) |
| { |
| try |
| { |
| css::uno::Reference< css::ui::dialogs::XFilePickerListener > xListener (pIterator.next(), css::uno::UNO_QUERY); |
| |
| RequestRef rRequest(new Request()); |
| rRequest->setRequest (eEventType); |
| rRequest->setArgument(PROP_PICKER_LISTENER, xListener); |
| if ( nControlID ) |
| rRequest->setArgument(PROP_CONTROL_ID, nControlID); |
| |
| aNotify.triggerRequestDirectly(rRequest); |
| //aNotify.triggerRequestNonBlocked(rRequest); |
| } |
| catch(const css::uno::RuntimeException&) |
| { |
| pIterator.remove(); |
| } |
| } |
| } |
| |
| } // namespace vista |
| } // namespace win32 |
| } // namespace fpicker |