/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * 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 . */ #include #include #include #include #include #include #include "FilePicker.hxx" #include "WinFileOpenImpl.hxx" #include "FPServiceInfo.hxx" #include "../misc/WinImplHelper.hxx" #include #include "filepickereventnotification.hxx" #include using namespace com::sun::star; using namespace ::com::sun::star::ui::dialogs; using namespace ::com::sun::star::ui::dialogs::TemplateDescription; #define FILE_PICKER_DLL_NAME L"fps.dll" namespace { // controlling event notifications const bool STARTUP_SUSPENDED = true; uno::Sequence SAL_CALL FilePicker_getSupportedServiceNames() { uno::Sequence aRet(2); aRet[0] = "com.sun.star.ui.dialogs.FilePicker"; aRet[1] = "com.sun.star.ui.dialogs.SystemFilePicker"; return aRet; } } CFilePicker::CFilePicker( const uno::Reference& xServiceMgr) : CFilePicker_Base(m_rbHelperMtx), m_xServiceMgr(xServiceMgr), m_aAsyncEventNotifier(rBHelper) { HINSTANCE hInstance = GetModuleHandleW(FILE_PICKER_DLL_NAME); SAL_WARN_IF( !hInstance, "fpicker", "The name of the service dll must have changed" ); // create a default FileOpen dialog without any additional ui elements m_pImpl = std::unique_ptr< CWinFileOpenImpl >( new CWinFileOpenImpl( this, true, 0, 0, hInstance ) ); } // XFPEventListenerManager void SAL_CALL CFilePicker::addFilePickerListener(const uno::Reference& xListener) { if ( rBHelper.bDisposed ) throw lang::DisposedException( "object is already disposed", static_cast< XFilePicker2* >( this ) ); if ( !rBHelper.bInDispose && !rBHelper.bDisposed ) rBHelper.aLC.addInterface(cppu::UnoType::get(), xListener ); } void SAL_CALL CFilePicker::removeFilePickerListener(const uno::Reference& xListener ) { if ( rBHelper.bDisposed ) throw lang::DisposedException( "object is already disposed", static_cast< XFilePicker2* >( this ) ); rBHelper.aLC.removeInterface(cppu::UnoType::get(), xListener ); } // XEventListener void SAL_CALL CFilePicker::disposing(const lang::EventObject& aEvent) { uno::Reference xFilePickerListener(aEvent.Source, css::uno::UNO_QUERY); if (xFilePickerListener.is()) removeFilePickerListener(xFilePickerListener); } void SAL_CALL CFilePicker::fileSelectionChanged(FilePickerEvent aEvent) { aEvent.Source.set(static_cast(this)); m_aAsyncEventNotifier.notifyEvent( new CFilePickerParamEventNotification(&XFilePickerListener::fileSelectionChanged,aEvent)); } void SAL_CALL CFilePicker::directoryChanged(FilePickerEvent aEvent) { aEvent.Source.set(static_cast(this)); m_aAsyncEventNotifier.notifyEvent( new CFilePickerParamEventNotification(&XFilePickerListener::directoryChanged,aEvent)); } void SAL_CALL CFilePicker::controlStateChanged(FilePickerEvent aEvent) { aEvent.Source.set(static_cast(this)); m_aAsyncEventNotifier.notifyEvent( new CFilePickerParamEventNotification(&XFilePickerListener::controlStateChanged,aEvent)); } void SAL_CALL CFilePicker::dialogSizeChanged() { m_aAsyncEventNotifier.notifyEvent( new CFilePickerEventNotification(&XFilePickerListener::dialogSizeChanged)); } // If there are more than one listener the return value of the last one wins OUString SAL_CALL CFilePicker::helpRequested(FilePickerEvent aEvent) const { OUString aHelpText; ::cppu::OInterfaceContainerHelper* pICHelper = rBHelper.getContainer( cppu::UnoType::get()); if (pICHelper) { ::cppu::OInterfaceIteratorHelper iter(*pICHelper); while(iter.hasMoreElements()) { try { /* if there are multiple listeners responding to this notification the next response overwrites the one before if it is not empty */ OUString temp; uno::Reference xFPListener(iter.next(), uno::UNO_QUERY); if (xFPListener.is()) { temp = xFPListener->helpRequested(aEvent); if (temp.getLength()) aHelpText = temp; } } catch(uno::RuntimeException&) { OSL_FAIL( "RuntimeException during event dispatching" ); } } } return aHelpText; } bool CFilePicker::startupEventNotification(bool bStartupSuspended) { return m_aAsyncEventNotifier.startup(bStartupSuspended); } void CFilePicker::shutdownEventNotification() { m_aAsyncEventNotifier.shutdown(); } void CFilePicker::suspendEventNotification() { m_aAsyncEventNotifier.suspend(); } void CFilePicker::resumeEventNotification() { m_aAsyncEventNotifier.resume(); } // XFilePicker void SAL_CALL CFilePicker::setMultiSelectionMode(sal_Bool bMode) { OSL_ASSERT(nullptr != m_pImpl.get()); osl::MutexGuard aGuard(m_aMutex); m_pImpl->setMultiSelectionMode(bMode); } void SAL_CALL CFilePicker::setTitle(const OUString& aTitle) { OSL_ASSERT(nullptr != m_pImpl.get()); osl::MutexGuard aGuard(m_aMutex); m_pImpl->setTitle(aTitle); } void SAL_CALL CFilePicker::appendFilter(const OUString& aTitle, const OUString& aFilter) { OSL_ASSERT(nullptr != m_pImpl.get()); osl::MutexGuard aGuard(m_aMutex); m_pImpl->appendFilter(aTitle, aFilter); } void SAL_CALL CFilePicker::setCurrentFilter(const OUString& aTitle) { OSL_ASSERT(nullptr != m_pImpl.get()); osl::MutexGuard aGuard(m_aMutex); m_pImpl->setCurrentFilter(aTitle); } OUString SAL_CALL CFilePicker::getCurrentFilter() { OSL_ASSERT(nullptr != m_pImpl.get()); osl::MutexGuard aGuard(m_aMutex); return m_pImpl->getCurrentFilter(); } void SAL_CALL CFilePicker::appendFilterGroup(const OUString& sGroupTitle, const uno::Sequence& aFilters) { OSL_ASSERT(nullptr != m_pImpl.get()); osl::MutexGuard aGuard(m_aMutex); m_pImpl->appendFilterGroup(sGroupTitle, aFilters); } void SAL_CALL CFilePicker::setDefaultName(const OUString& aName) { OSL_ASSERT(nullptr != m_pImpl.get()); osl::MutexGuard aGuard(m_aMutex); m_pImpl->setDefaultName(aName); } void SAL_CALL CFilePicker::setDisplayDirectory(const OUString& aDirectory) { OSL_ASSERT(nullptr != m_pImpl.get()); osl::MutexGuard aGuard(m_aMutex); m_pImpl->setDisplayDirectory(aDirectory); } OUString SAL_CALL CFilePicker::getDisplayDirectory() { OSL_ASSERT(nullptr != m_pImpl.get()); osl::MutexGuard aGuard(m_aMutex); return m_pImpl->getDisplayDirectory(); } uno::Sequence SAL_CALL CFilePicker::getFiles() { OSL_ASSERT(nullptr != m_pImpl.get()); osl::MutexGuard aGuard(m_aMutex); return m_pImpl->getFiles(); } uno::Sequence< OUString > SAL_CALL CFilePicker::getSelectedFiles() { OSL_ASSERT(nullptr != m_pImpl.get()); osl::MutexGuard aGuard(m_aMutex); const uno::Sequence< OUString > lSource = m_pImpl->getFiles(); const ::sal_Int32 c = lSource.getLength(); if (c < 2) return lSource; const OUString sPath = lSource[0]; ::std::vector< OUString > lTarget; ::sal_Int32 i = 1; for (i=1; i 0) { // a) file contains own path ! lTarget.push_back(sFile); } else { // b) file is relative to given path OUStringBuffer sFull(256); sFull.append (sPath); sFull.append("/" ); sFull.append (sFile); lTarget.push_back(sFull.makeStringAndClear()); } } return comphelper::containerToSequence(lTarget); } sal_Int16 SAL_CALL CFilePicker::execute() { OSL_ASSERT(nullptr != m_pImpl.get()); sal_Int16 ret; if (startupEventNotification(STARTUP_SUSPENDED)) { // we should not block in this call else // in the case of an event the client can't // call another function an we run into a // deadlock !!!!! ret = m_pImpl->execute( ); shutdownEventNotification(); } else { OSL_FAIL("Could not start event notifier thread!"); throw uno::RuntimeException( "Error executing dialog", static_cast(this)); } return ret; } void SAL_CALL CFilePicker::setValue(sal_Int16 aControlId, sal_Int16 aControlAction, const uno::Any& aValue) { OSL_ASSERT(nullptr != m_pImpl.get()); osl::MutexGuard aGuard(m_aMutex); m_pImpl->setValue(aControlId, aControlAction, aValue); } uno::Any SAL_CALL CFilePicker::getValue(sal_Int16 aControlId, sal_Int16 aControlAction) { OSL_ASSERT(nullptr != m_pImpl.get()); osl::MutexGuard aGuard(m_aMutex); return m_pImpl->getValue(aControlId, aControlAction); } void SAL_CALL CFilePicker::enableControl(sal_Int16 aControlId, sal_Bool bEnable) { OSL_ASSERT( nullptr != m_pImpl.get( ) ); osl::MutexGuard aGuard( m_aMutex ); m_pImpl->enableControl( aControlId, bEnable ); } void SAL_CALL CFilePicker::setLabel(sal_Int16 aControlId, const OUString& aLabel) { OSL_ASSERT(nullptr != m_pImpl.get()); osl::MutexGuard aGuard(m_aMutex); m_pImpl->setLabel(aControlId, aLabel); } OUString SAL_CALL CFilePicker::getLabel(sal_Int16 aControlId) { OSL_ASSERT(nullptr != m_pImpl.get()); osl::MutexGuard aGuard(m_aMutex); return m_pImpl->getLabel(aControlId); } uno::Sequence SAL_CALL CFilePicker::getSupportedImageFormats() { OSL_ASSERT(nullptr != m_pImpl.get()); osl::MutexGuard aGuard(m_aMutex); return m_pImpl->getSupportedImageFormats(); } sal_Int32 SAL_CALL CFilePicker::getTargetColorDepth() { OSL_ASSERT(nullptr != m_pImpl.get()); osl::MutexGuard aGuard(m_aMutex); return m_pImpl->getTargetColorDepth(); } sal_Int32 SAL_CALL CFilePicker::getAvailableWidth() { OSL_ASSERT(nullptr != m_pImpl.get()); osl::MutexGuard aGuard(m_aMutex); return m_pImpl->getAvailableWidth(); } sal_Int32 SAL_CALL CFilePicker::getAvailableHeight() { OSL_ASSERT(nullptr != m_pImpl.get()); osl::MutexGuard aGuard(m_aMutex); return m_pImpl->getAvailableHeight(); } void SAL_CALL CFilePicker::setImage(sal_Int16 aImageFormat, const uno::Any& aImage) { OSL_ASSERT(nullptr != m_pImpl.get()); osl::MutexGuard aGuard(m_aMutex); m_pImpl->setImage(aImageFormat, aImage); } sal_Bool SAL_CALL CFilePicker::setShowState(sal_Bool bShowState) { OSL_ASSERT(nullptr != m_pImpl.get()); osl::MutexGuard aGuard(m_aMutex); return m_pImpl->setShowState(bShowState); } sal_Bool SAL_CALL CFilePicker::getShowState() { OSL_ASSERT(nullptr != m_pImpl.get()); osl::MutexGuard aGuard(m_aMutex); return m_pImpl->getShowState(); } void SAL_CALL CFilePicker::initialize(const uno::Sequence& aArguments) { // parameter checking uno::Any aAny; if ( 0 == aArguments.getLength( ) ) throw lang::IllegalArgumentException( "no arguments", static_cast(this), 1); aAny = aArguments[0]; if ( (aAny.getValueType() != ::cppu::UnoType::get()) && (aAny.getValueType() != ::cppu::UnoType::get()) ) throw lang::IllegalArgumentException( "invalid argument type", static_cast(this), 1); sal_Int16 templateId = -1; aAny >>= templateId; bool bFileOpenDialog = true; sal_uInt32 winResTemplateId = 0; switch ( templateId ) { case FILEOPEN_SIMPLE: bFileOpenDialog = true; break; case FILESAVE_SIMPLE: bFileOpenDialog = false; break; case FILESAVE_AUTOEXTENSION_PASSWORD: bFileOpenDialog = false; winResTemplateId = TMPL2000_FILESAVE_AUTOEXT_PASSWORD_BOX_ID; break; case FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS: bFileOpenDialog = false; winResTemplateId = TMPL2000_AUTOEXT_PASSWORD_FILTEROPTION_BOX; break; case FILESAVE_AUTOEXTENSION_SELECTION: bFileOpenDialog = false; winResTemplateId = TMPL2000_AUTOEXT_SELECTION_BOX; break; case FILESAVE_AUTOEXTENSION_TEMPLATE: bFileOpenDialog = false; winResTemplateId = TMPL2000_FILEOPEN_AUTOEXT_TEMPLATE_BOX_ID; break; case FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE: winResTemplateId = TMPL2000_FILEOPEN_LINK_PREVIEW_BOX_ID; break; case FILEOPEN_PLAY: case FILEOPEN_LINK_PLAY: //FIXME: FILEOPEN_LINK_PLAY needs an own template, no idea how to create one winResTemplateId = TMPL2000_PLAY_PUSHBUTTON; break; case FILEOPEN_READONLY_VERSION: winResTemplateId = TMPL2000_FILEOPEN_READONLY_VERSION_BOX_ID; break; case FILEOPEN_LINK_PREVIEW: case FILEOPEN_PREVIEW: //FIXME: FILEOPEN_PREVIEW needs an own template, no idea how to create one winResTemplateId = TMPL2000_FILEOPEN_LINK_PREVIEW_BOX_SIMPLE_ID; break; case FILESAVE_AUTOEXTENSION: bFileOpenDialog = false; winResTemplateId = TMPL2000_FILESAVE_AUTOEXT; break; default: throw lang::IllegalArgumentException( "Unknown template", static_cast< XFilePicker2* >( this ), 1 ); } HINSTANCE hInstance = GetModuleHandle( FILE_PICKER_DLL_NAME ); SAL_WARN_IF( !hInstance, "fpicker", "The name of the service dll must have changed" ); // create a new impl-class here based on the // given string, if the given string is empty // we do nothing m_pImpl = std::unique_ptr< CWinFileOpenImpl >( new CWinFileOpenImpl( this, bFileOpenDialog, 0, winResTemplateId, hInstance ) ); } void SAL_CALL CFilePicker::cancel() { OSL_ASSERT(m_pImpl.get()); osl::MutexGuard aGuard(m_aMutex); m_pImpl->cancel(); } // XServiceInfo OUString SAL_CALL CFilePicker::getImplementationName() { return OUString(FILE_PICKER_IMPL_NAME); } sal_Bool SAL_CALL CFilePicker::supportsService(const OUString& ServiceName) { return cppu::supportsService(this, ServiceName); } uno::Sequence SAL_CALL CFilePicker::getSupportedServiceNames() { return FilePicker_getSupportedServiceNames(); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */