Bump version to 24.04.3.4
[LibreOffice.git] / fpicker / source / office / RemoteFilesDialog.cxx
blob2b7dbd3d46dba96e758629d5791cfd64a5321669
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, "fps/ui/remotefilesdialog.ui", "RemoteFilesDialog" )
31 , m_xContext( comphelper::getProcessComponentContext() )
32 , m_xMasterPasswd( PasswordContainer::create( m_xContext ) )
33 , m_bIsInExecute( false )
34 , m_xOk_btn(m_xBuilder->weld_button("ok"))
35 , m_xCancel_btn(m_xBuilder->weld_button("cancel"))
36 , m_xManageServices(m_xBuilder->weld_menu_button("add_service_btn"))
37 , m_xServices_lb(m_xBuilder->weld_combo_box("services_lb"))
38 , m_xPathContainer(m_xBuilder->weld_container("breadcrumb_container"))
39 , m_xNewFolder(m_xBuilder->weld_button("new_folder"))
40 , m_xListView_btn(m_xBuilder->weld_toggle_button("list_view"))
41 , m_xIconView_btn(m_xBuilder->weld_toggle_button("icon_view"))
42 , m_xFilter_lb(m_xBuilder->weld_combo_box("filter_lb"))
43 , m_xName_ed(new AutocompleteEdit(m_xBuilder->weld_entry("filename")))
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("container");
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("fileview"),
91 m_xBuilder->weld_icon_view("iconview"),
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("foldertree"), 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( "UserData",
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("change_password", bEnable);
169 m_xManageServices->set_item_visible("edit_service", bEnable);
170 m_xManageServices->set_item_visible("delete_service", bEnable);
171 m_xManageServices->set_item_visible("change_password", 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 "Google Drive";
204 else if( sHost.startsWith( ALFRESCO_CLOUD_BASE_URL ) )
205 return "Alfresco Cloud";
206 else if( sHost.startsWith( ONEDRIVE_BASE_URL ) )
207 return "OneDrive";
209 return "CMIS";
211 case INetProtocol::Smb:
212 return "Windows Share";
213 case INetProtocol::File:
214 return "SSH";
215 case INetProtocol::Http:
216 return "WebDAV";
217 case INetProtocol::Https:
218 return "WebDAV";
219 case INetProtocol::Generic:
220 return "SSH";
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( "UserData" );
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 OUString sName = rFilter;
328 m_aFilters.emplace_back( rFilter, rType );
329 if (rType.isEmpty())
330 m_xFilter_lb->append_separator("");
331 else
332 m_xFilter_lb->append_text(sName);
334 if (m_xFilter_lb->get_active() == -1)
335 m_xFilter_lb->set_active(0);
338 void RemoteFilesDialog::OpenURL( OUString const & sURL )
340 if( !m_xFileView )
341 return;
343 DisableControls();
345 auto xWait = std::make_unique<weld::WaitObject>(m_xDialog.get());
347 if( !sURL.isEmpty() )
349 OUString sFilter = FILEDIALOG_FILTER_ALL;
351 if( m_nCurrentFilter != -1)
353 sFilter = m_aFilters[m_nCurrentFilter].second;
356 m_xFileView->EndInplaceEditing();
358 DBG_ASSERT( !m_pCurrentAsyncAction.is(), "SvtFileDialog::executeAsync: previous async action not yet finished!" );
360 m_pCurrentAsyncAction = new AsyncPickerAction( this, m_xFileView.get(), AsyncPickerAction::Action::eOpenURL );
362 // -1 timeout - sync
363 m_pCurrentAsyncAction->execute( sURL, sFilter, -1, -1, GetDenyList() );
365 if( m_eMode != REMOTEDLG_MODE_SAVE )
366 m_xName_ed->set_text( "" );
368 m_xFileView->grab_focus();
370 else
372 xWait.reset();
374 // content doesn't exist
375 ErrorHandler::HandleError( ERRCODE_IO_NOTEXISTS );
377 EnableControls();
381 OUString RemoteFilesDialog::AddFileExtension(const OUString& rFileName)
383 if (m_nCurrentFilter == -1)
384 return rFileName;
386 OUString sExt = m_aFilters[m_nCurrentFilter].second;
387 sal_Int32 nDotPos = rFileName.lastIndexOf( '.' );
389 if (nDotPos == -1)
390 return rFileName + sExt.subView( 1 ); // without '*'
392 return rFileName;
395 void RemoteFilesDialog::EnableControls()
397 if (m_xServices_lb->get_count() > 0)
399 m_xServices_lb->set_sensitive(true);
401 if (m_xServices_lb->get_active() != -1)
403 m_xManageServices->set_item_sensitive("change_password", false);
407 if( m_xMasterPasswd->isPersistentStoringAllowed() )
409 int nPos = GetSelectedServicePos();
411 if( nPos >= 0 )
413 OUString sUrl( m_aServices[nPos]->GetUrl() );
415 UrlRecord aURLEntries = m_xMasterPasswd->find( sUrl, Reference< XInteractionHandler>() );
417 if( aURLEntries.UserList.hasElements() )
419 m_xManageServices->set_item_sensitive("change_password", true);
424 catch( const Exception& )
428 else
429 m_xServices_lb->set_sensitive(false);
431 if( m_bIsConnected )
433 m_xFilter_lb->set_sensitive(true);
434 m_xName_ed->set_sensitive(true);
435 m_xContainer->set_sensitive(true);
436 m_xNewFolder->set_sensitive(true);
438 if (!m_xName_ed->get_text().isEmpty())
439 m_xOk_btn->set_sensitive(true);
440 else
441 m_xOk_btn->set_sensitive(false);
443 else
445 m_xFilter_lb->set_sensitive(false);
446 m_xName_ed->set_sensitive(false);
447 m_xContainer->set_sensitive(false);
448 m_xNewFolder->set_sensitive(false);
449 m_xOk_btn->set_sensitive(false);
452 m_xPath->EnableFields( true );
453 m_xManageServices->set_sensitive(true);
456 void RemoteFilesDialog::DisableControls()
458 m_xServices_lb->set_sensitive(false);
459 m_xFilter_lb->set_sensitive(false);
460 m_xManageServices->set_sensitive(false);
461 m_xName_ed->set_sensitive(false);
462 m_xContainer->set_sensitive(false);
463 m_xOk_btn->set_sensitive(false);
464 m_xPath->EnableFields( false );
466 m_xCancel_btn->set_sensitive(true);
469 void RemoteFilesDialog::SavePassword(const OUString& rURL, const OUString& rUser,
470 const OUString& rPassword, bool bPersistent)
472 if( rURL.isEmpty() || rUser.isEmpty() || rPassword.isEmpty() )
473 return;
477 if( !bPersistent ||
478 ( m_xMasterPasswd->isPersistentStoringAllowed()
479 && m_xMasterPasswd->authorizateWithMasterPassword( Reference< XInteractionHandler>() ) )
482 Reference< XInteractionHandler > xInteractionHandler =
483 InteractionHandler::createWithParent( m_xContext, nullptr );
485 Sequence<OUString> aPasswd { rPassword };
487 if( bPersistent )
488 m_xMasterPasswd->addPersistent(
489 rURL, rUser, aPasswd, xInteractionHandler );
490 else
491 m_xMasterPasswd->add( rURL, rUser, aPasswd, xInteractionHandler );
494 catch( const Exception& )
498 IMPL_LINK_NOARG ( RemoteFilesDialog, IconViewHdl, weld::Button&, void )
500 m_xListView_btn->set_active(false);
501 m_xFileView->SetViewMode( eIcon );
504 IMPL_LINK_NOARG ( RemoteFilesDialog, ListViewHdl, weld::Button&, void )
506 m_xIconView_btn->set_active(false);
507 m_xFileView->SetViewMode( eDetailedList );
510 void RemoteFilesDialog::AddService()
512 PlaceEditDialog aDlg(m_xDialog.get());
513 aDlg.ShowPasswordControl();
514 short aRetCode = aDlg.run();
516 switch( aRetCode )
518 case RET_OK :
520 ServicePtr newService = aDlg.GetPlace();
521 m_aServices.push_back( newService );
523 OUString sPassword = aDlg.GetPassword();
524 OUString sUser = aDlg.GetUser();
525 if( !sUser.isEmpty() && !sPassword.isEmpty() )
527 bool bPersistent = aDlg.IsRememberChecked();
528 SavePassword( newService->GetUrl(), sUser, sPassword, bPersistent );
531 OUString sPrefix = lcl_GetServiceType( newService );
533 if(!sPrefix.isEmpty())
534 sPrefix += ": ";
536 m_xServices_lb->append_text( sPrefix + newService->GetName() );
537 m_xServices_lb->set_active( m_xServices_lb->get_count() - 1 );
538 EnableExtraMenuItems(true);
539 SelectServiceHdl( *m_xServices_lb );
541 m_bIsUpdated = true;
543 EnableControls();
544 break;
546 case RET_CANCEL :
547 default :
548 // Do Nothing
549 break;
553 IMPL_LINK_NOARG( RemoteFilesDialog, SelectServiceHdl, weld::ComboBox&, void )
555 int nPos = GetSelectedServicePos();
557 if( nPos >= 0 )
559 OUString sURL = m_aServices[nPos]->GetUrl();
560 EnableExtraMenuItems(true);
562 m_bServiceChanged = true;
563 OpenURL( sURL );
567 IMPL_LINK ( RemoteFilesDialog, EditServiceMenuHdl, const OUString&, rIdent, void )
569 OUString sIdent(rIdent);
570 if( sIdent == "edit_service" && m_xServices_lb->get_count() > 0 )
572 int nSelected = m_xServices_lb->get_active();
573 int nPos = GetSelectedServicePos();
575 if( nPos >= 0 )
577 PlaceEditDialog aDlg(m_xDialog.get(), m_aServices[nPos]);
578 short aRetCode = aDlg.run();
580 switch( aRetCode )
582 case RET_OK :
584 ServicePtr pEditedService = aDlg.GetPlace();
586 m_aServices[nPos] = pEditedService;
587 m_xServices_lb->remove( nSelected );
589 OUString sPrefix = lcl_GetServiceType( pEditedService );
591 if(!sPrefix.isEmpty())
592 sPrefix += ": ";
594 m_xServices_lb->insert_text(nSelected, sPrefix + pEditedService->GetName());
595 m_xServices_lb->set_active( nSelected );
597 m_bIsUpdated = true;
598 break;
600 case RET_NO:
601 sIdent = "delete_service";
602 break;
603 case RET_CANCEL :
604 default :
605 // Do Nothing
606 break;
610 if( sIdent == "delete_service" && m_xServices_lb->get_count() > 0 )
612 int nSelected = m_xServices_lb->get_active();
613 int nPos = GetSelectedServicePos();
615 if( nPos >= 0 )
617 OUString sMsg = FpsResId( STR_SVT_DELETESERVICE );
618 sMsg = sMsg.replaceFirst( "$servicename$", m_xServices_lb->get_active_text() );
619 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
620 VclMessageType::Question, VclButtonsType::YesNo, sMsg));
621 if (xBox->run() == RET_YES)
623 // remove password
626 if( m_xMasterPasswd->isPersistentStoringAllowed() )
628 OUString sUrl( m_aServices[nPos]->GetUrl() );
630 Reference< XInteractionHandler > xInteractionHandler =
631 InteractionHandler::createWithParent( m_xContext, nullptr );
633 UrlRecord aURLEntries = m_xMasterPasswd->find( sUrl, xInteractionHandler );
635 if( aURLEntries.Url == sUrl && aURLEntries.UserList.hasElements() )
637 OUString sUserName = aURLEntries.UserList[0].UserName;
639 m_xMasterPasswd->removePersistent( sUrl, sUserName );
643 catch( const Exception& )
646 m_aServices.erase( m_aServices.begin() + nPos );
647 m_xServices_lb->remove( nSelected );
649 m_xServices_lb->set_active(-1);
650 EnableExtraMenuItems(false);
652 m_bIsUpdated = true;
654 m_bIsConnected = false;
655 EnableControls();
659 else if( sIdent == "change_password" )
663 if( m_xMasterPasswd->isPersistentStoringAllowed() && m_xMasterPasswd->authorizateWithMasterPassword( Reference< XInteractionHandler>() ) )
665 int nPos = GetSelectedServicePos();
667 if( nPos >= 0 )
669 OUString sUrl( m_aServices[nPos]->GetUrl() );
671 Reference< XInteractionHandler > xInteractionHandler =
672 InteractionHandler::createWithParent( m_xContext, nullptr );
674 UrlRecord aURLEntries = m_xMasterPasswd->find( sUrl, xInteractionHandler );
676 if( aURLEntries.Url == sUrl && aURLEntries.UserList.hasElements() )
678 OUString sUserName = aURLEntries.UserList[0].UserName;
680 rtl::Reference<::comphelper::SimplePasswordRequest> pPasswordRequest
681 = new ::comphelper::SimplePasswordRequest;
683 xInteractionHandler->handle( pPasswordRequest );
685 if ( pPasswordRequest->isPassword() )
687 OUString aNewPass = pPasswordRequest->getPassword();
688 Sequence<OUString> aPasswd { aNewPass };
690 m_xMasterPasswd->addPersistent(
691 sUrl, sUserName, aPasswd, xInteractionHandler );
697 catch( const Exception& )
700 else if( sIdent == "add_service" )
701 AddService();
703 EnableControls();
706 IMPL_LINK_NOARG( RemoteFilesDialog, DoubleClickHdl, SvtFileView*, bool )
708 SvtContentEntry* pData = m_xFileView->FirstSelected();
709 if (pData)
711 if (!pData->mbIsFolder)
712 OkHdl(*m_xOk_btn);
713 else
714 OpenURL(pData->maURL);
716 return true;
719 IMPL_LINK_NOARG( RemoteFilesDialog, SelectHdl, SvtFileView*, void )
721 SvtContentEntry* pData = m_xFileView->FirstSelected();
722 if (!pData)
723 return;
725 if( ( pData->mbIsFolder && ( m_eType == REMOTEDLG_TYPE_PATHDLG ) )
726 || ( !pData->mbIsFolder && ( m_eType == REMOTEDLG_TYPE_FILEDLG ) ) )
728 // url must contain user info, because we need this info in recent files entry
729 // (to fill user field in login box by default)
730 INetURLObject aURL( pData->maURL );
731 INetURLObject aCurrentURL( m_sLastServiceUrl );
732 aURL.SetUser( aCurrentURL.GetUser() );
734 m_sPath = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
736 m_xName_ed->set_text( aURL.GetLastName(INetURLObject::DecodeMechanism::WithCharset) );
738 else
740 if( m_eMode == REMOTEDLG_MODE_OPEN )
742 m_sPath.clear();
743 m_xName_ed->set_text( "" );
747 EnableControls();
750 IMPL_LINK_NOARG(RemoteFilesDialog, FileNameGetFocusHdl, weld::Widget&, void)
752 m_xFileView->SetNoSelection();
755 IMPL_LINK_NOARG(RemoteFilesDialog, FileNameModifyHdl, weld::Entry&, void)
757 m_xFileView->SetNoSelection();
758 if (!m_xOk_btn->get_sensitive())
759 EnableControls();
762 IMPL_LINK_NOARG( RemoteFilesDialog, SelectFilterHdl, weld::ComboBox&, void )
764 int nPos = m_xFilter_lb->get_active();
766 if( nPos != -1 && !m_aFilters[nPos].second.isEmpty() )
768 m_nCurrentFilter = nPos;
770 OUString sCurrentURL = m_xFileView->GetViewURL();
772 if( !sCurrentURL.isEmpty() && m_bIsConnected )
773 OpenURL( sCurrentURL );
777 IMPL_LINK(RemoteFilesDialog, TreeSelectHdl, weld::TreeView&, rBox, void)
779 OpenURL(rBox.get_selected_id());
780 m_xFileView->grab_focus();
783 IMPL_LINK(RemoteFilesDialog, SelectBreadcrumbHdl, Breadcrumb*, pPtr, bool)
785 OpenURL( pPtr->GetHdlURL() );
786 return true;
789 IMPL_LINK_NOARG ( RemoteFilesDialog, NewFolderHdl, weld::Button&, void )
791 m_xFileView->EndInplaceEditing();
793 // will be bound after InteractionHandler is enabled
794 SmartContent aContent;
795 aContent.enableDefaultInteractionHandler();
796 // now it can be bound
797 aContent.bindTo( m_xFileView->GetViewURL() );
798 if( !aContent.canCreateFolder() )
799 return;
801 OUString aTitle;
802 aContent.getTitle( aTitle );
803 QueryFolderNameDialog aDlg(m_xDialog.get(), aTitle, FpsResId(STR_SVT_NEW_FOLDER));
804 bool bHandled = false;
806 while( !bHandled )
808 if (aDlg.run() == RET_OK)
810 OUString aUrl = aContent.createFolder(aDlg.GetName());
811 if( !aUrl.isEmpty() )
813 m_xFileView->CreatedFolder(aUrl, aDlg.GetName());
814 bHandled = true;
817 else
818 bHandled = true;
822 IMPL_LINK_NOARG ( RemoteFilesDialog, OkHdl, weld::Button&, void )
824 OUString sUserSelectedPath;
826 // check if file/path exists
827 OUString sCurrentPath = m_xFileView->GetViewURL();
828 OUString sSelectedItem = m_xFileView->GetCurrentURL();
829 OUString sUserTypedName = m_xName_ed->get_text();
830 OUString sFileName;
831 // auto extension
832 if( m_eMode == REMOTEDLG_MODE_SAVE )
833 sFileName = AddFileExtension(sUserTypedName);
834 else
835 sFileName = sUserTypedName;
837 bool bFileDlg = ( m_eType == REMOTEDLG_TYPE_FILEDLG );
838 bool bSelected = ( m_xFileView->GetSelectionCount() > 0 );
840 if( !sCurrentPath.endsWith("/") )
841 sCurrentPath += "/";
843 if( !bSelected )
845 m_sPath = sCurrentPath + INetURLObject::encode(sFileName, INetURLObject::PART_FPATH, INetURLObject::EncodeMechanism::All);
846 sUserSelectedPath = sCurrentPath + INetURLObject::encode(sUserTypedName, INetURLObject::PART_FPATH, INetURLObject::EncodeMechanism::All);
848 else
850 if( m_eType == REMOTEDLG_TYPE_PATHDLG )
851 m_sPath = sCurrentPath;
852 else
853 m_sPath = sSelectedItem;
855 // url must contain user info, because we need this info in recent files entry
856 // (to fill user field in login box by default)
857 INetURLObject aURL( m_sPath );
858 INetURLObject aCurrentURL( m_sLastServiceUrl );
859 aURL.SetUser( aCurrentURL.GetUser() );
861 m_sPath = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
862 sUserSelectedPath = m_sPath;
865 bool bExists = false;
867 if( bFileDlg )
868 bExists = ContentIsDocument( m_sPath );
869 else
870 bExists = ContentIsFolder( m_sPath );
872 if( bExists )
874 if( m_eMode == REMOTEDLG_MODE_SAVE )
876 OUString sMsg = FpsResId( STR_SVT_ALREADYEXISTOVERWRITE );
877 sMsg = sMsg.replaceFirst("$filename$", sFileName);
878 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
879 VclMessageType::Question, VclButtonsType::YesNo, sMsg));
880 if (xBox->run() != RET_YES)
881 return;
884 else
886 if (ContentIsFolder(sUserSelectedPath))
888 OpenURL(sUserSelectedPath);
890 if (!bSelected)
891 m_xName_ed->grab_focus();
893 return;
896 if( m_eMode == REMOTEDLG_MODE_OPEN )
897 return;
900 m_xDialog->response(RET_OK);
903 IMPL_LINK_NOARG ( RemoteFilesDialog, CancelHdl, weld::Button&, void )
905 if( m_pCurrentAsyncAction.is() )
907 m_pCurrentAsyncAction->cancel();
908 onAsyncOperationFinished();
910 else
912 m_xDialog->response(RET_CANCEL);
916 // SvtFileDialog_Base
917 SvtFileView* RemoteFilesDialog::GetView()
919 return m_xFileView.get();
922 void RemoteFilesDialog::SetHasFilename( bool )
926 void RemoteFilesDialog::SetDenyList( const css::uno::Sequence< OUString >& rDenyList )
928 m_aDenyList = rDenyList;
929 m_xTreeView->SetDenyList( rDenyList );
932 const css::uno::Sequence< OUString >& RemoteFilesDialog::GetDenyList() const
934 return m_aDenyList;
937 void RemoteFilesDialog::SetStandardDir( const OUString& rStdDir )
939 m_sStdDir = rStdDir;
942 const OUString& RemoteFilesDialog::GetStandardDir() const
944 return m_sStdDir;
947 void RemoteFilesDialog::SetPath( const OUString& rNewURL )
949 m_sPath = rNewURL;
951 if( m_eMode == REMOTEDLG_MODE_SAVE )
953 INetURLObject aUrl( m_sPath );
954 OUString sFileName = aUrl.GetLastName( INetURLObject::DecodeMechanism::WithCharset );
956 m_xName_ed->set_text( sFileName );
960 OUString RemoteFilesDialog::getCurrentFileText() const
962 OUString sReturn;
963 if( m_xName_ed )
964 sReturn = m_xName_ed->get_text();
965 return sReturn;
968 void RemoteFilesDialog::setCurrentFileText( const OUString& rText, bool bSelectAll )
970 if (m_xName_ed)
972 m_xName_ed->set_text(rText);
973 if( bSelectAll )
974 m_xName_ed->select_region(0, -1);
978 void RemoteFilesDialog::AddFilterGroup(
979 const OUString& rFilter,
980 const css::uno::Sequence< css::beans::StringPair >& rFilters )
982 AddFilter( rFilter, OUString() );
983 const StringPair* pSubFilters = rFilters.getConstArray();
984 const StringPair* pSubFiltersEnd = pSubFilters + rFilters.getLength();
985 for ( ; pSubFilters != pSubFiltersEnd; ++pSubFilters )
986 AddFilter( pSubFilters->First, pSubFilters->Second );
989 OUString RemoteFilesDialog::GetCurFilter() const
991 OUString sFilter;
993 if (m_nCurrentFilter != -1)
995 sFilter = m_aFilters[m_nCurrentFilter].first;
998 return sFilter;
1001 OUString RemoteFilesDialog::getCurFilter( ) const
1003 return GetCurFilter();
1006 void RemoteFilesDialog::SetCurFilter( const OUString& rFilter )
1008 DBG_ASSERT( !m_bIsInExecute, "SvtFileDialog::SetCurFilter: currently executing!" );
1010 // look for corresponding filter
1011 sal_uInt16 nPos = m_aFilters.size();
1013 while ( nPos-- )
1015 if ( m_aFilters[nPos].first == rFilter )
1017 m_nCurrentFilter = nPos;
1018 m_xFilter_lb->set_active( m_nCurrentFilter );
1019 break;
1024 void RemoteFilesDialog::FilterSelect()
1028 void RemoteFilesDialog::SetFileCallback( ::svt::IFilePickerListener * )
1032 void RemoteFilesDialog::onAsyncOperationStarted()
1034 DisableControls();
1037 void RemoteFilesDialog::onAsyncOperationFinished()
1039 m_pCurrentAsyncAction = nullptr;
1040 EnableControls();
1043 void RemoteFilesDialog::UpdateControls( const OUString& rURL )
1045 int nPos = GetSelectedServicePos();
1047 if( nPos >= 0 && m_bServiceChanged && rURL == m_aServices[nPos]->GetUrl() )
1049 OUString sURL = m_aServices[nPos]->GetUrl();
1051 m_xPath->SetRootName( m_sRootLabel );
1052 m_xTreeView->clear();
1054 m_xTreeView->InsertRootEntry(rURL, m_sRootLabel);
1056 m_xName_ed->grab_focus();
1058 m_sLastServiceUrl = sURL;
1060 m_bServiceChanged = false;
1063 m_xPath->SetURL( rURL );
1065 m_xTreeView->connect_changed(Link<weld::TreeView&,void>());
1067 // read cached data for this url and fill the tree
1068 const ::std::vector< SvtContentEntry >& rFolders = m_xFileView->GetContent();
1069 ::std::vector< std::pair< OUString, OUString > > aFolders;
1071 m_xName_ed->ClearEntries();
1073 for(const auto & rFolder : rFolders)
1075 //WebDAV folders path ends in '/', so strip it
1076 OUString aFolderName = rFolder.maURL;
1077 if( rFolder.mbIsFolder && ( ( aFolderName.lastIndexOf( '/' ) + 1 ) == aFolderName.getLength() ) )
1078 aFolderName = aFolderName.copy( 0, aFolderName.getLength() - 1 );
1080 int nTitleStart = aFolderName.lastIndexOf( '/' );
1081 if( nTitleStart != -1 )
1083 OUString sTitle( INetURLObject::decode(
1084 aFolderName.subView( nTitleStart + 1 ),
1085 INetURLObject::DecodeMechanism::WithCharset ) );
1087 if( rFolder.mbIsFolder )
1089 aFolders.emplace_back( sTitle, aFolderName );
1092 // add entries to the autocompletion mechanism
1093 m_xName_ed->AddEntry( sTitle );
1097 m_xTreeView->FillTreeEntry( rURL, aFolders );
1099 m_xTreeView->connect_changed( LINK( this, RemoteFilesDialog, TreeSelectHdl ) );
1101 m_bIsConnected = true;
1102 EnableControls();
1105 void RemoteFilesDialog::EnableAutocompletion( bool )
1107 // This dialog contains Breadcrumb, not Edit
1110 const OUString& RemoteFilesDialog::GetPath()
1112 return m_sPath;
1115 std::vector<OUString> RemoteFilesDialog::GetPathList() const
1117 std::vector<OUString> aList;
1119 m_xFileView->selected_foreach([this, &aList](weld::TreeIter& rCurEntry){
1120 // url must contain user info, because we need this info in recent files entry
1121 // (to fill user field in login box by default)
1122 INetURLObject aURL(m_xFileView->GetURL(rCurEntry));
1123 INetURLObject aCurrentURL( m_sLastServiceUrl );
1124 aURL.SetUser( aCurrentURL.GetUser() );
1126 aList.push_back( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
1128 return false;
1131 if( aList.empty() && !m_sPath.isEmpty() )
1132 aList.push_back( m_sPath );
1134 return aList;
1137 bool RemoteFilesDialog::ContentIsFolder( const OUString& rURL )
1141 ::ucbhelper::Content content(rURL,
1142 ::utl::UCBContentHelper::getDefaultCommandEnvironment(),
1143 m_xContext);
1144 return content.isFolder();
1146 catch (css::uno::Exception const&)
1148 return false;
1152 bool RemoteFilesDialog::ContentIsDocument( const OUString& rURL )
1156 ::ucbhelper::Content content(rURL,
1157 ::utl::UCBContentHelper::getDefaultCommandEnvironment(),
1158 m_xContext);
1159 return content.isDocument();
1161 catch (css::uno::Exception const&)
1163 return false;
1167 sal_Int32 RemoteFilesDialog::getAvailableWidth()
1169 // This dialog doesn't contain preview
1170 return 0;
1173 sal_Int32 RemoteFilesDialog::getAvailableHeight()
1175 // This dialog doesn't contain preview
1176 return 0;
1179 void RemoteFilesDialog::setImage( const css::uno::Any& )
1181 // This dialog doesn't contain preview
1184 bool RemoteFilesDialog::getShowState()
1186 // This dialog doesn't contain preview
1187 return false;
1190 weld::Widget* RemoteFilesDialog::getControl( sal_Int16, bool) const
1192 return nullptr;
1195 void RemoteFilesDialog::enableControl( sal_Int16, bool )
1199 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */