tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / fpicker / source / office / RemoteFilesDialog.cxx
blob9bc424d604c352599e77c47f6a10d79fd92112b3
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/.
8 */
10 #include <config_oauth2.h>
12 #include "fpsmartcontent.hxx"
13 #include "QueryFolderName.hxx"
14 #include "RemoteFilesDialog.hxx"
15 #include <fpicker/fpsofficeResMgr.hxx>
16 #include <fpicker/strings.hrc>
17 #include <strings.hrc>
18 #include <comphelper/docpasswordrequest.hxx>
19 #include <com/sun/star/task/InteractionHandler.hpp>
20 #include <com/sun/star/task/PasswordContainer.hpp>
21 #include <svtools/PlaceEditDialog.hxx>
22 #include <tools/debug.hxx>
23 #include <unotools/ucbhelper.hxx>
24 #include <vcl/errinf.hxx>
25 #include <officecfg/Office/Common.hxx>
27 using namespace ::svt;
29 RemoteFilesDialog::RemoteFilesDialog( weld::Window* pParent, PickerFlags nBits )
30 : SvtFileDialog_Base( pParent, u"fps/ui/remotefilesdialog.ui"_ustr, u"RemoteFilesDialog"_ustr )
31 , m_xContext( comphelper::getProcessComponentContext() )
32 , m_xMasterPasswd( PasswordContainer::create( m_xContext ) )
33 , m_bIsInExecute( false )
34 , m_xOk_btn(m_xBuilder->weld_button(u"ok"_ustr))
35 , m_xCancel_btn(m_xBuilder->weld_button(u"cancel"_ustr))
36 , m_xManageServices(m_xBuilder->weld_menu_button(u"add_service_btn"_ustr))
37 , m_xServices_lb(m_xBuilder->weld_combo_box(u"services_lb"_ustr))
38 , m_xPathContainer(m_xBuilder->weld_container(u"breadcrumb_container"_ustr))
39 , m_xNewFolder(m_xBuilder->weld_button(u"new_folder"_ustr))
40 , m_xListView_btn(m_xBuilder->weld_toggle_button(u"list_view"_ustr))
41 , m_xIconView_btn(m_xBuilder->weld_toggle_button(u"icon_view"_ustr))
42 , m_xFilter_lb(m_xBuilder->weld_combo_box(u"filter_lb"_ustr))
43 , m_xName_ed(new AutocompleteEdit(m_xBuilder->weld_entry(u"filename"_ustr)))
45 m_eMode = ( nBits & PickerFlags::SaveAs ) ? REMOTEDLG_MODE_SAVE : REMOTEDLG_MODE_OPEN;
46 m_eType = ( nBits & PickerFlags::PathDialog ) ? REMOTEDLG_TYPE_PATHDLG : REMOTEDLG_TYPE_FILEDLG;
47 bool bMultiselection = bool( nBits & PickerFlags::MultiSelection );
48 m_bIsUpdated = false;
49 m_bIsConnected = false;
50 m_bServiceChanged = false;
51 m_nCurrentFilter = -1;
53 m_xName_ed->show();
55 // limit width due to super wide strings that may end up here
56 m_xFilter_lb->set_size_request(m_xFilter_lb->get_approximate_digit_width() * 60, -1);
58 m_xFilter_lb->set_sensitive(false);
59 m_xName_ed->set_sensitive(false);
60 m_xNewFolder->set_sensitive(false);
62 if( m_eMode == REMOTEDLG_MODE_OPEN )
64 m_xNewFolder->hide();
66 else
68 m_xOk_btn->set_label(FpsResId(STR_EXPLORERFILE_BUTTONSAVE));
69 m_xNewFolder->connect_clicked( LINK( this, RemoteFilesDialog, NewFolderHdl ) );
72 m_xListView_btn->set_active(true);
73 m_xIconView_btn->connect_clicked( LINK( this, RemoteFilesDialog, IconViewHdl ) );
74 m_xListView_btn->connect_clicked( LINK( this, RemoteFilesDialog, ListViewHdl ) );
76 m_xOk_btn->set_sensitive(false);
78 m_xOk_btn->connect_clicked( LINK( this, RemoteFilesDialog, OkHdl ) );
79 m_xCancel_btn->connect_clicked( LINK( this, RemoteFilesDialog, CancelHdl ) );
81 m_sRootLabel = FpsResId( STR_SVT_ROOTLABEL );
82 m_xPath.reset(new Breadcrumb(m_xPathContainer.get()));
83 m_xPath->connect_clicked( LINK( this, RemoteFilesDialog, SelectBreadcrumbHdl ) );
84 m_xPath->SetMode( SvtBreadcrumbMode::ALL_VISITED );
86 m_xContainer = m_xBuilder->weld_container(u"container"_ustr);
87 m_xContainer->set_size_request(m_xContainer->get_approximate_digit_width() * 82, -1);
89 m_xFileView.reset(new SvtFileView(m_xDialog.get(),
90 m_xBuilder->weld_tree_view(u"fileview"_ustr),
91 m_xBuilder->weld_icon_view(u"iconview"_ustr),
92 REMOTEDLG_TYPE_PATHDLG == m_eType,
93 bMultiselection, false));
95 m_xFileView->SetDoubleClickHdl( LINK( this, RemoteFilesDialog, DoubleClickHdl ) );
96 m_xFileView->SetSelectHdl( LINK( this, RemoteFilesDialog, SelectHdl ) );
97 m_xFileView->EnableDelete( true );
99 m_xTreeView.reset(new FolderTree(m_xBuilder->weld_tree_view(u"foldertree"_ustr), m_xDialog.get()));
100 m_xTreeView->connect_changed(LINK(this, RemoteFilesDialog, TreeSelectHdl));
102 m_xContainer->set_sensitive(false);
104 m_sIniKey = "RemoteFilesDialog";
105 InitSize();
107 m_xName_ed->connect_focus_in(LINK(this, RemoteFilesDialog, FileNameGetFocusHdl));
108 m_xName_ed->connect_changed(LINK(this, RemoteFilesDialog, FileNameModifyHdl));
110 m_xManageServices->connect_selected(LINK(this, RemoteFilesDialog, EditServiceMenuHdl));
112 FillServicesListbox();
114 m_xServices_lb->connect_changed( LINK( this, RemoteFilesDialog, SelectServiceHdl ) );
116 m_xFilter_lb->connect_changed( LINK( this, RemoteFilesDialog, SelectFilterHdl ) );
119 RemoteFilesDialog::~RemoteFilesDialog()
121 m_xFileView->SetSelectHdl(Link<SvtFileView*,void>());
123 // save window state
124 if( !m_sIniKey.isEmpty() )
126 SvtViewOptions aDlgOpt( EViewType::Dialog, m_sIniKey );
127 aDlgOpt.SetWindowState(m_xDialog->get_window_state(vcl::WindowDataMask::All));
129 Size aSize(m_xDialog->get_size());
131 OUString sSize = OUString::number( aSize.Width() ) + "|";
132 sSize = sSize + OUString::number( aSize.Height() ) + "|";
134 OUString sUserData = m_xFileView->GetConfigString();
135 aDlgOpt.SetUserItem( u"UserData"_ustr,
136 Any( sSize + sUserData ) );
139 // save services
140 std::shared_ptr< comphelper::ConfigurationChanges > batch( comphelper::ConfigurationChanges::create() );
142 officecfg::Office::Common::Misc::FilePickerLastService::set( m_sLastServiceUrl, batch );
144 if( m_bIsUpdated )
146 Sequence< OUString > placesUrlsList( m_aServices.size() );
147 auto placesUrlsListRange = asNonConstRange(placesUrlsList);
148 Sequence< OUString > placesNamesList( m_aServices.size() );
149 auto placesNamesListRange = asNonConstRange(placesNamesList);
151 int i = 0;
152 for (auto const& service : m_aServices)
154 placesUrlsListRange[i] = service->GetUrl();
155 placesNamesListRange[i] = service->GetName();
156 ++i;
159 officecfg::Office::Common::Misc::FilePickerPlacesUrls::set( placesUrlsList, batch );
160 officecfg::Office::Common::Misc::FilePickerPlacesNames::set( placesNamesList, batch );
163 batch->commit();
166 void RemoteFilesDialog::EnableExtraMenuItems(bool bEnable)
168 m_xManageServices->set_item_visible(u"change_password"_ustr, bEnable);
169 m_xManageServices->set_item_visible(u"edit_service"_ustr, bEnable);
170 m_xManageServices->set_item_visible(u"delete_service"_ustr, bEnable);
171 m_xManageServices->set_item_visible(u"change_password"_ustr, bEnable);
174 short RemoteFilesDialog::run()
176 if (m_xServices_lb->get_count() > 0)
178 m_xDialog->show();
179 SelectServiceHdl(*m_xServices_lb);
181 if (!m_bIsConnected)
183 m_xServices_lb->set_active(-1);
184 EnableExtraMenuItems(false);
187 m_bIsInExecute = true;
188 short nRet = SvtFileDialog_Base::run();
189 m_bIsInExecute = false;
190 return nRet;
193 static OUString lcl_GetServiceType( const ServicePtr& pService )
195 INetProtocol aProtocol = pService->GetUrlObject().GetProtocol();
196 switch( aProtocol )
198 case INetProtocol::Cmis:
200 OUString sHost = pService->GetUrlObject().GetHost( INetURLObject::DecodeMechanism::WithCharset );
202 if( sHost.startsWith( GDRIVE_BASE_URL ) )
203 return u"Google Drive"_ustr;
204 else if( sHost.startsWith( ALFRESCO_CLOUD_BASE_URL ) )
205 return u"Alfresco Cloud"_ustr;
206 else if( sHost.startsWith( ONEDRIVE_BASE_URL ) )
207 return u"OneDrive"_ustr;
209 return u"CMIS"_ustr;
211 case INetProtocol::Smb:
212 return u"Windows Share"_ustr;
213 case INetProtocol::File:
214 return u"SSH"_ustr;
215 case INetProtocol::Http:
216 return u"WebDAV"_ustr;
217 case INetProtocol::Https:
218 return u"WebDAV"_ustr;
219 case INetProtocol::Generic:
220 return u"SSH"_ustr;
221 default:
222 return OUString();
226 void RemoteFilesDialog::InitSize()
228 if( m_sIniKey.isEmpty() )
229 return;
231 // initialize from config
232 SvtViewOptions aDlgOpt( EViewType::Dialog, m_sIniKey );
234 if( !aDlgOpt.Exists() )
235 return;
237 m_xDialog->set_window_state(aDlgOpt.GetWindowState());
239 Any aUserData = aDlgOpt.GetUserItem( u"UserData"_ustr );
240 OUString sCfgStr;
241 if( aUserData >>= sCfgStr )
243 sal_Int32 nPos1{ sCfgStr.indexOf('|') };
244 if (nPos1<0)
245 return;
246 sal_Int32 nPos2{ sCfgStr.indexOf('|', nPos1+1 ) };
247 if (nPos2<0)
248 return;
249 m_xFileView->SetConfigString( sCfgStr.subView(nPos2+1) );
253 void RemoteFilesDialog::FillServicesListbox()
255 m_xServices_lb->clear();
256 m_aServices.clear();
258 // Load from user settings
259 Sequence< OUString > placesUrlsList( officecfg::Office::Common::Misc::FilePickerPlacesUrls::get() );
260 Sequence< OUString > placesNamesList( officecfg::Office::Common::Misc::FilePickerPlacesNames::get() );
262 unsigned int nPos = 0;
263 unsigned int i = 0;
265 m_sLastServiceUrl = officecfg::Office::Common::Misc::FilePickerLastService::get();
267 for( sal_Int32 nPlace = 0; nPlace < placesUrlsList.getLength() && nPlace < placesNamesList.getLength(); ++nPlace )
269 ServicePtr pService = std::make_shared<Place>( placesNamesList[nPlace], placesUrlsList[nPlace], true );
270 m_aServices.push_back( pService );
272 // Add to the listbox only remote services, not local bookmarks
273 if( !pService->IsLocal() )
275 OUString sPrefix = lcl_GetServiceType( pService );
277 if( !sPrefix.isEmpty() )
278 sPrefix += ": ";
280 if( placesUrlsList[nPlace] == m_sLastServiceUrl )
281 nPos = i;
283 m_xServices_lb->append_text(sPrefix + placesNamesList[nPlace]);
285 i++;
289 if (m_xServices_lb->get_count() > 0)
291 m_xServices_lb->set_active(nPos);
292 EnableExtraMenuItems(true);
294 else
295 EnableExtraMenuItems(false);
297 EnableControls();
300 int RemoteFilesDialog::GetSelectedServicePos()
302 if( m_aServices.empty() )
303 return -1;
305 int nPos = 0;
306 int i = -1;
308 int nSelected = m_xServices_lb->get_active();
310 int nServices = static_cast<int>(m_aServices.size());
311 while( nPos < nServices )
313 while( (nPos < nServices) && m_aServices[nPos]->IsLocal() )
314 nPos++;
315 i++;
316 if( i == nSelected )
317 break;
318 nPos++;
321 return nPos;
324 void RemoteFilesDialog::AddFilter( const OUString& rFilter, const OUString& rType )
326 m_aFilters.emplace_back( rFilter, rType );
327 if (rType.isEmpty())
328 m_xFilter_lb->append_separator(u""_ustr);
329 else
330 m_xFilter_lb->append_text(rFilter);
332 if (m_xFilter_lb->get_active() == -1)
333 m_xFilter_lb->set_active(0);
336 void RemoteFilesDialog::OpenURL( OUString const & sURL )
338 if( !m_xFileView )
339 return;
341 DisableControls();
343 auto xWait = std::make_unique<weld::WaitObject>(m_xDialog.get());
345 if( !sURL.isEmpty() )
347 OUString sFilter = FILEDIALOG_FILTER_ALL;
349 if( m_nCurrentFilter != -1)
351 sFilter = m_aFilters[m_nCurrentFilter].second;
354 m_xFileView->EndInplaceEditing();
356 DBG_ASSERT( !m_pCurrentAsyncAction.is(), "SvtFileDialog::executeAsync: previous async action not yet finished!" );
358 m_pCurrentAsyncAction = new AsyncPickerAction( this, m_xFileView.get(), AsyncPickerAction::Action::eOpenURL );
360 // -1 timeout - sync
361 m_pCurrentAsyncAction->execute( sURL, sFilter, -1, -1, GetDenyList() );
363 if( m_eMode != REMOTEDLG_MODE_SAVE )
364 m_xName_ed->set_text( u""_ustr );
366 m_xFileView->grab_focus();
368 else
370 xWait.reset();
372 // content doesn't exist
373 ErrorHandler::HandleError( ERRCODE_IO_NOTEXISTS );
375 EnableControls();
379 OUString RemoteFilesDialog::AddFileExtension(const OUString& rFileName)
381 if (m_nCurrentFilter == -1)
382 return rFileName;
384 OUString sExt = m_aFilters[m_nCurrentFilter].second;
385 sal_Int32 nDotPos = rFileName.lastIndexOf( '.' );
387 if (nDotPos == -1)
388 return rFileName + sExt.subView( 1 ); // without '*'
390 return rFileName;
393 void RemoteFilesDialog::EnableControls()
395 if (m_xServices_lb->get_count() > 0)
397 m_xServices_lb->set_sensitive(true);
399 if (m_xServices_lb->get_active() != -1)
401 m_xManageServices->set_item_sensitive(u"change_password"_ustr, false);
405 if( m_xMasterPasswd->isPersistentStoringAllowed() )
407 int nPos = GetSelectedServicePos();
409 if( nPos >= 0 )
411 OUString sUrl( m_aServices[nPos]->GetUrl() );
413 UrlRecord aURLEntries = m_xMasterPasswd->find( sUrl, Reference< XInteractionHandler>() );
415 if( aURLEntries.UserList.hasElements() )
417 m_xManageServices->set_item_sensitive(u"change_password"_ustr, true);
422 catch( const Exception& )
426 else
427 m_xServices_lb->set_sensitive(false);
429 if( m_bIsConnected )
431 m_xFilter_lb->set_sensitive(true);
432 m_xName_ed->set_sensitive(true);
433 m_xContainer->set_sensitive(true);
434 m_xNewFolder->set_sensitive(true);
436 if (!m_xName_ed->get_text().isEmpty())
437 m_xOk_btn->set_sensitive(true);
438 else
439 m_xOk_btn->set_sensitive(false);
441 else
443 m_xFilter_lb->set_sensitive(false);
444 m_xName_ed->set_sensitive(false);
445 m_xContainer->set_sensitive(false);
446 m_xNewFolder->set_sensitive(false);
447 m_xOk_btn->set_sensitive(false);
450 m_xPath->EnableFields( true );
451 m_xManageServices->set_sensitive(true);
454 void RemoteFilesDialog::DisableControls()
456 m_xServices_lb->set_sensitive(false);
457 m_xFilter_lb->set_sensitive(false);
458 m_xManageServices->set_sensitive(false);
459 m_xName_ed->set_sensitive(false);
460 m_xContainer->set_sensitive(false);
461 m_xOk_btn->set_sensitive(false);
462 m_xPath->EnableFields( false );
464 m_xCancel_btn->set_sensitive(true);
467 void RemoteFilesDialog::SavePassword(const OUString& rURL, const OUString& rUser,
468 const OUString& rPassword, bool bPersistent)
470 if( rURL.isEmpty() || rUser.isEmpty() || rPassword.isEmpty() )
471 return;
475 if( !bPersistent ||
476 ( m_xMasterPasswd->isPersistentStoringAllowed()
477 && m_xMasterPasswd->authorizateWithMasterPassword( Reference< XInteractionHandler>() ) )
480 Reference< XInteractionHandler > xInteractionHandler =
481 InteractionHandler::createWithParent( m_xContext, nullptr );
483 Sequence<OUString> aPasswd { rPassword };
485 if( bPersistent )
486 m_xMasterPasswd->addPersistent(
487 rURL, rUser, aPasswd, xInteractionHandler );
488 else
489 m_xMasterPasswd->add( rURL, rUser, aPasswd, xInteractionHandler );
492 catch( const Exception& )
496 IMPL_LINK_NOARG ( RemoteFilesDialog, IconViewHdl, weld::Button&, void )
498 m_xListView_btn->set_active(false);
499 m_xFileView->SetViewMode( eIcon );
502 IMPL_LINK_NOARG ( RemoteFilesDialog, ListViewHdl, weld::Button&, void )
504 m_xIconView_btn->set_active(false);
505 m_xFileView->SetViewMode( eDetailedList );
508 void RemoteFilesDialog::AddService()
510 PlaceEditDialog aDlg(m_xDialog.get());
511 aDlg.ShowPasswordControl();
512 short aRetCode = aDlg.run();
514 switch( aRetCode )
516 case RET_OK :
518 ServicePtr newService = aDlg.GetPlace();
519 m_aServices.push_back( newService );
521 OUString sPassword = aDlg.GetPassword();
522 OUString sUser = aDlg.GetUser();
523 if( !sUser.isEmpty() && !sPassword.isEmpty() )
525 bool bPersistent = aDlg.IsRememberChecked();
526 SavePassword( newService->GetUrl(), sUser, sPassword, bPersistent );
529 OUString sPrefix = lcl_GetServiceType( newService );
531 if(!sPrefix.isEmpty())
532 sPrefix += ": ";
534 m_xServices_lb->append_text( sPrefix + newService->GetName() );
535 m_xServices_lb->set_active( m_xServices_lb->get_count() - 1 );
536 EnableExtraMenuItems(true);
537 SelectServiceHdl( *m_xServices_lb );
539 m_bIsUpdated = true;
541 EnableControls();
542 break;
544 case RET_CANCEL :
545 default :
546 // Do Nothing
547 break;
551 IMPL_LINK_NOARG( RemoteFilesDialog, SelectServiceHdl, weld::ComboBox&, void )
553 int nPos = GetSelectedServicePos();
555 if( nPos >= 0 )
557 OUString sURL = m_aServices[nPos]->GetUrl();
558 EnableExtraMenuItems(true);
560 m_bServiceChanged = true;
561 OpenURL( sURL );
565 IMPL_LINK ( RemoteFilesDialog, EditServiceMenuHdl, const OUString&, rIdent, void )
567 OUString sIdent(rIdent);
568 if( sIdent == "edit_service" && m_xServices_lb->get_count() > 0 )
570 int nSelected = m_xServices_lb->get_active();
571 int nPos = GetSelectedServicePos();
573 if( nPos >= 0 )
575 PlaceEditDialog aDlg(m_xDialog.get(), m_aServices[nPos]);
576 short aRetCode = aDlg.run();
578 switch( aRetCode )
580 case RET_OK :
582 ServicePtr pEditedService = aDlg.GetPlace();
584 m_aServices[nPos] = pEditedService;
585 m_xServices_lb->remove( nSelected );
587 OUString sPrefix = lcl_GetServiceType( pEditedService );
589 if(!sPrefix.isEmpty())
590 sPrefix += ": ";
592 m_xServices_lb->insert_text(nSelected, sPrefix + pEditedService->GetName());
593 m_xServices_lb->set_active( nSelected );
595 m_bIsUpdated = true;
596 break;
598 case RET_NO:
599 sIdent = "delete_service";
600 break;
601 case RET_CANCEL :
602 default :
603 // Do Nothing
604 break;
608 if( sIdent == "delete_service" && m_xServices_lb->get_count() > 0 )
610 int nSelected = m_xServices_lb->get_active();
611 int nPos = GetSelectedServicePos();
613 if( nPos >= 0 )
615 OUString sMsg = FpsResId( STR_SVT_DELETESERVICE );
616 sMsg = sMsg.replaceFirst( "$servicename$", m_xServices_lb->get_active_text() );
617 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
618 VclMessageType::Question, VclButtonsType::YesNo, sMsg));
619 if (xBox->run() == RET_YES)
621 // remove password
624 if( m_xMasterPasswd->isPersistentStoringAllowed() )
626 OUString sUrl( m_aServices[nPos]->GetUrl() );
628 Reference< XInteractionHandler > xInteractionHandler =
629 InteractionHandler::createWithParent( m_xContext, nullptr );
631 UrlRecord aURLEntries = m_xMasterPasswd->find( sUrl, xInteractionHandler );
633 if( aURLEntries.Url == sUrl && aURLEntries.UserList.hasElements() )
635 OUString sUserName = aURLEntries.UserList[0].UserName;
637 m_xMasterPasswd->removePersistent( sUrl, sUserName );
641 catch( const Exception& )
644 m_aServices.erase( m_aServices.begin() + nPos );
645 m_xServices_lb->remove( nSelected );
647 m_xServices_lb->set_active(-1);
648 EnableExtraMenuItems(false);
650 m_bIsUpdated = true;
652 m_bIsConnected = false;
653 EnableControls();
657 else if( sIdent == "change_password" )
661 if( m_xMasterPasswd->isPersistentStoringAllowed() && m_xMasterPasswd->authorizateWithMasterPassword( Reference< XInteractionHandler>() ) )
663 int nPos = GetSelectedServicePos();
665 if( nPos >= 0 )
667 OUString sUrl( m_aServices[nPos]->GetUrl() );
669 Reference< XInteractionHandler > xInteractionHandler =
670 InteractionHandler::createWithParent( m_xContext, nullptr );
672 UrlRecord aURLEntries = m_xMasterPasswd->find( sUrl, xInteractionHandler );
674 if( aURLEntries.Url == sUrl && aURLEntries.UserList.hasElements() )
676 OUString sUserName = aURLEntries.UserList[0].UserName;
678 rtl::Reference<::comphelper::SimplePasswordRequest> pPasswordRequest
679 = new ::comphelper::SimplePasswordRequest;
681 xInteractionHandler->handle( pPasswordRequest );
683 if ( pPasswordRequest->isPassword() )
685 Sequence<OUString> aPasswd { pPasswordRequest->getPassword() };
687 m_xMasterPasswd->addPersistent(
688 sUrl, sUserName, aPasswd, xInteractionHandler );
694 catch( const Exception& )
697 else if( sIdent == "add_service" )
698 AddService();
700 EnableControls();
703 IMPL_LINK_NOARG( RemoteFilesDialog, DoubleClickHdl, SvtFileView*, bool )
705 SvtContentEntry* pData = m_xFileView->FirstSelected();
706 if (pData)
708 if (!pData->mbIsFolder)
709 OkHdl(*m_xOk_btn);
710 else
711 OpenURL(pData->maURL);
713 return true;
716 IMPL_LINK_NOARG( RemoteFilesDialog, SelectHdl, SvtFileView*, void )
718 SvtContentEntry* pData = m_xFileView->FirstSelected();
719 if (!pData)
720 return;
722 if( ( pData->mbIsFolder && ( m_eType == REMOTEDLG_TYPE_PATHDLG ) )
723 || ( !pData->mbIsFolder && ( m_eType == REMOTEDLG_TYPE_FILEDLG ) ) )
725 // url must contain user info, because we need this info in recent files entry
726 // (to fill user field in login box by default)
727 INetURLObject aURL( pData->maURL );
728 INetURLObject aCurrentURL( m_sLastServiceUrl );
729 aURL.SetUser( aCurrentURL.GetUser() );
731 m_sPath = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
733 m_xName_ed->set_text( aURL.GetLastName(INetURLObject::DecodeMechanism::WithCharset) );
735 else
737 if( m_eMode == REMOTEDLG_MODE_OPEN )
739 m_sPath.clear();
740 m_xName_ed->set_text( u""_ustr );
744 EnableControls();
747 IMPL_LINK_NOARG(RemoteFilesDialog, FileNameGetFocusHdl, weld::Widget&, void)
749 m_xFileView->SetNoSelection();
752 IMPL_LINK_NOARG(RemoteFilesDialog, FileNameModifyHdl, weld::Entry&, void)
754 m_xFileView->SetNoSelection();
755 if (!m_xOk_btn->get_sensitive())
756 EnableControls();
759 IMPL_LINK_NOARG( RemoteFilesDialog, SelectFilterHdl, weld::ComboBox&, void )
761 int nPos = m_xFilter_lb->get_active();
763 if( nPos != -1 && !m_aFilters[nPos].second.isEmpty() )
765 m_nCurrentFilter = nPos;
767 OUString sCurrentURL = m_xFileView->GetViewURL();
769 if( !sCurrentURL.isEmpty() && m_bIsConnected )
770 OpenURL( sCurrentURL );
774 IMPL_LINK(RemoteFilesDialog, TreeSelectHdl, weld::TreeView&, rBox, void)
776 OpenURL(rBox.get_selected_id());
777 m_xFileView->grab_focus();
780 IMPL_LINK(RemoteFilesDialog, SelectBreadcrumbHdl, Breadcrumb*, pPtr, bool)
782 OpenURL( pPtr->GetHdlURL() );
783 return true;
786 IMPL_LINK_NOARG ( RemoteFilesDialog, NewFolderHdl, weld::Button&, void )
788 m_xFileView->EndInplaceEditing();
790 // will be bound after InteractionHandler is enabled
791 SmartContent aContent;
792 aContent.enableDefaultInteractionHandler();
793 // now it can be bound
794 aContent.bindTo( m_xFileView->GetViewURL() );
795 if( !aContent.canCreateFolder() )
796 return;
798 OUString aTitle;
799 aContent.getTitle( aTitle );
800 QueryFolderNameDialog aDlg(m_xDialog.get(), aTitle, FpsResId(STR_SVT_NEW_FOLDER));
801 bool bHandled = false;
803 while( !bHandled )
805 if (aDlg.run() == RET_OK)
807 OUString aUrl = aContent.createFolder(aDlg.GetName());
808 if( !aUrl.isEmpty() )
810 m_xFileView->CreatedFolder(aUrl, aDlg.GetName());
811 bHandled = true;
814 else
815 bHandled = true;
819 IMPL_LINK_NOARG ( RemoteFilesDialog, OkHdl, weld::Button&, void )
821 OUString sUserSelectedPath;
823 // check if file/path exists
824 OUString sCurrentPath = m_xFileView->GetViewURL();
825 OUString sSelectedItem = m_xFileView->GetCurrentURL();
826 OUString sUserTypedName = m_xName_ed->get_text();
827 OUString sFileName;
828 // auto extension
829 if( m_eMode == REMOTEDLG_MODE_SAVE )
830 sFileName = AddFileExtension(sUserTypedName);
831 else
832 sFileName = sUserTypedName;
834 bool bFileDlg = ( m_eType == REMOTEDLG_TYPE_FILEDLG );
835 bool bSelected = ( m_xFileView->GetSelectionCount() > 0 );
837 if( !sCurrentPath.endsWith("/") )
838 sCurrentPath += "/";
840 if( !bSelected )
842 m_sPath = sCurrentPath + INetURLObject::encode(sFileName, INetURLObject::PART_FPATH, INetURLObject::EncodeMechanism::All);
843 sUserSelectedPath = sCurrentPath + INetURLObject::encode(sUserTypedName, INetURLObject::PART_FPATH, INetURLObject::EncodeMechanism::All);
845 else
847 if( m_eType == REMOTEDLG_TYPE_PATHDLG )
848 m_sPath = sCurrentPath;
849 else
850 m_sPath = sSelectedItem;
852 // url must contain user info, because we need this info in recent files entry
853 // (to fill user field in login box by default)
854 INetURLObject aURL( m_sPath );
855 INetURLObject aCurrentURL( m_sLastServiceUrl );
856 aURL.SetUser( aCurrentURL.GetUser() );
858 m_sPath = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
859 sUserSelectedPath = m_sPath;
862 bool bExists = false;
864 if( bFileDlg )
865 bExists = ContentIsDocument( m_sPath );
866 else
867 bExists = ContentIsFolder( m_sPath );
869 if( bExists )
871 if( m_eMode == REMOTEDLG_MODE_SAVE )
873 OUString sMsg = FpsResId( STR_SVT_ALREADYEXISTOVERWRITE );
874 sMsg = sMsg.replaceFirst("$filename$", sFileName);
875 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
876 VclMessageType::Question, VclButtonsType::YesNo, sMsg));
877 if (xBox->run() != RET_YES)
878 return;
881 else
883 if (ContentIsFolder(sUserSelectedPath))
885 OpenURL(sUserSelectedPath);
887 if (!bSelected)
888 m_xName_ed->grab_focus();
890 return;
893 if( m_eMode == REMOTEDLG_MODE_OPEN )
894 return;
897 m_xDialog->response(RET_OK);
900 IMPL_LINK_NOARG ( RemoteFilesDialog, CancelHdl, weld::Button&, void )
902 if( m_pCurrentAsyncAction.is() )
904 m_pCurrentAsyncAction->cancel();
905 onAsyncOperationFinished();
907 else
909 m_xDialog->response(RET_CANCEL);
913 // SvtFileDialog_Base
914 SvtFileView* RemoteFilesDialog::GetView()
916 return m_xFileView.get();
919 void RemoteFilesDialog::SetHasFilename( bool )
923 void RemoteFilesDialog::SetDenyList( const css::uno::Sequence< OUString >& rDenyList )
925 m_aDenyList = rDenyList;
926 m_xTreeView->SetDenyList( rDenyList );
929 const css::uno::Sequence< OUString >& RemoteFilesDialog::GetDenyList() const
931 return m_aDenyList;
934 void RemoteFilesDialog::SetStandardDir( const OUString& rStdDir )
936 m_sStdDir = rStdDir;
939 const OUString& RemoteFilesDialog::GetStandardDir() const
941 return m_sStdDir;
944 void RemoteFilesDialog::SetPath( const OUString& rNewURL )
946 m_sPath = rNewURL;
948 if( m_eMode == REMOTEDLG_MODE_SAVE )
950 INetURLObject aUrl( m_sPath );
951 OUString sFileName = aUrl.GetLastName( INetURLObject::DecodeMechanism::WithCharset );
953 m_xName_ed->set_text( sFileName );
957 OUString RemoteFilesDialog::getCurrentFileText() const
959 OUString sReturn;
960 if( m_xName_ed )
961 sReturn = m_xName_ed->get_text();
962 return sReturn;
965 void RemoteFilesDialog::setCurrentFileText( const OUString& rText, bool bSelectAll )
967 if (m_xName_ed)
969 m_xName_ed->set_text(rText);
970 if( bSelectAll )
971 m_xName_ed->select_region(0, -1);
975 void RemoteFilesDialog::AddFilterGroup(
976 const OUString& rFilter,
977 const css::uno::Sequence< css::beans::StringPair >& rFilters )
979 AddFilter( rFilter, OUString() );
980 const StringPair* pSubFilters = rFilters.getConstArray();
981 const StringPair* pSubFiltersEnd = pSubFilters + rFilters.getLength();
982 for ( ; pSubFilters != pSubFiltersEnd; ++pSubFilters )
983 AddFilter( pSubFilters->First, pSubFilters->Second );
986 OUString RemoteFilesDialog::GetCurFilter() const
988 OUString sFilter;
990 if (m_nCurrentFilter != -1)
992 sFilter = m_aFilters[m_nCurrentFilter].first;
995 return sFilter;
998 OUString RemoteFilesDialog::getCurFilter( ) const
1000 return GetCurFilter();
1003 void RemoteFilesDialog::SetCurFilter( const OUString& rFilter )
1005 DBG_ASSERT( !m_bIsInExecute, "SvtFileDialog::SetCurFilter: currently executing!" );
1007 // look for corresponding filter
1008 sal_uInt16 nPos = m_aFilters.size();
1010 while ( nPos-- )
1012 if ( m_aFilters[nPos].first == rFilter )
1014 m_nCurrentFilter = nPos;
1015 m_xFilter_lb->set_active( m_nCurrentFilter );
1016 break;
1021 void RemoteFilesDialog::FilterSelect()
1025 void RemoteFilesDialog::SetFileCallback( ::svt::IFilePickerListener * )
1029 void RemoteFilesDialog::onAsyncOperationStarted()
1031 DisableControls();
1034 void RemoteFilesDialog::onAsyncOperationFinished()
1036 m_pCurrentAsyncAction = nullptr;
1037 EnableControls();
1040 void RemoteFilesDialog::UpdateControls( const OUString& rURL )
1042 int nPos = GetSelectedServicePos();
1044 if( nPos >= 0 && m_bServiceChanged && rURL == m_aServices[nPos]->GetUrl() )
1046 OUString sURL = m_aServices[nPos]->GetUrl();
1048 m_xPath->SetRootName( m_sRootLabel );
1049 m_xTreeView->clear();
1051 m_xTreeView->InsertRootEntry(rURL, m_sRootLabel);
1053 m_xName_ed->grab_focus();
1055 m_sLastServiceUrl = sURL;
1057 m_bServiceChanged = false;
1060 m_xPath->SetURL( rURL );
1062 m_xTreeView->connect_changed(Link<weld::TreeView&,void>());
1064 // read cached data for this url and fill the tree
1065 const ::std::vector< SvtContentEntry > aContentFolders = m_xFileView->GetContent();
1066 ::std::vector< std::pair< OUString, OUString > > aFolders;
1068 m_xName_ed->ClearEntries();
1070 for(const auto & rFolder : aContentFolders)
1072 //WebDAV folders path ends in '/', so strip it
1073 OUString aFolderName = rFolder.maURL;
1074 if( rFolder.mbIsFolder && ( ( aFolderName.lastIndexOf( '/' ) + 1 ) == aFolderName.getLength() ) )
1075 aFolderName = aFolderName.copy( 0, aFolderName.getLength() - 1 );
1077 int nTitleStart = aFolderName.lastIndexOf( '/' );
1078 if( nTitleStart != -1 )
1080 OUString sTitle( INetURLObject::decode(
1081 aFolderName.subView( nTitleStart + 1 ),
1082 INetURLObject::DecodeMechanism::WithCharset ) );
1084 if( rFolder.mbIsFolder )
1086 aFolders.emplace_back( sTitle, aFolderName );
1089 // add entries to the autocompletion mechanism
1090 m_xName_ed->AddEntry( sTitle );
1094 m_xTreeView->FillTreeEntry( rURL, aFolders );
1096 m_xTreeView->connect_changed( LINK( this, RemoteFilesDialog, TreeSelectHdl ) );
1098 m_bIsConnected = true;
1099 EnableControls();
1102 void RemoteFilesDialog::EnableAutocompletion( bool )
1104 // This dialog contains Breadcrumb, not Edit
1107 const OUString& RemoteFilesDialog::GetPath()
1109 return m_sPath;
1112 std::vector<OUString> RemoteFilesDialog::GetPathList() const
1114 std::vector<OUString> aList;
1116 m_xFileView->selected_foreach([this, &aList](weld::TreeIter& rCurEntry){
1117 // url must contain user info, because we need this info in recent files entry
1118 // (to fill user field in login box by default)
1119 INetURLObject aURL(m_xFileView->GetURL(rCurEntry));
1120 INetURLObject aCurrentURL( m_sLastServiceUrl );
1121 aURL.SetUser( aCurrentURL.GetUser() );
1123 aList.push_back( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
1125 return false;
1128 if( aList.empty() && !m_sPath.isEmpty() )
1129 aList.push_back( m_sPath );
1131 return aList;
1134 bool RemoteFilesDialog::ContentIsFolder( const OUString& rURL )
1138 ::ucbhelper::Content content(rURL,
1139 ::utl::UCBContentHelper::getDefaultCommandEnvironment(),
1140 m_xContext);
1141 return content.isFolder();
1143 catch (css::uno::Exception const&)
1145 return false;
1149 bool RemoteFilesDialog::ContentIsDocument( const OUString& rURL )
1153 ::ucbhelper::Content content(rURL,
1154 ::utl::UCBContentHelper::getDefaultCommandEnvironment(),
1155 m_xContext);
1156 return content.isDocument();
1158 catch (css::uno::Exception const&)
1160 return false;
1164 sal_Int32 RemoteFilesDialog::getAvailableWidth()
1166 // This dialog doesn't contain preview
1167 return 0;
1170 sal_Int32 RemoteFilesDialog::getAvailableHeight()
1172 // This dialog doesn't contain preview
1173 return 0;
1176 void RemoteFilesDialog::setImage( const css::uno::Any& )
1178 // This dialog doesn't contain preview
1181 bool RemoteFilesDialog::getShowState()
1183 // This dialog doesn't contain preview
1184 return false;
1187 weld::Widget* RemoteFilesDialog::getControl( sal_Int16, bool) const
1189 return nullptr;
1192 void RemoteFilesDialog::enableControl( sal_Int16, bool )
1196 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */