LibreOffice Module fpicker (master) 1
RemoteFilesDialog.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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 */
9
10#include <config_oauth2.h>
11
12#include "fpsmartcontent.hxx"
13#include "QueryFolderName.hxx"
14#include "RemoteFilesDialog.hxx"
16#include <fpicker/strings.hrc>
17#include <strings.hrc>
19#include <com/sun/star/task/InteractionHandler.hpp>
20#include <com/sun/star/task/PasswordContainer.hpp>
22#include <tools/debug.hxx>
24#include <vcl/errinf.hxx>
25#include <officecfg/Office/Common.hxx>
26
27using namespace ::svt;
28
30 : SvtFileDialog_Base( pParent, "fps/ui/remotefilesdialog.ui", "RemoteFilesDialog" )
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")))
44{
47 bool bMultiselection = bool( nBits & PickerFlags::MultiSelection );
48 m_bIsUpdated = false;
49 m_bIsConnected = false;
50 m_bServiceChanged = false;
52
53 m_xName_ed->show();
54
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);
57
58 m_xFilter_lb->set_sensitive(false);
59 m_xName_ed->set_sensitive(false);
60 m_xNewFolder->set_sensitive(false);
61
63 {
64 m_xNewFolder->hide();
65 }
66 else
67 {
68 m_xOk_btn->set_label(FpsResId(STR_EXPLORERFILE_BUTTONSAVE));
69 m_xNewFolder->connect_clicked( LINK( this, RemoteFilesDialog, NewFolderHdl ) );
70 }
71
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 ) );
75
76 m_xOk_btn->set_sensitive(false);
77
78 m_xOk_btn->connect_clicked( LINK( this, RemoteFilesDialog, OkHdl ) );
79 m_xCancel_btn->connect_clicked( LINK( this, RemoteFilesDialog, CancelHdl ) );
80
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 ) );
85
86 m_xContainer = m_xBuilder->weld_container("container");
87 m_xContainer->set_size_request(m_xContainer->get_approximate_digit_width() * 82, -1);
88
89 m_xFileView.reset(new SvtFileView(m_xDialog.get(),
90 m_xBuilder->weld_tree_view("fileview"),
91 m_xBuilder->weld_icon_view("iconview"),
93 bMultiselection, false));
94
95 m_xFileView->SetDoubleClickHdl( LINK( this, RemoteFilesDialog, DoubleClickHdl ) );
96 m_xFileView->SetSelectHdl( LINK( this, RemoteFilesDialog, SelectHdl ) );
97 m_xFileView->EnableDelete( true );
98
99 m_xTreeView.reset(new FolderTree(m_xBuilder->weld_tree_view("foldertree"), m_xDialog.get()));
100 m_xTreeView->connect_changed(LINK(this, RemoteFilesDialog, TreeSelectHdl));
101
102 m_xContainer->set_sensitive(false);
103
104 m_sIniKey = "RemoteFilesDialog";
105 InitSize();
106
107 m_xName_ed->connect_focus_in(LINK(this, RemoteFilesDialog, FileNameGetFocusHdl));
108 m_xName_ed->connect_changed(LINK(this, RemoteFilesDialog, FileNameModifyHdl));
109
110 m_xManageServices->connect_selected(LINK(this, RemoteFilesDialog, EditServiceMenuHdl));
111
113
114 m_xServices_lb->connect_changed( LINK( this, RemoteFilesDialog, SelectServiceHdl ) );
115
116 m_xFilter_lb->connect_changed( LINK( this, RemoteFilesDialog, SelectFilterHdl ) );
117}
118
120{
121 m_xFileView->SetSelectHdl(Link<SvtFileView*,void>());
122
123 // save window state
124 if( !m_sIniKey.isEmpty() )
125 {
126 SvtViewOptions aDlgOpt( EViewType::Dialog, m_sIniKey );
127 aDlgOpt.SetWindowState(m_xDialog->get_window_state(vcl::WindowDataMask::All));
128
129 Size aSize(m_xDialog->get_size());
130
131 OUString sSize = OUString::number( aSize.Width() ) + "|";
132 sSize = sSize + OUString::number( aSize.Height() ) + "|";
133
134 OUString sUserData = m_xFileView->GetConfigString();
135 aDlgOpt.SetUserItem( "UserData",
136 Any( sSize + sUserData ) );
137 }
138
139 // save services
140 std::shared_ptr< comphelper::ConfigurationChanges > batch( comphelper::ConfigurationChanges::create() );
141
142 officecfg::Office::Common::Misc::FilePickerLastService::set( m_sLastServiceUrl, batch );
143
144 if( m_bIsUpdated )
145 {
146 Sequence< OUString > placesUrlsList( m_aServices.size() );
147 auto placesUrlsListRange = asNonConstRange(placesUrlsList);
148 Sequence< OUString > placesNamesList( m_aServices.size() );
149 auto placesNamesListRange = asNonConstRange(placesNamesList);
150
151 int i = 0;
152 for (auto const& service : m_aServices)
153 {
154 placesUrlsListRange[i] = service->GetUrl();
155 placesNamesListRange[i] = service->GetName();
156 ++i;
157 }
158
159 officecfg::Office::Common::Misc::FilePickerPlacesUrls::set( placesUrlsList, batch );
160 officecfg::Office::Common::Misc::FilePickerPlacesNames::set( placesNamesList, batch );
161 }
162
163 batch->commit();
164}
165
167{
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);
172}
173
175{
176 if (m_xServices_lb->get_count() > 0)
177 {
178 m_xDialog->show();
179 SelectServiceHdl(*m_xServices_lb);
180 }
181 if (!m_bIsConnected)
182 {
183 m_xServices_lb->set_active(-1);
185 }
186
187 m_bIsInExecute = true;
188 short nRet = SvtFileDialog_Base::run();
189 m_bIsInExecute = false;
190 return nRet;
191}
192
193static OUString lcl_GetServiceType( const ServicePtr& pService )
194{
195 INetProtocol aProtocol = pService->GetUrlObject().GetProtocol();
196 switch( aProtocol )
197 {
198 case INetProtocol::Ftp:
199 return "FTP";
200 case INetProtocol::Cmis:
201 {
202 OUString sHost = pService->GetUrlObject().GetHost( INetURLObject::DecodeMechanism::WithCharset );
203
204 if( sHost.startsWith( GDRIVE_BASE_URL ) )
205 return "Google Drive";
206 else if( sHost.startsWith( ALFRESCO_CLOUD_BASE_URL ) )
207 return "Alfresco Cloud";
208 else if( sHost.startsWith( ONEDRIVE_BASE_URL ) )
209 return "OneDrive";
210
211 return "CMIS";
212 }
213 case INetProtocol::Smb:
214 return "Windows Share";
215 case INetProtocol::File:
216 return "SSH";
217 case INetProtocol::Http:
218 return "WebDAV";
219 case INetProtocol::Https:
220 return "WebDAV";
221 case INetProtocol::Generic:
222 return "SSH";
223 default:
224 return OUString();
225 }
226}
227
229{
230 if( m_sIniKey.isEmpty() )
231 return;
232
233 // initialize from config
234 SvtViewOptions aDlgOpt( EViewType::Dialog, m_sIniKey );
235
236 if( !aDlgOpt.Exists() )
237 return;
238
239 m_xDialog->set_window_state(aDlgOpt.GetWindowState());
240
241 Any aUserData = aDlgOpt.GetUserItem( "UserData" );
242 OUString sCfgStr;
243 if( aUserData >>= sCfgStr )
244 {
245 sal_Int32 nPos1{ sCfgStr.indexOf('|') };
246 if (nPos1<0)
247 return;
248 sal_Int32 nPos2{ sCfgStr.indexOf('|', nPos1+1 ) };
249 if (nPos2<0)
250 return;
251 m_xFileView->SetConfigString( sCfgStr.subView(nPos2+1) );
252 }
253}
254
256{
257 m_xServices_lb->clear();
258 m_aServices.clear();
259
260 // Load from user settings
261 Sequence< OUString > placesUrlsList( officecfg::Office::Common::Misc::FilePickerPlacesUrls::get() );
262 Sequence< OUString > placesNamesList( officecfg::Office::Common::Misc::FilePickerPlacesNames::get() );
263
264 unsigned int nPos = 0;
265 unsigned int i = 0;
266
267 m_sLastServiceUrl = officecfg::Office::Common::Misc::FilePickerLastService::get();
268
269 for( sal_Int32 nPlace = 0; nPlace < placesUrlsList.getLength() && nPlace < placesNamesList.getLength(); ++nPlace )
270 {
271 ServicePtr pService = std::make_shared<Place>( placesNamesList[nPlace], placesUrlsList[nPlace], true );
272 m_aServices.push_back( pService );
273
274 // Add to the listbox only remote services, not local bookmarks
275 if( !pService->IsLocal() )
276 {
277 OUString sPrefix = lcl_GetServiceType( pService );
278
279 if( !sPrefix.isEmpty() )
280 sPrefix += ": ";
281
282 if( placesUrlsList[nPlace] == m_sLastServiceUrl )
283 nPos = i;
284
285 m_xServices_lb->append_text(sPrefix + placesNamesList[nPlace]);
286
287 i++;
288 }
289 }
290
291 if (m_xServices_lb->get_count() > 0)
292 {
293 m_xServices_lb->set_active(nPos);
295 }
296 else
298
300}
301
303{
304 if( m_aServices.empty() )
305 return -1;
306
307 int nPos = 0;
308 int i = -1;
309
310 int nSelected = m_xServices_lb->get_active();
311
312 int nServices = static_cast<int>(m_aServices.size());
313 while( nPos < nServices )
314 {
315 while( (nPos < nServices) && m_aServices[nPos]->IsLocal() )
316 nPos++;
317 i++;
318 if( i == nSelected )
319 break;
320 nPos++;
321 }
322
323 return nPos;
324}
325
326void RemoteFilesDialog::AddFilter( const OUString& rFilter, const OUString& rType )
327{
328 OUString sName = rFilter;
329
330 m_aFilters.emplace_back( rFilter, rType );
331 if (rType.isEmpty())
332 m_xFilter_lb->append_separator("");
333 else
334 m_xFilter_lb->append_text(sName);
335
336 if (m_xFilter_lb->get_active() == -1)
337 m_xFilter_lb->set_active(0);
338}
339
340void RemoteFilesDialog::OpenURL( OUString const & sURL )
341{
342 if( !m_xFileView )
343 return;
344
346
347 auto xWait = std::make_unique<weld::WaitObject>(m_xDialog.get());
348
349 if( !sURL.isEmpty() )
350 {
351 OUString sFilter = FILEDIALOG_FILTER_ALL;
352
353 if( m_nCurrentFilter != -1)
354 {
355 sFilter = m_aFilters[m_nCurrentFilter].second;
356 }
357
358 m_xFileView->EndInplaceEditing();
359
360 DBG_ASSERT( !m_pCurrentAsyncAction.is(), "SvtFileDialog::executeAsync: previous async action not yet finished!" );
361
362 m_pCurrentAsyncAction = new AsyncPickerAction( this, m_xFileView.get(), AsyncPickerAction::Action::eOpenURL );
363
364 // -1 timeout - sync
365 m_pCurrentAsyncAction->execute( sURL, sFilter, -1, -1, GetDenyList() );
366
368 m_xName_ed->set_text( "" );
369
370 m_xFileView->grab_focus();
371 }
372 else
373 {
374 xWait.reset();
375
376 // content doesn't exist
378
380 }
381}
382
383OUString RemoteFilesDialog::AddFileExtension(const OUString& rFileName)
384{
385 if (m_nCurrentFilter == -1)
386 return rFileName;
387
388 OUString sExt = m_aFilters[m_nCurrentFilter].second;
389 sal_Int32 nDotPos = rFileName.lastIndexOf( '.' );
390
391 if (nDotPos == -1)
392 return rFileName + sExt.subView( 1 ); // without '*'
393
394 return rFileName;
395}
396
398{
399 if (m_xServices_lb->get_count() > 0)
400 {
401 m_xServices_lb->set_sensitive(true);
402
403 if (m_xServices_lb->get_active() != -1)
404 {
405 m_xManageServices->set_item_sensitive("change_password", false);
406
407 try
408 {
409 if( m_xMasterPasswd->isPersistentStoringAllowed() )
410 {
412
413 if( nPos >= 0 )
414 {
415 OUString sUrl( m_aServices[nPos]->GetUrl() );
416
417 UrlRecord aURLEntries = m_xMasterPasswd->find( sUrl, Reference< XInteractionHandler>() );
418
419 if( aURLEntries.UserList.hasElements() )
420 {
421 m_xManageServices->set_item_sensitive("change_password", true);
422 }
423 }
424 }
425 }
426 catch( const Exception& )
427 {}
428 }
429 }
430 else
431 m_xServices_lb->set_sensitive(false);
432
433 if( m_bIsConnected )
434 {
435 m_xFilter_lb->set_sensitive(true);
436 m_xName_ed->set_sensitive(true);
437 m_xContainer->set_sensitive(true);
438 m_xNewFolder->set_sensitive(true);
439
440 if (!m_xName_ed->get_text().isEmpty())
441 m_xOk_btn->set_sensitive(true);
442 else
443 m_xOk_btn->set_sensitive(false);
444 }
445 else
446 {
447 m_xFilter_lb->set_sensitive(false);
448 m_xName_ed->set_sensitive(false);
449 m_xContainer->set_sensitive(false);
450 m_xNewFolder->set_sensitive(false);
451 m_xOk_btn->set_sensitive(false);
452 }
453
454 m_xPath->EnableFields( true );
455 m_xManageServices->set_sensitive(true);
456}
457
459{
460 m_xServices_lb->set_sensitive(false);
461 m_xFilter_lb->set_sensitive(false);
462 m_xManageServices->set_sensitive(false);
463 m_xName_ed->set_sensitive(false);
464 m_xContainer->set_sensitive(false);
465 m_xOk_btn->set_sensitive(false);
466 m_xPath->EnableFields( false );
467
468 m_xCancel_btn->set_sensitive(true);
469}
470
471void RemoteFilesDialog::SavePassword(const OUString& rURL, const OUString& rUser,
472 const OUString& rPassword, bool bPersistent)
473{
474 if( rURL.isEmpty() || rUser.isEmpty() || rPassword.isEmpty() )
475 return;
476
477 try
478 {
479 if( !bPersistent ||
480 ( m_xMasterPasswd->isPersistentStoringAllowed()
481 && m_xMasterPasswd->authorizateWithMasterPassword( Reference< XInteractionHandler>() ) )
482 )
483 {
484 Reference< XInteractionHandler > xInteractionHandler =
485 InteractionHandler::createWithParent( m_xContext, nullptr );
486
487 Sequence<OUString> aPasswd { rPassword };
488
489 if( bPersistent )
490 m_xMasterPasswd->addPersistent(
491 rURL, rUser, aPasswd, xInteractionHandler );
492 else
493 m_xMasterPasswd->add( rURL, rUser, aPasswd, xInteractionHandler );
494 }
495 }
496 catch( const Exception& )
497 {}
498}
499
501{
502 m_xListView_btn->set_active(false);
503 m_xFileView->SetViewMode( eIcon );
504}
505
507{
508 m_xIconView_btn->set_active(false);
509 m_xFileView->SetViewMode( eDetailedList );
510}
511
513{
514 PlaceEditDialog aDlg(m_xDialog.get());
515 aDlg.ShowPasswordControl();
516 short aRetCode = aDlg.run();
517
518 switch( aRetCode )
519 {
520 case RET_OK :
521 {
522 ServicePtr newService = aDlg.GetPlace();
523 m_aServices.push_back( newService );
524
525 OUString sPassword = aDlg.GetPassword();
526 OUString sUser = aDlg.GetUser();
527 if( !sUser.isEmpty() && !sPassword.isEmpty() )
528 {
529 bool bPersistent = aDlg.IsRememberChecked();
530 SavePassword( newService->GetUrl(), sUser, sPassword, bPersistent );
531 }
532
533 OUString sPrefix = lcl_GetServiceType( newService );
534
535 if(!sPrefix.isEmpty())
536 sPrefix += ": ";
537
538 m_xServices_lb->append_text( sPrefix + newService->GetName() );
539 m_xServices_lb->set_active( m_xServices_lb->get_count() - 1 );
541 SelectServiceHdl( *m_xServices_lb );
542
543 m_bIsUpdated = true;
544
546 break;
547 }
548 case RET_CANCEL :
549 default :
550 // Do Nothing
551 break;
552 }
553}
554
556{
557 int nPos = GetSelectedServicePos();
558
559 if( nPos >= 0 )
560 {
561 OUString sURL = m_aServices[nPos]->GetUrl();
562 EnableExtraMenuItems(true);
563
564 m_bServiceChanged = true;
565 OpenURL( sURL );
566 }
567}
568
569IMPL_LINK ( RemoteFilesDialog, EditServiceMenuHdl, const OUString&, rIdent, void )
570{
571 OUString sIdent(rIdent);
572 if( sIdent == "edit_service" && m_xServices_lb->get_count() > 0 )
573 {
574 int nSelected = m_xServices_lb->get_active();
575 int nPos = GetSelectedServicePos();
576
577 if( nPos >= 0 )
578 {
579 PlaceEditDialog aDlg(m_xDialog.get(), m_aServices[nPos]);
580 short aRetCode = aDlg.run();
581
582 switch( aRetCode )
583 {
584 case RET_OK :
585 {
586 ServicePtr pEditedService = aDlg.GetPlace();
587
588 m_aServices[nPos] = pEditedService;
589 m_xServices_lb->remove( nSelected );
590
591 OUString sPrefix = lcl_GetServiceType( pEditedService );
592
593 if(!sPrefix.isEmpty())
594 sPrefix += ": ";
595
596 m_xServices_lb->insert_text(nSelected, sPrefix + pEditedService->GetName());
597 m_xServices_lb->set_active( nSelected );
598
599 m_bIsUpdated = true;
600 break;
601 }
602 case RET_NO:
603 sIdent = "delete_service";
604 break;
605 case RET_CANCEL :
606 default :
607 // Do Nothing
608 break;
609 }
610 }
611 }
612 if( sIdent == "delete_service" && m_xServices_lb->get_count() > 0 )
613 {
614 int nSelected = m_xServices_lb->get_active();
615 int nPos = GetSelectedServicePos();
616
617 if( nPos >= 0 )
618 {
619 OUString sMsg = FpsResId( STR_SVT_DELETESERVICE );
620 sMsg = sMsg.replaceFirst( "$servicename$", m_xServices_lb->get_active_text() );
621 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
622 VclMessageType::Question, VclButtonsType::YesNo, sMsg));
623 if (xBox->run() == RET_YES)
624 {
625 // remove password
626 try
627 {
628 if( m_xMasterPasswd->isPersistentStoringAllowed() )
629 {
630 OUString sUrl( m_aServices[nPos]->GetUrl() );
631
632 Reference< XInteractionHandler > xInteractionHandler =
633 InteractionHandler::createWithParent( m_xContext, nullptr );
634
635 UrlRecord aURLEntries = m_xMasterPasswd->find( sUrl, xInteractionHandler );
636
637 if( aURLEntries.Url == sUrl && aURLEntries.UserList.hasElements() )
638 {
639 OUString sUserName = aURLEntries.UserList[0].UserName;
640
641 m_xMasterPasswd->removePersistent( sUrl, sUserName );
642 }
643 }
644 }
645 catch( const Exception& )
646 {}
647
648 m_aServices.erase( m_aServices.begin() + nPos );
649 m_xServices_lb->remove( nSelected );
650
651 m_xServices_lb->set_active(-1);
652 EnableExtraMenuItems(false);
653
654 m_bIsUpdated = true;
655
656 m_bIsConnected = false;
657 EnableControls();
658 }
659 }
660 }
661 else if( sIdent == "change_password" )
662 {
663 try
664 {
665 if( m_xMasterPasswd->isPersistentStoringAllowed() && m_xMasterPasswd->authorizateWithMasterPassword( Reference< XInteractionHandler>() ) )
666 {
667 int nPos = GetSelectedServicePos();
668
669 if( nPos >= 0 )
670 {
671 OUString sUrl( m_aServices[nPos]->GetUrl() );
672
673 Reference< XInteractionHandler > xInteractionHandler =
674 InteractionHandler::createWithParent( m_xContext, nullptr );
675
676 UrlRecord aURLEntries = m_xMasterPasswd->find( sUrl, xInteractionHandler );
677
678 if( aURLEntries.Url == sUrl && aURLEntries.UserList.hasElements() )
679 {
680 OUString sUserName = aURLEntries.UserList[0].UserName;
681
683 = new ::comphelper::SimplePasswordRequest;
684
685 xInteractionHandler->handle( pPasswordRequest );
686
687 if ( pPasswordRequest->isPassword() )
688 {
689 OUString aNewPass = pPasswordRequest->getPassword();
690 Sequence<OUString> aPasswd { aNewPass };
691
692 m_xMasterPasswd->addPersistent(
693 sUrl, sUserName, aPasswd, xInteractionHandler );
694 }
695 }
696 }
697 }
698 }
699 catch( const Exception& )
700 {}
701 }
702 else if( sIdent == "add_service" )
703 AddService();
704
705 EnableControls();
706}
707
709{
710 SvtContentEntry* pData = m_xFileView->FirstSelected();
711 if (pData)
712 {
713 if (!pData->mbIsFolder)
714 OkHdl(*m_xOk_btn);
715 else
716 OpenURL(pData->maURL);
717 }
718 return true;
719}
720
722{
723 SvtContentEntry* pData = m_xFileView->FirstSelected();
724 if (!pData)
725 return;
726
727 if( ( pData->mbIsFolder && ( m_eType == REMOTEDLG_TYPE_PATHDLG ) )
728 || ( !pData->mbIsFolder && ( m_eType == REMOTEDLG_TYPE_FILEDLG ) ) )
729 {
730 // url must contain user info, because we need this info in recent files entry
731 // (to fill user field in login box by default)
732 INetURLObject aURL( pData->maURL );
733 INetURLObject aCurrentURL( m_sLastServiceUrl );
734 aURL.SetUser( aCurrentURL.GetUser() );
735
736 m_sPath = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
737
738 m_xName_ed->set_text( aURL.GetLastName(INetURLObject::DecodeMechanism::WithCharset) );
739 }
740 else
741 {
742 if( m_eMode == REMOTEDLG_MODE_OPEN )
743 {
744 m_sPath.clear();
745 m_xName_ed->set_text( "" );
746 }
747 }
748
749 EnableControls();
750}
751
752IMPL_LINK_NOARG(RemoteFilesDialog, FileNameGetFocusHdl, weld::Widget&, void)
753{
754 m_xFileView->SetNoSelection();
755}
756
758{
759 m_xFileView->SetNoSelection();
760 if (!m_xOk_btn->get_sensitive())
761 EnableControls();
762}
763
765{
766 int nPos = m_xFilter_lb->get_active();
767
768 if( nPos != -1 && !m_aFilters[nPos].second.isEmpty() )
769 {
770 m_nCurrentFilter = nPos;
771
772 OUString sCurrentURL = m_xFileView->GetViewURL();
773
774 if( !sCurrentURL.isEmpty() && m_bIsConnected )
775 OpenURL( sCurrentURL );
776 }
777}
778
779IMPL_LINK(RemoteFilesDialog, TreeSelectHdl, weld::TreeView&, rBox, void)
780{
781 OpenURL(rBox.get_selected_id());
782 m_xFileView->grab_focus();
783}
784
785IMPL_LINK(RemoteFilesDialog, SelectBreadcrumbHdl, Breadcrumb*, pPtr, bool)
786{
787 OpenURL( pPtr->GetHdlURL() );
788 return true;
789}
790
792{
793 m_xFileView->EndInplaceEditing();
794
795 // will be bound after InteractionHandler is enabled
796 SmartContent aContent;
797 aContent.enableDefaultInteractionHandler();
798 // now it can be bound
799 aContent.bindTo( m_xFileView->GetViewURL() );
800 if( !aContent.canCreateFolder() )
801 return;
802
803 OUString aTitle;
804 aContent.getTitle( aTitle );
805 QueryFolderNameDialog aDlg(m_xDialog.get(), aTitle, FpsResId(STR_SVT_NEW_FOLDER));
806 bool bHandled = false;
807
808 while( !bHandled )
809 {
810 if (aDlg.run() == RET_OK)
811 {
812 OUString aUrl = aContent.createFolder(aDlg.GetName());
813 if( !aUrl.isEmpty() )
814 {
815 m_xFileView->CreatedFolder(aUrl, aDlg.GetName());
816 bHandled = true;
817 }
818 }
819 else
820 bHandled = true;
821 }
822}
823
825{
826 OUString sUserSelectedPath;
827
828 // check if file/path exists
829 OUString sCurrentPath = m_xFileView->GetViewURL();
830 OUString sSelectedItem = m_xFileView->GetCurrentURL();
831 OUString sUserTypedName = m_xName_ed->get_text();
832 OUString sFileName;
833 // auto extension
834 if( m_eMode == REMOTEDLG_MODE_SAVE )
835 sFileName = AddFileExtension(sUserTypedName);
836 else
837 sFileName = sUserTypedName;
838
839 bool bFileDlg = ( m_eType == REMOTEDLG_TYPE_FILEDLG );
840 bool bSelected = ( m_xFileView->GetSelectionCount() > 0 );
841
842 if( !sCurrentPath.endsWith("/") )
843 sCurrentPath += "/";
844
845 if( !bSelected )
846 {
848 sUserSelectedPath = sCurrentPath + INetURLObject::encode(sUserTypedName, INetURLObject::PART_FPATH, INetURLObject::EncodeMechanism::All);
849 }
850 else
851 {
853 m_sPath = sCurrentPath;
854 else
855 m_sPath = sSelectedItem;
856
857 // url must contain user info, because we need this info in recent files entry
858 // (to fill user field in login box by default)
859 INetURLObject aURL( m_sPath );
860 INetURLObject aCurrentURL( m_sLastServiceUrl );
861 aURL.SetUser( aCurrentURL.GetUser() );
862
863 m_sPath = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
864 sUserSelectedPath = m_sPath;
865 }
866
867 bool bExists = false;
868
869 if( bFileDlg )
870 bExists = ContentIsDocument( m_sPath );
871 else
872 bExists = ContentIsFolder( m_sPath );
873
874 if( bExists )
875 {
876 if( m_eMode == REMOTEDLG_MODE_SAVE )
877 {
878 OUString sMsg = FpsResId( STR_SVT_ALREADYEXISTOVERWRITE );
879 sMsg = sMsg.replaceFirst("$filename$", sFileName);
880 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
881 VclMessageType::Question, VclButtonsType::YesNo, sMsg));
882 if (xBox->run() != RET_YES)
883 return;
884 }
885 }
886 else
887 {
888 if (ContentIsFolder(sUserSelectedPath))
889 {
890 OpenURL(sUserSelectedPath);
891
892 if (!bSelected)
893 m_xName_ed->grab_focus();
894
895 return;
896 }
897
898 if( m_eMode == REMOTEDLG_MODE_OPEN )
899 return;
900 }
901
902 m_xDialog->response(RET_OK);
903}
904
906{
907 if( m_pCurrentAsyncAction.is() )
908 {
909 m_pCurrentAsyncAction->cancel();
910 onAsyncOperationFinished();
911 }
912 else
913 {
914 m_xDialog->response(RET_CANCEL);
915 }
916}
917
918// SvtFileDialog_Base
920{
921 return m_xFileView.get();
922}
923
925{
926}
927
928void RemoteFilesDialog::SetDenyList( const css::uno::Sequence< OUString >& rDenyList )
929{
930 m_aDenyList = rDenyList;
931 m_xTreeView->SetDenyList( rDenyList );
932}
933
934const css::uno::Sequence< OUString >& RemoteFilesDialog::GetDenyList() const
935{
936 return m_aDenyList;
937}
938
939void RemoteFilesDialog::SetStandardDir( const OUString& rStdDir )
940{
941 m_sStdDir = rStdDir;
942}
943
945{
946 return m_sStdDir;
947}
948
949void RemoteFilesDialog::SetPath( const OUString& rNewURL )
950{
951 m_sPath = rNewURL;
952
954 {
955 INetURLObject aUrl( m_sPath );
956 OUString sFileName = aUrl.GetLastName( INetURLObject::DecodeMechanism::WithCharset );
957
958 m_xName_ed->set_text( sFileName );
959 }
960}
961
963{
964 OUString sReturn;
965 if( m_xName_ed )
966 sReturn = m_xName_ed->get_text();
967 return sReturn;
968}
969
970void RemoteFilesDialog::setCurrentFileText( const OUString& rText, bool bSelectAll )
971{
972 if (m_xName_ed)
973 {
974 m_xName_ed->set_text(rText);
975 if( bSelectAll )
976 m_xName_ed->select_region(0, -1);
977 }
978}
979
981 const OUString& rFilter,
982 const css::uno::Sequence< css::beans::StringPair >& rFilters )
983{
984 AddFilter( rFilter, OUString() );
985 const StringPair* pSubFilters = rFilters.getConstArray();
986 const StringPair* pSubFiltersEnd = pSubFilters + rFilters.getLength();
987 for ( ; pSubFilters != pSubFiltersEnd; ++pSubFilters )
988 AddFilter( pSubFilters->First, pSubFilters->Second );
989}
990
992{
993 OUString sFilter;
994
995 if (m_nCurrentFilter != -1)
996 {
997 sFilter = m_aFilters[m_nCurrentFilter].first;
998 }
999
1000 return sFilter;
1001}
1002
1004{
1005 return GetCurFilter();
1006}
1007
1008void RemoteFilesDialog::SetCurFilter( const OUString& rFilter )
1009{
1010 DBG_ASSERT( !m_bIsInExecute, "SvtFileDialog::SetCurFilter: currently executing!" );
1011
1012 // look for corresponding filter
1013 sal_uInt16 nPos = m_aFilters.size();
1014
1015 while ( nPos-- )
1016 {
1017 if ( m_aFilters[nPos].first == rFilter )
1018 {
1020 m_xFilter_lb->set_active( m_nCurrentFilter );
1021 break;
1022 }
1023 }
1024}
1025
1027{
1028}
1029
1031{
1032}
1033
1035{
1037}
1038
1040{
1041 m_pCurrentAsyncAction = nullptr;
1043}
1044
1045void RemoteFilesDialog::UpdateControls( const OUString& rURL )
1046{
1048
1049 if( nPos >= 0 && m_bServiceChanged && rURL == m_aServices[nPos]->GetUrl() )
1050 {
1051 OUString sURL = m_aServices[nPos]->GetUrl();
1052
1053 m_xPath->SetRootName( m_sRootLabel );
1054 m_xTreeView->clear();
1055
1056 m_xTreeView->InsertRootEntry(rURL, m_sRootLabel);
1057
1058 m_xName_ed->grab_focus();
1059
1060 m_sLastServiceUrl = sURL;
1061
1062 m_bServiceChanged = false;
1063 }
1064
1065 m_xPath->SetURL( rURL );
1066
1067 m_xTreeView->connect_changed(Link<weld::TreeView&,void>());
1068
1069 // read cached data for this url and fill the tree
1070 const ::std::vector< SvtContentEntry >& rFolders = m_xFileView->GetContent();
1071 ::std::vector< std::pair< OUString, OUString > > aFolders;
1072
1073 m_xName_ed->ClearEntries();
1074
1075 for(const auto & rFolder : rFolders)
1076 {
1077 //WebDAV folders path ends in '/', so strip it
1078 OUString aFolderName = rFolder.maURL;
1079 if( rFolder.mbIsFolder && ( ( aFolderName.lastIndexOf( '/' ) + 1 ) == aFolderName.getLength() ) )
1080 aFolderName = aFolderName.copy( 0, aFolderName.getLength() - 1 );
1081
1082 int nTitleStart = aFolderName.lastIndexOf( '/' );
1083 if( nTitleStart != -1 )
1084 {
1085 OUString sTitle( INetURLObject::decode(
1086 aFolderName.subView( nTitleStart + 1 ),
1088
1089 if( rFolder.mbIsFolder )
1090 {
1091 aFolders.emplace_back( sTitle, aFolderName );
1092 }
1093
1094 // add entries to the autocompletion mechanism
1095 m_xName_ed->AddEntry( sTitle );
1096 }
1097 }
1098
1099 m_xTreeView->FillTreeEntry( rURL, aFolders );
1100
1101 m_xTreeView->connect_changed( LINK( this, RemoteFilesDialog, TreeSelectHdl ) );
1102
1103 m_bIsConnected = true;
1105}
1106
1108{
1109 // This dialog contains Breadcrumb, not Edit
1110}
1111
1113{
1114 return m_sPath;
1115}
1116
1117std::vector<OUString> RemoteFilesDialog::GetPathList() const
1118{
1119 std::vector<OUString> aList;
1120
1121 m_xFileView->selected_foreach([this, &aList](weld::TreeIter& rCurEntry){
1122 // url must contain user info, because we need this info in recent files entry
1123 // (to fill user field in login box by default)
1124 INetURLObject aURL(m_xFileView->GetURL(rCurEntry));
1125 INetURLObject aCurrentURL( m_sLastServiceUrl );
1126 aURL.SetUser( aCurrentURL.GetUser() );
1127
1128 aList.push_back( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
1129
1130 return false;
1131 });
1132
1133 if( aList.empty() && !m_sPath.isEmpty() )
1134 aList.push_back( m_sPath );
1135
1136 return aList;
1137}
1138
1139bool RemoteFilesDialog::ContentIsFolder( const OUString& rURL )
1140{
1141 try
1142 {
1143 ::ucbhelper::Content content(rURL,
1144 ::utl::UCBContentHelper::getDefaultCommandEnvironment(),
1145 m_xContext);
1146 return content.isFolder();
1147 }
1148 catch (css::uno::Exception const&)
1149 {
1150 return false;
1151 }
1152}
1153
1154bool RemoteFilesDialog::ContentIsDocument( const OUString& rURL )
1155{
1156 try
1157 {
1158 ::ucbhelper::Content content(rURL,
1159 ::utl::UCBContentHelper::getDefaultCommandEnvironment(),
1160 m_xContext);
1161 return content.isDocument();
1162 }
1163 catch (css::uno::Exception const&)
1164 {
1165 return false;
1166 }
1167}
1168
1170{
1171 // This dialog doesn't contain preview
1172 return 0;
1173}
1174
1176{
1177 // This dialog doesn't contain preview
1178 return 0;
1179}
1180
1181void RemoteFilesDialog::setImage( const css::uno::Any& )
1182{
1183 // This dialog doesn't contain preview
1184}
1185
1187{
1188 // This dialog doesn't contain preview
1189 return false;
1190}
1191
1193{
1194 return nullptr;
1195}
1196
1198{
1199}
1200
1201/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Reference< XComponentContext > m_xContext
IMPL_LINK(RemoteFilesDialog, EditServiceMenuHdl, const OUString &, rIdent, void)
static OUString lcl_GetServiceType(const ServicePtr &pService)
IMPL_LINK_NOARG(RemoteFilesDialog, IconViewHdl, weld::Button &, void)
@ REMOTEDLG_TYPE_PATHDLG
@ REMOTEDLG_TYPE_FILEDLG
@ REMOTEDLG_MODE_SAVE
@ REMOTEDLG_MODE_OPEN
std::shared_ptr< Place > ServicePtr
Reference< XExecutableDialog > m_xDialog
@ ALL_VISITED
Definition: breadcrumb.hxx:21
static weld::MessageDialog * CreateMessageDialog(weld::Widget *pParent, VclMessageType eMessageType, VclButtonsType eButtonType, const OUString &rPrimaryMessage, const ILibreOfficeKitNotifier *pNotifier=nullptr)
static DialogMask HandleError(ErrCode nId, weld::Window *pParent=nullptr, DialogMask nMask=DialogMask::MAX)
static OUString decode(std::u16string_view rText, DecodeMechanism eMechanism, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8)
OUString GetLastName(DecodeMechanism eMechanism=DecodeMechanism::ToIUri, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
OUString GetUser(DecodeMechanism eMechanism=DecodeMechanism::ToIUri, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
static OUString encode(std::u16string_view rText, Part ePart, EncodeMechanism eMechanism, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8)
OUString GetName() const
void EnableExtraMenuItems(bool bEnable)
virtual bool getShowState() override
std::vector< ServicePtr > m_aServices
OUString AddFileExtension(const OUString &rFileName)
void OpenURL(OUString const &sURL)
std::unique_ptr< weld::ComboBox > m_xFilter_lb
std::unique_ptr< weld::ToggleButton > m_xIconView_btn
virtual void onAsyncOperationFinished() override
virtual OUString getCurFilter() const override
std::unique_ptr< weld::Container > m_xContainer
std::unique_ptr< weld::Button > m_xNewFolder
virtual OUString GetCurFilter() const override
virtual const css::uno::Sequence< OUString > & GetDenyList() const override
virtual void EnableAutocompletion(bool=true) override
void SavePassword(const OUString &rURL, const OUString &rUser, const OUString &rPassword, bool bPersistent)
std::unique_ptr< weld::Button > m_xCancel_btn
std::unique_ptr< weld::Container > m_xPathContainer
virtual void onAsyncOperationStarted() override
virtual void SetDenyList(const css::uno::Sequence< OUString > &rDenyList) override
virtual const OUString & GetStandardDir() const override
virtual void AddFilter(const OUString &rFilter, const OUString &rType) override
css::uno::Sequence< OUString > m_aDenyList
Reference< XComponentContext > m_xContext
std::unique_ptr< SvtFileView > m_xFileView
std::vector< std::pair< OUString, OUString > > m_aFilters
std::unique_ptr< FolderTree > m_xTreeView
virtual std::vector< OUString > GetPathList() const override
virtual void SetCurFilter(const OUString &rFilter) override
virtual void setImage(const css::uno::Any &rImage) override
virtual void enableControl(sal_Int16 nControlId, bool bEnable) override
virtual sal_Int32 getAvailableHeight() override
virtual short run() override
bool ContentIsDocument(const OUString &rURL)
virtual weld::Widget * getControl(sal_Int16 nControlId, bool bLabelControl=false) const override
::rtl::Reference< ::svt::AsyncPickerAction > m_pCurrentAsyncAction
std::unique_ptr< AutocompleteEdit > m_xName_ed
std::unique_ptr< Breadcrumb > m_xPath
virtual void SetPath(const OUString &rNewURL) override
virtual void SetStandardDir(const OUString &rStdDir) override
virtual const OUString & GetPath() override
virtual void UpdateControls(const OUString &rURL) override
virtual void AddFilterGroup(const OUString &_rFilter, const css::uno::Sequence< css::beans::StringPair > &rFilters) override
virtual void SetHasFilename(bool) override
virtual OUString getCurrentFileText() const override
std::unique_ptr< weld::ComboBox > m_xServices_lb
virtual void setCurrentFileText(const OUString &rText, bool bSelectAll=false) override
virtual void SetFileCallback(::svt::IFilePickerListener *pNotifier) override
std::unique_ptr< weld::Button > m_xOk_btn
std::unique_ptr< weld::MenuButton > m_xManageServices
Reference< XPasswordContainer2 > m_xMasterPasswd
virtual SvtFileView * GetView() override
SvtRemoteDlgMode m_eMode
RemoteFilesDialog(weld::Window *pParent, PickerFlags nBits)
virtual bool ContentIsFolder(const OUString &rURL) override
virtual ~RemoteFilesDialog() override
virtual sal_Int32 getAvailableWidth() override
virtual void FilterSelect() override
SvtRemoteDlgType m_eType
std::unique_ptr< weld::ToggleButton > m_xListView_btn
constexpr tools::Long Height() const
constexpr tools::Long Width() const
css::uno::Any GetUserItem(const OUString &sName) const
void SetUserItem(const OUString &sName, const css::uno::Any &aValue)
void SetWindowState(const OUString &sState)
OUString GetWindowState() const
bool Exists() const
static std::shared_ptr< ConfigurationChanges > create()
virtual short run()
std::shared_ptr< weld::Dialog > m_xDialog
std::unique_ptr< weld::Builder > m_xBuilder
#define DBG_ASSERT(sCon, aError)
URL aURL
const EnumerationType m_eType
#define ERRCODE_IO_NOTEXISTS
@ eIcon
Definition: fileview.hxx:46
@ eDetailedList
Definition: fileview.hxx:45
OUString sName
constexpr OUStringLiteral FILEDIALOG_FILTER_ALL
PickerFlags
OUString FpsResId(TranslateId aId)
OUString sPrefix
sal_uInt16 nPos
std::unique_ptr< sal_Int32[]> pData
@ Exception
Reference< XComponentContext > getProcessComponentContext()
css::uno::Reference< css::deployment::XPackageRegistry > create(css::uno::Reference< css::deployment::XPackageRegistry > const &xRootRegistry, OUString const &context, OUString const &cachePath, css::uno::Reference< css::uno::XComponentContext > const &xComponentContext)
int i
constexpr OUStringLiteral first
INetProtocol
RET_OK
RET_CANCEL
RET_NO
RET_YES