build fix
[LibreOffice.git] / fpicker / source / office / iodlg.cxx
blob9e4851e6a5fb46810a0706d2fb4e89f55fcfcbf9
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include <sal/macros.h>
23 #include "iodlg.hxx"
24 #include <svtools/PlaceEditDialog.hxx>
25 #include "PlacesListBox.hxx"
26 #include "fpsofficeResMgr.hxx"
27 #include <tools/stream.hxx>
28 #include <tools/urlobj.hxx>
29 #include <vcl/fixed.hxx>
30 #include <vcl/layout.hxx>
31 #include <vcl/lstbox.hxx>
32 #include <vcl/svapp.hxx>
33 #include <vcl/timer.hxx>
34 #include <unotools/ucbhelper.hxx>
35 #include "svtools/ehdl.hxx"
36 #include "svl/urihelper.hxx"
37 #include "unotools/pathoptions.hxx"
38 #include "unotools/viewoptions.hxx"
39 #include "svtools/fileview.hxx"
40 #include "svtools/sfxecode.hxx"
41 #include "svtools/svtabbx.hxx"
42 #include "svtools/treelistentry.hxx"
43 #include <toolkit/helper/vclunohelper.hxx>
45 #include "svtools/helpid.hrc"
46 #include <svtools/svtools.hrc>
47 #include "OfficeFilePicker.hrc"
48 #include "iodlg.hrc"
49 #include "asyncfilepicker.hxx"
50 #include "iodlgimp.hxx"
51 #include "svtools/inettbc.hxx"
52 #include "unotools/syslocale.hxx"
53 #include "QueryFolderName.hxx"
54 #include <rtl/ustring.hxx>
55 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
56 #include <com/sun/star/ucb/UniversalContentBroker.hpp>
57 #include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp>
58 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
59 #include <com/sun/star/ui/dialogs/ControlActions.hpp>
60 #include <com/sun/star/beans/PropertyValue.hpp>
61 #include <com/sun/star/sdbc/XResultSet.hpp>
62 #include <com/sun/star/sdbc/XRow.hpp>
63 #include <com/sun/star/util/URL.hpp>
64 #include <com/sun/star/uno/Exception.hpp>
65 #include <com/sun/star/uno/Reference.hxx>
66 #include <com/sun/star/util/XURLTransformer.hpp>
67 #include <com/sun/star/uno/RuntimeException.hpp>
68 #include <com/sun/star/beans/XPropertySet.hpp>
70 #include <comphelper/interaction.hxx>
71 #include <comphelper/lok.hxx>
72 #include <comphelper/processfactory.hxx>
73 #include <comphelper/string.hxx>
75 #include <osl/file.hxx>
76 #include <vcl/dibtools.hxx>
77 #include <vcl/waitobj.hxx>
78 #include <vcl/settings.hxx>
80 #include <com/sun/star/task/InteractionHandler.hpp>
81 #include "com/sun/star/ucb/InteractiveAugmentedIOException.hpp"
82 #include "fpinteraction.hxx"
83 #include <osl/process.h>
85 #include <officecfg/Office/Common.hxx>
87 #include <algorithm>
88 #include <functional>
89 #include <vector>
90 #include <memory>
92 using namespace ::com::sun::star::beans;
93 using namespace ::com::sun::star::frame;
94 using namespace ::com::sun::star::ui::dialogs;
95 using namespace ::com::sun::star::uno;
96 using namespace ::com::sun::star::lang;
97 using namespace ::com::sun::star::ucb;
98 using namespace ::com::sun::star::container;
99 using namespace ::com::sun::star::task;
100 using namespace ::com::sun::star::sdbc;
101 using namespace ::fpicker;
102 using namespace ::utl;
103 using namespace ::svt;
105 using namespace ExtendedFilePickerElementIds;
106 using namespace CommonFilePickerElementIds;
107 using namespace InternalFilePickerElementIds;
109 // Time to wait while traveling in the filterbox until
110 // the browsebox gets filtered ( in ms).
111 #define TRAVELFILTER_TIMEOUT 750
113 // functions -------------------------------------------------------------
115 namespace
119 OUString getMostCurrentFilter( std::unique_ptr<SvtExpFileDlg_Impl>& pImpl )
121 assert( pImpl && "invalid impl pointer" );
122 const SvtFileDialogFilter_Impl* pFilter = pImpl->_pUserFilter;
124 if ( !pFilter )
125 pFilter = pImpl->GetCurFilter();
127 if ( !pFilter )
128 return OUString();
130 return pFilter->GetType();
134 bool restoreCurrentFilter( std::unique_ptr<SvtExpFileDlg_Impl>& pImpl )
136 SAL_WARN_IF( !pImpl->GetCurFilter(), "fpicker.office", "restoreCurrentFilter: no current filter!" );
137 SAL_WARN_IF( pImpl->GetCurFilterDisplayName().isEmpty(), "fpicker.office", "restoreCurrentFilter: no current filter (no display name)!" );
139 pImpl->SelectFilterListEntry( pImpl->GetCurFilterDisplayName() );
141 #ifdef DBG_UTIL
142 OUString sSelectedDisplayName;
143 DBG_ASSERT( ( pImpl->GetSelectedFilterEntry( sSelectedDisplayName ) == pImpl->GetCurFilter() )
144 && ( sSelectedDisplayName == pImpl->GetCurFilterDisplayName() ),
145 "restoreCurrentFilter: inconsistence!" );
146 #endif
147 return pImpl->m_bNeedDelayedFilterExecute;
151 OUString GetFsysExtension_Impl( const OUString& rFile, const OUString& rLastFilterExt )
153 sal_Int32 nDotPos = rFile.lastIndexOf( '.' );
154 if ( nDotPos != -1 )
156 if ( !rLastFilterExt.isEmpty() )
158 if ( rFile.copy( nDotPos + 1 ).equalsIgnoreAsciiCase( rLastFilterExt ) )
159 return rLastFilterExt;
161 else
162 return rFile.copy( nDotPos );
164 return OUString();
168 void SetFsysExtension_Impl( OUString& rFile, const OUString& rExtension )
170 const sal_Unicode* p0 = rFile.getStr();
171 const sal_Unicode* p1 = p0 + rFile.getLength() - 1;
172 while ( p1 >= p0 && *p1 != '.' )
173 p1--;
174 if ( p1 >= p0 )
175 // remove old extension
176 rFile = rFile.copy( 0, p1 - p0 + 1 - ( rExtension.getLength() > 0 ? 0 : 1 ) );
177 else if ( !rExtension.isEmpty() )
178 // no old extension
179 rFile += ".";
180 rFile += rExtension;
183 void lcl_autoUpdateFileExtension( SvtFileDialog* _pDialog, const OUString& _rLastFilterExt )
185 // if auto extension is enabled ....
186 if ( _pDialog->isAutoExtensionEnabled() )
188 // automatically switch to the extension of the (maybe just newly selected) extension
189 OUString aNewFile = _pDialog->getCurrentFileText( );
190 OUString aExt = GetFsysExtension_Impl( aNewFile, _rLastFilterExt );
192 // but only if there already is an extension
193 if ( !aExt.isEmpty() )
195 // check if it is a real file extension, and not only the "post-dot" part in
196 // a directory name
197 bool bRealExtensions = true;
198 if ( -1 != aExt.indexOf( '/' ) )
199 bRealExtensions = false;
200 else if ( -1 != aExt.indexOf( '\\' ) )
201 bRealExtensions = false;
202 else
204 // no easy way to tell, because the part containing the dot already is the last
205 // segment of the complete file name
206 // So we have to check if the file name denotes a folder or a file.
207 // For performance reasons, we do this for file urls only
208 INetURLObject aURL( aNewFile );
209 if ( INetProtocol::NotValid == aURL.GetProtocol() )
211 OUString sURL;
212 if ( osl::FileBase::getFileURLFromSystemPath( aNewFile, sURL )
213 == osl::FileBase::E_None )
214 aURL = INetURLObject( sURL );
216 if ( INetProtocol::File == aURL.GetProtocol() )
220 bRealExtensions = !_pDialog->ContentIsFolder( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
222 catch( const css::uno::Exception& )
224 SAL_INFO( "fpicker", "Exception in lcl_autoUpdateFileExtension" );
229 if ( bRealExtensions )
231 SetFsysExtension_Impl( aNewFile, _pDialog->GetDefaultExt() );
232 _pDialog->setCurrentFileText( aNewFile );
238 #if defined( UNX )
239 bool lcl_getHomeDirectory( const OUString& _rForURL, OUString& /* [out] */ _rHomeDir )
241 _rHomeDir.clear();
243 // now ask the content broker for a provider for this scheme
247 // get the provider for the current scheme
248 Reference< XContentProvider > xProvider(
249 UniversalContentBroker::create(
250 comphelper::getProcessComponentContext() )->
251 queryContentProvider( _rForURL ) );
253 SAL_WARN_IF( !xProvider.is(), "fpicker.office", "lcl_getHomeDirectory: could not find a (valid) content provider for the current URL!" );
254 Reference< XPropertySet > xProviderProps( xProvider, UNO_QUERY );
255 if ( xProviderProps.is() )
257 Reference< XPropertySetInfo > xPropInfo = xProviderProps->getPropertySetInfo();
258 const OUString sHomeDirPropertyName( "HomeDirectory" );
259 if ( !xPropInfo.is() || xPropInfo->hasPropertyByName( sHomeDirPropertyName ) )
261 OUString sHomeDirectory;
262 xProviderProps->getPropertyValue( sHomeDirPropertyName ) >>= sHomeDirectory;
263 _rHomeDir = sHomeDirectory;
267 catch( const Exception& )
269 OSL_FAIL( "lcl_getHomeDirectory: caught an exception!" );
271 return !_rHomeDir.isEmpty();
273 #endif
275 OUString lcl_ensureFinalSlash( const OUString& _rDir )
277 INetURLObject aWorkPathObj( _rDir, INetProtocol::File );
278 aWorkPathObj.setFinalSlash();
279 return aWorkPathObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
283 /** retrieves the value of an environment variable
284 @return <TRUE/> if and only if the retrieved string value is not empty
286 bool getEnvironmentValue( const sal_Char* _pAsciiEnvName, OUString& _rValue )
288 _rValue.clear();
289 OUString sEnvName = OUString::createFromAscii( _pAsciiEnvName );
290 osl_getEnvironment( sEnvName.pData, &_rValue.pData );
291 return !_rValue.isEmpty();
295 // SvtFileDialog
297 SvtFileDialog::SvtFileDialog
299 vcl::Window* _pParent,
300 PickerFlags nBits
302 SvtFileDialog_Base( _pParent, "ExplorerFileDialog", "fps/ui/explorerfiledialog.ui" )
304 ,_pCbReadOnly( nullptr )
305 ,_pCbLinkBox( nullptr)
306 ,_pCbPreviewBox( nullptr )
307 ,_pCbSelection( nullptr )
308 ,_pPbPlay( nullptr )
309 ,_pPrevWin( nullptr )
310 ,_pPrevBmp( nullptr )
311 ,_pFileView( nullptr )
312 ,_pFileNotifier( nullptr )
313 ,pImpl( new SvtExpFileDlg_Impl )
314 ,_nPickerFlags( nBits )
315 ,_bIsInExecute( false )
316 ,m_bInExecuteAsync( false )
317 ,m_bHasFilename( false )
318 ,m_context(comphelper::getProcessComponentContext())
320 Init_Impl( nBits );
324 class CustomContainer : public vcl::Window
326 enum FocusState
328 Prev = 0,
329 Places,
330 Add,
331 Delete,
332 FileView,
333 Next,
334 FocusCount
337 SvtExpFileDlg_Impl* pImpl;
338 VclPtr<SvtFileView> _pFileView;
339 VclPtr<Splitter> _pSplitter;
341 int m_nCurrentFocus;
342 VclPtr<vcl::Window> m_pFocusWidgets[FocusState::FocusCount];
344 public:
345 explicit CustomContainer(vcl::Window *pParent)
346 : Window(pParent)
347 , pImpl(nullptr)
348 , _pFileView(nullptr)
349 , _pSplitter(nullptr)
350 , m_nCurrentFocus(FocusState::Prev)
353 virtual ~CustomContainer() override { disposeOnce(); }
354 virtual void dispose() override
356 _pFileView.clear();
357 _pSplitter.clear();
358 vcl::Window::dispose();
361 void init(SvtExpFileDlg_Impl* pImp,
362 SvtFileView* pFileView,
363 Splitter* pSplitter,
364 vcl::Window* pPrev,
365 vcl::Window* pNext)
367 pImpl = pImp;
368 _pFileView = pFileView;
369 _pSplitter = pSplitter;
371 m_pFocusWidgets[FocusState::Prev] = pPrev;
372 m_pFocusWidgets[FocusState::Places] = pImpl->_pPlaces->GetPlacesListBox();
373 m_pFocusWidgets[FocusState::Add] = pImpl->_pPlaces->GetAddButton();
374 m_pFocusWidgets[FocusState::Delete] = pImpl->_pPlaces->GetDeleteButton();
375 m_pFocusWidgets[FocusState::FileView] = pFileView;
376 m_pFocusWidgets[FocusState::Next] = pNext;
379 virtual void Resize() override
381 Window::Resize();
383 if (!pImpl || !pImpl->_pPlaces)
384 return;
386 Size aSize = GetSizePixel();
388 Point aBoxPos(_pFileView->GetPosPixel());
389 Size aNewSize(aSize.Width() - aBoxPos.X(), aSize.Height());
390 _pFileView->SetSizePixel( aNewSize );
392 // Resize the Splitter to fit the height
393 Size splitterNewSize = _pSplitter->GetSizePixel( );
394 splitterNewSize.Height() = aSize.Height();
395 _pSplitter->SetSizePixel( splitterNewSize );
396 sal_Int32 nMinX = pImpl->_pPlaces->GetPosPixel( ).X( );
397 sal_Int32 nMaxX = _pFileView->GetPosPixel( ).X( ) + _pFileView->GetSizePixel( ).Width() - nMinX;
398 _pSplitter->SetDragRectPixel( Rectangle( Point( nMinX, 0 ), Size( nMaxX, aSize.Width() ) ) );
400 // Resize the places list box to fit the height of the FileView
401 Size placesNewSize(pImpl->_pPlaces->GetSizePixel());
402 placesNewSize.Height() = aSize.Height();
403 pImpl->_pPlaces->SetSizePixel( placesNewSize );
406 void changeFocus( bool bReverse )
408 if( !_pFileView || !pImpl || !pImpl->_pPlaces )
409 return;
411 if( bReverse && m_nCurrentFocus > FocusState::Prev && m_nCurrentFocus <= FocusState::Next )
413 m_pFocusWidgets[m_nCurrentFocus]->SetFakeFocus(false);
414 m_pFocusWidgets[m_nCurrentFocus]->LoseFocus();
416 m_pFocusWidgets[--m_nCurrentFocus]->SetFakeFocus( true );
417 m_pFocusWidgets[m_nCurrentFocus]->GrabFocus();
419 else if( !bReverse && m_nCurrentFocus >= FocusState::Prev && m_nCurrentFocus < FocusState::Next )
421 m_pFocusWidgets[m_nCurrentFocus]->SetFakeFocus(false);
422 m_pFocusWidgets[m_nCurrentFocus]->LoseFocus();
424 m_pFocusWidgets[++m_nCurrentFocus]->SetFakeFocus( true );
425 m_pFocusWidgets[m_nCurrentFocus]->GrabFocus();
429 virtual void GetFocus() override
431 if( !_pFileView || !pImpl || !pImpl->_pPlaces )
432 return;
434 GetFocusFlags aFlags = GetGetFocusFlags();
436 if( aFlags & GetFocusFlags::Forward )
437 m_nCurrentFocus = FocusState::Places;
438 else if( aFlags & GetFocusFlags::Backward )
439 m_nCurrentFocus = FocusState::FileView;
441 if( m_nCurrentFocus >= FocusState::Prev && m_nCurrentFocus <= FocusState::Next )
443 m_pFocusWidgets[m_nCurrentFocus]->SetFakeFocus( true );
444 m_pFocusWidgets[m_nCurrentFocus]->GrabFocus();
448 virtual bool EventNotify( NotifyEvent& rNEvt ) override
450 if( rNEvt.GetType() == MouseNotifyEvent::GETFOCUS )
452 // we must also update counter when user change focus using mouse
453 for(int i = FocusState::Prev; i <= FocusState::Next; i++)
455 if( rNEvt.GetWindow() == m_pFocusWidgets[i] )
457 m_nCurrentFocus = i;
458 return true;
462 // GETFOCUS for one of FileView's subcontrols
463 m_nCurrentFocus = FocusState::FileView;
464 return true;
466 if( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT )
468 const KeyEvent* pKeyEvent = rNEvt.GetKeyEvent();
469 const vcl::KeyCode& rCode = pKeyEvent->GetKeyCode();
470 bool bShift = rCode.IsShift();
471 if( rCode.GetCode() == KEY_TAB )
473 changeFocus( bShift );
474 return true;
477 return Window::EventNotify(rNEvt);
481 SvtFileDialog::~SvtFileDialog()
483 disposeOnce();
486 void SvtFileDialog::dispose()
488 if ( !pImpl->_aIniKey.isEmpty() )
490 // save window state
491 SvtViewOptions aDlgOpt( E_DIALOG, pImpl->_aIniKey );
492 aDlgOpt.SetWindowState(OStringToOUString(GetWindowState(), osl_getThreadTextEncoding()));
493 OUString sUserData = _pFileView->GetConfigString();
494 aDlgOpt.SetUserItem( "UserData",
495 makeAny( sUserData ) );
498 _pFileView->SetSelectHdl( Link<SvTreeListBox*,void>() );
500 // Save bookmarked places
501 if(pImpl->_pPlaces->IsUpdated()) {
502 const std::vector<PlacePtr> aPlaces = pImpl->_pPlaces->GetPlaces();
503 Sequence< OUString > placesUrlsList(pImpl->_pPlaces->GetNbEditablePlaces());
504 Sequence< OUString > placesNamesList(pImpl->_pPlaces->GetNbEditablePlaces());
505 int i(0);
506 for(std::vector<PlacePtr>::const_iterator it = aPlaces.begin(); it != aPlaces.end(); ++it) {
507 if((*it)->IsEditable()) {
508 placesUrlsList[i] = (*it)->GetUrl();
509 placesNamesList[i] = (*it)->GetName();
510 ++i;
514 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create(m_context));
515 officecfg::Office::Common::Misc::FilePickerPlacesUrls::set(placesUrlsList, batch);
516 officecfg::Office::Common::Misc::FilePickerPlacesNames::set(placesNamesList, batch);
517 batch->commit();
520 pImpl.reset();
521 _pFileView.disposeAndClear();
522 _pSplitter.disposeAndClear();
523 _pContainer.disposeAndClear();
524 _pPrevBmp.disposeAndClear();
525 _pCbReadOnly.clear();
526 _pCbLinkBox.clear();
527 _pCbPreviewBox.clear();
528 _pCbSelection.clear();
529 _pPbPlay.clear();
530 _pPrevWin.clear();
531 m_aDisabledControls.clear();
532 ModalDialog::dispose();
535 void SvtFileDialog::Init_Impl
537 PickerFlags nStyle
540 get(_pCbReadOnly, "readonly");
541 get(_pCbLinkBox, "link");
542 get(_pCbPreviewBox, "cb_preview");
543 get(_pCbSelection, "selection");
544 get(_pPrevWin, "preview");
545 get(_pPbPlay, "play");
546 get(pImpl->_pCbOptions, "options");
547 get(pImpl->_pFtFileName, "file_name_label");
548 get(pImpl->_pEdFileName, "file_name");
549 pImpl->_pEdFileName->GetFocus();
550 get(pImpl->_pFtFileType, "file_type_label");
551 get(pImpl->_pLbFilter, "file_type");
552 get(pImpl->_pEdCurrentPath, "current_path");
553 get(pImpl->_pBtnFileOpen, "open");
554 get(pImpl->_pBtnCancel, "cancel");
555 get(pImpl->_pBtnHelp, "help");
556 get(pImpl->_pBtnConnectToServer, "connect_to_server");
557 get(pImpl->_pBtnNewFolder, "new_folder");
558 get(pImpl->_pCbPassword, "password");
559 get(pImpl->_pCbAutoExtension, "extension");
560 get(pImpl->_pFtFileVersion, "shared_label");
561 get(pImpl->_pLbFileVersion, "shared");
562 get(pImpl->_pFtTemplates, "shared_label");
563 get(pImpl->_pLbTemplates, "shared");
564 get(pImpl->_pFtImageTemplates, "shared_label");
565 get(pImpl->_pLbImageTemplates, "shared");
567 pImpl->_pLbImageTemplates->setMaxWidthChars(40);
568 pImpl->_pLbFilter->setMaxWidthChars(40);
570 m_aImages = ImageList( SvtResId( RID_FILEPICKER_IMAGES ) );
571 vcl::Window *pUpContainer = get<vcl::Window>("up");
572 pImpl->_pBtnUp = VclPtr<SvtUpButton_Impl>::Create(pUpContainer, this, 0);
573 pImpl->_pBtnUp->SetHelpId( HID_FILEOPEN_LEVELUP );
574 pImpl->_pBtnUp->set_vexpand(true);
575 pImpl->_pBtnUp->Show();
577 pImpl->_nStyle = nStyle;
578 pImpl->_eMode = ( nStyle & PickerFlags::SaveAs ) ? FILEDLG_MODE_SAVE : FILEDLG_MODE_OPEN;
579 pImpl->_eDlgType = FILEDLG_TYPE_FILEDLG;
581 if ( nStyle & PickerFlags::PathDialog )
582 pImpl->_eDlgType = FILEDLG_TYPE_PATHDLG;
584 // Set the directory for the "back to the default dir" button
585 INetURLObject aStdDirObj( SvtPathOptions().GetWorkPath() );
586 SetStandardDir( aStdDirObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
588 // Create control element, the order defines the tab control.
589 pImpl->_pEdFileName->SetSelectHdl( LINK( this, SvtFileDialog, EntrySelectHdl_Impl ) );
590 pImpl->_pEdFileName->SetOpenHdl( LINK( this, SvtFileDialog, OpenUrlHdl_Impl ) );
592 // in folder picker mode, only auto-complete directories (no files)
593 bool bIsFolderPicker = ( pImpl->_eDlgType == FILEDLG_TYPE_PATHDLG );
594 pImpl->_pEdFileName->SetOnlyDirectories( bIsFolderPicker );
596 // in save mode, don't use the autocompletion as selection in the edit part
597 bool bSaveMode = ( FILEDLG_MODE_SAVE == pImpl->_eMode );
598 pImpl->_pEdFileName->SetNoURLSelection( bSaveMode );
600 pImpl->_pBtnNewFolder->SetStyle( pImpl->_pBtnNewFolder->GetStyle() | WB_NOPOINTERFOCUS );
601 pImpl->_pBtnUp->SetAccessibleName( pImpl->_pBtnUp->GetQuickHelpText() );
603 if ( nStyle & PickerFlags::MultiSelection )
604 pImpl->_bMultiSelection = true;
606 _pContainer.reset(VclPtr<CustomContainer>::Create(get<vcl::Window>("container")));
607 Size aSize(LogicToPixel(Size(270, 85), MapUnit::MapAppFont));
608 _pContainer->set_height_request(aSize.Height());
609 _pContainer->set_width_request(aSize.Width());
610 _pContainer->set_hexpand(true);
611 _pContainer->set_vexpand(true);
612 _pContainer->SetStyle( _pContainer->GetStyle() | WB_TABSTOP );
614 _pFileView = VclPtr<SvtFileView>::Create( _pContainer, WB_BORDER,
615 FILEDLG_TYPE_PATHDLG == pImpl->_eDlgType,
616 pImpl->_bMultiSelection );
617 _pFileView->Show();
618 _pFileView->EnableAutoResize();
619 _pFileView->SetHelpId( HID_FILEDLG_STANDARD );
620 _pFileView->SetStyle( _pFileView->GetStyle() | WB_TABSTOP );
622 _pSplitter = VclPtr<Splitter>::Create( _pContainer, WB_HSCROLL );
623 _pSplitter->SetBackground( Wallpaper( Application::GetSettings().GetStyleSettings().GetFaceColor() ));
624 _pSplitter->SetSplitHdl( LINK( this, SvtFileDialog, Split_Hdl ) );
626 Image aNewFolderImg( GetButtonImage( IMG_FILEDLG_CREATEFOLDER ) );
627 pImpl->_pBtnNewFolder->SetModeImage( aNewFolderImg );
629 if ( nStyle & PickerFlags::ReadOnly )
631 _pCbReadOnly->SetHelpId( HID_FILEOPEN_READONLY );
632 _pCbReadOnly->SetText( SvtResId( STR_SVT_FILEPICKER_READONLY ) );
633 _pCbReadOnly->SetClickHdl( LINK( this, SvtFileDialog, ClickHdl_Impl ) );
634 _pCbReadOnly->Show();
637 if ( nStyle & PickerFlags::Password )
639 pImpl->_pCbPassword->SetText( SvtResId( STR_SVT_FILEPICKER_PASSWORD ) );
640 pImpl->_pCbPassword->SetClickHdl( LINK( this, SvtFileDialog, ClickHdl_Impl ) );
641 pImpl->_pCbPassword->Show();
644 // set the ini file for extracting the size
645 pImpl->_aIniKey = "FileDialog";
647 AddControls_Impl( );
649 // adjust the labels to the mode
650 sal_uInt16 nResId = STR_EXPLORERFILE_OPEN;
651 sal_uInt16 nButtonResId = 0;
653 if ( nStyle & PickerFlags::SaveAs )
655 nResId = STR_EXPLORERFILE_SAVE;
656 nButtonResId = STR_EXPLORERFILE_BUTTONSAVE;
659 if ( nStyle & PickerFlags::PathDialog )
661 pImpl->_pFtFileName->SetText( SvtResId( STR_PATHNAME ) );
662 nResId = STR_PATHSELECT;
663 nButtonResId = STR_BUTTONSELECT;
666 SetText( SvtResId( nResId ) );
668 if ( nButtonResId )
669 pImpl->_pBtnFileOpen->SetText( SvtResId( nButtonResId ) );
671 if ( FILEDLG_TYPE_FILEDLG != pImpl->_eDlgType )
673 pImpl->_pFtFileType->Hide();
674 pImpl->GetFilterListControl()->Hide();
677 // Setting preferences of the control elements.
678 pImpl->_pBtnNewFolder->SetClickHdl( LINK( this, SvtFileDialog, NewFolderHdl_Impl ) );
679 pImpl->_pBtnFileOpen->SetClickHdl( LINK( this, SvtFileDialog, OpenClickHdl_Impl ) );
680 pImpl->_pBtnCancel->SetClickHdl( LINK( this, SvtFileDialog, CancelHdl_Impl ) );
681 pImpl->SetFilterListSelectHdl( LINK( this, SvtFileDialog, FilterSelectHdl_Impl ) );
682 pImpl->_pEdFileName->SetGetFocusHdl( LINK( this, SvtFileDialog, FileNameGetFocusHdl_Impl ) );
683 pImpl->_pEdFileName->SetModifyHdl( LINK( this, SvtFileDialog, FileNameModifiedHdl_Impl ) );
684 pImpl->_pEdCurrentPath->SetOpenHdl ( LINK( this, SvtFileDialog, URLBoxModifiedHdl_Impl ) );
685 pImpl->_pBtnConnectToServer->SetClickHdl( LINK ( this, SvtFileDialog, ConnectToServerPressed_Hdl ) );
688 _pFileView->SetSelectHdl( LINK( this, SvtFileDialog, SelectHdl_Impl ) );
689 _pFileView->SetDoubleClickHdl( LINK( this, SvtFileDialog, DblClickHdl_Impl ) );
690 _pFileView->SetOpenDoneHdl( LINK( this, SvtFileDialog, OpenDoneHdl_Impl ) );
693 // set timer for the filterbox travel
694 pImpl->_aFilterTimer.SetTimeout( TRAVELFILTER_TIMEOUT );
695 pImpl->_aFilterTimer.SetTimeoutHdl( LINK( this, SvtFileDialog, FilterSelectTimerHdl_Impl ) );
697 if ( PickerFlags::SaveAs & nStyle )
699 // different help ids if in save-as mode
700 SetHelpId( HID_FILESAVE_DIALOG );
702 pImpl->_pEdFileName->SetHelpId( HID_FILESAVE_FILEURL );
703 pImpl->_pBtnFileOpen->SetHelpId( HID_FILESAVE_DOSAVE );
704 pImpl->_pBtnNewFolder->SetHelpId( HID_FILESAVE_CREATEDIRECTORY );
705 pImpl->_pBtnUp->SetHelpId( HID_FILESAVE_LEVELUP );
706 pImpl->GetFilterListControl()->SetHelpId( HID_FILESAVE_FILETYPE );
707 _pFileView->SetHelpId( HID_FILESAVE_FILEVIEW );
709 // formerly, there was only _pLbFileVersion, which was used for 3 different
710 // use cases. For reasons of maintainability, I introduced extra members (_pLbTemplates, _pLbImageTemplates)
711 // for the extra use cases, and separated _pLbFileVersion
712 // I did not find out in which cases the help ID is really needed HID_FILESAVE_TEMPLATE - all
713 // tests I made lead to a dialog where _no_ of the three list boxes was present.
714 if ( pImpl->_pLbFileVersion )
715 pImpl->_pLbFileVersion->SetHelpId( HID_FILESAVE_TEMPLATE );
716 if ( pImpl->_pLbTemplates )
717 pImpl->_pLbTemplates->SetHelpId( HID_FILESAVE_TEMPLATE );
718 if ( pImpl->_pLbImageTemplates )
719 pImpl->_pLbImageTemplates->SetHelpId( HID_FILESAVE_TEMPLATE );
721 if ( pImpl->_pCbPassword ) pImpl->_pCbPassword->SetHelpId( HID_FILESAVE_SAVEWITHPASSWORD );
722 if ( pImpl->_pCbAutoExtension ) pImpl->_pCbAutoExtension->SetHelpId( HID_FILESAVE_AUTOEXTENSION );
723 if ( pImpl->_pCbOptions ) pImpl->_pCbOptions->SetHelpId( HID_FILESAVE_CUSTOMIZEFILTER );
724 if ( _pCbSelection ) _pCbSelection->SetHelpId( HID_FILESAVE_SELECTION );
727 /// read our settings from the configuration
728 m_aConfiguration = OConfigurationTreeRoot::createWithComponentContext(
729 ::comphelper::getProcessComponentContext(),
730 "/org.openoffice.Office.UI/FilePicker"
733 _pContainer->init(pImpl.get(), _pFileView, _pSplitter, pImpl->_pBtnNewFolder, pImpl->_pEdFileName);
734 _pContainer->Show();
736 Resize();
739 IMPL_LINK_NOARG( SvtFileDialog, NewFolderHdl_Impl, Button*, void)
741 _pFileView->EndInplaceEditing();
743 SmartContent aContent( _pFileView->GetViewURL( ) );
744 OUString aTitle;
745 aContent.getTitle( aTitle );
746 ScopedVclPtrInstance< QueryFolderNameDialog > aDlg(this, aTitle, SVT_RESSTR(STR_SVT_NEW_FOLDER));
747 bool bHandled = false;
749 while ( !bHandled )
751 if ( aDlg->Execute() == RET_OK )
753 OUString aUrl = aContent.createFolder( aDlg->GetName( ) );
754 if ( !aUrl.isEmpty( ) )
756 _pFileView->CreatedFolder( aUrl, aDlg->GetName() );
757 bHandled = true;
760 else
761 bHandled = true;
765 bool SvtFileDialog::createNewUserFilter( const OUString& _rNewFilter )
767 // delete the old user filter and create a new one
768 DELETEZ( pImpl->_pUserFilter );
769 pImpl->_pUserFilter = new SvtFileDialogFilter_Impl( _rNewFilter, _rNewFilter );
771 // remember the extension
772 bool bIsAllFiles = _rNewFilter == FILEDIALOG_FILTER_ALL;
773 if ( bIsAllFiles )
774 EraseDefaultExt();
775 else
776 SetDefaultExt( _rNewFilter.copy( 2 ) );
777 // TODO: this is nonsense. In the whole file there are a lot of places where we assume that a user filter
778 // is always "*.<something>". But changing this would take some more time than I have now...
780 // now, the default extension is set to the one of the user filter (or empty)
781 if ( pImpl->GetCurFilter( ) )
782 SetDefaultExt( pImpl->GetCurFilter( )->GetExtension() );
783 else
784 EraseDefaultExt();
786 // outta here
787 return bIsAllFiles;
791 #define FLT_NONEMPTY 0x0001
792 #define FLT_CHANGED 0x0002
793 #define FLT_USERFILTER 0x0004
794 #define FLT_ALLFILESFILTER 0x0008
797 sal_uInt16 SvtFileDialog::adjustFilter( const OUString& _rFilter )
799 sal_uInt16 nReturn = 0;
801 const bool bNonEmpty = !_rFilter.isEmpty();
802 if ( bNonEmpty )
804 nReturn |= FLT_NONEMPTY;
806 bool bFilterChanged = true;
808 // search for a corresponding filter
809 SvtFileDialogFilter_Impl* pFilter = FindFilter_Impl( _rFilter, false, bFilterChanged );
811 // look for multi-ext filters if necessary
812 if ( !pFilter )
813 pFilter = FindFilter_Impl( _rFilter, true, bFilterChanged );
815 if ( bFilterChanged )
816 nReturn |= FLT_CHANGED;
818 if ( !pFilter )
820 nReturn |= FLT_USERFILTER;
821 // no filter found : use it as user defined filter
822 if ( createNewUserFilter( _rFilter ) )
823 { // it's the "all files" filter
824 nReturn |= FLT_ALLFILESFILTER;
830 return nReturn;
834 IMPL_LINK_NOARG(SvtFileDialog, CancelHdl_Impl, Button*, void)
836 if ( m_pCurrentAsyncAction.is() )
838 m_pCurrentAsyncAction->cancel();
839 onAsyncOperationFinished();
841 else
843 EndDialog();
848 IMPL_LINK( SvtFileDialog, OpenClickHdl_Impl, Button*, pVoid, void )
850 OpenHdl_Impl(pVoid);
852 IMPL_LINK( SvtFileDialog, OpenUrlHdl_Impl, SvtURLBox*, pVoid, void )
854 OpenHdl_Impl(pVoid);
856 void SvtFileDialog::OpenHdl_Impl(void* pVoid)
858 if ( pImpl->_bMultiSelection && _pFileView->GetSelectionCount() > 1 )
860 // special open in case of multiselection
861 OpenMultiSelection_Impl();
862 return;
865 OUString aFileName;
866 OUString aOldPath( _pFileView->GetViewURL() );
867 if ( pImpl->_bDoubleClick || _pFileView->HasChildPathFocus() )
868 // Selection done by doubleclicking in the view, get filename from the view
869 aFileName = _pFileView->GetCurrentURL();
871 if ( aFileName.isEmpty() )
873 // if an entry is selected in the view ....
874 if ( _pFileView->GetSelectionCount() )
875 { // -> use this one. This will allow us to step down this folder
876 aFileName = _pFileView->GetCurrentURL();
880 if ( aFileName.isEmpty() )
882 if ( pImpl->_eMode == FILEDLG_MODE_OPEN && pImpl->_pEdFileName->IsTravelSelect() )
883 // OpenHdl called from URLBox; travelling through the list of URLs should not cause an opening
884 return; // MBA->PB: seems to be called never ?!
886 // get the URL from the edit field ( if not empty )
887 if ( !pImpl->_pEdFileName->GetText().isEmpty() )
889 OUString aText = pImpl->_pEdFileName->GetText();
891 // did we reach the root?
892 if ( !INetURLObject( aOldPath ).getSegmentCount() )
894 if ( ( aText.getLength() == 2 && aText == ".." ) ||
895 ( aText.getLength() == 3 && ( aText == "..\\" || aText == "../" ) ) )
896 // don't go higher than the root
897 return;
900 #if defined( UNX )
901 if ( ( 1 == aText.getLength() ) && ( '~' == aText[0] ) )
903 // go to the home directory
904 if ( lcl_getHomeDirectory( _pFileView->GetViewURL(), aFileName ) )
905 // in case we got a home dir, reset the text of the edit
906 pImpl->_pEdFileName->SetText( OUString() );
908 if ( aFileName.isEmpty() )
909 #endif
911 // get url from autocomplete edit
912 aFileName = pImpl->_pEdFileName->GetURL();
915 else if ( pVoid == pImpl->_pBtnFileOpen.get() )
916 // OpenHdl was called for the "Open" Button; if edit field is empty, use selected element in the view
917 aFileName = _pFileView->GetCurrentURL();
920 // MBA->PB: ?!
921 if ( aFileName.isEmpty() && pVoid == pImpl->_pEdFileName && pImpl->_pUserFilter )
923 DELETEZ( pImpl->_pUserFilter );
924 return;
927 sal_Int32 nLen = aFileName.getLength();
928 if ( !nLen )
930 // if the dialog was opened to select a folder, the last selected folder should be selected
931 if( pImpl->_eDlgType == FILEDLG_TYPE_PATHDLG )
933 aFileName = pImpl->_pEdCurrentPath->GetText();
934 nLen = aFileName.getLength();
936 else
937 // no file selected !
938 return;
941 // mark input as selected
942 pImpl->_pEdFileName->SetSelection( Selection( 0, nLen ) );
944 // if a path with wildcards is given, divide the string into path and wildcards
945 OUString aFilter;
946 if ( !SvtFileDialog::IsolateFilterFromPath_Impl( aFileName, aFilter ) )
947 return;
949 // if a filter was retrieved, there were wildcards !
950 sal_uInt16 nNewFilterFlags = adjustFilter( aFilter );
951 if ( nNewFilterFlags & FLT_CHANGED )
953 // cut off all text before wildcard in edit and select wildcard
954 pImpl->_pEdFileName->SetText( aFilter );
955 pImpl->_pEdFileName->SetSelection( Selection( 0, aFilter.getLength() ) );
959 INetURLObject aFileObject( aFileName );
960 if ( ( aFileObject.GetProtocol() == INetProtocol::NotValid ) && !aFileName.isEmpty() )
962 OUString sCompleted = SvtURLBox::ParseSmart( aFileName, _pFileView->GetViewURL() );
963 if ( !sCompleted.isEmpty() )
964 aFileName = sCompleted;
968 // check if it is a folder
969 bool bIsFolder = false;
971 // first thing before doing anything with the content: Reset it. When the user presses "open" (or "save" or "export",
972 // for that matter), s/he wants the complete handling, including all possible error messages, even if s/he
973 // does the same thing for the same content twice, s/he wants both fails to be displayed.
974 // Without the reset, it could be that the content cached all relevant information, and will not display any
975 // error messages for the same content a second time...
976 m_aContent.bindTo( OUString( ) );
978 if ( !aFileName.isEmpty() )
980 // Make sure we have own Interaction Handler in place. We do not need
981 // to intercept interactions here, but to record the fact that there
982 // was an interaction.
983 SmartContent::InteractionHandlerType eInterActionHandlerType
984 = m_aContent.queryCurrentInteractionHandler();
985 if ( ( eInterActionHandlerType == SmartContent::IHT_NONE ) ||
986 ( eInterActionHandlerType == SmartContent::IHT_DEFAULT ) )
987 m_aContent.enableOwnInteractionHandler(
988 OFilePickerInteractionHandler::E_NOINTERCEPTION );
990 bIsFolder = m_aContent.isFolder( aFileName );
992 // access denied to the given resource - and interaction was already
993 // used => break following operations
994 OFilePickerInteractionHandler* pHandler
995 = m_aContent.getOwnInteractionHandler();
997 OSL_ENSURE( pHandler, "Got no Interaction Handler!!!" );
999 if ( pHandler->wasAccessDenied() )
1000 return;
1002 if ( m_aContent.isInvalid() &&
1003 ( pImpl->_eMode == FILEDLG_MODE_OPEN ) )
1005 if ( !pHandler->wasUsed() )
1006 ErrorHandler::HandleError( ERRCODE_IO_NOTEXISTS );
1008 return;
1011 // restore previous Interaction Handler
1012 if ( eInterActionHandlerType == SmartContent::IHT_NONE )
1013 m_aContent.disableInteractionHandler();
1014 else if ( eInterActionHandlerType == SmartContent::IHT_DEFAULT )
1015 m_aContent.enableDefaultInteractionHandler();
1018 if ( !bIsFolder // no existent folder
1019 && pImpl->_pCbAutoExtension // auto extension is enabled in general
1020 && pImpl->_pCbAutoExtension->IsChecked() // auto extension is really to be used
1021 && !GetDefaultExt().isEmpty() // there is a default extension
1022 && GetDefaultExt() != "*" // the default extension is not "all"
1023 && !( FILEDLG_MODE_SAVE == pImpl->_eMode // we're saving a file
1024 && _pFileView->GetSelectionCount() // there is a selected file in the file view -> it will later on
1025 ) // (in SvtFileDialog::GetPathList) be taken as file to save to
1027 && FILEDLG_MODE_OPEN != pImpl->_eMode // #i83408# don't append extension on open
1030 // check extension and append the default extension if necessary
1031 appendDefaultExtension(aFileName,
1032 GetDefaultExt(),
1033 pImpl->GetCurFilter()->GetType());
1036 bool bOpenFolder = ( FILEDLG_TYPE_PATHDLG == pImpl->_eDlgType ) &&
1037 !pImpl->_bDoubleClick && pVoid != pImpl->_pEdFileName;
1038 if ( bIsFolder )
1040 if ( bOpenFolder )
1042 _aPath = aFileName;
1044 else
1046 if ( aFileName != _pFileView->GetViewURL() )
1048 OpenURL_Impl( aFileName );
1050 else
1052 if ( nNewFilterFlags & FLT_CHANGED )
1053 ExecuteFilter();
1056 return;
1059 else if ( !( nNewFilterFlags & FLT_NONEMPTY ) )
1061 // if applicable save URL
1062 _aPath = aFileName;
1064 else
1066 // if applicable filter again
1067 if ( nNewFilterFlags & FLT_CHANGED )
1068 ExecuteFilter();
1069 return;
1072 INetURLObject aFileObj( aFileName );
1073 if ( aFileObj.HasError() )
1075 ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
1076 return;
1079 switch ( pImpl->_eMode )
1081 case FILEDLG_MODE_SAVE:
1083 if ( ::utl::UCBContentHelper::Exists( aFileObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) )
1085 OUString aMsg = SVT_RESSTR( STR_SVT_ALREADYEXISTOVERWRITE );
1086 aMsg = aMsg.replaceFirst(
1087 "$filename$",
1088 aFileObj.getName(INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::WithCharset)
1090 ScopedVclPtrInstance< MessageDialog > aBox(this, aMsg, VclMessageType::Question, VCL_BUTTONS_YES_NO);
1091 if ( aBox->Execute() != RET_YES )
1092 return;
1094 else
1096 OUString aCurPath;
1097 if (osl::FileBase::getSystemPathFromFileURL(aFileName, aCurPath) == osl::FileBase::E_None)
1099 // if content does not exist: at least its path must exist
1100 INetURLObject aPathObj = aFileObj;
1101 aPathObj.removeSegment();
1102 bool bFolder = m_aContent.isFolder( aPathObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
1103 if ( !bFolder )
1105 ErrorHandler::HandleError( ERRCODE_IO_NOTEXISTSPATH );
1106 return;
1111 break;
1113 case FILEDLG_MODE_OPEN:
1115 // do an existence check herein, again
1117 if ( INetProtocol::File == aFileObj.GetProtocol( ) )
1119 bool bExists = m_aContent.is( aFileObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
1121 if ( !bExists )
1123 OUString sError( SVT_RESSTR( RID_FILEOPEN_NOTEXISTENTFILE ) );
1125 OUString sInvalidFile( aFileObj.GetMainURL( INetURLObject::DecodeMechanism::ToIUri ) );
1126 if ( INetProtocol::File == aFileObj.GetProtocol() )
1127 { // if it's a file URL, transform the URL into system notation
1128 OUString sURL( sInvalidFile );
1129 OUString sSystem;
1130 osl_getSystemPathFromFileURL( sURL.pData, &sSystem.pData );
1131 sInvalidFile = sSystem;
1133 sError = sError.replaceFirst( "$name$", sInvalidFile );
1135 ScopedVclPtrInstance< MessageDialog > aError(this, sError);
1136 aError->Execute();
1137 return;
1141 break;
1143 default:
1144 OSL_FAIL("SvtFileDialog, OpenHdl_Impl: invalid mode!");
1147 EndDialog( RET_OK );
1151 void SvtFileDialog::EnableAutocompletion( bool _bEnable )
1153 pImpl->_pEdFileName->EnableAutocompletion( _bEnable );
1157 IMPL_LINK_NOARG( SvtFileDialog, FilterSelectHdl_Impl, ListBox&, void )
1159 OUString sSelectedFilterDisplayName;
1160 SvtFileDialogFilter_Impl* pSelectedFilter = pImpl->GetSelectedFilterEntry( sSelectedFilterDisplayName );
1161 if ( !pSelectedFilter )
1162 { // there is no current selection. This happens if for instance the user selects a group separator using
1163 // the keyboard, and then presses enter: When the selection happens, we immediately deselect the entry,
1164 // so in this situation there is no current selection.
1165 if ( restoreCurrentFilter( pImpl ) )
1166 ExecuteFilter();
1168 else
1170 if ( pSelectedFilter->isGroupSeparator() )
1171 { // group separators can't be selected
1172 // return to the previously selected entry
1173 if ( pImpl->IsFilterListTravelSelect() )
1175 pImpl->SetNoFilterListSelection( );
1177 // stop the timer for executing the filter
1178 if ( pImpl->_aFilterTimer.IsActive() )
1179 pImpl->m_bNeedDelayedFilterExecute = true;
1180 pImpl->_aFilterTimer.Stop();
1182 else
1184 if ( restoreCurrentFilter( pImpl ) )
1185 ExecuteFilter();
1188 else if ( ( pSelectedFilter != pImpl->GetCurFilter() )
1189 || pImpl->_pUserFilter
1192 // Store the old filter for the auto extension handling
1193 OUString sLastFilterExt = pImpl->GetCurFilter()->GetExtension();
1194 DELETEZ( pImpl->_pUserFilter );
1196 // if applicable remove filter of the user
1197 pImpl->SetCurFilter( pSelectedFilter, sSelectedFilterDisplayName );
1199 // if applicable show extension
1200 SetDefaultExt( pSelectedFilter->GetExtension() );
1201 sal_Int32 nSepPos = GetDefaultExt().indexOf( FILEDIALOG_DEF_EXTSEP );
1203 if ( nSepPos != -1 )
1204 EraseDefaultExt( nSepPos );
1206 // update the extension of the current file if necessary
1207 lcl_autoUpdateFileExtension( this, sLastFilterExt );
1209 // if the user is traveling fast through the filterbox
1210 // do not filter instantly
1211 if ( pImpl->IsFilterListTravelSelect() )
1213 // FilterSelectHdl_Impl should be started again in
1214 // TRAVELFILTER_TIMEOUT ms
1215 pImpl->_aFilterTimer.Start();
1217 else
1219 // stop previously started timer
1220 pImpl->_aFilterTimer.Stop();
1222 // filter the view again
1223 ExecuteFilter();
1229 IMPL_LINK_NOARG(SvtFileDialog, FilterSelectTimerHdl_Impl, Timer*, void)
1231 // filter the view again
1232 ExecuteFilter();
1235 IMPL_LINK_NOARG( SvtFileDialog, FileNameGetFocusHdl_Impl, Control&, void )
1237 _pFileView->SetNoSelection();
1238 _pFileView->Update();
1242 IMPL_LINK_NOARG( SvtFileDialog, FileNameModifiedHdl_Impl, Edit&, void )
1244 FileNameGetFocusHdl_Impl( *pImpl->_pEdFileName );
1248 IMPL_LINK_NOARG( SvtFileDialog, URLBoxModifiedHdl_Impl, SvtURLBox*, void )
1250 OUString aPath = pImpl->_pEdCurrentPath->GetURL();
1251 OpenURL_Impl(aPath);
1255 IMPL_LINK_NOARG( SvtFileDialog, ConnectToServerPressed_Hdl, Button*, void )
1257 _pFileView->EndInplaceEditing();
1259 ScopedVclPtrInstance< PlaceEditDialog > aDlg(this);
1260 short aRetCode = aDlg->Execute();
1262 switch (aRetCode) {
1263 case RET_OK :
1265 PlacePtr newPlace = aDlg->GetPlace();
1266 pImpl->_pPlaces->AppendPlace(newPlace);
1268 break;
1270 case RET_CANCEL :
1271 default :
1272 // Do Nothing
1273 break;
1278 IMPL_LINK_NOARG ( SvtFileDialog, AddPlacePressed_Hdl, Button*, void )
1280 // Maybe open the PlacesDialog would have been a better idea
1281 // there is an ux choice to make we did not make...
1282 INetURLObject aURLObj( _pFileView->GetViewURL() );
1283 PlacePtr newPlace(
1284 new Place( aURLObj.GetLastName(INetURLObject::DecodeMechanism::WithCharset),
1285 OUString(_pFileView->GetViewURL()), true));
1286 pImpl->_pPlaces->AppendPlace(newPlace);
1290 IMPL_LINK_NOARG ( SvtFileDialog, RemovePlacePressed_Hdl, Button*, void )
1292 pImpl->_pPlaces->RemoveSelectedPlace();
1296 SvtFileDialogFilter_Impl* SvtFileDialog::FindFilter_Impl
1298 const OUString& _rFilter,
1299 bool _bMultiExt,/* TRUE - regard filter with several extensions
1300 FALSE - do not ...
1302 bool& _rFilterChanged
1305 /* [Description]
1307 This method looks for the specified extension in the included filters.
1311 SvtFileDialogFilter_Impl* pFoundFilter = nullptr;
1312 SvtFileDialogFilterList_Impl& rList = pImpl->m_aFilter;
1313 sal_uInt16 nFilter = rList.size();
1315 while ( nFilter-- )
1317 SvtFileDialogFilter_Impl* pFilter = rList[ nFilter ].get();
1318 const OUString& rType = pFilter->GetType();
1319 OUString aSingleType = rType;
1321 if ( _bMultiExt )
1323 sal_Int32 nIdx = 0;
1324 while ( !pFoundFilter && nIdx != -1 )
1326 aSingleType = rType.getToken( 0, FILEDIALOG_DEF_EXTSEP, nIdx );
1327 #ifdef UNX
1328 if ( aSingleType == _rFilter )
1329 #else
1330 if ( aSingleType.equalsIgnoreAsciiCase( _rFilter ) )
1331 #endif
1332 pFoundFilter = pFilter;
1335 #ifdef UNX
1336 else if ( rType == _rFilter )
1337 #else
1338 else if ( rType.equalsIgnoreAsciiCase( _rFilter ) )
1339 #endif
1340 pFoundFilter = pFilter;
1342 if ( pFoundFilter )
1344 // activate filter
1345 _rFilterChanged = pImpl->_pUserFilter || ( pImpl->GetCurFilter() != pFilter );
1347 createNewUserFilter( _rFilter );
1349 break;
1352 return pFoundFilter;
1356 void SvtFileDialog::ExecuteFilter()
1358 pImpl->m_bNeedDelayedFilterExecute = false;
1359 executeAsync( AsyncPickerAction::eExecuteFilter, OUString(), getMostCurrentFilter( pImpl ) );
1363 void SvtFileDialog::OpenMultiSelection_Impl()
1365 /* [Description]
1367 OpenHandler for MultiSelection
1371 sal_uLong nCount = _pFileView->GetSelectionCount();
1372 SvTreeListEntry* pEntry = nCount ? _pFileView->FirstSelected() : nullptr;
1374 if ( nCount && pEntry )
1375 _aPath = SvtFileView::GetURL( pEntry );
1377 EndDialog( RET_OK );
1381 void SvtFileDialog::UpdateControls( const OUString& rURL )
1383 pImpl->_pEdFileName->SetBaseURL( rURL );
1385 INetURLObject aObj( rURL );
1389 OUString sText;
1390 SAL_WARN_IF( INetProtocol::NotValid == aObj.GetProtocol(), "fpicker.office", "SvtFileDialog::UpdateControls: Invalid URL!" );
1392 if ( aObj.getSegmentCount() )
1394 osl::FileBase::getSystemPathFromFileURL(rURL, sText);
1395 if ( !sText.isEmpty() )
1397 // no Fsys path for server file system ( only UCB has mountpoints! )
1398 if ( INetProtocol::File != aObj.GetProtocol() )
1399 sText = rURL.copy( INetURLObject::GetScheme( aObj.GetProtocol() ).getLength() );
1402 if ( sText.isEmpty() && aObj.getSegmentCount() )
1403 sText = rURL;
1406 // path mode ?
1407 if ( FILEDLG_TYPE_PATHDLG == pImpl->_eDlgType )
1408 // -> set new path in the edit field
1409 pImpl->_pEdFileName->SetText( sText );
1411 // in the "current path" field, truncate the trailing slash
1412 if ( aObj.hasFinalSlash() )
1414 aObj.removeFinalSlash();
1415 OUString sURL( aObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
1416 if (osl::FileBase::getSystemPathFromFileURL(sURL, sText) != osl::FileBase::E_None)
1417 sText = sURL;
1420 if ( sText.isEmpty() && !rURL.isEmpty() )
1421 // happens, for instance, for URLs which the INetURLObject does not know to belong to a hierarchical scheme
1422 sText = rURL;
1423 pImpl->_pEdCurrentPath->SetText( sText );
1427 _aPath = rURL;
1428 if ( _pFileNotifier )
1429 _pFileNotifier->notify( DIRECTORY_CHANGED, 0 );
1433 IMPL_LINK( SvtFileDialog, SelectHdl_Impl, SvTreeListBox*, pBox, void )
1435 SvTreeListEntry* pEntry = pBox->FirstSelected();
1436 assert( pEntry && "SelectHandler without selected entry" );
1437 SvtContentEntry* pUserData = static_cast<SvtContentEntry*>(pEntry->GetUserData());
1439 if ( pUserData )
1441 INetURLObject aObj( pUserData->maURL );
1442 if ( FILEDLG_TYPE_PATHDLG == pImpl->_eDlgType )
1444 if ( aObj.GetProtocol() == INetProtocol::File )
1446 if ( !pUserData->mbIsFolder )
1447 aObj.removeSegment();
1448 OUString aName = aObj.getFSysPath( (INetURLObject::FSysStyle)(INetURLObject::FSYS_DETECT & ~INetURLObject::FSYS_VOS) );
1449 pImpl->_pEdFileName->SetText( aName );
1450 pImpl->_pEdFileName->SetSelection( Selection( 0, aName.getLength() ) );
1451 _aPath = pUserData->maURL;
1453 else if ( !pUserData->mbIsFolder )
1455 pImpl->_pEdFileName->SetText( pUserData->maURL );
1456 pImpl->_pEdFileName->SetSelection( Selection( 0, pUserData->maURL.getLength() ) );
1457 _aPath = pUserData->maURL;
1459 else
1460 pImpl->_pEdFileName->SetText( OUString() );
1462 else
1464 if ( !pUserData->mbIsFolder )
1466 OUString aName = SvTabListBox::GetEntryText( pEntry, 0 );
1467 pImpl->_pEdFileName->SetText( aName );
1468 pImpl->_pEdFileName->SetSelection( Selection( 0, aName.getLength() ) );
1469 _aPath = pUserData->maURL;
1474 if ( pImpl->_bMultiSelection && _pFileView->GetSelectionCount() > 1 )
1476 // clear the file edit for multiselection
1477 pImpl->_pEdFileName->SetText( OUString() );
1480 FileSelect();
1484 IMPL_LINK_NOARG(SvtFileDialog, DblClickHdl_Impl, SvTreeListBox*, bool)
1486 pImpl->_bDoubleClick = true;
1487 OpenHdl_Impl( nullptr );
1488 pImpl->_bDoubleClick = false;
1490 return false;
1494 IMPL_LINK_NOARG(SvtFileDialog, EntrySelectHdl_Impl, ComboBox&, void)
1496 FileSelect();
1500 IMPL_LINK( SvtFileDialog, OpenDoneHdl_Impl, SvtFileView*, pView, void )
1502 OUString sCurrentFolder( pView->GetViewURL() );
1503 // check if we can create new folders
1504 EnableControl( pImpl->_pBtnNewFolder, ContentCanMakeFolder( sCurrentFolder ) );
1506 // check if we can travel one level up
1507 bool bCanTravelUp = ContentHasParentFolder( pView->GetViewURL() );
1508 if ( bCanTravelUp )
1510 // additional check: the parent folder should not be prohibited
1511 INetURLObject aCurrentFolder( sCurrentFolder );
1512 SAL_WARN_IF( INetProtocol::NotValid == aCurrentFolder.GetProtocol(),
1513 "fpicker.office", "SvtFileDialog::OpenDoneHdl_Impl: invalid current URL!" );
1515 aCurrentFolder.removeSegment();
1517 EnableControl( pImpl->_pBtnUp, bCanTravelUp );
1521 IMPL_LINK_NOARG(SvtFileDialog, AutoExtensionHdl_Impl, Button*, void)
1523 if ( _pFileNotifier )
1524 _pFileNotifier->notify( CTRL_STATE_CHANGED,
1525 CHECKBOX_AUTOEXTENSION );
1527 // update the extension of the current file if necessary
1528 lcl_autoUpdateFileExtension( this, pImpl->GetCurFilter()->GetExtension() );
1532 IMPL_LINK( SvtFileDialog, ClickHdl_Impl, Button*, pCheckBox, void )
1534 if ( ! _pFileNotifier )
1535 return;
1537 sal_Int16 nId = -1;
1539 if ( pCheckBox == pImpl->_pCbOptions )
1540 nId = CHECKBOX_FILTEROPTIONS;
1541 else if ( pCheckBox == _pCbSelection )
1542 nId = CHECKBOX_SELECTION;
1543 else if ( pCheckBox == _pCbReadOnly )
1544 nId = CHECKBOX_READONLY;
1545 else if ( pCheckBox == pImpl->_pCbPassword )
1546 nId = CHECKBOX_PASSWORD;
1547 else if ( pCheckBox == _pCbLinkBox )
1548 nId = CHECKBOX_LINK;
1549 else if ( pCheckBox == _pCbPreviewBox )
1550 nId = CHECKBOX_PREVIEW;
1552 if ( nId != -1 )
1553 _pFileNotifier->notify( CTRL_STATE_CHANGED, nId );
1557 IMPL_LINK_NOARG(SvtFileDialog, PlayButtonHdl_Impl, Button*, void)
1559 if ( _pFileNotifier )
1560 _pFileNotifier->notify( CTRL_STATE_CHANGED,
1561 PUSHBUTTON_PLAY );
1565 bool SvtFileDialog::EventNotify( NotifyEvent& rNEvt )
1567 /* [Description]
1569 This method gets called to catch <BACKSPACE>.
1573 MouseNotifyEvent nType = rNEvt.GetType();
1574 bool bRet = false;
1576 if ( MouseNotifyEvent::KEYINPUT == nType && rNEvt.GetKeyEvent() )
1578 const vcl::KeyCode& rKeyCode = rNEvt.GetKeyEvent()->GetKeyCode();
1579 sal_uInt16 nCode = rKeyCode.GetCode();
1581 if ( !rKeyCode.GetModifier() &&
1582 KEY_BACKSPACE == nCode && !pImpl->_pEdFileName->HasChildPathFocus() )
1584 bRet = false;
1586 if ( !bRet && pImpl->_pBtnUp->IsEnabled() )
1588 PrevLevel_Impl();
1589 bRet = true;
1593 return bRet || ModalDialog::EventNotify(rNEvt);
1596 namespace
1599 bool implIsInvalid( const OUString & rURL )
1601 SmartContent aContent( rURL );
1602 aContent.enableOwnInteractionHandler( ::svt::OFilePickerInteractionHandler::E_DOESNOTEXIST );
1603 aContent.isFolder(); // do this _before_ asking isInvalid! Otherwise result might be wrong.
1604 return aContent.isInvalid();
1610 OUString SvtFileDialog::implGetInitialURL( const OUString& _rPath, const OUString& _rFallback )
1612 // an URL parser for the fallback
1613 INetURLObject aURLParser;
1615 // set the path
1616 bool bWasAbsolute = false;
1617 aURLParser = aURLParser.smartRel2Abs( _rPath, bWasAbsolute );
1619 // is it a valid folder?
1620 m_aContent.bindTo( aURLParser.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
1621 bool bIsFolder = m_aContent.isFolder( ); // do this _before_ asking isInvalid!
1622 bool bIsInvalid = m_aContent.isInvalid();
1624 if ( bIsInvalid && m_bHasFilename && !aURLParser.hasFinalSlash() )
1625 { // check if the parent folder exists
1626 INetURLObject aParent( aURLParser );
1627 aParent.removeSegment( );
1628 aParent.setFinalSlash( );
1629 bIsInvalid = implIsInvalid( aParent.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
1632 if ( bIsInvalid )
1634 INetURLObject aFallback( _rFallback );
1635 bIsInvalid = implIsInvalid( aFallback.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
1637 if ( !bIsInvalid )
1638 aURLParser = aFallback;
1641 if ( bIsInvalid )
1643 INetURLObject aParent( aURLParser );
1644 while ( bIsInvalid && aParent.removeSegment() )
1646 aParent.setFinalSlash( );
1647 bIsInvalid = implIsInvalid( aParent.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
1650 if ( !bIsInvalid )
1651 aURLParser = aParent;
1654 if ( !bIsInvalid && bIsFolder )
1656 aURLParser.setFinalSlash();
1658 return aURLParser.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1662 short SvtFileDialog::Execute()
1664 if ( !PrepareExecute() )
1665 return 0;
1667 // start the dialog
1668 _bIsInExecute = true;
1669 short nResult = ModalDialog::Execute();
1670 _bIsInExecute = false;
1672 SAL_WARN_IF( m_pCurrentAsyncAction.is(), "fpicker.office", "SvtFilePicker::Execute: still running an async action!" );
1673 // the dialog should not be cancellable while an async action is running - first, the action
1674 // needs to be cancelled
1676 // remember last directory
1677 if ( RET_OK == nResult )
1679 INetURLObject aURL( _aPath );
1680 if ( aURL.GetProtocol() == INetProtocol::File )
1682 // remember the selected directory only for file URLs not for virtual folders
1683 sal_Int32 nLevel = aURL.getSegmentCount();
1684 bool bDir = m_aContent.isFolder( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
1685 if ( nLevel > 1 && ( FILEDLG_TYPE_FILEDLG == pImpl->_eDlgType || !bDir ) )
1686 aURL.removeSegment();
1690 return nResult;
1694 void SvtFileDialog::StartExecuteModal( const Link<Dialog&,void>& rEndDialogHdl )
1696 if (!PrepareExecute())
1697 return;
1699 // start of the dialog
1700 ModalDialog::StartExecuteModal( rEndDialogHdl );
1704 void SvtFileDialog::onAsyncOperationStarted()
1706 EnableUI( false );
1707 // the cancel button must be always enabled
1708 pImpl->_pBtnCancel->Enable();
1709 pImpl->_pBtnCancel->GrabFocus();
1713 void SvtFileDialog::onAsyncOperationFinished()
1715 EnableUI( true );
1716 m_pCurrentAsyncAction = nullptr;
1717 if ( !m_bInExecuteAsync )
1718 pImpl->_pEdFileName->GrabFocus();
1719 // (if m_bInExecuteAsync is true, then the operation was finished within the minimum wait time,
1720 // and to the user, the operation appears to be synchronous)
1724 void SvtFileDialog::RemovablePlaceSelected(bool enable)
1726 pImpl->_pPlaces->SetDelEnabled( enable );
1730 void SvtFileDialog::displayIOException( const OUString& _rURL, IOErrorCode _eCode )
1734 // create make a human-readable string from the URL
1735 OUString sDisplayPath;
1736 if (osl::FileBase::getSystemPathFromFileURL(_rURL, sDisplayPath)
1737 == osl::FileBase::E_None)
1739 sDisplayPath = _rURL;
1742 // build an own exception which tells "access denied"
1743 InteractiveAugmentedIOException aException;
1744 aException.Arguments.realloc( 2 );
1745 aException.Arguments[ 0 ] <<= sDisplayPath;
1746 aException.Arguments[ 1 ] <<= PropertyValue(
1747 OUString( "Uri" ),
1748 -1, aException.Arguments[ 0 ], PropertyState_DIRECT_VALUE
1750 // (formerly, it was sufficient to put the URL first parameter. Nowadays,
1751 // the services expects the URL in a PropertyValue named "Uri" ...)
1752 aException.Code = _eCode;
1753 aException.Classification = InteractionClassification_ERROR;
1755 // let and interaction handler handle this exception
1756 ::comphelper::OInteractionRequest* pRequest = nullptr;
1757 Reference< css::task::XInteractionRequest > xRequest = pRequest =
1758 new ::comphelper::OInteractionRequest( makeAny( aException ) );
1759 pRequest->addContinuation( new ::comphelper::OInteractionAbort( ) );
1761 Reference< XInteractionHandler2 > xHandler(
1762 InteractionHandler::createWithParent( ::comphelper::getProcessComponentContext(), nullptr ) );
1763 xHandler->handle( xRequest );
1765 catch( const Exception& )
1767 OSL_FAIL( "iodlg::displayIOException: caught an exception!" );
1772 void SvtFileDialog::EnableUI( bool _bEnable )
1774 Enable( _bEnable );
1776 if ( _bEnable )
1778 for ( auto aLoop = m_aDisabledControls.begin();
1779 aLoop != m_aDisabledControls.end();
1780 ++aLoop
1783 (*aLoop)->Enable( false );
1789 void SvtFileDialog::EnableControl( Control* _pControl, bool _bEnable )
1791 if ( !_pControl )
1793 SAL_WARN( "fpicker.office", "SvtFileDialog::EnableControl: invalid control!" );
1794 return;
1797 _pControl->Enable( _bEnable );
1799 if ( _bEnable )
1801 auto aPos = m_aDisabledControls.find( _pControl );
1802 if ( m_aDisabledControls.end() != aPos )
1803 m_aDisabledControls.erase( aPos );
1805 else
1806 m_aDisabledControls.insert( _pControl );
1810 short SvtFileDialog::PrepareExecute()
1812 if (comphelper::LibreOfficeKit::isActive())
1813 return 0;
1815 OUString aEnvValue;
1816 if ( getEnvironmentValue( "WorkDirMustContainRemovableMedia", aEnvValue ) && aEnvValue == "1" )
1820 INetURLObject aStdDir( GetStandardDir() );
1821 ::ucbhelper::Content aCnt( OUString( aStdDir.GetMainURL(
1822 INetURLObject::DecodeMechanism::NONE ) ),
1823 Reference< XCommandEnvironment >(),
1824 comphelper::getProcessComponentContext() );
1825 Sequence< OUString > aProps(2);
1826 aProps[0] = "IsVolume";
1827 aProps[1] = "IsRemoveable";
1829 Reference< XResultSet > xResultSet
1830 = aCnt.createCursor( aProps, ::ucbhelper::INCLUDE_FOLDERS_ONLY );
1831 if ( xResultSet.is() )
1833 Reference< XRow > xRow( xResultSet, UNO_QUERY );
1835 bool bEmpty = true;
1836 if ( !xResultSet->next() )
1838 // folder is empty
1839 bEmpty = true;
1841 else
1843 bEmpty = false;
1846 if ( bEmpty )
1848 ScopedVclPtrInstance< MessageDialog > aBox(this, SVT_RESSTR(STR_SVT_NOREMOVABLEDEVICE));
1849 aBox->Execute();
1850 return 0;
1854 catch ( ContentCreationException const & )
1857 catch ( CommandAbortedException const & )
1862 if ( ( pImpl->_nStyle & PickerFlags::SaveAs ) && m_bHasFilename )
1863 // when doing a save-as, we do not want the handler to handle "this file does not exist" messages
1864 // - finally we're going to save that file, aren't we?
1865 m_aContent.enableOwnInteractionHandler(::svt::OFilePickerInteractionHandler::E_DOESNOTEXIST);
1866 else
1867 m_aContent.enableDefaultInteractionHandler();
1869 // possibly just a filename without a path
1870 OUString aFileNameOnly;
1871 if( !_aPath.isEmpty() && (pImpl->_eMode == FILEDLG_MODE_SAVE)
1872 && (_aPath.indexOf(':') == -1)
1873 && (_aPath.indexOf('\\') == -1)
1874 && (_aPath.indexOf('/') == -1))
1876 aFileNameOnly = _aPath;
1877 _aPath.clear();
1880 // no starting path specified?
1881 if ( _aPath.isEmpty() )
1883 // then use the standard directory
1884 _aPath = lcl_ensureFinalSlash( pImpl->GetStandardDir() );
1886 // attach given filename to path
1887 if ( !aFileNameOnly.isEmpty() )
1888 _aPath += aFileNameOnly;
1892 _aPath = implGetInitialURL( _aPath, GetStandardDir() );
1894 if ( pImpl->_nStyle & PickerFlags::SaveAs && !m_bHasFilename )
1895 // when doing a save-as, we do not want the handler to handle "this file does not exist" messages
1896 // - finally we're going to save that file, aren't we?
1897 m_aContent.enableOwnInteractionHandler(::svt::OFilePickerInteractionHandler::E_DOESNOTEXIST);
1899 // if applicable show filter
1900 pImpl->InitFilterList();
1902 // set up initial filter
1903 sal_uInt16 nFilterCount = GetFilterCount();
1904 OUString aAll = SvtResId( STR_FILTERNAME_ALL ).toString();
1905 bool bHasAll = pImpl->HasFilterListEntry( aAll );
1906 if ( pImpl->GetCurFilter() || nFilterCount == 1 || ( nFilterCount == 2 && bHasAll ) )
1908 // if applicable set the only filter or the only filter that
1909 // does not refer to all files, as the current one
1910 if ( !pImpl->GetCurFilter() )
1912 sal_uInt16 nPos = 0;
1913 if ( 2 == nFilterCount && bHasAll )
1915 nPos = nFilterCount;
1916 while ( nPos-- )
1918 if ( aAll != GetFilterName( nPos ) )
1919 break;
1922 SvtFileDialogFilter_Impl* pNewCurFilter = pImpl->m_aFilter[ nPos ].get();
1923 assert( pNewCurFilter && "SvtFileDialog::Execute: invalid filter pos!" );
1924 pImpl->SetCurFilter( pNewCurFilter, pNewCurFilter->GetName() );
1927 // adjust view
1928 pImpl->SelectFilterListEntry( pImpl->GetCurFilter()->GetName() );
1929 SetDefaultExt( pImpl->GetCurFilter()->GetExtension() );
1930 sal_Int32 nSepPos = GetDefaultExt().indexOf( FILEDIALOG_DEF_EXTSEP );
1931 if ( nSepPos != -1 )
1932 EraseDefaultExt( nSepPos );
1934 else
1936 // if applicable set respectively create filter for all files
1937 if ( !bHasAll )
1939 SvtFileDialogFilter_Impl* pAllFilter = implAddFilter( aAll, FILEDIALOG_FILTER_ALL );
1940 pImpl->InsertFilterListEntry( pAllFilter );
1941 pImpl->SetCurFilter( pAllFilter, aAll );
1943 pImpl->SelectFilterListEntry( aAll );
1946 pImpl->_pDefaultFilter = pImpl->GetCurFilter();
1948 // if applicable isolate filter
1949 OUString aFilter;
1951 if ( !IsolateFilterFromPath_Impl( _aPath, aFilter ) )
1952 return 0;
1954 sal_uInt16 nNewFilterFlags = adjustFilter( aFilter );
1955 if ( nNewFilterFlags & ( FLT_NONEMPTY | FLT_USERFILTER ) )
1957 pImpl->_pEdFileName->SetText( aFilter );
1960 // create and show instance for set path
1961 INetURLObject aFolderURL( _aPath );
1962 OUString aFileName( aFolderURL.getName( INetURLObject::LAST_SEGMENT, false ) );
1963 sal_Int32 nFileNameLen = aFileName.getLength();
1964 bool bFileToSelect = nFileNameLen != 0;
1965 if ( bFileToSelect && aFileName[ nFileNameLen - 1 ] != '/' )
1967 OUString aDecodedName = aFolderURL.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::WithCharset );
1968 pImpl->_pEdFileName->SetText( aDecodedName );
1969 aFolderURL.removeSegment();
1972 INetURLObject aObj = aFolderURL;
1973 if ( aObj.GetProtocol() == INetProtocol::File )
1975 // set folder as current directory
1976 aObj.setFinalSlash();
1979 UpdateControls( aObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
1981 // Somebody might want to enable some controls according to the current filter
1982 FilterSelect();
1984 OpenURL_Impl( aObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
1986 _pFileView->Show();
1987 _pSplitter->Show();
1989 // if applicable read and set size from ini
1990 InitSize();
1992 return 1;
1996 void SvtFileDialog::executeAsync( ::svt::AsyncPickerAction::Action _eAction,
1997 const OUString& _rURL, const OUString& _rFilter )
1999 SAL_WARN_IF( m_pCurrentAsyncAction.is(), "fpicker.office", "SvtFileDialog::executeAsync: previous async action not yet finished!" );
2001 m_pCurrentAsyncAction = new AsyncPickerAction( this, _pFileView, _eAction );
2003 bool bReallyAsync = true;
2004 m_aConfiguration.getNodeValue( OUString( "FillAsynchronously" ) ) >>= bReallyAsync;
2006 sal_Int32 nMinTimeout = 0;
2007 m_aConfiguration.getNodeValue( OUString( "Timeout/Min" ) ) >>= nMinTimeout;
2008 sal_Int32 nMaxTimeout = 0;
2009 m_aConfiguration.getNodeValue( OUString( "Timeout/Max" ) ) >>= nMaxTimeout;
2011 m_bInExecuteAsync = true;
2012 m_pCurrentAsyncAction->execute( _rURL, _rFilter, bReallyAsync ? nMinTimeout : -1, nMaxTimeout, GetBlackList() );
2013 m_bInExecuteAsync = false;
2017 void SvtFileDialog::FileSelect()
2019 if ( _pFileNotifier )
2020 _pFileNotifier->notify( FILE_SELECTION_CHANGED, 0 );
2024 void SvtFileDialog::FilterSelect()
2026 if ( _pFileNotifier )
2027 _pFileNotifier->notify( CTRL_STATE_CHANGED,
2028 LISTBOX_FILTER );
2032 void SvtFileDialog::SetStandardDir( const OUString& rStdDir )
2034 /* [Description]
2036 This method sets the path for the default button.
2040 INetURLObject aObj( rStdDir );
2041 SAL_WARN_IF( aObj.GetProtocol() == INetProtocol::NotValid, "fpicker.office", "Invalid protocol!" );
2042 aObj.setFinalSlash();
2043 pImpl->SetStandardDir( aObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
2046 void SvtFileDialog::SetBlackList( const css::uno::Sequence< OUString >& rBlackList )
2048 pImpl->SetBlackList( rBlackList );
2052 const css::uno::Sequence< OUString >& SvtFileDialog::GetBlackList() const
2054 return pImpl->GetBlackList();
2058 const OUString& SvtFileDialog::GetStandardDir() const
2060 /* [Description]
2062 This method returns the standard path.
2066 return pImpl->GetStandardDir();
2070 void SvtFileDialog::PrevLevel_Impl()
2072 _pFileView->EndInplaceEditing();
2074 OUString sDummy;
2075 executeAsync( AsyncPickerAction::ePrevLevel, sDummy, sDummy );
2079 void SvtFileDialog::OpenURL_Impl( const OUString& _rURL )
2081 _pFileView->EndInplaceEditing();
2083 executeAsync( AsyncPickerAction::eOpenURL, _rURL, getMostCurrentFilter( pImpl ) );
2087 SvtFileDialogFilter_Impl* SvtFileDialog::implAddFilter( const OUString& _rFilter, const OUString& _rType )
2089 SvtFileDialogFilter_Impl* pNewFilter = new SvtFileDialogFilter_Impl( _rFilter, _rType );
2090 pImpl->m_aFilter.push_front( std::unique_ptr<SvtFileDialogFilter_Impl>( pNewFilter ) );
2092 if ( !pImpl->GetCurFilter() )
2093 pImpl->SetCurFilter( pNewFilter, _rFilter );
2095 return pNewFilter;
2099 void SvtFileDialog::AddFilter( const OUString& _rFilter, const OUString& _rType )
2101 SAL_WARN_IF( IsInExecute(), "fpicker.office", "SvtFileDialog::AddFilter: currently executing!" );
2102 implAddFilter ( _rFilter, _rType );
2106 void SvtFileDialog::AddFilterGroup( const OUString& _rFilter, const Sequence< StringPair >& _rFilters )
2108 SAL_WARN_IF( IsInExecute(), "fpicker.office", "SvtFileDialog::AddFilter: currently executing!" );
2110 implAddFilter( _rFilter, OUString() );
2111 const StringPair* pSubFilters = _rFilters.getConstArray();
2112 const StringPair* pSubFiltersEnd = pSubFilters + _rFilters.getLength();
2113 for ( ; pSubFilters != pSubFiltersEnd; ++pSubFilters )
2114 implAddFilter( pSubFilters->First, pSubFilters->Second );
2118 void SvtFileDialog::SetCurFilter( const OUString& rFilter )
2120 SAL_WARN_IF( IsInExecute(), "fpicker.office", "SvtFileDialog::SetCurFilter: currently executing!" );
2122 // look for corresponding filter
2123 sal_uInt16 nPos = pImpl->m_aFilter.size();
2125 while ( nPos-- )
2127 SvtFileDialogFilter_Impl* pFilter = pImpl->m_aFilter[ nPos ].get();
2128 if ( pFilter->GetName() == rFilter )
2130 pImpl->SetCurFilter( pFilter, rFilter );
2131 break;
2137 OUString SvtFileDialog::GetCurFilter() const
2139 OUString aFilter;
2141 const SvtFileDialogFilter_Impl* pCurrentFilter = pImpl->GetCurFilter();
2142 if ( pCurrentFilter )
2143 aFilter = pCurrentFilter->GetName();
2145 return aFilter;
2148 OUString SvtFileDialog::getCurFilter( ) const
2150 return GetCurFilter();
2154 sal_uInt16 SvtFileDialog::GetFilterCount() const
2156 return pImpl->m_aFilter.size();
2160 const OUString& SvtFileDialog::GetFilterName( sal_uInt16 nPos ) const
2162 assert( nPos < GetFilterCount() && "invalid index" );
2163 return pImpl->m_aFilter[ nPos ]->GetName();
2167 void SvtFileDialog::InitSize()
2169 if ( pImpl->_aIniKey.isEmpty() )
2170 return;
2172 // initialize from config
2173 SvtViewOptions aDlgOpt( E_DIALOG, pImpl->_aIniKey );
2175 if ( aDlgOpt.Exists() )
2177 SetWindowState(OUStringToOString(aDlgOpt.GetWindowState(), osl_getThreadTextEncoding()));
2179 Any aUserData = aDlgOpt.GetUserItem( "UserData");
2180 OUString sCfgStr;
2181 if ( aUserData >>= sCfgStr )
2182 _pFileView->SetConfigString( sCfgStr );
2187 std::vector<OUString> SvtFileDialog::GetPathList() const
2189 std::vector<OUString> aList;
2190 sal_uLong nCount = _pFileView->GetSelectionCount();
2191 SvTreeListEntry* pEntry = nCount ? _pFileView->FirstSelected() : nullptr;
2193 if ( ! pEntry )
2195 if ( !pImpl->_pEdFileName->GetText().isEmpty() && _bIsInExecute )
2196 aList.push_back(pImpl->_pEdFileName->GetURL());
2197 else
2198 aList.push_back(_aPath);
2200 else
2202 while ( pEntry )
2204 aList.push_back(SvtFileView::GetURL(pEntry));
2205 pEntry = _pFileView->NextSelected( pEntry );
2209 return aList;
2213 bool SvtFileDialog::IsolateFilterFromPath_Impl( OUString& rPath, OUString& rFilter )
2215 OUString aReversePath = comphelper::string::reverseString(rPath);
2216 sal_Int32 nQuestionMarkPos = rPath.indexOf( '?' );
2217 sal_Int32 nWildCardPos = rPath.indexOf( FILEDIALOG_DEF_WILDCARD );
2219 if ( nQuestionMarkPos != -1 )
2221 // use question mark as wildcard only for files
2222 INetProtocol eProt = INetURLObject::CompareProtocolScheme( rPath );
2224 if ( INetProtocol::NotValid != eProt && INetProtocol::File != eProt )
2225 nQuestionMarkPos = -1;
2227 nWildCardPos = std::min( nWildCardPos, nQuestionMarkPos );
2230 rFilter.clear();
2232 if ( nWildCardPos != -1 )
2234 sal_Int32 nPathTokenPos = aReversePath.indexOf( '/' );
2236 if ( nPathTokenPos == -1 )
2238 OUString aDelim(
2239 #if defined(_WIN32)
2240 '\\'
2241 #else
2243 #endif
2246 nPathTokenPos = aReversePath.indexOf( aDelim );
2247 #if !defined( UNX )
2248 if ( nPathTokenPos == -1 )
2250 nPathTokenPos = aReversePath.indexOf( ':' );
2252 #endif
2255 // check syntax
2256 if ( nPathTokenPos != -1 )
2258 if ( nPathTokenPos < (rPath.getLength() - nWildCardPos - 1) )
2260 ErrorHandler::HandleError( ERRCODE_SFX_INVALIDSYNTAX );
2261 return false;
2264 // cut off filter
2265 rFilter = aReversePath;
2266 rFilter = rFilter.copy( 0, nPathTokenPos );
2267 rFilter = comphelper::string::reverseString(rFilter);
2269 // determine folder
2270 rPath = aReversePath;
2271 rPath = rPath.copy( nPathTokenPos );
2272 rPath = comphelper::string::reverseString(rPath);
2274 else
2276 rFilter = rPath;
2277 rPath.clear();
2281 return true;
2285 void SvtFileDialog::implUpdateImages( )
2287 m_aImages = ImageList( SvtResId( RID_FILEPICKER_IMAGES ) );
2289 // set the appropriate images on the buttons
2290 if ( pImpl->_pBtnUp )
2291 pImpl->_pBtnUp->SetModeImage( GetButtonImage( IMG_FILEDLG_BTN_UP ) );
2293 if ( pImpl->_pBtnNewFolder )
2294 pImpl->_pBtnNewFolder->SetModeImage( GetButtonImage( IMG_FILEDLG_CREATEFOLDER ) );
2298 void SvtFileDialog::DataChanged( const DataChangedEvent& _rDCEvt )
2300 if ( DataChangedEventType::SETTINGS == _rDCEvt.GetType() )
2301 implUpdateImages( );
2303 ModalDialog::DataChanged( _rDCEvt );
2307 void SvtFileDialog::Resize()
2309 Dialog::Resize();
2311 if ( IsRollUp() )
2312 return;
2314 if ( _pFileNotifier )
2315 _pFileNotifier->notify( DIALOG_SIZE_CHANGED, 0 );
2318 Control* SvtFileDialog::getControl( sal_Int16 _nControlId, bool _bLabelControl ) const
2320 Control* pReturn = nullptr;
2322 switch ( _nControlId )
2324 case CONTROL_FILEVIEW:
2325 pReturn = _bLabelControl ? nullptr : static_cast< Control* >( _pFileView );
2326 break;
2328 case EDIT_FILEURL:
2329 pReturn = _bLabelControl
2330 ? static_cast< Control* >( pImpl->_pFtFileName )
2331 : static_cast< Control* >( pImpl->_pEdFileName );
2332 break;
2334 case EDIT_FILEURL_LABEL:
2335 pReturn = static_cast< Control* >( pImpl->_pFtFileName );
2336 break;
2338 case CHECKBOX_AUTOEXTENSION:
2339 pReturn = pImpl->_pCbAutoExtension;
2340 break;
2342 case CHECKBOX_PASSWORD:
2343 pReturn = pImpl->_pCbPassword;
2344 break;
2346 case CHECKBOX_FILTEROPTIONS:
2347 pReturn = pImpl->_pCbOptions;
2348 break;
2350 case CHECKBOX_READONLY:
2351 pReturn = _pCbReadOnly;
2352 break;
2354 case CHECKBOX_LINK:
2355 pReturn = _pCbLinkBox;
2356 break;
2358 case CHECKBOX_PREVIEW:
2359 pReturn = _pCbPreviewBox;
2360 break;
2362 case CHECKBOX_SELECTION:
2363 pReturn = _pCbSelection;
2364 break;
2366 case LISTBOX_FILTER:
2367 pReturn = _bLabelControl ? pImpl->_pFtFileType : pImpl->GetFilterListControl();
2368 break;
2370 case LISTBOX_FILTER_LABEL:
2371 pReturn = pImpl->_pFtFileType;
2372 break;
2374 case FIXEDTEXT_CURRENTFOLDER:
2375 pReturn = pImpl->_pEdCurrentPath;
2376 break;
2378 case LISTBOX_VERSION:
2379 pReturn = _bLabelControl
2380 ? static_cast< Control* >( pImpl->_pFtFileVersion )
2381 : static_cast< Control* >( pImpl->_pLbFileVersion );
2382 break;
2384 case LISTBOX_TEMPLATE:
2385 pReturn = _bLabelControl
2386 ? static_cast< Control* >( pImpl->_pFtTemplates )
2387 : static_cast< Control* >( pImpl->_pLbTemplates );
2388 break;
2390 case LISTBOX_IMAGE_TEMPLATE:
2391 pReturn = _bLabelControl
2392 ? static_cast< Control* >( pImpl->_pFtImageTemplates )
2393 : static_cast< Control* >( pImpl->_pLbImageTemplates );
2394 break;
2396 case LISTBOX_VERSION_LABEL:
2397 pReturn = pImpl->_pFtFileVersion;
2398 break;
2400 case LISTBOX_TEMPLATE_LABEL:
2401 pReturn = pImpl->_pFtTemplates;
2402 break;
2404 case LISTBOX_IMAGE_TEMPLATE_LABEL:
2405 pReturn = pImpl->_pFtImageTemplates;
2406 break;
2408 case PUSHBUTTON_OK:
2409 pReturn = pImpl->_pBtnFileOpen;
2410 break;
2412 case PUSHBUTTON_CANCEL:
2413 pReturn = pImpl->_pBtnCancel;
2414 break;
2416 case PUSHBUTTON_PLAY:
2417 pReturn = _pPbPlay;
2418 break;
2420 case PUSHBUTTON_HELP:
2421 pReturn = pImpl->_pBtnHelp;
2422 break;
2424 case TOOLBOXBUTOON_LEVEL_UP:
2425 pReturn = pImpl->_pBtnUp;
2426 break;
2428 case TOOLBOXBUTOON_NEW_FOLDER:
2429 pReturn = pImpl->_pBtnNewFolder;
2430 break;
2432 case LISTBOX_FILTER_SELECTOR:
2433 // only exists on SalGtkFilePicker
2434 break;
2436 default:
2437 SAL_WARN( "fpicker.office", "SvtFileDialog::getControl: invalid id!" );
2439 return pReturn;
2443 void SvtFileDialog::enableControl( sal_Int16 _nControlId, bool _bEnable )
2445 Control* pControl = getControl( _nControlId );
2446 if ( pControl )
2447 EnableControl( pControl, _bEnable );
2448 Control* pLabel = getControl( _nControlId, true );
2449 if ( pLabel )
2450 EnableControl( pLabel, _bEnable );
2454 void SvtFileDialog::AddControls_Impl( )
2456 // create the "insert as link" checkbox, if needed
2457 if ( _nPickerFlags & PickerFlags::InsertAsLink )
2459 _pCbLinkBox ->SetText( SvtResId( STR_SVT_FILEPICKER_INSERT_AS_LINK ) );
2460 _pCbLinkBox ->SetHelpId( HID_FILEDLG_LINK_CB );
2461 _pCbLinkBox->SetClickHdl( LINK( this, SvtFileDialog, ClickHdl_Impl ) );
2462 _pCbLinkBox->Show();
2465 // create the "show preview" checkbox ( and the preview window, too ), if needed
2466 if ( _nPickerFlags & PickerFlags::ShowPreview )
2468 pImpl->_aIniKey = "ImportGraphicDialog";
2469 // because the "<All Formats> (*.bmp,*...)" entry is to wide,
2470 // we need to disable the auto width feature of the filter box
2471 pImpl->DisableFilterBoxAutoWidth();
2473 // "preview"
2474 _pCbPreviewBox->SetText( SvtResId( STR_SVT_FILEPICKER_SHOW_PREVIEW ) );
2475 _pCbPreviewBox->SetHelpId( HID_FILEDLG_PREVIEW_CB );
2476 _pCbPreviewBox->SetClickHdl( LINK( this, SvtFileDialog, ClickHdl_Impl ) );
2477 _pCbPreviewBox->Show();
2479 // generate preview window just here
2480 _pPrevWin->SetOutputSizePixel(Size(200, 300));
2481 _pPrevWin->Show();
2483 _pPrevBmp = VclPtr<FixedBitmap>::Create( _pPrevWin, WinBits( WB_BORDER ) );
2484 _pPrevBmp->SetBackground( Wallpaper( Color( COL_WHITE ) ) );
2485 _pPrevBmp->SetSizePixel(_pPrevWin->GetSizePixel());
2486 _pPrevBmp->Show();
2487 _pPrevBmp->SetAccessibleName(SVT_RESSTR(STR_PREVIEW));
2490 if ( _nPickerFlags & PickerFlags::AutoExtension )
2492 pImpl->_pCbAutoExtension->SetText( SvtResId( STR_SVT_FILEPICKER_AUTO_EXTENSION ) );
2493 pImpl->_pCbAutoExtension->Check();
2494 pImpl->_pCbAutoExtension->SetClickHdl( LINK( this, SvtFileDialog, AutoExtensionHdl_Impl ) );
2495 pImpl->_pCbAutoExtension->Show();
2498 if ( _nPickerFlags & PickerFlags::FilterOptions )
2500 pImpl->_pCbOptions->SetText( SvtResId( STR_SVT_FILEPICKER_FILTER_OPTIONS ) );
2501 pImpl->_pCbOptions->SetClickHdl( LINK( this, SvtFileDialog, ClickHdl_Impl ) );
2502 pImpl->_pCbOptions->Show();
2505 if ( _nPickerFlags & PickerFlags::Selection )
2507 _pCbSelection->SetText( SvtResId( STR_SVT_FILEPICKER_SELECTION ) );
2508 _pCbSelection->SetClickHdl( LINK( this, SvtFileDialog, ClickHdl_Impl ) );
2509 _pCbSelection->Show();
2512 if ( _nPickerFlags & PickerFlags::PlayButton )
2514 _pPbPlay->SetText( SvtResId( STR_SVT_FILEPICKER_PLAY ) );
2515 _pPbPlay->SetHelpId( HID_FILESAVE_DOPLAY );
2516 _pPbPlay->SetClickHdl( LINK( this, SvtFileDialog, PlayButtonHdl_Impl ) );
2517 _pPbPlay->Show();
2520 if ( _nPickerFlags & PickerFlags::ShowVersions )
2522 pImpl->_pFtFileVersion->SetText( SvtResId( STR_SVT_FILEPICKER_VERSION ) );
2523 pImpl->_pFtFileVersion->Show();
2525 pImpl->_pLbFileVersion->SetHelpId( HID_FILEOPEN_VERSION );
2526 pImpl->_pLbFileVersion->Show();
2528 else if ( _nPickerFlags & PickerFlags::Templates )
2530 pImpl->_pFtTemplates->SetText( SvtResId( STR_SVT_FILEPICKER_TEMPLATES ) );
2531 pImpl->_pFtTemplates->Show();
2533 pImpl->_pLbTemplates->SetHelpId( HID_FILEOPEN_VERSION );
2534 pImpl->_pLbTemplates->Show();
2535 // This is strange. During the re-factoring during 96930, I discovered that this help id
2536 // is set in the "Templates mode". This was hidden in the previous implementation.
2537 // Shouldn't this be a more meaningfull help id.
2539 else if ( _nPickerFlags & PickerFlags::ImageTemplate )
2541 pImpl->_pFtImageTemplates->SetText( SvtResId( STR_SVT_FILEPICKER_IMAGE_TEMPLATE ) );
2542 pImpl->_pFtImageTemplates->Show();
2544 pImpl->_pLbImageTemplates->SetHelpId( HID_FILEOPEN_IMAGE_TEMPLATE );
2545 pImpl->_pLbImageTemplates->Show();
2548 pImpl->_pPlaces = VclPtr<PlacesListBox>::Create(_pContainer, this, SVT_RESSTR(STR_PLACES_TITLE), WB_BORDER);
2549 pImpl->_pPlaces->SetHelpId("SVT_HID_FILESAVE_PLACES_LISTBOX");
2550 Size aSize(LogicToPixel(Size(50, 85), MapUnit::MapAppFont));
2551 pImpl->_pPlaces->set_height_request(aSize.Height());
2552 pImpl->_pPlaces->set_width_request(aSize.Width());
2553 pImpl->_pPlaces->SetSizePixel(aSize);
2554 pImpl->_pPlaces->Show();
2556 sal_Int32 nPosX = pImpl->_pPlaces->GetSizePixel().Width();
2557 _pSplitter->SetPosPixel(Point(nPosX, 0));
2558 nPosX += _pSplitter->GetSizePixel().Width();
2559 _pFileView->SetPosPixel(Point(nPosX, 0));
2561 pImpl->_pPlaces->SetAddHdl( LINK ( this, SvtFileDialog, AddPlacePressed_Hdl ) );
2562 pImpl->_pPlaces->SetDelHdl( LINK ( this, SvtFileDialog, RemovePlacePressed_Hdl ) );
2564 initDefaultPlaces();
2568 sal_Int32 SvtFileDialog::getTargetColorDepth()
2570 if ( _pPrevBmp )
2571 return _pPrevBmp->GetBitCount();
2572 else
2573 return 0;
2577 sal_Int32 SvtFileDialog::getAvailableWidth()
2579 if ( _pPrevBmp )
2580 return _pPrevBmp->GetOutputSizePixel().Width();
2581 else
2582 return 0;
2586 sal_Int32 SvtFileDialog::getAvailableHeight()
2588 if ( _pPrevBmp )
2589 return _pPrevBmp->GetOutputSizePixel().Height();
2590 else
2591 return 0;
2595 void SvtFileDialog::setImage( sal_Int16 /*aImageFormat*/, const Any& rImage )
2597 if ( ! _pPrevBmp || ! _pPrevBmp->IsVisible() )
2598 return;
2600 Sequence < sal_Int8 > aBmpSequence;
2602 if ( rImage >>= aBmpSequence )
2604 Bitmap aBmp;
2605 SvMemoryStream aData( aBmpSequence.getArray(),
2606 aBmpSequence.getLength(),
2607 StreamMode::READ );
2608 ReadDIB(aBmp, aData, true);
2610 _pPrevBmp->SetBitmap( aBmp );
2612 else
2614 Bitmap aEmpty;
2615 _pPrevBmp->SetBitmap( aEmpty );
2620 OUString SvtFileDialog::getCurrentFileText( ) const
2622 OUString sReturn;
2623 if ( pImpl && pImpl->_pEdFileName )
2624 sReturn = pImpl->_pEdFileName->GetText();
2625 return sReturn;
2629 void SvtFileDialog::setCurrentFileText( const OUString& _rText, bool _bSelectAll )
2631 if ( pImpl && pImpl->_pEdFileName )
2633 pImpl->_pEdFileName->SetText( _rText );
2634 if ( _bSelectAll )
2635 pImpl->_pEdFileName->SetSelection( Selection( 0, _rText.getLength() ) );
2640 bool SvtFileDialog::isAutoExtensionEnabled()
2642 return pImpl->_pCbAutoExtension && pImpl->_pCbAutoExtension->IsChecked();
2646 bool SvtFileDialog::getShowState()
2648 if ( _pPrevBmp )
2649 return _pPrevBmp->IsVisible();
2650 else
2651 return false;
2654 bool SvtFileDialog::ContentHasParentFolder( const OUString& rURL )
2656 m_aContent.bindTo( rURL );
2658 if ( m_aContent.isInvalid() )
2659 return false;
2661 return m_aContent.hasParentFolder( ) && m_aContent.isValid();
2664 bool SvtFileDialog::ContentCanMakeFolder( const OUString& rURL )
2666 m_aContent.bindTo( rURL );
2668 if ( m_aContent.isInvalid() )
2669 return false;
2671 return m_aContent.canCreateFolder( ) && m_aContent.isValid();
2674 bool SvtFileDialog::ContentGetTitle( const OUString& rURL, OUString& rTitle )
2676 m_aContent.bindTo( rURL );
2678 if ( m_aContent.isInvalid() )
2679 return false;
2681 OUString sTitle;
2682 m_aContent.getTitle( sTitle );
2683 rTitle = sTitle;
2685 return m_aContent.isValid();
2688 void SvtFileDialog::appendDefaultExtension(OUString& _rFileName,
2689 const OUString& _rFilterDefaultExtension,
2690 const OUString& _rFilterExtensions)
2692 const OUString aType(_rFilterExtensions.toAsciiLowerCase());
2694 if ( aType != FILEDIALOG_FILTER_ALL )
2696 const OUString aTemp(_rFileName.toAsciiLowerCase());
2697 sal_Int32 nPos = 0;
2701 if (nPos+1<aType.getLength() && aType[nPos]=='*') // take care of a leading *
2702 ++nPos;
2703 const OUString aExt(aType.getToken( 0, FILEDIALOG_DEF_EXTSEP, nPos ));
2704 if (aExt.isEmpty())
2705 continue;
2706 if (aTemp.endsWith(aExt))
2707 return;
2709 while (nPos>=0);
2711 _rFileName += "." + _rFilterDefaultExtension;
2715 void SvtFileDialog::initDefaultPlaces( )
2717 PlacePtr pRootPlace( new Place( SVT_RESSTR(STR_DEFAULT_DIRECTORY), GetStandardDir() ) );
2718 pImpl->_pPlaces->AppendPlace( pRootPlace );
2720 // Load from user settings
2721 Sequence< OUString > placesUrlsList(officecfg::Office::Common::Misc::FilePickerPlacesUrls::get(m_context));
2722 Sequence< OUString > placesNamesList(officecfg::Office::Common::Misc::FilePickerPlacesNames::get(m_context));
2724 for(sal_Int32 nPlace = 0; nPlace < placesUrlsList.getLength() && nPlace < placesNamesList.getLength(); ++nPlace)
2726 PlacePtr pPlace(new Place(placesNamesList[nPlace], placesUrlsList[nPlace], true));
2727 pImpl->_pPlaces->AppendPlace(pPlace);
2730 // Reset the placesList "updated" state
2731 pImpl->_pPlaces->IsUpdated();
2734 IMPL_LINK_NOARG( SvtFileDialog, Split_Hdl, Splitter*, void )
2736 sal_Int32 nSplitPos = _pSplitter->GetSplitPosPixel();
2738 // Resize the places list
2739 sal_Int32 nPlaceX = pImpl->_pPlaces->GetPosPixel( ).X();
2740 Size placeSize = pImpl->_pPlaces->GetSizePixel( );
2741 placeSize.Width() = nSplitPos - nPlaceX;
2742 pImpl->_pPlaces->SetSizePixel( placeSize );
2744 // Change Pos and size of the fileview
2745 Point fileViewPos = _pFileView->GetPosPixel();
2746 sal_Int32 nOldX = fileViewPos.X();
2747 sal_Int32 nNewX = nSplitPos + _pSplitter->GetSizePixel().Width();
2748 fileViewPos.X() = nNewX;
2749 Size fileViewSize = _pFileView->GetSizePixel();
2750 fileViewSize.Width() -= ( nNewX - nOldX );
2751 _pFileView->SetPosSizePixel( fileViewPos, fileViewSize );
2753 _pSplitter->SetPosPixel( Point( placeSize.Width(), _pSplitter->GetPosPixel().Y() ) );
2756 QueryFolderNameDialog::QueryFolderNameDialog(vcl::Window* _pParent,
2757 const OUString& rTitle, const OUString& rDefaultText)
2758 : ModalDialog(_pParent, "FolderNameDialog", "fps/ui/foldernamedialog.ui")
2760 get(m_pNameEdit, "entry");
2761 get(m_pNameLine, "frame");
2762 get(m_pOKBtn, "ok");
2764 SetText( rTitle );
2765 m_pNameEdit->SetText( rDefaultText );
2766 m_pNameEdit->SetSelection( Selection( 0, rDefaultText.getLength() ) );
2767 m_pOKBtn->SetClickHdl( LINK( this, QueryFolderNameDialog, OKHdl ) );
2768 m_pNameEdit->SetModifyHdl( LINK( this, QueryFolderNameDialog, NameHdl ) );
2771 QueryFolderNameDialog::~QueryFolderNameDialog()
2773 disposeOnce();
2776 void QueryFolderNameDialog::dispose()
2778 m_pNameEdit.clear();
2779 m_pNameLine.clear();
2780 m_pOKBtn.clear();
2781 ModalDialog::dispose();
2784 IMPL_LINK_NOARG(QueryFolderNameDialog, OKHdl, Button*, void)
2786 // trim the strings
2787 m_pNameEdit->SetText(comphelper::string::strip(m_pNameEdit->GetText(), ' '));
2788 EndDialog( RET_OK );
2792 IMPL_LINK_NOARG(QueryFolderNameDialog, NameHdl, Edit&, void)
2794 // trim the strings
2795 OUString aName = comphelper::string::strip(m_pNameEdit->GetText(), ' ');
2796 if ( !aName.isEmpty() )
2798 if ( !m_pOKBtn->IsEnabled() )
2799 m_pOKBtn->Enable();
2801 else
2803 if ( m_pOKBtn->IsEnabled() )
2804 m_pOKBtn->Enable( false );
2808 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */