/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. * Copyright 2010 Novell, Inc. * * OpenOffice.org - a multi-platform office productivity suite * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ #include "ODMAFilePicker.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef ODMA_LIB_HXX #include #include #endif // using ---------------------------------------------------------------- using namespace ::com::sun::star::beans; using namespace ::com::sun::star::lang; using namespace ::com::sun::star::ui::dialogs; using namespace ::com::sun::star::ucb; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::util; using namespace ::utl; //------------------------------------------------------------------------------------ // class ODMAFilePicker //------------------------------------------------------------------------------------ ODMAFilePicker::ODMAFilePicker( const Reference < XMultiServiceFactory >& xFactory ) : cppu::WeakComponentImplHelper9< XFilterManager, XFilterGroupManager, XFilePickerControlAccess, XFilePickerNotifier, XFilePreview, XInitialization, XCancellable, XEventListener, XServiceInfo>( m_rbHelperMtx ), m_bMultiSelectionMode( sal_False ), m_aDefaultName( ), m_aFiles( ), m_nDialogKind( OPEN ) { m_bUseDMS = ::odma::DMSsAvailable(); m_xSystemFilePicker = xFactory->createInstance( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.Win32FilePicker" ) )); } // XExecutableDialog functions void SAL_CALL ODMAFilePicker::setTitle( const ::rtl::OUString& aTitle ) throw (RuntimeException) { Reference< XExecutableDialog > xExecutableDialog( m_xSystemFilePicker, UNO_QUERY ); xExecutableDialog->setTitle( aTitle); } inline bool is_current_process_window(HWND hwnd) { DWORD pid; GetWindowThreadProcessId(hwnd, &pid); return (pid == GetCurrentProcessId()); } HWND choose_parent_window() { HWND hwnd_parent = GetForegroundWindow(); if (!is_current_process_window(hwnd_parent)) hwnd_parent = GetDesktopWindow(); return hwnd_parent; } sal_Int16 SAL_CALL ODMAFilePicker::execute( ) throw (RuntimeException) { ODMSTATUS status; ODMHANDLE handle; WORD count = 0; DWORD flags; status = NODMRegisterApp( &handle, ODM_API_VERSION, "sodma", (DWORD) choose_parent_window( ), NULL ); if (status == ODM_SUCCESS) { if (m_nDialogKind == OPEN) { const int MAXDOCS = 10; char docids[ODM_DOCID_MAX*MAXDOCS+1]; WORD docidslen = sizeof( docids ); flags = 0; if (m_bMultiSelectionMode) count = MAXDOCS; else count = 1; status = NODMSelectDocEx( handle, docids, &docidslen, &count, &flags, NULL ); if (status == ODM_SUCCESS) { // GroupWise doesn't set docidslen or count, so // calculate number of document IDs manually char *p = docids; count = 0; while (*p) { count++; p += strlen( p ) + 1; } } else if (status == ODM_E_NOSUPPORT) { status = NODMSelectDoc( handle, docids, &flags ); if (status == ODM_SUCCESS) count = 1; } NODMUnRegisterApp( handle ); if (status == ODM_SUCCESS) { rtl::OUString *strings = new rtl::OUString[count]; int i; char *p = docids; for (i = 0; i < count; i++) { // Insane API... the first element is a full URI, the rest // are just the "basenames" in the same "directory". if (i == 0) strings[0] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.odma:/" )) + rtl::OUString::createFromAscii( p ); else strings[i] = rtl::OUString::createFromAscii( p ); p += strlen( p ); } m_aFiles = Sequence< rtl::OUString >( strings, count ); delete[] strings; return ExecutableDialogResults::OK; } } else /* m_nDialogKind == SAVE */ { char newdocid[ODM_DOCID_MAX+1]; if (m_aDefaultName.getLength() == 0 || !m_aDefaultName.matchIgnoreAsciiCaseAsciiL( "::ODMA\\", 7, 0 )) { char tempdocid[ODM_DOCID_MAX+1]; status = NODMNewDoc( handle, tempdocid, ODM_SILENT, NULL, NULL ); if (status == ODM_SUCCESS) status = NODMSaveAs( handle, tempdocid, newdocid, NULL, NULL, NULL ); } else { rtl::OString sDefaultName = rtl::OUStringToOString( m_aDefaultName, RTL_TEXTENCODING_ASCII_US ); status = NODMSaveAs( handle, const_cast( sDefaultName.getStr() ), newdocid, NULL, NULL, NULL ); } NODMUnRegisterApp( handle ); if (status == ODM_SUCCESS) { rtl::OUString s( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.odma:/" )) + rtl::OUString::createFromAscii( newdocid ) ); // Create a Content for the odma URL so that // odma::ContentProvider will learn about the DOCID we // just created. ucbhelper::Content content( s, Reference< XCommandEnvironment >() ); m_aFiles = Sequence< rtl::OUString >( &s, 1 ); return ExecutableDialogResults::OK; } } } if (status == ODM_E_APPSELECT) { m_bUseDMS = sal_False; Reference< XExecutableDialog > xExecutableDialog( m_xSystemFilePicker, UNO_QUERY ); return xExecutableDialog->execute(); } // Fallback return ExecutableDialogResults::CANCEL; } // XFilePicker functions void SAL_CALL ODMAFilePicker::setMultiSelectionMode( sal_Bool bMode ) throw( RuntimeException ) { m_bMultiSelectionMode = bMode; Reference< XFilePicker > xFilePicker( m_xSystemFilePicker, UNO_QUERY ); xFilePicker->setMultiSelectionMode( bMode ); } void SAL_CALL ODMAFilePicker::setDefaultName( const rtl::OUString& aName ) throw( RuntimeException ) { // When editing a document from DMS, and doing Save As, this is // called twice, first with the complete DOCID, the second time // with the "extension" removed. Of course, this is bogus, as // DOCIDs should be treated as opaque strings, they don't have // "extensions". // In the GroupWise case a DOCID is like // ::ODMA\GRPWISE\FOO1.BAR.FOO-Bla_bla:12345.12 where the final // dot separates the version number, not an "extension". // // So ignore the second call. // // The second call without "extension" is done if the // XFilePickerControlAccess is set to have auto-extension turned // on. (See sfx2/source/dialog/filedlghelper.cxx: // FileDialogHelper_Impl::implInitializeFileName().) Thus we could // alternatively make sure that a getValue call to get // ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION returns // false. But that might be hard as we don't know in advance // whether the user will click the "use application dialog" // button. If so, we indeed do use auto-extensions. // // Yes, this is ugly, relying on knowing details on how this // function will be called. if ( m_aDefaultName.getLength() == 0 ) m_aDefaultName = aName; Reference< XFilePicker > xFilePicker( m_xSystemFilePicker, UNO_QUERY ); xFilePicker->setDefaultName( aName ); } void SAL_CALL ODMAFilePicker::setDisplayDirectory( const rtl::OUString& aDirectory ) throw( IllegalArgumentException, RuntimeException ) { m_aDisplayDirectory = aDirectory; Reference< XFilePicker > xFilePicker( m_xSystemFilePicker, UNO_QUERY ); xFilePicker->setDisplayDirectory( aDirectory ); } rtl::OUString SAL_CALL ODMAFilePicker::getDisplayDirectory( ) throw( RuntimeException ) { if (m_bUseDMS) return m_aDisplayDirectory; Reference< XFilePicker > xFilePicker( m_xSystemFilePicker, UNO_QUERY ); return xFilePicker->getDisplayDirectory(); } Sequence< rtl::OUString > SAL_CALL ODMAFilePicker::getFiles( ) throw( RuntimeException ) { if (m_bUseDMS) return m_aFiles; Reference< XFilePicker > xFilePicker( m_xSystemFilePicker, UNO_QUERY ); return xFilePicker->getFiles(); } // XFilePickerControlAccess functions void SAL_CALL ODMAFilePicker::setValue( sal_Int16 nElementID, sal_Int16 nControlAction, const Any& rValue ) throw( RuntimeException ) { Reference< XFilePickerControlAccess > xFilePickerControlAccess( m_xSystemFilePicker, UNO_QUERY ); xFilePickerControlAccess->setValue( nElementID, nControlAction, rValue ); } Any SAL_CALL ODMAFilePicker::getValue( sal_Int16 nElementID, sal_Int16 nControlAction ) throw( RuntimeException ) { Reference< XFilePickerControlAccess > xFilePickerControlAccess( m_xSystemFilePicker, UNO_QUERY ); return xFilePickerControlAccess->getValue( nElementID, nControlAction ); } void SAL_CALL ODMAFilePicker::setLabel( sal_Int16 nLabelID, const rtl::OUString& rValue ) throw ( RuntimeException ) { Reference< XFilePickerControlAccess > xFilePickerControlAccess( m_xSystemFilePicker, UNO_QUERY ); xFilePickerControlAccess->setLabel( nLabelID, rValue ); } rtl::OUString SAL_CALL ODMAFilePicker::getLabel( sal_Int16 nLabelID ) throw ( RuntimeException ) { Reference< XFilePickerControlAccess > xFilePickerControlAccess( m_xSystemFilePicker, UNO_QUERY ); return xFilePickerControlAccess->getLabel( nLabelID ); } void SAL_CALL ODMAFilePicker::enableControl( sal_Int16 nElementID, sal_Bool bEnable ) throw( RuntimeException ) { Reference< XFilePickerControlAccess > xFilePickerControlAccess( m_xSystemFilePicker, UNO_QUERY ); xFilePickerControlAccess->enableControl( nElementID, bEnable ); } // XFilePickerNotifier functions void SAL_CALL ODMAFilePicker::addFilePickerListener( const Reference< XFilePickerListener >& xListener ) throw ( RuntimeException ) { Reference< XFilePickerNotifier > xFilePickerNotifier( m_xSystemFilePicker, UNO_QUERY ); xFilePickerNotifier->addFilePickerListener( xListener ); } void SAL_CALL ODMAFilePicker::removeFilePickerListener( const Reference< XFilePickerListener >& xListener ) throw ( RuntimeException ) { Reference< XFilePickerNotifier > xFilePickerNotifier( m_xSystemFilePicker, UNO_QUERY ); xFilePickerNotifier->removeFilePickerListener( xListener ); } // XFilePreview functions Sequence< sal_Int16 > SAL_CALL ODMAFilePicker::getSupportedImageFormats( ) throw ( RuntimeException ) { Reference< XFilePreview > xFilePreview( m_xSystemFilePicker, UNO_QUERY ); return xFilePreview->getSupportedImageFormats(); } sal_Int32 SAL_CALL ODMAFilePicker::getTargetColorDepth( ) throw ( RuntimeException ) { Reference< XFilePreview > xFilePreview( m_xSystemFilePicker, UNO_QUERY ); return xFilePreview->getTargetColorDepth(); } sal_Int32 SAL_CALL ODMAFilePicker::getAvailableWidth( ) throw ( RuntimeException ) { Reference< XFilePreview > xFilePreview( m_xSystemFilePicker, UNO_QUERY ); return xFilePreview->getAvailableWidth(); } sal_Int32 SAL_CALL ODMAFilePicker::getAvailableHeight( ) throw ( RuntimeException ) { Reference< XFilePreview > xFilePreview( m_xSystemFilePicker, UNO_QUERY ); return xFilePreview->getAvailableHeight(); } void SAL_CALL ODMAFilePicker::setImage( sal_Int16 aImageFormat, const Any& rImage ) throw ( IllegalArgumentException, RuntimeException ) { Reference< XFilePreview > xFilePreview( m_xSystemFilePicker, UNO_QUERY ); xFilePreview->setImage( aImageFormat, rImage); } sal_Bool SAL_CALL ODMAFilePicker::setShowState( sal_Bool bShowState ) throw ( RuntimeException ) { Reference< XFilePreview > xFilePreview( m_xSystemFilePicker, UNO_QUERY ); return xFilePreview->setShowState( bShowState); } sal_Bool SAL_CALL ODMAFilePicker::getShowState( ) throw ( RuntimeException ) { Reference< XFilePreview > xFilePreview( m_xSystemFilePicker, UNO_QUERY ); return xFilePreview->getShowState(); } // XFilterGroupManager functions void SAL_CALL ODMAFilePicker::appendFilterGroup( const ::rtl::OUString& sGroupTitle, const Sequence< StringPair >& aFilters ) throw ( IllegalArgumentException, RuntimeException ) { Reference< XFilterGroupManager > xFilterGroupManager( m_xSystemFilePicker, UNO_QUERY ); xFilterGroupManager->appendFilterGroup( sGroupTitle, aFilters ); } // XFilterManager functions void SAL_CALL ODMAFilePicker::appendFilter( const rtl::OUString& aTitle, const rtl::OUString& aFilter ) throw( IllegalArgumentException, RuntimeException ) { Reference< XFilterManager > xFilterManager( m_xSystemFilePicker, UNO_QUERY ); xFilterManager->appendFilter( aTitle, aFilter ); } void SAL_CALL ODMAFilePicker::setCurrentFilter( const rtl::OUString& aTitle ) throw( IllegalArgumentException, RuntimeException ) { Reference< XFilterManager > xFilterManager( m_xSystemFilePicker, UNO_QUERY ); xFilterManager->setCurrentFilter( aTitle ); } rtl::OUString SAL_CALL ODMAFilePicker::getCurrentFilter( ) throw( RuntimeException ) { Reference< XFilterManager > xFilterManager( m_xSystemFilePicker, UNO_QUERY ); return xFilterManager->getCurrentFilter(); } // XInitialization functions void SAL_CALL ODMAFilePicker::initialize( const Sequence< Any >& aArguments ) throw ( Exception, RuntimeException ) { if (aArguments.getLength( ) > 0) { Any aAny = aArguments[0]; if ( (aAny.getValueType() == ::getCppuType((sal_Int16*)0)) || (aAny.getValueType() == ::getCppuType((sal_Int8*)0)) ) { sal_Int16 nTemplateId = -1; aAny >>= nTemplateId; switch (nTemplateId) { case TemplateDescription::FILEOPEN_SIMPLE: case TemplateDescription::FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE: case TemplateDescription::FILEOPEN_PLAY: case TemplateDescription::FILEOPEN_READONLY_VERSION: case TemplateDescription::FILEOPEN_LINK_PREVIEW: m_nDialogKind = OPEN; break; default: m_nDialogKind = SAVE; } } } Reference< XInitialization > xInitialization( m_xSystemFilePicker, UNO_QUERY ); xInitialization->initialize( aArguments ); } // XCancellable functions void SAL_CALL ODMAFilePicker::cancel( ) throw( ::com::sun::star::uno::RuntimeException ) { Reference< XCancellable > xCancellable( m_xSystemFilePicker, UNO_QUERY ); xCancellable->cancel(); } // XEventListener functions void SAL_CALL ODMAFilePicker::disposing( const ::com::sun::star::lang::EventObject& aEvent ) throw( RuntimeException ) { Reference< XEventListener > xEventListener( m_xSystemFilePicker, UNO_QUERY ); xEventListener->disposing( aEvent ); } // XServiceInfo functions rtl::OUString SAL_CALL ODMAFilePicker::getImplementationName( ) throw( RuntimeException ) { return impl_getStaticImplementationName(); } sal_Bool SAL_CALL ODMAFilePicker::supportsService( const rtl::OUString& sServiceName ) throw( RuntimeException ) { Sequence< rtl::OUString > seqServiceNames = getSupportedServiceNames(); const rtl::OUString* pArray = seqServiceNames.getConstArray(); for ( sal_Int32 i = 0; i < seqServiceNames.getLength(); i++ ) { if ( sServiceName == pArray[i] ) { return sal_True ; } } return sal_False ; } Sequence< rtl::OUString > SAL_CALL ODMAFilePicker::getSupportedServiceNames( ) throw( RuntimeException ) { return impl_getStaticSupportedServiceNames(); } Sequence< rtl::OUString > ODMAFilePicker::impl_getStaticSupportedServiceNames( ) { Sequence< rtl::OUString > seqServiceNames( 2 ); rtl::OUString* pArray = seqServiceNames.getArray(); pArray[0] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.ODMAFilePicker" )); // Super-ugly, but check the function sal_Bool // lcl_isSystemFilePicker( const Reference< XFilePicker >& ) in // sfx2/source/dialog/filedlghelper.cxx // Lovely undocumented coupling right across abstraction layers, // isn't it? If we don't claim to implement this "service" (which // is not defined in any IDL file, btw), we get hangs. pArray[1] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.SystemFilePicker" )); return seqServiceNames ; } rtl::OUString ODMAFilePicker::impl_getStaticImplementationName( ) { return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.svtools.ODMAFilePicker" )); } Reference< XInterface > SAL_CALL ODMAFilePicker::impl_createInstance( const Reference< XComponentContext >& rxContext) throw( Exception ) { Reference< XMultiServiceFactory > xServiceManager (rxContext->getServiceManager(), UNO_QUERY_THROW); return Reference< XInterface >( *new ODMAFilePicker( xServiceManager ) ); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */