diff options
author | Oliver Bolte <obo@openoffice.org> | 2005-04-13 07:54:11 +0000 |
---|---|---|
committer | Oliver Bolte <obo@openoffice.org> | 2005-04-13 07:54:11 +0000 |
commit | 90fcf5718668f0f9f41ac141a7fc4306633e693a (patch) | |
tree | 5858c2352f6d7a5c87826341bc97f289872729af /fpicker | |
parent | 35ff93a2d1abad1c1571f68405139d2ef320d763 (diff) |
INTEGRATION: CWS visibility03 (1.1.2); FILE ADDED
2005/03/26 15:46:38 mhu 1.1.2.2: #i45006# Manual merge after cwsresync.
2005/03/24 16:44:07 mhu 1.1.2.1: #i45006# Factored out and moved from svtools/source/filepicker/
Diffstat (limited to 'fpicker')
-rw-r--r-- | fpicker/source/office/iodlg.cxx | 3517 |
1 files changed, 3517 insertions, 0 deletions
diff --git a/fpicker/source/office/iodlg.cxx b/fpicker/source/office/iodlg.cxx new file mode 100644 index 000000000000..633ebbf65615 --- /dev/null +++ b/fpicker/source/office/iodlg.cxx @@ -0,0 +1,3517 @@ +/************************************************************************* + * + * $RCSfile: iodlg.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: obo $ $Date: 2005-04-13 08:54:11 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (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.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +// includes -------------------------------------------------------------- + +#include "iodlg.hxx" + +#ifndef _STREAM_HXX +#include <tools/stream.hxx> +#endif +#ifndef _URLOBJ_HXX //autogen +#include <tools/urlobj.hxx> +#endif + +#ifndef _SV_FIXED_HXX +#include <vcl/fixed.hxx> +#endif +#ifndef _SV_LSTBOX_HXX +#include <vcl/lstbox.hxx> +#endif +#ifndef _SV_MSGBOX_HXX +#include <vcl/msgbox.hxx> +#endif +#ifndef _SV_SVAPP_HXX +#include <vcl/svapp.hxx> +#endif +#ifndef _SV_TIMER_HXX +#include <vcl/timer.hxx> +#endif + +#ifndef _UNOTOOLS_UCBHELPER_HXX +#include <unotools/ucbhelper.hxx> +#endif +#ifndef _UCBHELPER_CONTENTBROKER_HXX +#include <ucbhelper/contentbroker.hxx> +#endif + +#ifndef _EHDL_HXX +#include "svtools/ehdl.hxx" +#endif +#ifndef SVTOOLS_URIHELPER_HXX +#include "svtools/urihelper.hxx" +#endif +#ifndef INCLUDED_SVTOOLS_PATHOPTIONS_HXX +#include "svtools/pathoptions.hxx" +#endif +#ifndef INCLUDED_SVTOOLS_VIEWOPTIONS_HXX +#include "svtools/viewoptions.hxx" +#endif +#ifndef _SVT_FILEVIEW_HXX +#include "svtools/fileview.hxx" +#endif + +#ifndef _SVTOOLS_INETOPTIONS_HXX_ +#include "svtools/inetoptions.hxx" +#endif +#ifndef _SFXECODE_HXX +#include "svtools/sfxecode.hxx" +#endif +#ifndef _SVARRAY_HXX +#include "svtools/svarray.hxx" +#endif +#ifndef _SVTABBX_HXX +#include "svtools/svtabbx.hxx" +#endif + +#define _SVSTDARR_USHORTS +#define _SVSTDARR_STRINGSDTOR +#include "svtools/svstdarr.hxx" + +#ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_ +#include <toolkit/helper/vclunohelper.hxx> +#endif +#ifndef _UNOTOOLS_LOCALFILEHELPER_HXX +#include <unotools/localfilehelper.hxx> +#endif + +#ifndef _SVTOOLS_HRC +#include "svtools/svtools.hrc" +#endif +#ifndef _SVT_HELPID_HRC +#include "svtools/helpid.hrc" +#endif +#ifndef _SVTOOLS_IODLGIMPL_HRC +#include "iodlg.hrc" +#endif +#ifndef INCLUDED_RTL_INSTANCE_HXX +#include "rtl/instance.hxx" +#endif + +#ifndef SVTOOLS_SOURCE_FILEPICKER_ASYNCFILEPICKER_HXX +#include "asyncfilepicker.hxx" +#endif +#ifndef _IODLGIMP_HXX +#include "iodlgimp.hxx" +#endif +#ifndef _SVTOOLS_INETTBC_HXX +#include "svtools/inettbc.hxx" +#endif +#ifndef INCLUDED_SVTOOLS_SYSLOCALE_HXX +#include "svtools/syslocale.hxx" +#endif +#ifndef SVT_QUERYFOLDER_HXX +#include "svtools/QueryFolderName.hxx" +#endif +#ifndef _RTL_USTRING_HXX +#include <rtl/ustring.hxx> +#endif + +#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_ +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#endif +#ifndef _COM_SUN_STAR_UCB_XCONTENTPROVIDERMANAGER_HPP_ +#include <com/sun/star/ucb/XContentProviderManager.hpp> +#endif +#ifndef _COM_SUN_STAR_UCB_XREMOTECONTENTPROVIDERSUPPLIER_HPP_ +#include <com/sun/star/ucb/XRemoteContentProviderSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_UI_DIALOGS_COMMONFILEPICKERELEMENTIDS_HPP_ +#include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp> +#endif +#ifndef _COM_SUN_STAR_UI_DIALOGS_EXTENDEDFILEPICKERELEMENTIDS_HPP_ +#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp> +#endif +#ifndef _COM_SUN_STAR_UI_DIALOGS_CONTROLACTIONS_HPP_ +#include <com/sun/star/ui/dialogs/ControlActions.hpp> +#endif +#ifndef _COM_SUN_STAR_BEANS_PROPERTYVALUE_HPP_ +#include <com/sun/star/beans/PropertyValue.hpp> +#endif + +#ifndef _COM_SUN_STAR_UTIL_URL_HPP_ +#include <com/sun/star/util/URL.hpp> +#endif +#ifndef _COM_SUN_STAR_UNO_EXCEPTION_HPP_ +#include <com/sun/star/uno/Exception.hpp> +#endif +#ifndef _COM_SUN_STAR_UNO_REFERENCE_HXX_ +#include <com/sun/star/uno/Reference.hxx> +#endif +#ifndef _COM_SUN_STAR_UTIL_XURLTRANSFORMER_HPP_ +#include <com/sun/star/util/XURLTransformer.hpp> +#endif +#ifndef _COM_SUN_STAR_UNO_RUNTIMEEXCEPTION_HPP_ +#include <com/sun/star/uno/RuntimeException.hpp> +#endif +#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_ +#include <com/sun/star/beans/XPropertySet.hpp> +#endif + +#ifndef _UNOTOOLS_PROCESSFACTORY_HXX +#include <comphelper/processfactory.hxx> +#endif + +#ifndef _OSL_FILE_H_ +#include <osl/file.h> +#endif +#ifndef _SV_WAITOBJ_HXX +#include <vcl/waitobj.hxx> +#endif + +// #97148# ------------------------------------ +#ifndef _COM_SUN_STAR_TASK_XINTERACTIONHANDLER_HPP_ +#include <com/sun/star/task/XInteractionHandler.hpp> +#endif +#ifndef _COM_SUN_STAR_UCB_INTERACTIVEAUGMENTEDIOEXCEPTION_HPP_ +#include "com/sun/star/ucb/InteractiveAugmentedIOException.hpp" +#endif + +#ifndef SVTOOLS_FILEPICKER_INTERACTION_HXX +#include "fpinteraction.hxx" +#endif +#ifndef _OSL_PROCESS_H_ +#include <osl/process.h> +#endif +#ifndef _COMPHELPER_INTERACTION_HXX_ +#include <comphelper/interaction.hxx> +#endif + +#include <algorithm> +#include <functional> + +//#define AUTOSELECT_USERFILTER + // define this for the experimental feature of user-filter auto selection + // means if the user enters e.g. *.doc<enter>, and there is a filter which is responsible for *.doc files (only), + // then this filter is selected automatically + +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::ui::dialogs; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::ucb; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::task; +using namespace ::utl; +using namespace ::svt; + +using namespace ExtendedFilePickerElementIds; +using namespace CommonFilePickerElementIds; +using namespace InternalFilePickerElementIds; + +#define IODLG_CONFIGNAME String(RTL_CONSTASCII_USTRINGPARAM("FileDialog")) +#define IMPGRF_CONFIGNAME String(RTL_CONSTASCII_USTRINGPARAM("ImportGraphicDialog")) + +#define GET_DECODED_NAME(aObj) \ + aObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET ) + +// Zeit die beim Traveln in der Filterbox gewartet wird, +// bis in der Browsebox gefiltert wird ( in ms ). +#define TRAVELFILTER_TIMEOUT 750 + +#define WIDTH_ADDITION 15 + +// functions ------------------------------------------------------------- + +namespace +{ + + //----------------------------------------------------------------------------- + String getMostCurrentFilter( SvtExpFileDlg_Impl* pImpl ) + { + DBG_ASSERT( pImpl, "invalid impl pointer" ); + const SvtFileDialogFilter_Impl* pFilter = pImpl->_pUserFilter; + + if ( !pFilter ) + pFilter = pImpl->GetCurFilter(); + + // Filtern. + if ( !pFilter ) + return String(); + + return pFilter->GetType(); + } + + //----------------------------------------------------------------------------- + sal_Bool restoreCurrentFilter( SvtExpFileDlg_Impl* _pImpl ) + { + DBG_ASSERT( _pImpl->GetCurFilter(), "restoreCurrentFilter: no current filter!" ); + DBG_ASSERT( _pImpl->GetCurFilterDisplayName().Len(), "restoreCurrentFilter: no current filter (no display name)!" ); + + _pImpl->SelectFilterListEntry( _pImpl->GetCurFilterDisplayName() ); + +#ifdef DBG_UTIL + String sSelectedDisplayName; + DBG_ASSERT( ( _pImpl->GetSelectedFilterEntry( sSelectedDisplayName ) == _pImpl->GetCurFilter() ) + && ( sSelectedDisplayName == _pImpl->GetCurFilterDisplayName() ), + "restoreCurrentFilter: inconsistence!" ); +#endif + return _pImpl->m_bNeedDelayedFilterExecute; + } + + //----------------------------------------------------------------------------- + String GetFsysExtension_Impl( const String& rFile ) + { + const sal_Unicode* p0 = rFile.GetBuffer(); + const sal_Unicode* p1 = p0 + rFile.Len() - 1; + while ( p1 >= p0 && *p1 != sal_Unicode( '.' ) ) + p1--; + if ( p1 >= p0 ) + return String( rFile.Copy( p1 - p0 + 1 ) ); + return String(); + } + + //----------------------------------------------------------------------------- + void SetFsysExtension_Impl( String& rFile, const String& rExtension ) + { + const sal_Unicode* p0 = rFile.GetBuffer(); + const sal_Unicode* p1 = p0 + rFile.Len() - 1; + while ( p1 >= p0 && *p1 != sal_Unicode( '.' ) ) + p1--; + if ( p1 >= p0 ) + // remove old extension + rFile.Erase( p1 - p0 + 1 - ( rExtension.Len() > 0 ? 0 : 1 ) ); + else if ( rExtension.Len() ) + // no old extension + rFile += sal_Unicode( '.' ); + rFile += rExtension; + } + + //----------------------------------------------------------------------------- + sal_Bool IsFileURL( const String& rURL ) + { + return ( INetURLObject::CompareProtocolScheme( rURL ) == INET_PROT_FILE ); + } + + //----------------------------------------------------------------------------- + // move the control with the given offset + void lcl_MoveControl( Control* _pControl, sal_Int32 _nDeltaX, sal_Int32 _nDeltaY, sal_Int32* _pMaxY = NULL ) + { + if ( _pControl ) + { + Point aNewPos = _pControl->GetPosPixel(); + + // adjust the vertical position + aNewPos.Y() += _nDeltaY; + if ( _pMaxY && ( aNewPos.Y() > *_pMaxY ) ) + *_pMaxY = aNewPos.Y(); + + // adjust the horizontal position + aNewPos.X() += _nDeltaX; + + _pControl->SetPosPixel( aNewPos ); + } + } + + //------------------------------------------------------------------------- + void lcl_autoUpdateFileExtension( SvtFileDialog* _pDialog ) + { + // if auto extension is enabled .... + if ( _pDialog->isAutoExtensionEnabled() ) + { + // automatically switch to the extension of the (maybe just newly selected) extension + String aNewFile = _pDialog->getCurrentFileText( ); + String aExt = GetFsysExtension_Impl( aNewFile ); + + // but only if there already is an extension + if ( aExt.Len() ) + { + // check if it is a real file extension, and not only the "post-dot" part in + // a directory name + // 28.03.2002 - 98337 - fs@openoffice.org + sal_Bool bRealExtensions = sal_True; + if ( STRING_NOTFOUND != aExt.Search( '/' ) ) + bRealExtensions = sal_False; + else if ( STRING_NOTFOUND != aExt.Search( '\\' ) ) + bRealExtensions = sal_False; + else + { + // no easy way to tell, because the part containing the dot already is the last + // segment of the complete file name + // So we have to check if the file name denotes a folder or a file. + // For performance reasons, we do this for file urls only + INetURLObject aURL( aNewFile ); + if ( INET_PROT_NOT_VALID == aURL.GetProtocol() ) + { + String sURL; + if ( ::utl::LocalFileHelper::ConvertPhysicalNameToURL( aNewFile, sURL ) ) + aURL = INetURLObject( sURL ); + } + if ( INET_PROT_FILE == aURL.GetProtocol() ) + { + // #97148# & #102204# ----- + try + { + bRealExtensions = !_pDialog->ContentIsFolder( aURL.GetMainURL( INetURLObject::NO_DECODE ) ); + } + catch( ::com::sun::star::uno::Exception& ) + { + DBG_WARNING( "Exception in lcl_autoUpdateFileExtension" ); + } + } + } + + if ( bRealExtensions ) + { + SetFsysExtension_Impl( aNewFile, _pDialog->GetDefaultExt() ); + _pDialog->setCurrentFileText( aNewFile ); + } + } + } + } + + //------------------------------------------------------------------------- + sal_Bool lcl_getHomeDirectory( const String& _rForURL, String& /* [out] */ _rHomeDir ) + { + _rHomeDir.Erase(); + + // now ask the content broker for a provider for this scheme + //================================================================= + try + { + // get the content provider manager + ::ucb::ContentBroker* pBroker = ::ucb::ContentBroker::get(); + Reference< XContentProviderManager > xProviderManager; + if ( pBroker ) + xProviderManager = pBroker->getContentProviderManagerInterface(); + + //================================================================= + // get the provider for the current scheme + Reference< XContentProvider > xProvider; + if ( xProviderManager.is() ) + xProvider = xProviderManager->queryContentProvider( _rForURL ); + + DBG_ASSERT( xProvider.is(), "lcl_getHomeDirectory: could not find a (valid) content provider for the current URL!" ); + Reference< XPropertySet > xProviderProps( xProvider, UNO_QUERY ); + if ( xProviderProps.is() ) + { + Reference< XPropertySetInfo > xPropInfo = xProviderProps->getPropertySetInfo(); + const ::rtl::OUString sHomeDirPropertyName( RTL_CONSTASCII_USTRINGPARAM( "HomeDirectory" ) ); + if ( !xPropInfo.is() || xPropInfo->hasPropertyByName( sHomeDirPropertyName ) ) + { + ::rtl::OUString sHomeDirectory; + xProviderProps->getPropertyValue( sHomeDirPropertyName ) >>= sHomeDirectory; + _rHomeDir = sHomeDirectory; + } + } + } + catch( const Exception& ) + { + DBG_ERROR( "lcl_getHomeDirectory: caught an exception!" ); + } + return 0 < _rHomeDir.Len(); + } + + //--------------------------------------------------------------------- + static String lcl_ensureFinalSlash( const String& _rDir ) + { + INetURLObject aWorkPathObj( _rDir, INET_PROT_FILE ); + aWorkPathObj.setFinalSlash(); + return aWorkPathObj.GetMainURL( INetURLObject::NO_DECODE ); + } + + //--------------------------------------------------------------------- + void convertStringListToUrls( const String& _rColonSeparatedList, ::std::vector< String >& _rTokens, bool _bFinalSlash ) + { + const sal_Unicode s_cSeparator = +#if defined(WNT) + ';' +#else + ':' +#endif + ; + xub_StrLen nTokens = _rColonSeparatedList.GetTokenCount( s_cSeparator ); + _rTokens.resize( 0 ); _rTokens.reserve( nTokens ); + for ( xub_StrLen i=0; i<nTokens; ++i ) + { + // the current token in the list + String sCurrentToken = _rColonSeparatedList.GetToken( i, s_cSeparator ); + if ( !sCurrentToken.Len() ) + continue; + + INetURLObject aCurrentURL; + + String sURL; + if ( ::utl::LocalFileHelper::ConvertPhysicalNameToURL( sCurrentToken, sURL ) ) + aCurrentURL = INetURLObject( sURL ); + else + { + // smart URL parsing, assuming FILE protocol + aCurrentURL = INetURLObject( sCurrentToken, INET_PROT_FILE ); + } + + if ( _bFinalSlash ) + aCurrentURL.setFinalSlash( ); + else + aCurrentURL.removeFinalSlash( ); + _rTokens.push_back( aCurrentURL.GetMainURL( INetURLObject::NO_DECODE ) ); + } + } + + //--------------------------------------------------------------------- + struct RemoveFinalSlash : public ::std::unary_function< String, void > + { + void operator()( String& _rURL ) + { + INetURLObject aURL( _rURL ); +#ifdef WNT + if ( aURL.getSegmentCount() > 1 ) +#endif + aURL.removeFinalSlash( ); + _rURL = aURL.GetMainURL( INetURLObject::NO_DECODE ); + } + }; + + // ----------------------------------------------------------------------- + /** retrieves the value of an environment variable + @return <TRUE/> if and only if the retrieved string value is not empty + */ + bool getEnvironmentValue( const sal_Char* _pAsciiEnvName, ::rtl::OUString& _rValue ) + { + _rValue = ::rtl::OUString(); + ::rtl::OUString sEnvName = ::rtl::OUString::createFromAscii( _pAsciiEnvName ); + osl_getEnvironment( sEnvName.pData, &_rValue.pData ); + return _rValue.getLength() != 0; + } +} + +//........................................................................ +namespace svt +{ +//........................................................................ + + // ----------------------------------------------------------------------- + void getUnrestrictedFolders( ::std::vector< String >& _rFolders ) + { + _rFolders.resize( 0 ); + ::rtl::OUString sRestrictedPathList; + if ( getEnvironmentValue( "RestrictedPath", sRestrictedPathList ) ) + // append a final slash. This ensures that when we later on check + // for unrestricted paths, we don't allow paths like "/home/user35" just because + // "/home/user3" is allowed - with the final slash, we make it "/home/user3/". + convertStringListToUrls( sRestrictedPathList, _rFolders, true ); + } + +//........................................................................ +} // namespace svt +//........................................................................ + +//*************************************************************************** +// ControlChain_Impl +//*************************************************************************** + +struct ControlChain_Impl +{ + Window* _pControl; + ControlChain_Impl* _pNext; + BOOL _bHasOwnerShip; + + ControlChain_Impl( Window* pControl, ControlChain_Impl* pNext, BOOL bFlag ); + ~ControlChain_Impl(); +}; + +//*************************************************************************** + +ControlChain_Impl::ControlChain_Impl +( + Window* pControl, + ControlChain_Impl* pNext, + BOOL bHasOwnerShip +) + : _pControl( pControl ), + _pNext( pNext ), + _bHasOwnerShip( TRUE ) +{ +} + +//*************************************************************************** + +ControlChain_Impl::~ControlChain_Impl() +{ + if ( _bHasOwnerShip ) + { + delete _pControl; + } + delete _pNext; +} + +//***************************************************************************** +// ResMgrHolder +//***************************************************************************** +namespace +{ + struct ResMgrHolder + { + ResMgr * operator ()() + { + return ResMgr::CreateResMgr (CREATEVERSIONRESMGR_NAME(fps_office)); + } + + static ResMgr * getOrCreate() + { + return rtl_Instance< + ResMgr, ResMgrHolder, + osl::MutexGuard, osl::GetGlobalMutex >::create ( + ResMgrHolder(), osl::GetGlobalMutex()); + } + }; + + struct SvtResId : public ResId + { + SvtResId (USHORT nId) : ResId (nId, ResMgrHolder::getOrCreate()) {} + }; +}; + +//***************************************************************************** +// SvtFileDialog +//***************************************************************************** +SvtFileDialog::SvtFileDialog +( + Window* _pParent, + WinBits nBits, + WinBits nExtraBits +) : + ModalDialog( _pParent, SvtResId( DLG_SVT_EXPLORERFILE ) ) + + ,_pFileView( NULL ) + ,_pCbReadOnly( NULL ) + ,_pCbLinkBox( NULL) + ,_pCbPreviewBox( NULL ) + ,_pCbSelection( NULL ) + ,_pPbPlay( NULL ) + ,_pPrevWin( NULL ) + ,_pPrevBmp( NULL ) + ,_pImp( new SvtExpFileDlg_Impl( nBits ) ) + ,_pFileNotifier( NULL ) + ,_nExtraBits( nExtraBits ) + ,_bIsInExecute( FALSE ) + ,_pUserControls( NULL ) + ,m_bInExecuteAsync( false ) +{ + Init_Impl( nBits ); +} + +//***************************************************************************** + +SvtFileDialog::SvtFileDialog ( Window* _pParent, WinBits nBits ) + :ModalDialog( _pParent, SvtResId( DLG_SVT_EXPLORERFILE ) ) + ,_pFileView( NULL ) + ,_pCbReadOnly( NULL ) + ,_pCbLinkBox( NULL) + ,_pCbPreviewBox( NULL ) + ,_pCbSelection( NULL ) + ,_pPbPlay( NULL ) + ,_pPrevWin( NULL ) + ,_pPrevBmp( NULL ) + ,_pImp( new SvtExpFileDlg_Impl( nBits ) ) + ,_pFileNotifier( NULL ) + ,_nExtraBits( 0L ) + ,_bIsInExecute( FALSE ) + ,_pUserControls( NULL ) +{ + Init_Impl( nBits ); +} + +//***************************************************************************** + +SvtFileDialog::~SvtFileDialog() +{ + if ( _pImp->_aIniKey.Len() ) + { + // save window state + SvtViewOptions aDlgOpt( E_DIALOG, _pImp->_aIniKey ); + aDlgOpt.SetWindowState( String( GetWindowState(), osl_getThreadTextEncoding() ) ); + String sUserData = _pFileView->GetConfigString(); + aDlgOpt.SetUserItem( ::rtl::OUString::createFromAscii( "UserData" ), + makeAny( ::rtl::OUString( sUserData ) ) ); + } + + _pFileView->SetSelectHdl( Link() ); + + delete _pImp; + delete _pFileView; + + delete _pCbReadOnly; + delete _pCbLinkBox; + delete _pCbPreviewBox; + delete _pCbSelection; + delete _pPbPlay; + delete _pPrevWin; + delete _pPrevBmp; + + delete _pUserControls; +} + +//***************************************************************************** + +void SvtFileDialog::Init_Impl +( + WinBits nStyle +) +{ + sal_Bool bIsHighContrast = GetDisplayBackground().GetColor().IsDark(); + m_aImages = ImageList( SvtResId( bIsHighContrast ? RID_FILEPICKER_IMAGES_HC : RID_FILEPICKER_IMAGES ) ); + + _pImp->_nStyle = nStyle; + _pImp->_a6Size = LogicToPixel( Size( 6, 6 ), MAP_APPFONT ); + _pImp->_eMode = ( nStyle & WB_SAVEAS ) ? FILEDLG_MODE_SAVE : FILEDLG_MODE_OPEN; + _pImp->_eDlgType = FILEDLG_TYPE_FILEDLG; + + if ( ( nStyle & SFXWB_PATHDIALOG ) == SFXWB_PATHDIALOG ) + _pImp->_eDlgType = FILEDLG_TYPE_PATHDLG; + + // Set the directory for the "back to the default dir" button + INetURLObject aStdDirObj( SvtPathOptions().GetWorkPath() ); + SetStandardDir( aStdDirObj.GetMainURL( INetURLObject::NO_DECODE ) ); + + // Reichweite bestimmen. + if ( !( nStyle & SFXWB_NOREMOTE ) ) + { + _pImp->_nState |= FILEDLG_STATE_REMOTE; + } + + // Kontrollelement erzeugen, wobei die Reihenfolge die Tab-Steuerung + // bestimmt. + _pImp->_pFtFileName = new FixedText( this, SvtResId( FT_EXPLORERFILE_FILENAME ) ); + + SvtURLBox* pURLBox = new SvtURLBox( this ); + pURLBox->SetUrlFilter( this ); + _pImp->_pEdFileName = pURLBox; + + Edit aDummy( this, SvtResId( ED_EXPLORERFILE_FILENAME ) ); + _pImp->_pEdFileName->SetPosSizePixel( aDummy.GetPosPixel(), aDummy.GetSizePixel() ); + _pImp->_pEdFileName->Show(); + pURLBox->SetSelectHdl( LINK( this, SvtFileDialog, EntrySelectHdl_Impl ) ); + pURLBox->SetOpenHdl( STATIC_LINK( this, SvtFileDialog, OpenHdl_Impl ) ); + + // in folder picker mode, only auto-complete directories (no files) + bool bIsFolderPicker = ( _pImp->_eDlgType == FILEDLG_TYPE_PATHDLG ); + pURLBox->SetOnlyDirectories( bIsFolderPicker ); + + // in save mode, don't use the autocompletion as selection in the edit part + bool bSaveMode = ( FILEDLG_MODE_SAVE == _pImp->_eMode ); + pURLBox->SetNoSelection( bSaveMode ); + + _pImp->_pEdFileName->SetHelpId( HID_FILEDLG_AUTOCOMPLETEBOX ); + + _pImp->_pFtFileType = new FixedText( this, SvtResId( FT_EXPLORERFILE_FILETYPE ) ); + _pImp->CreateFilterListControl( this, SvtResId( LB_EXPLORERFILE_FILETYPE ) ); + + // move the filter listbox to the space occupied by the version listbox + // if that box isn't needed + if ( !( _nExtraBits & SFX_EXTRA_SHOWVERSIONS ) && + !( _nExtraBits & SFX_EXTRA_TEMPLATES ) && + !( _nExtraBits & SFX_EXTRA_IMAGE_TEMPLATE ) ) + { + { + FixedText aSharedListBoxLabel( this, SvtResId( FT_EXPLORERFILE_SHARED_LISTBOX ) ); + _pImp->_pFtFileType->SetPosPixel( aSharedListBoxLabel.GetPosPixel() ); + } + + { + ListBox aSharedListBox( this, SvtResId( LB_EXPLORERFILE_SHARED_LISTBOX ) ); + _pImp->GetFilterListControl()->SetPosPixel( aSharedListBox.GetPosPixel() ); + } + } + + _pImp->_pFtCurrentPath = new FixedText( this, SvtResId( FT_EXPLORERFILE_CURRENTPATH ) ); + WinBits nTmpStyle = _pImp->_pFtCurrentPath->GetStyle(); + nTmpStyle |= WB_PATHELLIPSIS; + _pImp->_pFtCurrentPath->SetStyle( nTmpStyle ); + + _pImp->_pBtnFileOpen = new PushButton( this, SvtResId( BTN_EXPLORERFILE_OPEN ) ); + _pImp->_pBtnCancel = new CancelButton( this, SvtResId( BTN_EXPLORERFILE_CANCEL ) ); + _pImp->_pBtnHelp = new HelpButton( this, SvtResId( BTN_EXPLORERFILE_HELP ) ); + + _pImp->_pBtnUp = new SvtUpButton_Impl( this, SvtResId( BTN_EXPLORERFILE_UP ) ); + _pImp->_pBtnNewFolder = new ImageButton( this, SvtResId( BTN_EXPLORERFILE_NEWFOLDER ) ); + _pImp->_pBtnNewFolder->SetStyle( _pImp->_pBtnNewFolder->GetStyle() | WB_NOPOINTERFOCUS ); + _pImp->_pBtnStandard = new SvtTravelButton_Impl( this, SvtResId( BTN_EXPLORERFILE_STANDARD ) ); + + _pImp->_pBtnUp->SetAccessibleName( _pImp->_pBtnUp->GetQuickHelpText() ); + _pImp->_pBtnNewFolder->SetAccessibleName( _pImp->_pBtnNewFolder->GetQuickHelpText() ); + _pImp->_pBtnStandard->SetAccessibleName( _pImp->_pBtnStandard->GetQuickHelpText() ); + + if ( ( nStyle & SFXWB_MULTISELECTION ) == SFXWB_MULTISELECTION ) + _pImp->_bMultiSelection = TRUE; + + _pFileView = new SvtFileView( this, SvtResId( CTL_EXPLORERFILE_FILELIST ), + FILEDLG_TYPE_PATHDLG == _pImp->_eDlgType, + _pImp->_bMultiSelection ); + _pFileView->SetUrlFilter( this ); + _pFileView->EnableAutoResize(); + + _pFileView->SetHelpId( HID_FILEDLG_STANDARD ); + _pFileView->SetStyle( _pFileView->GetStyle() | WB_TABSTOP ); + + // Positionen und Groessen der Knoepfe bestimmen. + Image aNewFolderImg( GetButtonImage( IMG_FILEDLG_CREATEFOLDER ) ); + _pImp->_pBtnNewFolder->SetModeImage( aNewFolderImg ); + + Size aSize( aNewFolderImg.GetSizePixel() ); + aSize.Width() += FILEDIALOG_DEF_IMAGEBORDER; + aSize.Height() += FILEDIALOG_DEF_IMAGEBORDER; + _pImp->_pBtnNewFolder->SetSizePixel( aSize ); + _pImp->_pBtnUp->SetSizePixel( aSize ); + _pImp->_pBtnStandard->SetSizePixel( aSize ); + + Size aDlgSize = GetOutputSizePixel(); + long n6AppFontInPixel = + LogicToPixel( Size( 6, 0 ), MAP_APPFONT ).Width(); + long n3AppFontInPixel = + LogicToPixel( Size( 3, 0 ), MAP_APPFONT ).Width(); + + // calculate the length of all buttons + const USHORT nBtnCount = 3; // "previous level", "new folder" and "standard dir" + long nDelta = n6AppFontInPixel; // right border + nDelta += ( nBtnCount * aSize.Width() ); // button count * button width + nDelta += ( n3AppFontInPixel + n3AppFontInPixel / 2 ); // spacing 1*big 1*small + + Point aPos( + aDlgSize.Width() - nDelta, + _pImp->_pBtnUp->GetPosPixel().Y() + ); + Size aCurPathSize( + aPos.X() - n6AppFontInPixel, + _pImp->_pFtCurrentPath->GetOutputSizePixel().Height() + ); + _pImp->_pFtCurrentPath->SetOutputSizePixel( aCurPathSize ); + _pImp->_pBtnUp->SetPosPixel( aPos ); + aPos.X() += aSize.Width(); + aPos.X() += n3AppFontInPixel; + _pImp->_pBtnNewFolder->SetPosPixel( aPos ); + aPos.X() += aSize.Width(); + aPos.X() += n3AppFontInPixel / 2; + _pImp->_pBtnStandard->SetPosPixel( aPos ); + nDelta = aSize.Height(); + nDelta -= aCurPathSize.Height(); + nDelta /= 2; + Point aCurPathPos = _pImp->_pFtCurrentPath->GetPosPixel(); + aCurPathPos.Y() += nDelta; + _pImp->_pFtCurrentPath->SetPosPixel( aCurPathPos ); + + // Zahl der Pixel bestimmen, um die die anderen Elemente in der Position + // Angepasst werden muessen. + aPos.Y() += aSize.Height(); + aPos.Y() += LogicToPixel( Size( 0, 6 ), MAP_APPFONT ).Height(); + long nYOffset = aPos.Y(); + aPos = _pFileView->GetPosPixel(); + nYOffset -= aPos.Y(); + + // Positionen der uebrigen Elemente anpassen. + aPos.Y() += nYOffset; + _pFileView->SetPosPixel( aPos ); + + lcl_MoveControl( _pImp->_pFtFileName, 0, nYOffset ); + lcl_MoveControl( _pImp->_pEdFileName, 0, nYOffset ); + + lcl_MoveControl( _pImp->_pFtFileVersion, 0, nYOffset ); + lcl_MoveControl( _pImp->_pLbFileVersion, 0, nYOffset ); + + lcl_MoveControl( _pImp->_pFtTemplates, 0, nYOffset ); + lcl_MoveControl( _pImp->_pLbTemplates, 0, nYOffset ); + + lcl_MoveControl( _pImp->_pFtImageTemplates, 0, nYOffset ); + lcl_MoveControl( _pImp->_pLbImageTemplates, 0, nYOffset ); + + lcl_MoveControl( _pImp->_pFtFileType, 0, nYOffset ); + lcl_MoveControl( _pImp->GetFilterListControl(), 0, nYOffset ); + + lcl_MoveControl( _pImp->_pBtnFileOpen, 0, nYOffset ); + lcl_MoveControl( _pImp->_pBtnCancel, 0, nYOffset ); + + lcl_MoveControl( _pImp->_pBtnHelp, 0, nYOffset + 3 ); + // a little more spacing between Cancel- and HelpButton + + // Groesse des Dialoges anpassen. + aSize = GetSizePixel(); + aSize.Height() += nYOffset; + SetSizePixel( aSize ); + + if ( nStyle & SFXWB_READONLY ) + { + _pCbReadOnly = new CheckBox( this, SvtResId( CB_EXPLORERFILE_READONLY ) ); + _pCbReadOnly->SetHelpId( HID_FILEOPEN_READONLY ); + _pCbReadOnly->SetText( SvtResId( STR_SVT_FILEPICKER_READONLY ) ); + AddControl( _pCbReadOnly ); + ReleaseOwnerShip( _pCbReadOnly ); + _pCbReadOnly->SetClickHdl( LINK( this, SvtFileDialog, ClickHdl_Impl ) ); + } + + if ( nStyle & SFXWB_PASSWORD ) + { + _pImp->_pCbPassword = new CheckBox( this, SvtResId( CB_EXPLORERFILE_PASSWORD ) ); + _pImp->_pCbPassword->SetText( SvtResId( STR_SVT_FILEPICKER_PASSWORD ) ); + AddControl( _pImp->_pCbPassword ); + ReleaseOwnerShip( _pImp->_pCbPassword ); + _pImp->_pCbPassword->SetClickHdl( LINK( this, SvtFileDialog, ClickHdl_Impl ) ); + } + + // set the ini file for extracting the size + _pImp->_aIniKey = IODLG_CONFIGNAME; + + AddControls_Impl( ); + + // Beschriftungen dem Modus anpassen. + USHORT nResId = STR_EXPLORERFILE_OPEN; + USHORT nButtonResId = 0; + + if ( nStyle & WB_SAVEAS ) + { + nResId = STR_EXPLORERFILE_SAVE; + nButtonResId = STR_EXPLORERFILE_BUTTONSAVE; + } + + if ( ( nStyle & SFXWB_PATHDIALOG ) == SFXWB_PATHDIALOG ) + { + _pImp->_pFtFileName->SetText( SvtResId( STR_PATHNAME ) ); + nResId = STR_PATHSELECT; + nButtonResId = STR_BUTTONSELECT; + } + + SetText( SvtResId( nResId ) ); + + if ( nButtonResId ) + _pImp->_pBtnFileOpen->SetText( SvtResId( nButtonResId ) ); + + if ( FILEDLG_TYPE_FILEDLG != _pImp->_eDlgType ) + { + _pImp->_pFtFileType->Hide(); + _pImp->GetFilterListControl()->Hide(); + } + + // Einstellungen der Steuerelemente vornehmen. + _pImp->_pBtnNewFolder->SetClickHdl( STATIC_LINK( this, SvtFileDialog, NewFolderHdl_Impl ) ); + _pImp->_pBtnFileOpen->SetClickHdl( STATIC_LINK( this, SvtFileDialog, OpenHdl_Impl ) ); + _pImp->_pBtnCancel->SetClickHdl( LINK( this, SvtFileDialog, CancelHdl_Impl ) ); + _pImp->SetFilterListSelectHdl( STATIC_LINK( this, SvtFileDialog, FilterSelectHdl_Impl ) ); + _pImp->_pEdFileName->SetGetFocusHdl( STATIC_LINK( this, SvtFileDialog, FileNameGetFocusHdl_Impl ) ); + _pImp->_pEdFileName->SetModifyHdl( STATIC_LINK( this, SvtFileDialog, FileNameModifiedHdl_Impl ) ); + _pFileView->SetSelectHdl( LINK( this, SvtFileDialog, SelectHdl_Impl ) ); + _pFileView->SetDoubleClickHdl( LINK( this, SvtFileDialog, DblClickHdl_Impl ) ); + _pFileView->SetOpenDoneHdl( LINK( this, SvtFileDialog, OpenDoneHdl_Impl ) ); + + // Resourcen freigeben. + FreeResource(); + + // Timer fuer Filterbox Travel setzen + _pImp->_aFilterTimer.SetTimeout( TRAVELFILTER_TIMEOUT ); + _pImp->_aFilterTimer.SetTimeoutHdl( STATIC_LINK( this, SvtFileDialog, FilterSelectHdl_Impl ) ); + + if ( WB_SAVEAS & nStyle ) + { + // different help ids if in save-as mode + // 90744 - 09.08.2001 - frank.schoenheit@sun.com + SetHelpId( HID_FILESAVE_DIALOG ); + + _pImp->_pEdFileName->SetHelpId( HID_FILESAVE_FILEURL ); + _pImp->_pBtnFileOpen->SetHelpId( HID_FILESAVE_DOSAVE ); + _pImp->_pBtnNewFolder->SetHelpId( HID_FILESAVE_CREATEDIRECTORY ); + _pImp->_pBtnStandard->SetHelpId( HID_FILESAVE_DEFAULTDIRECTORY ); + _pImp->_pBtnUp->SetHelpId( HID_FILESAVE_LEVELUP ); + _pImp->GetFilterListControl()->SetHelpId( HID_FILESAVE_FILETYPE ); + _pFileView->SetHelpId( HID_FILESAVE_FILEVIEW ); + + // formerly, there was only _pLbFileVersion, which was used for 3 different + // use cases. For reasons of maintainability, I introduced extra members (_pLbTemplates, _pLbImageTemplates) + // for the extra use cases, and separated _pLbFileVersion + // I did not find out in which cases the help ID is really needed HID_FILESAVE_TEMPLATE - all + // tests I made lead to a dialog where _no_ of the three list boxes was present. + // 96930 - 15.08.2002 - fs@openoffice.org + if ( _pImp->_pLbFileVersion ) + _pImp->_pLbFileVersion->SetHelpId( HID_FILESAVE_TEMPLATE ); + if ( _pImp->_pLbTemplates ) + _pImp->_pLbTemplates->SetHelpId( HID_FILESAVE_TEMPLATE ); + if ( _pImp->_pLbImageTemplates ) + _pImp->_pLbImageTemplates->SetHelpId( HID_FILESAVE_TEMPLATE ); + + if ( _pImp->_pCbPassword ) _pImp->_pCbPassword->SetHelpId( HID_FILESAVE_SAVEWITHPASSWORD ); + if ( _pImp->_pCbAutoExtension ) _pImp->_pCbAutoExtension->SetHelpId( HID_FILESAVE_AUTOEXTENSION ); + if ( _pImp->_pCbOptions ) _pImp->_pCbOptions->SetHelpId( HID_FILESAVE_CUSTOMIZEFILTER ); + if ( _pCbSelection ) _pCbSelection->SetHelpId( HID_FILESAVE_SELECTION ); + } + + // correct the z-order of the controls + implArrangeControls(); + + // #102204# --------------- + if ( nStyle & WB_SAVEAS ) + // when doing a save-as, we do not want the handler to handle "this file does not exist" messages + // - finally we're going to save that file, aren't we? + // #105812# - 2002-12-02 - fs@openoffice.org + m_aContent.enableOwnInteractionHandler(::svt::OFilePickerInteractionHandler::E_DOESNOTEXIST); + else + m_aContent.enableDefaultInteractionHandler(); + + // special URLs, such as favourites and "restricted" paths + implInitializeSpecialURLLists( ); + + /// read our settings from the configuration + m_aConfiguration = OConfigurationTreeRoot::createWithServiceFactory( + ::comphelper::getProcessServiceFactory(), + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.UI/FilePicker" ) ) + ); +} + +//***************************************************************************** + +IMPL_STATIC_LINK( SvtFileDialog, NewFolderHdl_Impl, PushButton*, pBtn ) +{ + INetURLObject aObj( pThis->_pFileView->GetViewURL() ); + String sFolderName = aObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET, RTL_TEXTENCODING_UTF8 ); + svtools::QueryFolderNameDialog aDlg( pThis, sFolderName, String( SvtResId( STR_SVT_NEW_FOLDER ) ) ); + sal_Bool bHandled = sal_False; + + while ( !bHandled ) + { + if ( aDlg.Execute() == RET_OK ) + bHandled = pThis->_pFileView->CreateNewFolder( aDlg.GetName() ); + else + bHandled = sal_True; + } + + return 0; +} + +//***************************************************************************** + +IMPL_STATIC_LINK( SvtFileDialog, ViewHdl_Impl, ImageButton*, pBtn ) +{ + return 0; +} + +//***************************************************************************** +//----------------------------------------------------------------------------- +sal_Bool SvtFileDialog::createNewUserFilter( const String& _rNewFilter, sal_Bool _bAllowUserDefExt ) +{ + // delete the old user filter and create a new one + DELETEZ( _pImp->_pUserFilter ); + _pImp->_pUserFilter = new SvtFileDialogFilter_Impl( _rNewFilter, _rNewFilter ); + + // remember the extension + sal_Bool bIsAllFiles = _rNewFilter.EqualsAscii( FILEDIALOG_FILTER_ALL ); + if ( bIsAllFiles ) + EraseDefaultExt(); + else + SetDefaultExt( _rNewFilter.Copy( 2 ) ); + // TODO: this is nonsense. In the whole file there are a lotta places where we assume that a user filter + // is always "*.<something>". But changing this would take some more time than I have now ... + // 05.12.2001 - 95486 - fs@openoffice.org + + // now, the default extension is set to the one of the user filter (or empty) + // if the former is not allowed (_bAllowUserDefExt = <FALSE/>), we have to use the ext of the current filter + // (if possible) + sal_Bool bUseCurFilterExt = sal_True; + String sUserFilter = _pImp->_pUserFilter->GetType(); + xub_StrLen nSepPos = sUserFilter.SearchBackward( '.' ); + if ( STRING_NOTFOUND != nSepPos ) + { + String sUserExt = sUserFilter.Copy( nSepPos + 1 ); + if ( ( STRING_NOTFOUND == sUserExt.Search( '*' ) ) + && ( STRING_NOTFOUND == sUserExt.Search( '?' ) ) + ) + bUseCurFilterExt = sal_False; + } + + if ( !_bAllowUserDefExt || bUseCurFilterExt ) + { + if ( _pImp->GetCurFilter( ) ) + SetDefaultExt( _pImp->GetCurFilter( )->GetType().Copy(2) ); + else + EraseDefaultExt(); + } + + // outta here + return bIsAllFiles; +} + +//----------------------------------------------------------------------------- +#define FLT_NONEMPTY 0x0001 +#define FLT_CHANGED 0x0002 +#define FLT_USERFILTER 0x0004 +#define FLT_ALLFILESFILTER 0x0008 + +//----------------------------------------------------------------------------- +sal_uInt16 SvtFileDialog::adjustFilter( const String& _rFilter ) +{ + sal_uInt16 nReturn = 0; + + const sal_Bool bNonEmpty = ( _rFilter.Len() != 0 ); + if ( bNonEmpty ) + { + nReturn |= FLT_NONEMPTY; + + sal_Bool bFilterChanged = sal_True; + + // search for a corresponding filter + SvtFileDialogFilter_Impl* pFilter = FindFilter_Impl( _rFilter, FALSE, bFilterChanged ); + +#ifdef AUTOSELECT_USERFILTER + // if we found a filter which without allowing multi-extensions -> select it + if ( pFilter ) + { + _pImp->SelectFilterListEntry( pFilter->GetName() ); + _pImp->SetCurFilter( pFilter ); + } +#endif // AUTOSELECT_USERFILTER + + // look for multi-ext filters if necessary + if ( !pFilter ) + pFilter = FindFilter_Impl( _rFilter, TRUE, bFilterChanged ); + + if ( bFilterChanged ) + nReturn |= FLT_CHANGED; + + if ( !pFilter ) + { + nReturn |= FLT_USERFILTER; + // no filter found : use it as user defined filter +#ifdef AUTOSELECT_USERFILTER + if ( createNewUserFilter( _rFilter, sal_True ) ) +#else + if ( createNewUserFilter( _rFilter, sal_False ) ) +#endif + { // it's the "all files" filter + nReturn |= FLT_ALLFILESFILTER; + +#ifdef AUTOSELECT_USERFILTER + // select the "all files" entry + String sAllFilesFilter( SvtResId( STR_FILTERNAME_ALL ) ); + if ( _pImp->HasFilterListEntry( sAllFilesFilter ) ) + { + _pImp->SelectFilterListEntry( sAllFilesFilter ); + _pImp->SetCurFilter( _pImp->GetSelectedFilterEntry( sAllFilesFilter ) ); + } + else + _pImp->SetNoFilterListSelection( ); // there is no "all files" entry +#endif // AUTOSELECT_USERFILTER + } +#ifdef AUTOSELECT_USERFILTER + else + _pImp->SetNoFilterListSelection( ); +#endif // AUTOSELECT_USERFILTER + } + } + + return nReturn; +} + +//----------------------------------------------------------------------------- +IMPL_LINK( SvtFileDialog, CancelHdl_Impl, void*, pVoid ) +{ + if ( m_pCurrentAsyncAction.is() ) + { + m_pCurrentAsyncAction->cancel(); + onAsyncOperationFinished(); + } + else + { + EndDialog( FALSE ); + } + return 1L; +} + +//----------------------------------------------------------------------------- +IMPL_STATIC_LINK( SvtFileDialog, OpenHdl_Impl, void*, pVoid ) +{ + if ( pThis->_pImp->_bMultiSelection && pThis->_pFileView->GetSelectionCount() > 1 ) + { + // bei Multiselektion spezielles Open + pThis->OpenMultiSelection_Impl(); + return 0; + } + + String aFileName; + String aOldPath( pThis->_pFileView->GetViewURL() ); + if ( pThis->_pImp->_bDoubleClick || pThis->_pFileView->HasChildPathFocus() ) + // Selection done by doubleclicking in the view, get filename from the view + aFileName = pThis->_pFileView->GetCurrentURL(); + + if ( !aFileName.Len() ) + { + // if an entry is selected in the view .... + if ( pThis->_pFileView->GetSelectionCount() ) + { // -> use this one. This will allow us to step down this folder + // #i8928# - 2002-12-20 - fs@openoffice.org + aFileName = pThis->_pFileView->GetCurrentURL(); + } + } + + if ( !aFileName.Len() ) + { + if ( pThis->_pImp->_eMode == FILEDLG_MODE_OPEN && pThis->_pImp->_pEdFileName->IsTravelSelect() ) + // OpenHdl called from URLBox; travelling through the list of URLs should not cause an opening + return 0; // MBA->PB: seems to be called never ?! + + // get the URL from from the edit field ( if not empty ) + if ( pThis->_pImp->_pEdFileName->GetText().Len() ) + { + String aText = pThis->_pImp->_pEdFileName->GetText(); + + // did we reach the root? + if ( !INetURLObject( aOldPath ).getSegmentCount() ) + { + if ( ( aText.Len() == 2 && aText.EqualsAscii( ".." ) ) || + ( aText.Len() == 3 && ( aText.EqualsAscii( "..\\" ) || aText.EqualsAscii( "../" ) ) ) ) + // don't go higher than the root + return 0; + } + +#if defined( UNX ) || defined( FS_PRIV_DEBUG ) + if ( ( 1 == aText.Len() ) && ( '~' == aText.GetBuffer()[0] ) ) + { + // go to the home directory + if ( lcl_getHomeDirectory( pThis->_pFileView->GetViewURL(), aFileName ) ) + // in case we got a home dir, reset the text of the edit + pThis->_pImp->_pEdFileName->SetText( String() ); + } + if ( !aFileName.Len() ) +#endif + { + // get url from autocomplete edit + aFileName = pThis->_pImp->_pEdFileName->GetURL(); + } + } + else if ( pVoid == pThis->_pImp->_pBtnFileOpen ) + // OpenHdl was called for the "Open" Button; if edit field is empty, use selected element in the view + aFileName = pThis->_pFileView->GetCurrentURL(); + } + + // MBA->PB: ?! + if ( !aFileName.Len() && pVoid == pThis->_pImp->_pEdFileName && pThis->_pImp->_pUserFilter ) + { + DELETEZ( pThis->_pImp->_pUserFilter ); + return 0; + } + + USHORT nLen = aFileName.Len(); + if ( !nLen ) + { + // if the dialog was opened to select a folder, the last selected folder should be selected + if( pThis->_pImp->_eDlgType == FILEDLG_TYPE_PATHDLG ) + { + aFileName = pThis->_pImp->_pFtCurrentPath->GetText(); + nLen = aFileName.Len(); + } + else + // no file selected ! + return 0; + } + + // mark input as selected + pThis->_pImp->_pEdFileName->SetSelection( Selection( 0, nLen ) ); + + // if a path with wildcards is given, divide the string into path and wildcards + String aFilter; + if ( !pThis->IsolateFilterFromPath_Impl( aFileName, aFilter ) ) + return 0; + + // if a filter was retrieved, there were wildcards ! + sal_uInt16 nNewFilterFlags = pThis->adjustFilter( aFilter ); + if ( nNewFilterFlags & FLT_CHANGED ) + { + // cut off all text before wildcard in edit and select wildcard + pThis->_pImp->_pEdFileName->SetText( aFilter ); + pThis->_pImp->_pEdFileName->SetSelection( Selection( 0, aFilter.Len() ) ); + } + + { + INetURLObject aFileObject( aFileName ); + if ( ( aFileObject.GetProtocol() == INET_PROT_NOT_VALID ) && aFileName.Len() ) + { + String sCompleted = SvtURLBox::ParseSmart( aFileName, pThis->_pFileView->GetViewURL(), SvtPathOptions().GetWorkPath() ); + if ( sCompleted.Len() ) + aFileName = sCompleted; + } + } + + // Pr"ufen, ob es sich um einen Ordner handelt. + BOOL bFolder = FALSE; + + // first thing before doing anyhing with the content: Reset it. When the user presses "open" (or "save" or "export", + // for that matter), s/he wants the complete handling, including all possible error messages, even if s/he + // does the same thing for the same content twice, s/he wants both fails to be displayed. + // Without the reset, it could be that the content cached all relevant information, and will not display any + // error messages for the same content a second time .... + pThis->m_aContent.bindTo( ::rtl::OUString( ) ); + + // #97148# & #102204# --------- + if ( aFileName.Len() ) + { + bFolder = pThis->m_aContent.isFolder( aFileName ); + + // access denied to the given resource - and interaction was already used => break following operations + OFilePickerInteractionHandler* pHandler = pThis->m_aContent.getOwnInteractionHandler(); + if (pHandler && pHandler->wasAccessDenied()) + return 0; + + if ( pThis->m_aContent.isInvalid() + && ( FILEDLG_MODE_OPEN == pThis->_pImp->_eMode ) + ) + return 0; + } + + + if ( !bFolder // no existent folder + && pThis->_pImp->_pCbAutoExtension // auto extension is enabled in general + && pThis->_pImp->_pCbAutoExtension->IsChecked() // auto extension is really to be used + && pThis->GetDefaultExt().Len() // there is a default extension + && pThis->GetDefaultExt() != '*' // the default extension is not "all" + && !( FILEDLG_MODE_SAVE == pThis->_pImp->_eMode // we're saving a file + && pThis->_pFileView->GetSelectionCount() // there is a selected file in the file view -> it will later on + ) // (in SvtFileDialog::GetPathList) be taken as file to save to + ) // (#114818# - 2004-03-17 - fs@openoffice.org) + { + // und diese nicht eh schon dran haengt + String aExt = String(RTL_CONSTASCII_USTRINGPARAM("*.")); + INetURLObject aTemp( aFileName ); + aExt += String(aTemp.GetExtension().toAsciiLowerCase()); + const String& rType = pThis->_pImp->GetCurFilter()->GetType(); + String aType = rType; + aType.ToLowerAscii(); + + if ( ! aType.EqualsAscii(FILEDIALOG_FILTER_ALL) ) + { + USHORT nWildCard = aType.GetTokenCount( FILEDIALOG_DEF_EXTSEP ); + USHORT nIndex, nPos = 0; + + for ( nIndex = 0; nIndex < nWildCard; nIndex++ ) + { + if ( aExt == aType.GetToken( 0, FILEDIALOG_DEF_EXTSEP, nPos ) ) + break; + } + + if ( nIndex >= nWildCard ) + { + aFileName += '.'; + aFileName += pThis->GetDefaultExt(); + } + } + } + + BOOL bOpenFolder = ( FILEDLG_TYPE_PATHDLG == pThis->_pImp->_eDlgType ) && + !pThis->_pImp->_bDoubleClick && pVoid != pThis->_pImp->_pEdFileName; + if ( bFolder ) + { + if ( bOpenFolder ) + { + pThis->_aPath = aFileName; + } + else + { + if ( aFileName != pThis->_pFileView->GetViewURL() ) + { + if ( !pThis->isUrlAllowed( aFileName ) ) + { + pThis->simulateAccessDenied( aFileName ); + return 0; + } + + pThis->OpenURL_Impl( aFileName ); + } + else + { + if ( nNewFilterFlags & FLT_CHANGED ) + pThis->ExecuteFilter(); + } + + return 0; + } + } + else if ( !( nNewFilterFlags & FLT_NONEMPTY ) ) + { + // Ggf. URL speichern. + pThis->_aPath = aFileName; + } + else + { + // Ggf. neu filtern. + if ( nNewFilterFlags & FLT_CHANGED ) + pThis->ExecuteFilter(); + return 0; + } + + INetURLObject aFileObj( aFileName ); + if ( aFileObj.HasError() ) + { + ErrorHandler::HandleError( ERRCODE_IO_GENERAL ); + return 0; + } + + // if restrictions for the allowed folders are in place, we need to do a check here + if ( !pThis->isUrlAllowed( aFileObj.GetMainURL( INetURLObject::NO_DECODE ) ) ) + { + pThis->simulateAccessDenied( aFileName ); + return 0; + } + + switch ( pThis->_pImp->_eMode ) + { + case FILEDLG_MODE_SAVE: + { + if ( ::utl::UCBContentHelper::Exists( aFileObj.GetMainURL( INetURLObject::NO_DECODE ) ) ) + { + QueryBox aBox( pThis, WB_YES_NO, SvtResId( STR_SVT_ALREADYEXISTOVERWRITE ) ); + if ( aBox.Execute() != RET_YES ) + return 0; + } + else + { + String aCurPath; + if ( ::utl::LocalFileHelper::ConvertURLToSystemPath( aFileName, aCurPath ) ) + { + // if content does not exist: at least its path must exist + INetURLObject aPathObj = aFileObj; + aPathObj.removeSegment(); + // #97148# & #102204# ------------ + BOOL bFolder = pThis->m_aContent.isFolder( aPathObj.GetMainURL( INetURLObject::NO_DECODE ) ); + if ( !bFolder ) + { + ErrorHandler::HandleError( ERRCODE_IO_NOTEXISTSPATH ); + return 0; + } + } + } + } + break; + + case FILEDLG_MODE_OPEN: + { + // do an existence check herein, again + // 16.11.2001 - 93107 - frank.schoenheit@sun.com + + if ( INET_PROT_FILE == aFileObj.GetProtocol( ) ) + { + sal_Bool bExists = sal_False; + // #102204# -------------- + bExists = pThis->m_aContent.is( aFileObj.GetMainURL( INetURLObject::NO_DECODE ) ); + + + if ( !bExists ) + { + String sError( SvtResId( RID_FILEOPEN_NOTEXISTENTFILE ) ); + + String sInvalidFile( aFileObj.GetMainURL( INetURLObject::DECODE_TO_IURI ) ); + if ( INET_PROT_FILE == aFileObj.GetProtocol() ) + { // if it's a file URL, transform the URL into system notation + ::rtl::OUString sURL( sInvalidFile ); + ::rtl::OUString sSystem; + osl_getSystemPathFromFileURL( sURL.pData, &sSystem.pData ); + sInvalidFile = sSystem; + } + sError.SearchAndReplaceAscii( "$name$", sInvalidFile ); + + ErrorBox aError( pThis, WB_OK, sError ); + aError.Execute(); + return 0; + } + } + } + break; + + default: + DBG_ERROR("SvtFileDialog, OpenHdl_Impl: invalid mode!"); + } + + // Interessenten benachrichtigen. + long nRet; + + if ( pThis->_aOKHdl.IsSet() ) + nRet = pThis->_aOKHdl.Call( pThis ); + else + nRet = pThis->OK(); + + if ( nRet ) + { + pThis->EndDialog( TRUE ); + } + + return nRet; +} + +//***************************************************************************** + +IMPL_STATIC_LINK( SvtFileDialog, FilterSelectHdl_Impl, ListBox*, pBox ) +{ + DBG_ASSERT( pBox, "SvtFileDialog:keine Instanz" ); + + // wurde der Handler vom Travel-Timer gefeuert? + if ( pBox == (ListBox*)&pThis->_pImp->_aFilterTimer ) + { + // Anzeige erneut filtern. + pThis->ExecuteFilter(); + return 0; + } + + String sSelectedFilterDisplayName; + SvtFileDialogFilter_Impl* pSelectedFilter = pThis->_pImp->GetSelectedFilterEntry( sSelectedFilterDisplayName ); + if ( !pSelectedFilter ) + { // there is no current selection. This happens if for instance the user selects a group separator using + // the keyboard, and then presses enter: When the selection happens, we immediately deselect the entry, + // so in this situation there is no current selection. + if ( restoreCurrentFilter( pThis->_pImp ) ) + pThis->ExecuteFilter(); + } + else + { + if ( pSelectedFilter->isGroupSeparator() ) + { // group separators can't be selected + // return to the previously selected entry + if ( pThis->_pImp->IsFilterListTravelSelect() ) + { + pThis->_pImp->SetNoFilterListSelection( ); + + // stop the timer for executing the filter + if ( pThis->_pImp->_aFilterTimer.IsActive() ) + pThis->_pImp->m_bNeedDelayedFilterExecute = sal_True; + pThis->_pImp->_aFilterTimer.Stop(); + } + else + { + if ( restoreCurrentFilter( pThis->_pImp ) ) + pThis->ExecuteFilter(); + } + } + else if ( ( pSelectedFilter != pThis->_pImp->GetCurFilter() ) + || pThis->_pImp->_pUserFilter + ) + { + // Ggf. Filter des Benutzers entfernen. + DELETEZ( pThis->_pImp->_pUserFilter ); + pThis->_pImp->SetCurFilter( pSelectedFilter, sSelectedFilterDisplayName ); + + // Ggf. Endung anzeigen. + const String& rType = pSelectedFilter->GetType(); + pThis->SetDefaultExt( rType.Copy( 2 ) ); + USHORT nSepPos = pThis->GetDefaultExt().Search( FILEDIALOG_DEF_EXTSEP ); + + if ( nSepPos != STRING_NOTFOUND ) + pThis->EraseDefaultExt( nSepPos ); + + // update the extension of the current file if necessary + lcl_autoUpdateFileExtension( pThis ); + + // wenn der Benutzer schnell durch die Filterbox + // travelt, nicht sofort Filtern + if ( pThis->_pImp->IsFilterListTravelSelect() ) + { + // FilterSelectHdl_Impl soll in + // TRAVELFILTER_TIMEOUT ms neu gefeuert werden + pThis->_pImp->_aFilterTimer.Start(); + } + else + { + // evtl. vorher gestarteten Timer stoppen + pThis->_pImp->_aFilterTimer.Stop(); + + // Anzeige erneut filtern. + pThis->ExecuteFilter(); + } + } + } + + return 0; +} + +//***************************************************************************** + +IMPL_STATIC_LINK( SvtFileDialog, FileNameGetFocusHdl_Impl, void*, EMPTYARG ) +{ + pThis->_pFileView->SetNoSelection(); + pThis->_pFileView->Update(); + return 0; +} + +//***************************************************************************** + +IMPL_STATIC_LINK( SvtFileDialog, FileNameModifiedHdl_Impl, void*, EMPTYARG ) +{ + FileNameGetFocusHdl_Impl( pThis, NULL ); + return 0; +} + +//***************************************************************************** + +SvtFileDialogFilter_Impl* SvtFileDialog::FindFilter_Impl +( + const String& _rFilter, + sal_Bool _bMultiExt,/* TRUE - auch Filter mit mehreren Endungen + beruecksichtigen + FALSE - keine ... + */ + sal_Bool& _rFilterChanged +) + +/* [Beschreibung] + + Die Methode sucht in den eingef"ugten Filtern nach der + spezifizierten Endung. +*/ + +{ + SvtFileDialogFilter_Impl* pFoundFilter = NULL; + SvtFileDialogFilterList_Impl* pList = _pImp->_pFilter; + USHORT nFilter = pList->Count(); + + while ( nFilter-- ) + { + SvtFileDialogFilter_Impl* pFilter = pList->GetObject( nFilter ); + const String& rType = pFilter->GetType(); + String aSingleType = rType; + USHORT nWildCard = rType.GetTokenCount( FILEDIALOG_DEF_EXTSEP ); + + if ( _bMultiExt ) + { + USHORT nIdx = 0; + while ( !pFoundFilter && nIdx != STRING_NOTFOUND ) + { + aSingleType = rType.GetToken( 0, FILEDIALOG_DEF_EXTSEP, nIdx ); +#ifdef UNX + if ( aSingleType.CompareTo( _rFilter ) == COMPARE_EQUAL ) +#else + if ( aSingleType.CompareIgnoreCaseToAscii( _rFilter ) == COMPARE_EQUAL ) +#endif + pFoundFilter = pFilter; + } + } +#ifdef UNX + else if ( rType.CompareTo( _rFilter ) == COMPARE_EQUAL ) +#else + else if ( rType.CompareIgnoreCaseToAscii( _rFilter ) == COMPARE_EQUAL ) +#endif + pFoundFilter = pFilter; + + if ( pFoundFilter ) + { + // Filter aktivieren. + _rFilterChanged = _pImp->_pUserFilter || ( _pImp->GetCurFilter() != pFilter ); + + createNewUserFilter( _rFilter, sal_False ); + + break; + } + } + return pFoundFilter; +} + +//***************************************************************************** + +void SvtFileDialog::ExecuteFilter() +{ + _pImp->m_bNeedDelayedFilterExecute = sal_False; + executeAsync( AsyncPickerAction::eExecuteFilter, String(), getMostCurrentFilter( _pImp ) ); +} + +//***************************************************************************** + +void SvtFileDialog::OpenMultiSelection_Impl() + +/* [Beschreibung] + + OpenHandler f"ur MultiSelektion +*/ + +{ + String aPath; + ULONG nCount = _pFileView->GetSelectionCount(); + SvLBoxEntry* pEntry = nCount ? _pFileView->FirstSelected() : NULL; + + if ( nCount && pEntry ) + _aPath = _pFileView->GetURL( pEntry ); + + // Interessenten benachrichtigen. + long nRet; + + if ( _aOKHdl.IsSet() ) + nRet = _aOKHdl.Call( this ); + else + nRet = OK(); + + if ( nRet ) + EndDialog( TRUE ); +} + +//***************************************************************************** + +void SvtFileDialog::UpdateControls( const String& rURL ) +{ + _pImp->_pEdFileName->SetBaseURL( rURL ); + + INetURLObject aObj( rURL ); + + //========================================================================= + { + String sText; + DBG_ASSERT( INET_PROT_NOT_VALID != aObj.GetProtocol(), "SvtFileDialog::UpdateControls: Invalid URL!" ); + + if ( aObj.getSegmentCount() ) + { + ::utl::LocalFileHelper::ConvertURLToSystemPath( rURL, sText ); + if ( sText.Len() ) + { + // no Fsys path for server file system ( only UCB has mountpoints! ) + if ( INET_PROT_FILE != aObj.GetProtocol() ) + sText = rURL.Copy( INetURLObject::GetScheme( aObj.GetProtocol() ).getLength() ); + } + + if ( !sText.Len() && aObj.getSegmentCount() ) + sText = rURL; + } + + // path mode ? + if ( FILEDLG_TYPE_PATHDLG == _pImp->_eDlgType ) + // -> set new path in the edit field + _pImp->_pEdFileName->SetText( sText ); + + // in the "current path" field, truncate the trailing slash + if ( aObj.hasFinalSlash() ) + { + aObj.removeFinalSlash(); + String sURL( aObj.GetMainURL( INetURLObject::NO_DECODE ) ); + if ( !::utl::LocalFileHelper::ConvertURLToSystemPath( sURL, sText ) ) + sText = sURL; + } + + _pImp->_pFtCurrentPath->SetText( sText ); + } + + //========================================================================= + _aPath = rURL; + if ( _pFileNotifier ) + _pFileNotifier->notify( DIRECTORY_CHANGED, 0 ); +} + +//***************************************************************************** + +IMPL_LINK( SvtFileDialog, SelectHdl_Impl, SvTabListBox*, pBox ) +{ + SvLBoxEntry* pEntry = pBox->FirstSelected(); + DBG_ASSERT( pEntry, "SelectHandler without selected entry" ); + SvtContentEntry* pUserData = (SvtContentEntry*)pEntry->GetUserData(); + + if ( pUserData ) + { + INetURLObject aObj( pUserData->maURL ); + if ( FILEDLG_TYPE_PATHDLG == _pImp->_eDlgType ) + { + if ( aObj.GetProtocol() == INET_PROT_FILE ) + { + if ( !pUserData->mbIsFolder ) + aObj.removeSegment(); + String aName = aObj.getFSysPath( (INetURLObject::FSysStyle)(INetURLObject::FSYS_DETECT & ~INetURLObject::FSYS_VOS) ); + _pImp->_pEdFileName->SetText( aName ); + _pImp->_pEdFileName->SetSelection( Selection( 0, aName.Len() ) ); + _aPath = pUserData->maURL; + } + else if ( !pUserData->mbIsFolder ) + { + _pImp->_pEdFileName->SetText( pUserData->maURL ); + _pImp->_pEdFileName->SetSelection( Selection( 0, pUserData->maURL.Len() ) ); + _aPath = pUserData->maURL; + } + else + _pImp->_pEdFileName->SetText( UniString() ); + } + else + { + if ( !pUserData->mbIsFolder ) + { + String aName = pBox->GetEntryText( pEntry, 0 ); + _pImp->_pEdFileName->SetText( aName ); + _pImp->_pEdFileName->SetSelection( Selection( 0, aName.Len() ) ); + _aPath = pUserData->maURL; + } + } + } + + if ( _pImp->_bMultiSelection && _pFileView->GetSelectionCount() > 1 ) + { + // bei Multiselektion den Datei-Edit leeren + _pImp->_pEdFileName->SetText( String() ); + } + + FileSelect(); + + return 0; +} + +//***************************************************************************** + +IMPL_LINK( SvtFileDialog, DblClickHdl_Impl, SvTabListBox*, EMPTYARG ) +{ + _pImp->_bDoubleClick = TRUE; + OpenHdl_Impl( this, NULL ); + _pImp->_bDoubleClick = FALSE; + + return 0; +} + +//***************************************************************************** + +IMPL_LINK( SvtFileDialog, EntrySelectHdl_Impl, ComboBox*, EMPTYARG ) +{ + FileSelect(); + + return 0; +} + +//***************************************************************************** + +IMPL_LINK( SvtFileDialog, OpenDoneHdl_Impl, SvtFileView*, pView ) +{ + String sCurrentFolder( pView->GetViewURL() ); + // check if we can create new folders + EnableControl( _pImp->_pBtnNewFolder, ContentCanMakeFolder( sCurrentFolder ) ); + + // check if we can travel one level up + bool bCanTravelUp = ContentHasParentFolder( pView->GetViewURL() ); + if ( bCanTravelUp ) + { + // additional check: the parent folder should not be prohibited + INetURLObject aCurrentFolder( sCurrentFolder ); + DBG_ASSERT( INET_PROT_NOT_VALID != aCurrentFolder.GetProtocol(), + "SvtFileDialog::OpenDoneHdl_Impl: invalid current URL!" ); + + aCurrentFolder.removeSegment(); + bCanTravelUp &= isUrlAllowed( aCurrentFolder.GetMainURL( INetURLObject::NO_DECODE ) ); + } + EnableControl( _pImp->_pBtnUp, bCanTravelUp ); + + return 0; +} + +//***************************************************************************** + +IMPL_LINK( SvtFileDialog, AutoExtensionHdl_Impl, CheckBox*, EMPTYARG ) +{ + if ( _pFileNotifier ) + _pFileNotifier->notify( CTRL_STATE_CHANGED, + CHECKBOX_AUTOEXTENSION ); + + // update the extension of the current file if necessary + lcl_autoUpdateFileExtension( this ); + + return 0; +} + +//***************************************************************************** + +IMPL_LINK( SvtFileDialog, ClickHdl_Impl, CheckBox*, pCheckBox ) +{ + if ( ! _pFileNotifier ) + return 0; + + sal_Int16 nId = -1; + + if ( pCheckBox == _pImp->_pCbOptions ) + nId = CHECKBOX_FILTEROPTIONS; + else if ( pCheckBox == _pCbSelection ) + nId = CHECKBOX_SELECTION; + else if ( pCheckBox == _pCbReadOnly ) + nId = CHECKBOX_READONLY; + else if ( pCheckBox == _pImp->_pCbPassword ) + nId = CHECKBOX_PASSWORD; + else if ( pCheckBox == _pCbLinkBox ) + nId = CHECKBOX_LINK; + else if ( pCheckBox == _pCbPreviewBox ) + nId = CHECKBOX_PREVIEW; + + if ( nId != -1 ) + _pFileNotifier->notify( CTRL_STATE_CHANGED, nId ); + + return 0; +} + +//***************************************************************************** + +IMPL_LINK( SvtFileDialog, PlayButtonHdl_Impl, PushButton*, EMPTYARG ) +{ + if ( _pFileNotifier ) + _pFileNotifier->notify( CTRL_STATE_CHANGED, + PUSHBUTTON_PLAY ); + + return 0; +} + +//***************************************************************************** + +long SvtFileDialog::Notify( NotifyEvent& rNEvt ) + +/* [Beschreibung] + + Die Methode wird gerufen, <BACKSPACE> abzufangen. +*/ + +{ + USHORT nType = rNEvt.GetType(); + long nRet = 0; + + if ( EVENT_KEYINPUT == nType && rNEvt.GetKeyEvent() ) + { + const KeyCode& rKeyCode = rNEvt.GetKeyEvent()->GetKeyCode(); + USHORT nCode = rKeyCode.GetCode(); + + if ( !rKeyCode.GetModifier() && + KEY_BACKSPACE == nCode && !_pImp->_pEdFileName->HasChildPathFocus() ) + { + nRet = 0; //! (long)_pFileView->DoBeamerKeyInput( *rNEvt.GetKeyEvent() ); + + if ( !nRet && _pImp->_pBtnUp->IsEnabled() ) + { + PrevLevel_Impl(); + nRet = 1; + } + } +// else if ( rKeyCode.IsMod1() && ( KEY_C == nCode || KEY_V == nCode || KEY_X == nCode ) ) +// { +/* (mhu) + String aVerb = KEY_C == nCode ? UniString(RTL_CONSTASCII_USTRINGPARAM(SVT_MENUPART_VERB_COPY)) : + ( KEY_V == nCode ? UniString(RTL_CONSTASCII_USTRINGPARAM(SVT_MENUPART_VERB_PASTE)) : UniString(RTL_CONSTASCII_USTRINGPARAM(SVT_MENUPART_VERB_CUT)) ); +//(dv) if ( !CntPopupMenu::DoVerbCommand( aVerb, _pFileView->GetView() ) ) +//(dv) Sound::Beep(); +*/ +// } + } + return nRet ? nRet : ModalDialog::Notify( rNEvt ); +} + +//***************************************************************************** + +long SvtFileDialog::OK() +{ + return TRUE; +} + +//***************************************************************************** + +class SvtDefModalDialogParent_Impl +{ +private: + Window* _pOld; + +public: + SvtDefModalDialogParent_Impl( Window *pNew ) : + _pOld( Application::GetDefDialogParent() ) + { Application::SetDefDialogParent( pNew ); } + + ~SvtDefModalDialogParent_Impl() { Application::SetDefDialogParent( _pOld ); } +}; + +//***************************************************************************** + +//--------------------------------------------------------------------- +void SvtFileDialog::updateListboxLabelSizes() +{ + sal_Int16 nLineControlId[5] = { + LISTBOX_VERSION, LISTBOX_TEMPLATE, LISTBOX_IMAGE_TEMPLATE, LISTBOX_FILTER, EDIT_FILEURL + }; + + // determine the maximum width needed for the listbox labels + long nMaxWidth = 0; + for ( sal_Int32 i=0; i<5; ++i ) + { + FixedText* pLabel = static_cast< FixedText* >( getControl( nLineControlId[i], sal_True ) ); + if ( !pLabel ) + continue; + nMaxWidth = ::std::max( pLabel->GetTextWidth( pLabel->GetText() ), nMaxWidth ); + } + + // ensure that all labels are wide enough + for ( sal_Int32 i=0; i<5; ++i ) + { + FixedText* pLabel = static_cast< FixedText* >( getControl( nLineControlId[i], sal_True ) ); + ListBox* pListbox = static_cast< ListBox* >( getControl( nLineControlId[i], sal_False ) ); + if ( !pLabel || !pListbox ) + continue; + Size aCurrentSize( pLabel->GetSizePixel() ); + if ( aCurrentSize.Width() >= nMaxWidth ) + continue; + + long nChange = nMaxWidth - aCurrentSize.Width(); + pLabel->SetSizePixel( Size( nMaxWidth, aCurrentSize.Height() ) ); + + aCurrentSize = pListbox->GetSizePixel(); + pListbox->SetSizePixel( Size( aCurrentSize.Width() - nChange, aCurrentSize.Height() ) ); + lcl_MoveControl( pListbox, nChange, 0 ); + } +} + +//--------------------------------------------------------------------- +String SvtFileDialog::implConvertToURL( const String& _rPath, sal_Bool _bAssumeFile, const String& _rFallback ) +{ + // an URL parser for the fallback + INetURLObject aURLParser; + + // set the path + bool bWasAbsolute = FALSE; + aURLParser = aURLParser.smartRel2Abs( _rPath, bWasAbsolute ); + + // is it an valid folder? + m_aContent.bindTo( aURLParser.GetMainURL( INetURLObject::NO_DECODE ) ); + sal_Bool bIsFolder = m_aContent.isFolder( ); // do this _before_ asking isInvalid! + sal_Bool bIsInvalid = m_aContent.isInvalid(); + + if ( bIsInvalid && _bAssumeFile && !aURLParser.hasFinalSlash() ) + { // check if the parent folder exists + // #108429# - 2003-03-26 - fs@openoffice.org + INetURLObject aParent( aURLParser ); + aParent.removeSegment( ); + aParent.setFinalSlash( ); + SmartContent aTemporary( aParent.GetMainURL( INetURLObject::NO_DECODE ) ); + bIsInvalid = aTemporary.isInvalid(); + } + + if ( bIsInvalid ) + aURLParser = INetURLObject( _rFallback ); + else if ( bIsFolder ) + aURLParser.setFinalSlash(); + + return aURLParser.GetMainURL( INetURLObject::NO_DECODE ); +} + +//--------------------------------------------------------------------- +short SvtFileDialog::Execute() +{ + // #53016# evtl. nur ein Filename ohne Pfad? + String aFileNameOnly; + if( _aPath.Len() && (_pImp->_eMode == FILEDLG_MODE_SAVE) + && (_aPath.Search(':') == STRING_NOTFOUND) + && (_aPath.Search('\\') == STRING_NOTFOUND) + && (_aPath.Search('/') == STRING_NOTFOUND)) + { + aFileNameOnly = _aPath; + _aPath.Erase(); + } + + // kein Startpfad angegeben? + if ( !_aPath.Len() ) + { + // dann das Standard-Dir verwenden + _aPath = lcl_ensureFinalSlash( _pImp->GetStandardDir() ); + + // #53016# vorgegebener Dateiname an Pfad anh"angen + if ( aFileNameOnly.Len() ) + _aPath += aFileNameOnly; + } + + //..................................................................... + // convert input (_aPath) to url + _aPath = implConvertToURL( _aPath, ( FILEDLG_MODE_SAVE == _pImp->_eMode ), GetStandardDir() ); + + //..................................................................... + // care for possible restrictions on the paths we're allowed to show + if ( !isUrlAllowed( _aPath ) ) + { + DBG_ASSERT( !m_aApprovedURLs.empty(), "SvtFileDialog::Execute: how this?" ); + // isUrlAllowed should return true if m_aApprovedURLs is empty + if ( !m_aApprovedURLs.empty() ) + _aPath = m_aApprovedURLs[0]; + } + + // Ggf. Filter anzeigen. + _pImp->InitFilterList(); + + // Initialen Filter einstellen. + USHORT nFilterCount = GetFilterCount(); + String aAll( SvtResId( STR_FILTERNAME_ALL ) ); + BOOL bHasAll = _pImp->HasFilterListEntry( aAll ); + if ( _pImp->GetCurFilter() || nFilterCount == 1 || ( nFilterCount == 2 && bHasAll ) ) + { + // Ggf. einzigen Filter als aktuellen Filter setzen oder den einzigen + // Filter, der nicht auf alle Dateien verweist. + if ( !_pImp->GetCurFilter() ) + { + USHORT nPos = 0; + if ( 2 == nFilterCount && bHasAll ) + { + nPos = nFilterCount; + while ( nPos-- ) + { + if ( GetFilterName( nPos ) != aAll ) + break; + } + } + SvtFileDialogFilter_Impl* pNewCurFilter = _pImp->_pFilter->GetObject( nPos ); + DBG_ASSERT( pNewCurFilter, "SvtFileDialog::Execute: invalid filter pos!" ); + _pImp->SetCurFilter( pNewCurFilter, pNewCurFilter->GetName() ); + } + + // Anzeige anpassen. + _pImp->SelectFilterListEntry( _pImp->GetCurFilter()->GetName() ); + String aType( _pImp->GetCurFilter()->GetType() ); + SetDefaultExt( aType.Copy( 2 ) ); + USHORT nSepPos = GetDefaultExt().Search( FILEDIALOG_DEF_EXTSEP ); + if ( nSepPos != STRING_NOTFOUND ) + EraseDefaultExt( nSepPos ); + } + else + { + // Ggf. Filter fuer alle Dateien setzen bzw. erzeugen. + if ( !bHasAll ) + { + SvtFileDialogFilter_Impl* pAllFilter = implAddFilter( aAll, UniString(RTL_CONSTASCII_USTRINGPARAM(FILEDIALOG_FILTER_ALL)) ); + _pImp->InsertFilterListEntry( pAllFilter ); + _pImp->SetCurFilter( pAllFilter, aAll ); + } + _pImp->SelectFilterListEntry( aAll ); + } + + _pImp->_pDefaultFilter = _pImp->GetCurFilter(); + + // HACK #50065# + // ggf. Filter isolieren. + String aFilter; + + if ( !IsolateFilterFromPath_Impl( _aPath, aFilter ) ) + return 0; + + sal_uInt16 nNewFilterFlags = adjustFilter( aFilter ); + if ( nNewFilterFlags & ( FLT_NONEMPTY | FLT_USERFILTER ) ) + { + _pImp->_pEdFileName->SetText( aFilter ); + } + // HACK #50065# + + // Instanz fuer den gesetzten Pfad erzeugen und anzeigen. + INetURLObject aFolderURL( _aPath ); + String aFileName( aFolderURL.getName( INetURLObject::LAST_SEGMENT, false ) ); + USHORT nFileNameLen = aFileName.Len(); + BOOL bFileToSelect; + if ( ( bFileToSelect = nFileNameLen && aFileName.GetChar( nFileNameLen - 1 ) != INET_PATH_TOKEN ) ) + { + _pImp->_pEdFileName->SetText( GET_DECODED_NAME( aFolderURL ) ); + aFolderURL.removeSegment(); + } + + INetURLObject aObj = aFolderURL; + if ( aObj.GetProtocol() == INET_PROT_FILE ) + { + // Ordner als aktuelles Verzeichnis setzen. + aObj.setFinalSlash(); + } + + UpdateControls( aObj.GetMainURL( INetURLObject::NO_DECODE ) ); + + // Somebody might want to enable some controls acording to the current filter + FilterSelect(); + + // Zustand der Steuerelemente anpassen. +// EndListeningAll(); + + ViewHdl_Impl( this, NULL ); + OpenURL_Impl( aObj.GetMainURL( INetURLObject::NO_DECODE ) ); + + _pFileView->Show(); + SvtDefModalDialogParent_Impl aDefParent( this ); + + // ggf. Gr"osse aus Ini lesen und setzen + InitSize(); + + // Start des Dialogs. + _bIsInExecute = TRUE; + short nResult = ModalDialog::Execute(); + _bIsInExecute = FALSE; + + DBG_ASSERT( !m_pCurrentAsyncAction.is(), "SvtFilePicker::Execute: still running an async action!" ); + // the dialog should not be cancellable while an async action is running - firs, the action + // needs to be cancelled + + // letztes Verzeichnis merken + if ( RET_OK == nResult ) + { + INetURLObject aURL( _aPath ); + if ( aURL.GetProtocol() == INET_PROT_FILE ) + { + // nur bei File-URL's und nicht bei virtuelle Folder + // das ausgew"ahlte Verzeichnis merken + sal_Int32 nLevel = aURL.getSegmentCount(); + // #97148# & #102204# ------ + sal_Bool bDir = m_aContent.isFolder( aURL.GetMainURL( INetURLObject::NO_DECODE ) ); + BOOL bClassPath = ( ( _pImp->_nStyle & SFXWB_CLASSPATH ) == SFXWB_CLASSPATH ); + if ( nLevel > 1 && ( FILEDLG_TYPE_FILEDLG == _pImp->_eDlgType || !bDir ) ) + aURL.removeSegment(); + } + } + + return nResult; +} + +//----------------------------------------------------------------------------- +void SvtFileDialog::onAsyncOperationStarted() +{ + EnableUI( FALSE ); + // the cancel button must be always enabled + _pImp->_pBtnCancel->Enable( TRUE ); + _pImp->_pBtnCancel->GrabFocus(); +} + +//----------------------------------------------------------------------------- +void SvtFileDialog::onAsyncOperationFinished() +{ + EnableUI( TRUE ); + m_pCurrentAsyncAction = NULL; + if ( !m_bInExecuteAsync ) + _pImp->_pEdFileName->GrabFocus(); + // (if m_bInExecuteAsync is true, then the operation was finished within the minium wait time, + // and to the user, the operation appears to be synchronous) +} + +//------------------------------------------------------------------------- +void SvtFileDialog::displayIOException( const String& _rURL, ::com::sun::star::ucb::IOErrorCode _eCode ) +{ + try + { + // create make a human-readable string from the URL + String sDisplayPath( _rURL ); + ::utl::LocalFileHelper::ConvertURLToSystemPath( _rURL, sDisplayPath ); + + // build an own exception which tells "access denied" + ::com::sun::star::ucb::InteractiveAugmentedIOException aException; + aException.Arguments.realloc( 2 ); + aException.Arguments[ 0 ] <<= ::rtl::OUString( sDisplayPath ); + aException.Arguments[ 1 ] <<= PropertyValue( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Uri" ) ), + -1, aException.Arguments[ 0 ], PropertyState_DIRECT_VALUE + ); + // (formerly, it was sufficient to put the URL first parameter. Nowadays, + // the services expects the URL in a PropertyValue named "Uri" ...) + aException.Code = _eCode; + aException.Classification = InteractionClassification_ERROR; + + // let and interaction handler handle this exception + ::comphelper::OInteractionRequest* pRequest = NULL; + Reference< ::com::sun::star::task::XInteractionRequest > xRequest = pRequest = + new ::comphelper::OInteractionRequest( makeAny( aException ) ); + pRequest->addContinuation( new ::comphelper::OInteractionAbort( ) ); + + Reference< XInteractionHandler > xHandler( + ::comphelper::getProcessServiceFactory()->createInstance( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.task.InteractionHandler") ) + ), + UNO_QUERY + ); + if ( xHandler.is() ) + xHandler->handle( xRequest ); + } + catch( const Exception& ) + { + DBG_ERROR( "iodlg::displayIOException: caught an exception!" ); + } +} + +//----------------------------------------------------------------------------- +void SvtFileDialog::EnableUI( BOOL _bEnable ) +{ + Enable( _bEnable ); + + if ( _bEnable ) + { + for ( ::std::set< Control* >::iterator aLoop = m_aDisabledControls.begin(); + aLoop != m_aDisabledControls.end(); + ++aLoop + ) + { + (*aLoop)->Enable( FALSE ); + } + } +} + +//----------------------------------------------------------------------------- +void SvtFileDialog::EnableControl( Control* _pControl, BOOL _bEnable ) +{ + if ( !_pControl ) + { + DBG_ERRORFILE( "SvtFileDialog::EnableControl: invalid control!" ); + return; + } + + _pControl->Enable( _bEnable ); + + if ( _bEnable ) + { + ::std::set< Control* >::iterator aPos = m_aDisabledControls.find( _pControl ); + if ( m_aDisabledControls.end() != aPos ) + m_aDisabledControls.erase( aPos ); + } + else + m_aDisabledControls.insert( _pControl ); +} + +//----------------------------------------------------------------------------- +void SvtFileDialog::implInitializeSpecialURLLists( ) +{ + m_aApprovedURLs.resize( 0 ); + ::std::vector< String > aFavourites; + + getUnrestrictedFolders( m_aApprovedURLs ); + if ( !m_aApprovedURLs.empty() ) + { + // if we have restrictions, then the "favourites" are the restricted folders only + aFavourites = m_aApprovedURLs; + // for approved URLs, we needed the final slashes, for + // favourites, we do not want to have them + ::std::for_each( aFavourites.begin(), aFavourites.end(), RemoveFinalSlash() ); + } + else + { + ::rtl::OUString sFavouritesList; + if ( getEnvironmentValue( "PathFavourites", sFavouritesList ) ) + convertStringListToUrls( sFavouritesList, aFavourites, false ); + } + + DBG_ASSERT( _pImp->_pBtnStandard, "SvtFileDialog::implInitializeSpecialURLLists: how this?" ); + if ( _pImp->_pBtnStandard ) + _pImp->_pBtnStandard->SetFavouriteLocations( aFavourites ); +} + +//----------------------------------------------------------------------------- +void SvtFileDialog::executeAsync( ::svt::AsyncPickerAction::Action _eAction, + const String& _rURL, const String& _rFilter ) +{ + DBG_ASSERT( !m_pCurrentAsyncAction.is(), "SvtFileDialog::executeAsync: previous async action not yet finished!" ); + + m_pCurrentAsyncAction = new AsyncPickerAction( this, _pFileView, _eAction ); + + bool bReallyAsync = true; + m_aConfiguration.getNodeValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FillAsynchronously" ) ) ) >>= bReallyAsync; + + sal_Int32 nMinTimeout = 0; + m_aConfiguration.getNodeValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Timeout/Min" ) ) ) >>= nMinTimeout; + sal_Int32 nMaxTimeout = 0; + m_aConfiguration.getNodeValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Timeout/Max" ) ) ) >>= nMaxTimeout; + + m_bInExecuteAsync = true; + m_pCurrentAsyncAction->execute( _rURL, _rFilter, bReallyAsync ? nMinTimeout : -1, nMaxTimeout ); + m_bInExecuteAsync = false; +} + +//***************************************************************************** + +void SvtFileDialog::FileSelect() +{ + if ( _pFileNotifier ) + _pFileNotifier->notify( FILE_SELECTION_CHANGED, 0 ); +} + +//***************************************************************************** + +void SvtFileDialog::FilterSelect() +{ + if ( _pFileNotifier ) + _pFileNotifier->notify( CTRL_STATE_CHANGED, + LISTBOX_FILTER ); +} + +//***************************************************************************** + +void SvtFileDialog::SetStandardDir( const String& rStdDir ) + +/* [Beschreibung] + + Die Methode setzt den Pfad f"ur den Standardknopf. +*/ + +{ + INetURLObject aObj( rStdDir ); + DBG_ASSERT( aObj.GetProtocol() != INET_PROT_NOT_VALID, "Invalid protocol!" ); + aObj.setFinalSlash(); + _pImp->SetStandardDir( aObj.GetMainURL( INetURLObject::NO_DECODE ) ); +} + +//***************************************************************************** + +const String& SvtFileDialog::GetStandardDir() const + +/* [Beschreibung] + + Diese Methode gibt den eingestellten Standardpfad zur"uck. +*/ + +{ + return _pImp->GetStandardDir(); +} + +//***************************************************************************** + +void SvtFileDialog::PrevLevel_Impl() +{ + String sDummy; + executeAsync( AsyncPickerAction::ePrevLevel, sDummy, sDummy ); +} + +//***************************************************************************** + +void SvtFileDialog::OpenURL_Impl( const String& _rURL ) +{ + DBG_ASSERT( isUrlAllowed( _rURL ), "SvtFileDialog::OpenURL_Impl: forbidden URL! Should have been handled by the caller!" ); + executeAsync( AsyncPickerAction::eOpenURL, _rURL, getMostCurrentFilter( _pImp ) ); +} + +//***************************************************************************** +SvtFileDialogFilter_Impl* SvtFileDialog::implAddFilter( const String& _rFilter, const String& _rType ) +{ + SvtFileDialogFilter_Impl* pNewFilter = new SvtFileDialogFilter_Impl( _rFilter, _rType ); + _pImp->_pFilter->C40_INSERT( SvtFileDialogFilter_Impl, pNewFilter, (USHORT)0 ); + + if ( !_pImp->GetCurFilter() ) + _pImp->SetCurFilter( pNewFilter, _rFilter ); + + return pNewFilter; +} + +//***************************************************************************** + +void SvtFileDialog::AddFilter( const String& _rFilter, const String& _rType ) +{ + DBG_ASSERT( !IsInExecute(), "SvtFileDialog::AddFilter: currently executing!" ); + implAddFilter ( _rFilter, _rType ); +} + +//***************************************************************************** +void SvtFileDialog::AddFilterGroup( const String& _rFilter, const Sequence< StringPair >& _rFilters ) +{ + DBG_ASSERT( !IsInExecute(), "SvtFileDialog::AddFilter: currently executing!" ); + + implAddFilter( _rFilter, String() ); + const StringPair* pSubFilters = _rFilters.getConstArray(); + const StringPair* pSubFiltersEnd = pSubFilters + _rFilters.getLength(); + for ( ; pSubFilters != pSubFiltersEnd; ++pSubFilters ) + implAddFilter( pSubFilters->First, pSubFilters->Second ); +} + +//***************************************************************************** + +//----------------------------------------------------------------------------- +void SvtFileDialog::SetCurFilter( const String& rFilter ) +{ + DBG_ASSERT( !IsInExecute(), "SvtFileDialog::SetCurFilter: currently executing!" ); + + // Entsprechenden Filter suchen. + USHORT nPos = _pImp->_pFilter->Count(); + + while ( nPos-- ) + { + SvtFileDialogFilter_Impl* pFilter = _pImp->_pFilter->GetObject( nPos ); + if ( pFilter->GetName() == rFilter ) + { + _pImp->SetCurFilter( pFilter, rFilter ); + break; + } + } +} + +//***************************************************************************** + +String SvtFileDialog::GetCurFilter() const +{ + String aFilter; + + const SvtFileDialogFilter_Impl* pCurrentFilter = _pImp->GetCurFilter(); + if ( pCurrentFilter ) + aFilter = pCurrentFilter->GetName(); + + return aFilter; +} + +String SvtFileDialog::getCurFilter( ) const +{ + return GetCurFilter(); +} + +//***************************************************************************** + +USHORT SvtFileDialog::GetFilterCount() const +{ + return _pImp->_pFilter->Count(); +} + +//***************************************************************************** + +const String& SvtFileDialog::GetFilterName( USHORT nPos ) const +{ + DBG_ASSERT( nPos < GetFilterCount(), "invalid index" ); + return _pImp->_pFilter->GetObject( nPos )->GetName(); +} + +//***************************************************************************** + +const String& SvtFileDialog::GetFilterType( USHORT nPos ) const +{ + DBG_ASSERT( nPos < GetFilterCount(), "invalid index" ); + return _pImp->_pFilter->GetObject( nPos )->GetType(); +} + +//***************************************************************************** + +void SvtFileDialog::SetDefaultButtonText( const XubString& rText, ULONG nHelpId ) +{ + if ( _pImp && _pImp->_pBtnFileOpen ) + { + _pImp->_pBtnFileOpen->SetText( rText ); + if ( nHelpId ) + _pImp->_pBtnFileOpen->SetHelpId( nHelpId ); + } +} + +//***************************************************************************** + +void SvtFileDialog::InitSize() +{ + if ( ! _pImp->_aIniKey.Len() ) + return; + + Size aDlgSize = GetResizeOutputSizePixel(); + SetMinOutputSizePixel( aDlgSize ); + + if ( !_pImp->_nFixDeltaHeight ) + { + // Fixgr"ossen errechnen und merken + Point aPnt = _pFileView->GetPosPixel(); + long nBoxH = _pFileView->GetSizePixel().Height(); + long nH = GetSizePixel().Height(); + _pImp->_nFixDeltaHeight = nH - nBoxH; + } + + // initialize from config + SvtViewOptions aDlgOpt( E_DIALOG, _pImp->_aIniKey ); + + if ( aDlgOpt.Exists() ) + { + SetWindowState( ByteString( String( aDlgOpt.GetWindowState() ), osl_getThreadTextEncoding() ) ); + + Any aUserData = aDlgOpt.GetUserItem( ::rtl::OUString::createFromAscii( "UserData" ) ); + ::rtl::OUString sCfgStr; + if ( aUserData >>= sCfgStr ) + _pFileView->SetConfigString( String( sCfgStr ) ); + } +} + +//***************************************************************************** + +SvStringsDtor* SvtFileDialog::GetPathList() const +{ + SvStringsDtor* pList = new SvStringsDtor; + ULONG nCount = _pFileView->GetSelectionCount(); + SvLBoxEntry* pEntry = nCount ? _pFileView->FirstSelected() : NULL; + + if ( ! pEntry ) + { + String* pURL; + + if ( _pImp->_pEdFileName->GetText().Len() && _bIsInExecute ) + pURL = new String( _pImp->_pEdFileName->GetURL() ); + else + pURL = new String( _aPath ); + + pList->Insert( pURL, pList->Count() ); + } + else + { + while ( pEntry ) + { + String* pURL = new String( _pFileView->GetURL( pEntry ) ); + pList->Insert( pURL, pList->Count() ); + pEntry = _pFileView->NextSelected( pEntry ); + } + } + + return pList; +} + +//***************************************************************************** + +void SvtFileDialog::implArrangeControls() +{ + // this is the list of controls in the order they should be tabbed + // the focus is initially in the first control of this list + Control* pControls[] = + { + _pImp->_pFtFileName, _pImp->_pEdFileName, _pImp->_pFtFileVersion, _pImp->_pLbFileVersion, + _pImp->_pFtTemplates, _pImp->_pLbTemplates, _pImp->_pFtImageTemplates, _pImp->_pLbImageTemplates, + _pImp->_pFtFileType, _pImp->GetFilterListControl(), // edit fields/list boxes + _pImp->_pCbPassword, _pImp->_pCbAutoExtension, _pImp->_pCbOptions, // checkboxes + _pCbReadOnly, _pCbLinkBox, _pCbPreviewBox, _pCbSelection, _pPbPlay, // check boxes (continued) + _pImp->_pBtnFileOpen, _pImp->_pBtnCancel, _pImp->_pBtnHelp, // buttons + _pImp->_pBtnUp, _pImp->_pBtnNewFolder, _pImp->_pBtnStandard, // image buttons + _pFileView // the file view + }; + // (including the FixedTexts is important - not for tabbing order (they're irrelevant there), but for working + // keyboard shortcuts) + // 96861 - 23.01.2002 - fs@openoffice.org + + // loop through all these controls and adjust the z-order + Window* pPreviousWin = NULL; + Control** pCurrent = pControls; + for ( sal_Int32 i = 0; i < sizeof( pControls ) / sizeof( pControls[ 0 ] ); ++i, ++pCurrent ) + { + if ( !*pCurrent ) + // this control is not available in the current operation mode -> skip + continue; + + if ( pPreviousWin ) + (*pCurrent)->SetZOrder( pPreviousWin, WINDOW_ZORDER_BEHIND ); + else + (*pCurrent)->SetZOrder( NULL, WINDOW_ZORDER_FIRST ); + + pPreviousWin = *pCurrent; + } +} + +//***************************************************************************** + +BOOL SvtFileDialog::IsolateFilterFromPath_Impl( String& rPath, String& rFilter ) +{ + String aEmpty; + String aReversePath( rPath ); + aReversePath.Reverse(); + USHORT nQuestionMarkPos = rPath.Search( '?' ); + + if ( nQuestionMarkPos != STRING_NOTFOUND ) + { + // Fragezeichen als Wildcard nur bei Files + INetProtocol eProt = INetURLObject::CompareProtocolScheme( rPath ); + + if ( INET_PROT_NOT_VALID != eProt && INET_PROT_FILE != eProt ) + nQuestionMarkPos = STRING_NOTFOUND; + } + USHORT nWildCardPos = Min( rPath.Search( FILEDIALOG_DEF_WILDCARD ), nQuestionMarkPos ); + rFilter = aEmpty; + + if ( nWildCardPos != STRING_NOTFOUND ) + { + USHORT nPathTokenPos = aReversePath.Search( INET_PATH_TOKEN ); + + if ( nPathTokenPos == STRING_NOTFOUND ) + { + String aDelim( +#ifdef WNT + '\\' +#elif MAC + ':' +#else + '/' +#endif + ); + + nPathTokenPos = aReversePath.Search( aDelim ); +#if !defined( UNX ) && !defined( MAC ) + if ( nPathTokenPos == STRING_NOTFOUND ) + { + nPathTokenPos = aReversePath.Search( ':' ); + } +#endif + } + + // Syntax pr"ufen. + if ( nPathTokenPos != STRING_NOTFOUND ) + { + if ( nPathTokenPos < (rPath.Len() - nWildCardPos - 1) ) + { + ErrorHandler::HandleError( ERRCODE_SFX_INVALIDSYNTAX ); + return FALSE; + } + + // Filter abschneiden. + rFilter = aReversePath; + rFilter.Erase( nPathTokenPos ); + rFilter.Reverse(); + + // Ordner bestimmen. + rPath = aReversePath; + rPath.Erase( 0, nPathTokenPos ); + rPath.Reverse(); + } + else + { + rFilter = rPath; + rPath = aEmpty; + } + } + + return TRUE; +} + +//***************************************************************************** + +//----------------------------------------------------------------------------- +void SvtFileDialog::implUpdateImages( ) +{ + // determine high contrast mode + { + sal_Bool bIsHighContrast = GetDisplayBackground().GetColor().IsDark(); + m_aImages = ImageList( SvtResId( bIsHighContrast ? RID_FILEPICKER_IMAGES_HC : RID_FILEPICKER_IMAGES ) ); + } + + // set the appropriate images on the buttons + if ( _pImp->_pBtnUp ) + _pImp->_pBtnUp->SetModeImage( GetButtonImage( IMG_FILEDLG_BTN_UP ) ); + + if ( _pImp->_pBtnStandard ) + _pImp->_pBtnStandard->SetModeImage( GetButtonImage( IMG_FILEDLG_BTN_STD ) ); + + if ( _pImp->_pBtnNewFolder ) + _pImp->_pBtnNewFolder->SetModeImage( GetButtonImage( IMG_FILEDLG_CREATEFOLDER ) ); +} + +//----------------------------------------------------------------------------- +void SvtFileDialog::DataChanged( const DataChangedEvent& _rDCEvt ) +{ + if ( DATACHANGED_SETTINGS == _rDCEvt.GetType() ) + implUpdateImages( ); + + ModalDialog::DataChanged( _rDCEvt ); +} + +//----------------------------------------------------------------------------- +void SvtFileDialog::Resize() +{ + if ( IsRollUp() ) + return; + + Size aDlgSize = GetResizeOutputSizePixel(); + Size aOldSize = _pImp->_aDlgSize; + _pImp->_aDlgSize = aDlgSize; + long nWinDeltaW = 0; + + if ( _pPrevWin && + _pPrevWin->GetPosPixel().X() > _pFileView->GetPosPixel().X() ) + { + nWinDeltaW = _pPrevWin->GetOutputSizePixel().Width() + _pImp->_a6Size.Width(); + } + + Size aNewSize = _pFileView->GetSizePixel(); + Point aBoxPos( _pFileView->GetPosPixel() ); + long nDeltaY = aNewSize.Height(); + long nDeltaX = aNewSize.Width(); + aNewSize.Height() = aDlgSize.Height() - _pImp->_nFixDeltaHeight; + aNewSize.Width() = aDlgSize.Width() - aBoxPos.X() - _pImp->_a6Size.Width() - nWinDeltaW; + if ( aOldSize.Height() ) + nDeltaY = _pImp->_aDlgSize.Height() - aOldSize.Height(); + else + nDeltaY = aNewSize.Height() - nDeltaY; + nDeltaX = aNewSize.Width() - nDeltaX; + + if ( nWinDeltaW ) + nWinDeltaW = nDeltaX * 2 / 3; + aNewSize.Width() -= nWinDeltaW; + nDeltaX -= nWinDeltaW; + + _pFileView->SetSizePixel( aNewSize ); + + if ( !nDeltaY && !nDeltaX ) + // Dieses Resize wurde nur zum Ein - oder Ausblenden des Indicators aufgerufen + return; + + long nMaxYPos = 0; + + // ------------- + // move controls + + // controls to move vertically + { + Control* aMoveControlsVert[] = + { + _pImp->_pFtFileName, _pImp->_pEdFileName, _pImp->_pFtFileVersion, _pImp->_pLbFileVersion, + _pImp->_pFtTemplates, _pImp->_pLbTemplates, _pImp->_pFtImageTemplates, _pImp->_pLbImageTemplates, + _pImp->_pFtFileType, _pImp->GetFilterListControl(), _pCbReadOnly, _pCbLinkBox, _pCbPreviewBox, + _pPbPlay, _pImp->_pCbPassword, _pImp->_pCbAutoExtension, _pImp->_pCbOptions, _pCbSelection + }; + Control** ppMoveControls = aMoveControlsVert; + Control** ppMoveControlsEnd = ppMoveControls + sizeof( aMoveControlsVert ) / sizeof( aMoveControlsVert[0] ); + for ( ; ppMoveControls != ppMoveControlsEnd; ++ppMoveControls ) + lcl_MoveControl( *ppMoveControls, 0, nDeltaY, &nMaxYPos ); + } + + // controls to move vertically and horizontally + { + Control* aMoveControlsBoth[] = + { + _pImp->_pBtnFileOpen, _pImp->_pBtnCancel, _pImp->_pBtnHelp + }; + Control** ppMoveControls = aMoveControlsBoth; + Control** ppMoveControlsEnd = ppMoveControls + sizeof( aMoveControlsBoth ) / sizeof( aMoveControlsBoth[0] ); + for ( ; ppMoveControls != ppMoveControlsEnd; ++ppMoveControls ) + lcl_MoveControl( *ppMoveControls, nDeltaX, nDeltaY, &nMaxYPos ); + } + + // controls to move horizontally + { + Control* aMoveControlsHor[] = + { + _pImp->_pBtnUp, _pImp->_pBtnNewFolder, _pImp->_pBtnStandard + }; + Control** ppMoveControls = aMoveControlsHor; + Control** ppMoveControlsEnd = ppMoveControls + sizeof( aMoveControlsHor ) / sizeof( aMoveControlsHor[0] ); + for ( ; ppMoveControls != ppMoveControlsEnd; ++ppMoveControls ) + lcl_MoveControl( *ppMoveControls, nDeltaX, 0, &nMaxYPos ); + } + + // --------------- + // resize controls + { + Control* aSizeControls[] = + { + _pImp->_pEdFileName, _pImp->_pLbFileVersion, _pImp->_pLbTemplates, _pImp->_pLbImageTemplates, + _pImp->GetFilterListControl(), _pImp->_pFtCurrentPath, + }; + sal_Int32 nSizeControls = sizeof( aSizeControls ) / sizeof( aSizeControls[0] ); + Control** ppSizeControls = aSizeControls; + for ( sal_Int32 j=0; j<nSizeControls; ++j, ++ppSizeControls ) + { + if ( *ppSizeControls ) + { + aNewSize = (*ppSizeControls)->GetSizePixel(); + aNewSize.Width() += nDeltaX; + (*ppSizeControls)->SetSizePixel( aNewSize ); + } + } + } + + // zus"atzliche Controls ausrichten + if ( _pPrevWin && + _pPrevWin->GetPosPixel().X() > _pFileView->GetPosPixel().X() ) + { + // Controls vom Typ Window speziell ausrichten + // auch die Gr"osse anpassen + Point aNewPos = _pPrevWin->GetPosPixel(); + aNewPos.X() += nDeltaX; + _pPrevWin->SetPosPixel( aNewPos ); + _pPrevBmp->SetPosPixel( aNewPos ); + aNewSize = _pPrevWin->GetOutputSizePixel(); + aNewSize.Width() += nWinDeltaW; + aNewSize.Height() += nDeltaY; + if ( !aOldSize.Height() ) + aNewSize.Height() -= ( _pImp->_a6Size.Height() / 2 ); + _pPrevWin->SetOutputSizePixel( aNewSize ); + _pPrevBmp->SetOutputSizePixel( aNewSize ); + _pPrevBmp->Invalidate(); + } + + if ( _pFileNotifier ) + _pFileNotifier->notify( DIALOG_SIZE_CHANGED, 0 ); +} + +//***************************************************************************** + +//----------------------------------------------------------------------------- +Control* SvtFileDialog::getControl( sal_Int16 _nControlId, sal_Bool _bLabelControl ) const +{ + Control* pReturn = NULL; + + switch ( _nControlId ) + { + case CONTROL_FILEVIEW: + pReturn = _bLabelControl ? NULL : static_cast< Control* >( _pFileView ); + break; + + case EDIT_FILEURL: + pReturn = _bLabelControl + ? static_cast< Control* >( _pImp->_pFtFileName ) + : static_cast< Control* >( _pImp->_pEdFileName ); + break; + + case EDIT_FILEURL_LABEL: + pReturn = static_cast< Control* >( _pImp->_pFtFileName ); + break; + + case CHECKBOX_AUTOEXTENSION: + pReturn = _pImp->_pCbAutoExtension; + break; + + case CHECKBOX_PASSWORD: + pReturn = _pImp->_pCbPassword; + break; + + case CHECKBOX_FILTEROPTIONS: + pReturn = _pImp->_pCbOptions; + break; + + case CHECKBOX_READONLY: + pReturn = _pCbReadOnly; + break; + + case CHECKBOX_LINK: + pReturn = _pCbLinkBox; + break; + + case CHECKBOX_PREVIEW: + pReturn = _pCbPreviewBox; + break; + + case CHECKBOX_SELECTION: + pReturn = _pCbSelection; + break; + + case LISTBOX_FILTER: + pReturn = _bLabelControl ? _pImp->_pFtFileType : _pImp->GetFilterListControl(); + break; + + case LISTBOX_FILTER_LABEL: + pReturn = _pImp->_pFtFileType; + break; + + case FIXEDTEXT_CURRENTFOLDER: + pReturn = _pImp->_pFtCurrentPath; + break; + + case LISTBOX_VERSION: + pReturn = _bLabelControl + ? static_cast< Control* >( _pImp->_pFtFileVersion ) + : static_cast< Control* >( _pImp->_pLbFileVersion ); + break; + + case LISTBOX_TEMPLATE: + pReturn = _bLabelControl + ? static_cast< Control* >( _pImp->_pFtTemplates ) + : static_cast< Control* >( _pImp->_pLbTemplates ); + break; + + case LISTBOX_IMAGE_TEMPLATE: + pReturn = _bLabelControl + ? static_cast< Control* >( _pImp->_pFtImageTemplates ) + : static_cast< Control* >( _pImp->_pLbImageTemplates ); + break; + + case LISTBOX_VERSION_LABEL: + pReturn = _pImp->_pFtFileVersion; + break; + + case LISTBOX_TEMPLATE_LABEL: + pReturn = _pImp->_pFtTemplates; + break; + + case LISTBOX_IMAGE_TEMPLATE_LABEL: + pReturn = _pImp->_pFtImageTemplates; + break; + + case PUSHBUTTON_OK: + pReturn = _pImp->_pBtnFileOpen; + break; + + case PUSHBUTTON_CANCEL: + pReturn = _pImp->_pBtnCancel; + break; + + case PUSHBUTTON_PLAY: + pReturn = _pPbPlay; + break; + + case PUSHBUTTON_HELP: + pReturn = _pImp->_pBtnHelp; + break; + + case TOOLBOXBUTOON_DEFAULT_LOCATION: + pReturn = _pImp->_pBtnStandard; + break; + + case TOOLBOXBUTOON_LEVEL_UP: + pReturn = _pImp->_pBtnUp; + break; + + case TOOLBOXBUTOON_NEW_FOLDER: + pReturn = _pImp->_pBtnNewFolder; + break; + + default: + DBG_ERRORFILE( "SvtFileDialog::getControl: invalid id!" ); + } + return pReturn; +} + +// ----------------------------------------------------------------------- +void SvtFileDialog::enableControl( sal_Int16 _nControlId, sal_Bool _bEnable ) +{ + Control* pControl = getControl( _nControlId, sal_False ); + if ( pControl ) + EnableControl( pControl, _bEnable ); + Control* pLabel = getControl( _nControlId, sal_True ); + if ( pLabel ) + EnableControl( pLabel, _bEnable ); +} + +// ----------------------------------------------------------------------- +void SvtFileDialog::AddControls_Impl( ) +{ + // create the "insert as link" checkbox, if needed + if ( _nExtraBits & SFX_EXTRA_INSERTASLINK ) + { + _pCbLinkBox = new CheckBox( this ); + _pCbLinkBox ->SetText( SvtResId( STR_SVT_FILEPICKER_INSERT_AS_LINK ) ); + _pCbLinkBox ->SetHelpId( HID_FILEDLG_LINK_CB ); + AddControl( _pCbLinkBox ); + ReleaseOwnerShip( _pCbLinkBox ); + _pCbLinkBox->SetClickHdl( LINK( this, SvtFileDialog, ClickHdl_Impl ) ); + } + + // create the "show preview" checkbox ( and the preview window, too ), if needed + if ( _nExtraBits & SFX_EXTRA_SHOWPREVIEW ) + { + _pImp->_aIniKey = IMPGRF_CONFIGNAME; + // because the "<All Formats> (*.bmp,*...)" entry is to wide, + // we need to disable the auto width feature of the filter box + _pImp->DisableFilterBoxAutoWidth(); + + // "Vorschau" + _pCbPreviewBox = new CheckBox( this ); + _pCbPreviewBox->SetText( SvtResId( STR_SVT_FILEPICKER_SHOW_PREVIEW ) ); + _pCbPreviewBox->SetHelpId( HID_FILEDLG_PREVIEW_CB ); + AddControl( _pCbPreviewBox ); + ReleaseOwnerShip( _pCbPreviewBox ); + _pCbPreviewBox->SetClickHdl( LINK( this, SvtFileDialog, ClickHdl_Impl ) ); + + // Preview-Fenster erst hier erzeugen + _pPrevWin = new Window( this, WinBits( WB_BORDER ) ); + AddControl( _pPrevWin ); + ReleaseOwnerShip( _pPrevWin ); + _pPrevWin->Hide(); + + _pPrevBmp = new FixedBitmap( this, WinBits( WB_BORDER ) ); + _pPrevBmp->SetBackground( Wallpaper( Color( COL_WHITE ) ) ); + _pPrevBmp->Show(); + } + + if ( _nExtraBits & SFX_EXTRA_AUTOEXTENSION ) + { + _pImp->_pCbAutoExtension = new CheckBox( this, SvtResId( CB_AUTO_EXTENSION ) ); + _pImp->_pCbAutoExtension->SetText( SvtResId( STR_SVT_FILEPICKER_AUTO_EXTENSION ) ); + _pImp->_pCbAutoExtension->Check( TRUE ); + AddControl( _pImp->_pCbAutoExtension ); + ReleaseOwnerShip( _pImp->_pCbAutoExtension ); + _pImp->_pCbAutoExtension->SetClickHdl( LINK( this, SvtFileDialog, AutoExtensionHdl_Impl ) ); + } + + if ( _nExtraBits & SFX_EXTRA_FILTEROPTIONS ) + { + _pImp->_pCbOptions = new CheckBox( this, SvtResId( CB_OPTIONS ) ); + _pImp->_pCbOptions->SetText( SvtResId( STR_SVT_FILEPICKER_FILTER_OPTIONS ) ); + AddControl( _pImp->_pCbOptions ); + ReleaseOwnerShip( _pImp->_pCbOptions ); + _pImp->_pCbOptions->SetClickHdl( LINK( this, SvtFileDialog, ClickHdl_Impl ) ); + } + + if ( _nExtraBits & SFX_EXTRA_SELECTION ) + { + _pCbSelection = new CheckBox( this, SvtResId( CB_OPTIONS ) ); + _pCbSelection->SetText( SvtResId( STR_SVT_FILEPICKER_SELECTION ) ); + AddControl( _pCbSelection ); + ReleaseOwnerShip( _pCbSelection ); + _pCbSelection->SetClickHdl( LINK( this, SvtFileDialog, ClickHdl_Impl ) ); + } + + if ( _nExtraBits & SFX_EXTRA_PLAYBUTTON ) + { + _pPbPlay = new PushButton( this ); + _pPbPlay->SetText( SvtResId( STR_SVT_FILEPICKER_PLAY ) ); + _pPbPlay->SetHelpId( HID_FILESAVE_DOPLAY ); + AddControl( _pPbPlay ); + ReleaseOwnerShip( _pPbPlay ); + _pPbPlay->SetClickHdl( LINK( this, SvtFileDialog, PlayButtonHdl_Impl ) ); + } + + if ( _nExtraBits & SFX_EXTRA_SHOWVERSIONS ) + { + _pImp->_pFtFileVersion = new FixedText( this, SvtResId( FT_EXPLORERFILE_SHARED_LISTBOX ) ); + _pImp->_pFtFileVersion->SetText( SvtResId( STR_SVT_FILEPICKER_VERSION ) ); + + _pImp->_pLbFileVersion = new ListBox( this, SvtResId( LB_EXPLORERFILE_SHARED_LISTBOX ) ); + _pImp->_pLbFileVersion->SetHelpId( HID_FILEOPEN_VERSION ); + } + else if ( _nExtraBits & SFX_EXTRA_TEMPLATES ) + { + _pImp->_pFtTemplates = new FixedText( this, SvtResId( FT_EXPLORERFILE_SHARED_LISTBOX ) ); + _pImp->_pFtTemplates->SetText( SvtResId( STR_SVT_FILEPICKER_TEMPLATES ) ); + + _pImp->_pLbTemplates = new ListBox( this, SvtResId( LB_EXPLORERFILE_SHARED_LISTBOX ) ); + _pImp->_pLbTemplates->SetHelpId( HID_FILEOPEN_VERSION ); + // This is strange. During the re-factoring during 96930, I discovered that this help id + // is set in the "Templates mode". This was hidden in the previous implementation. + // Shouldn't this be a more meaningfull help id. + // 96930 - 15.08.2002 - fs@openoffice.org + } + else if ( _nExtraBits & SFX_EXTRA_IMAGE_TEMPLATE ) + { + _pImp->_pFtImageTemplates = new FixedText( this, SvtResId( FT_EXPLORERFILE_SHARED_LISTBOX ) ); + _pImp->_pFtImageTemplates->SetText( SvtResId( STR_SVT_FILEPICKER_IMAGE_TEMPLATE ) ); + + _pImp->_pLbImageTemplates = new ListBox( this, SvtResId( LB_EXPLORERFILE_SHARED_LISTBOX ) ); + _pImp->_pLbImageTemplates->SetHelpId( HID_FILEOPEN_IMAGE_TEMPLATE ); + } +} + +// ----------------------------------------------------------------------- +sal_Int32 SvtFileDialog::getTargetColorDepth() +{ + if ( _pPrevBmp ) + return _pPrevBmp->GetBitCount(); + else + return 0; +} + +// ----------------------------------------------------------------------- +sal_Int32 SvtFileDialog::getAvailableWidth() +{ + if ( _pPrevBmp ) + return _pPrevBmp->GetOutputSizePixel().Width(); + else + return 0; +} + +// ----------------------------------------------------------------------- +sal_Int32 SvtFileDialog::getAvailableHeight() +{ + if ( _pPrevBmp ) + return _pPrevBmp->GetOutputSizePixel().Height(); + else + return 0; +} + +// ----------------------------------------------------------------------- +void SvtFileDialog::setImage( sal_Int16 aImageFormat, + const Any& rImage ) +{ + if ( ! _pPrevBmp || ! _pPrevBmp->IsVisible() ) + return; + + Sequence < sal_Int8 > aBmpSequence; + + if ( rImage >>= aBmpSequence ) + { + Bitmap aBmp; + SvMemoryStream aData( aBmpSequence.getArray(), + aBmpSequence.getLength(), + STREAM_READ ); + aData >> aBmp; + + _pPrevBmp->SetBitmap( aBmp ); + } + else + { + Bitmap aEmpty; + _pPrevBmp->SetBitmap( aEmpty ); + } +} + +// ----------------------------------------------------------------------- +sal_Bool SvtFileDialog::setShowState( sal_Bool bShowState ) +{ + // #97633 for the system filedialog it's + // usefull to make the preview switchable + // because the preview occupies + // half of the size of the file listbox + // which is not the case here, + // so we (TRA/FS) decided not to make + // the preview window switchable because + // else we would have to change the layout + // of the file dialog dynamically + // support for set/getShowState is opionally + // see com::sun::star::ui::dialogs::XFilePreview + /* + if ( _pPrevBmp ) + { + _pPrevBmp->Show( bShowState ); + return sal_True; + } + else + return sal_False; + */ + + return sal_False; +} + +// ----------------------------------------------------------------------- +String SvtFileDialog::getCurrentFileText( ) const +{ + String sReturn; + if ( _pImp && _pImp->_pEdFileName ) + sReturn = _pImp->_pEdFileName->GetText(); + return sReturn; +} + +// ----------------------------------------------------------------------- +void SvtFileDialog::setCurrentFileText( const String& _rText, bool _bSelectAll ) +{ + if ( _pImp && _pImp->_pEdFileName ) + { + _pImp->_pEdFileName->SetText( _rText ); + if ( _bSelectAll ) + _pImp->_pEdFileName->SetSelection( Selection( 0, _rText.Len() ) ); + } +} + +// ----------------------------------------------------------------------- +sal_Bool SvtFileDialog::isAutoExtensionEnabled() +{ + return _pImp->_pCbAutoExtension && _pImp->_pCbAutoExtension->IsChecked(); +} + +// ----------------------------------------------------------------------- +sal_Bool SvtFileDialog::getShowState() +{ + if ( _pPrevBmp ) + return _pPrevBmp->IsVisible(); + else + return sal_False; +} + +// ----------------------------------------------------------------------- +void SvtFileDialog::ReleaseOwnerShip( Window* pUserControl ) + +/* + [Beschreibung] + Die Methode sorgt dafuer das das spezifizierte Element nicht mehr im Besitz + der Instanz ist. +*/ + +{ + ControlChain_Impl* pElement = _pUserControls; + while ( pElement ) + { + if ( pElement->_pControl == pUserControl ) + { + pElement->_bHasOwnerShip = FALSE; + break; + } + pElement = pElement->_pNext; + } +} + +//*************************************************************************** + +BOOL SvtFileDialog::AddControl( Window* pControl, BOOL bNewLine ) +{ + // control already exists + ControlChain_Impl* pElement = _pUserControls; + while ( pElement ) + { + if ( pElement->_pControl == pControl ) + return FALSE; + pElement = pElement->_pNext; + } + + // Check if controls have already been added. + Size aNewControlSize( pControl->GetOutputSizePixel() ); + Size aDlgSize( GetOutputSizePixel() ); + WindowType nType = pControl->GetType(); + if ( !aNewControlSize.Height() ) + { + // Detect a size. + Size aSize( 0, 10 ); + if ( nType == WINDOW_PUSHBUTTON ) + { + Size aDefSiz = LogicToPixel( Size( 50, 14 ), MAP_APPFONT ); + long nTextWidth = pControl->GetTextWidth( pControl->GetText() ); + aSize.Width() = nTextWidth + WIDTH_ADDITION; + + // PushButton: Mindestbreite 50 logische Einheiten, + // H"ohe immer 14 logische Einheiten + if ( aDefSiz.Width() > aSize.Width() ) + aSize.Width() = aDefSiz.Width(); + aSize.Height() = aDefSiz.Height(); + aNewControlSize = aSize; + } + else + aNewControlSize = LogicToPixel( aSize, MAP_APPFONT ); + if ( nType != WINDOW_PUSHBUTTON ) + aNewControlSize.Width() = pControl->GetTextWidth( pControl->GetText() ) + WIDTH_ADDITION; + if ( nType == WINDOW_CHECKBOX ) + aNewControlSize.Width() += WIDTH_ADDITION; + if ( nType == WINDOW_WINDOW ) + { + aNewControlSize.Height() = GetOutputSizePixel().Height() - 18; + aNewControlSize.Width() = 200; + aDlgSize.Width() += 210; + SetOutputSizePixel( aDlgSize ); + } + pControl->SetOutputSizePixel( aNewControlSize ); + } + Point aNewControlPos; + Size* pNewDlgSize = NULL; + BOOL bNewRow = bNewLine; + FASTBOOL bFirstNewRow = FALSE; + + if ( nType == WINDOW_WINDOW ) + { + aNewControlPos.X() = aDlgSize.Width() - 210; + aNewControlPos.Y() = 8; + } + else if ( _pUserControls ) + { + Point aNewControlRange( _pUserControls->_pControl->GetPosPixel() ); + long nPrevControlHeight = _pUserControls->_pControl->GetSizePixel().Height(); + aNewControlRange += + Point( _pUserControls->_pControl->GetOutputSizePixel().Width(), 0 ); + aNewControlPos = aNewControlRange; + if ( nPrevControlHeight > aNewControlSize.Height() ) + { + long nY = nPrevControlHeight; + nY -= aNewControlSize.Height(); + nY /= 2; + aNewControlPos.Y() += nY; + } + aNewControlPos += LogicToPixel( Point( 3, 0 ), MAP_APPFONT ); + aNewControlRange += LogicToPixel( Point( 9, 0 ), MAP_APPFONT ); + aNewControlRange += Point( aNewControlSize.Width(), 0 ); + + // Check if a new row has to be created. + if ( aNewControlRange.X() > aDlgSize.Width() ) + bNewRow = TRUE; + } + else + { + // Create a new row if there was no usercontrol before. + bNewRow = TRUE; + bFirstNewRow = TRUE; + } + + // Check if a new row has to be created. + Size aBorderSize = LogicToPixel( Size( 6, 6 ), MAP_APPFONT ); + long nLeftBorder = aBorderSize.Width(); + long nLowerBorder = aBorderSize.Height(); + if ( bNewRow ) + { + // Set control at the beginning of a new line. + long nSmallBorderHeight = nLowerBorder / 2; + aNewControlPos = Point( nLeftBorder, 0 ); + aNewControlPos += Point( 0, aDlgSize.Height() ); + aNewControlPos.Y() -= nSmallBorderHeight; + // Set new size. + pNewDlgSize = new Size( aDlgSize ); + pNewDlgSize->Height() -= nSmallBorderHeight; + pNewDlgSize->Height() += aNewControlSize.Height(); + pNewDlgSize->Height() += nLowerBorder; + } + else + { + // Check if the window has to be resized. + Size aNewControlRange( 0, aNewControlPos.Y() ); + aNewControlRange.Height() += aNewControlSize.Height(); + aNewControlRange.Height() += nLowerBorder; + if ( aNewControlRange.Height() > aDlgSize.Height() ) + pNewDlgSize = new Size( aDlgSize.Width(), aNewControlRange.Height() ); + } + + // Update view. + if ( pNewDlgSize ) + { + SetOutputSizePixel( *pNewDlgSize ); + delete pNewDlgSize; + } + pControl->SetPosPixel( aNewControlPos ); + pControl->Show(); + _pUserControls = new ControlChain_Impl( pControl, _pUserControls, TRUE ); + + return TRUE; +} + +sal_Bool SvtFileDialog::ContentHasParentFolder( const rtl::OUString& rURL ) +{ + m_aContent.bindTo( rURL ); + + if ( m_aContent.isInvalid() ) + return sal_False; + + return m_aContent.hasParentFolder( ) && m_aContent.isValid(); +} + +sal_Bool SvtFileDialog::ContentCanMakeFolder( const rtl::OUString& rURL ) +{ + m_aContent.bindTo( rURL ); + + if ( m_aContent.isInvalid() ) + return sal_False; + + return m_aContent.canCreateFolder( ) && m_aContent.isValid(); +} + +sal_Bool SvtFileDialog::ContentGetTitle( const rtl::OUString& rURL, String& rTitle ) +{ + m_aContent.bindTo( rURL ); + + if ( m_aContent.isInvalid() ) + return sal_False; + + ::rtl::OUString sTitle; + m_aContent.getTitle( sTitle ); + rTitle = sTitle; + + return m_aContent.isValid(); +} + +// ----------------------------------------------------------------------- +struct CheckURLAllowed +{ +protected: +#ifdef WNT + SvtSysLocale m_aSysLocale; +#endif + String m_sCheckURL; // the URL to check + +public: + inline CheckURLAllowed( const String& _rCheckURL ) + :m_sCheckURL( _rCheckURL ) + { +#ifdef WNT + // on windows, assume that the relevant file systems are case insensitive, + // thus normalize the URL + m_sCheckURL = m_aSysLocale.GetCharClass().toLower( m_sCheckURL, 0, m_sCheckURL.Len() ); +#endif + } + + bool operator()( const String& _rApprovedURL ) + { +#ifdef WNT + // on windows, assume that the relevant file systems are case insensitive, + // thus normalize the URL + String sApprovedURL( m_aSysLocale.GetCharClass().toLower( _rApprovedURL, 0, _rApprovedURL.Len() ) ); +#else + String sApprovedURL( _rApprovedURL ); +#endif + + // check if m_rCheckURL denotes a folder which is a descendant + // of _rApprovedURL + if ( 0 == m_sCheckURL.Search( sApprovedURL ) ) + return true; + // check if m_rCheckURL denotes a folder which is a ancestor + // of _rApprovedURL + if ( 0 == sApprovedURL.Search( m_sCheckURL ) ) + return true; + return false; + } +}; + +// ----------------------------------------------------------------------- +bool SvtFileDialog::isUrlAllowed( const String& _rURL ) const +{ + if ( m_aApprovedURLs.empty() ) + return true; + + ::std::vector< String >::const_iterator aApprovedURL = ::std::find_if( + m_aApprovedURLs.begin(), + m_aApprovedURLs.end(), + CheckURLAllowed( _rURL ) + ); + + return ( aApprovedURL != m_aApprovedURLs.end() ); +} + +// ----------------------------------------------------------------------- + +// QueryFolderNameDialog ------------------------------------------------------- + +namespace svtools { + +QueryFolderNameDialog::QueryFolderNameDialog +( + Window* _pParent, + const String& rTitle, + const String& rDefaultText, + String* pGroupName +) : + ModalDialog( _pParent, SvtResId( DLG_SVT_QUERYFOLDERNAME ) ), + + aNameText ( this, SvtResId( FT_SVT_QUERYFOLDERNAME_DLG_NAME ) ), + aNameEdit ( this, SvtResId( ED_SVT_QUERYFOLDERNAME_DLG_NAME ) ), + aNameLine ( this, SvtResId( FL_SVT_QUERYFOLDERNAME_DLG_NAME ) ), + aOKBtn ( this, SvtResId( BT_SVT_QUERYFOLDERNAME_DLG_OK ) ), + aCancelBtn ( this, SvtResId( BT_SVT_QUERYFOLDERNAME_DLG_CANCEL ) ) +{ + FreeResource(); + SetText( rTitle ); + aNameEdit.SetText( rDefaultText ); + aNameEdit.SetSelection( Selection( 0, rDefaultText.Len() ) ); + aOKBtn.SetClickHdl( LINK( this, QueryFolderNameDialog, OKHdl ) ); + aNameEdit.SetModifyHdl( LINK( this, QueryFolderNameDialog, NameHdl ) ); + + if ( pGroupName ) + aNameLine.SetText( *pGroupName ); +}; + +// ----------------------------------------------------------------------- +IMPL_LINK( QueryFolderNameDialog, OKHdl, Button *, EMPTYARG ) +{ + // trim the strings + aNameEdit.SetText( aNameEdit.GetText().EraseLeadingChars().EraseTrailingChars() ); + EndDialog( RET_OK ); + return 1; +} + +// ----------------------------------------------------------------------- +IMPL_LINK( QueryFolderNameDialog, NameHdl, Edit *, EMPTYARG ) +{ + // trim the strings + String aName = aNameEdit.GetText(); + aName.EraseLeadingChars().EraseTrailingChars(); + if ( aName.Len() ) + { + if ( !aOKBtn.IsEnabled() ) + aOKBtn.Enable( TRUE ); + } + else + { + if ( aOKBtn.IsEnabled() ) + aOKBtn.Enable( FALSE ); + } + + return 0; +} + +} |