1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
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
);
49 m_bIsConnected
= false;
50 m_bServiceChanged
= false;
51 m_nCurrentFilter
= -1;
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
)
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";
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>());
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
) );
140 std::shared_ptr
< comphelper::ConfigurationChanges
> batch( comphelper::ConfigurationChanges::create() );
142 officecfg::Office::Common::Misc::FilePickerLastService::set( m_sLastServiceUrl
, batch
);
146 Sequence
< OUString
> placesUrlsList( m_aServices
.size() );
147 auto placesUrlsListRange
= asNonConstRange(placesUrlsList
);
148 Sequence
< OUString
> placesNamesList( m_aServices
.size() );
149 auto placesNamesListRange
= asNonConstRange(placesNamesList
);
152 for (auto const& service
: m_aServices
)
154 placesUrlsListRange
[i
] = service
->GetUrl();
155 placesNamesListRange
[i
] = service
->GetName();
159 officecfg::Office::Common::Misc::FilePickerPlacesUrls::set( placesUrlsList
, batch
);
160 officecfg::Office::Common::Misc::FilePickerPlacesNames::set( placesNamesList
, batch
);
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)
179 SelectServiceHdl(*m_xServices_lb
);
183 m_xServices_lb
->set_active(-1);
184 EnableExtraMenuItems(false);
187 m_bIsInExecute
= true;
188 short nRet
= SvtFileDialog_Base::run();
189 m_bIsInExecute
= false;
193 static OUString
lcl_GetServiceType( const ServicePtr
& pService
)
195 INetProtocol aProtocol
= pService
->GetUrlObject().GetProtocol();
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
;
211 case INetProtocol::Smb
:
212 return u
"Windows Share"_ustr
;
213 case INetProtocol::File
:
215 case INetProtocol::Http
:
216 return u
"WebDAV"_ustr
;
217 case INetProtocol::Https
:
218 return u
"WebDAV"_ustr
;
219 case INetProtocol::Generic
:
226 void RemoteFilesDialog::InitSize()
228 if( m_sIniKey
.isEmpty() )
231 // initialize from config
232 SvtViewOptions
aDlgOpt( EViewType::Dialog
, m_sIniKey
);
234 if( !aDlgOpt
.Exists() )
237 m_xDialog
->set_window_state(aDlgOpt
.GetWindowState());
239 Any aUserData
= aDlgOpt
.GetUserItem( u
"UserData"_ustr
);
241 if( aUserData
>>= sCfgStr
)
243 sal_Int32 nPos1
{ sCfgStr
.indexOf('|') };
246 sal_Int32 nPos2
{ sCfgStr
.indexOf('|', nPos1
+1 ) };
249 m_xFileView
->SetConfigString( sCfgStr
.subView(nPos2
+1) );
253 void RemoteFilesDialog::FillServicesListbox()
255 m_xServices_lb
->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;
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() )
280 if( placesUrlsList
[nPlace
] == m_sLastServiceUrl
)
283 m_xServices_lb
->append_text(sPrefix
+ placesNamesList
[nPlace
]);
289 if (m_xServices_lb
->get_count() > 0)
291 m_xServices_lb
->set_active(nPos
);
292 EnableExtraMenuItems(true);
295 EnableExtraMenuItems(false);
300 int RemoteFilesDialog::GetSelectedServicePos()
302 if( m_aServices
.empty() )
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() )
324 void RemoteFilesDialog::AddFilter( const OUString
& rFilter
, const OUString
& rType
)
326 m_aFilters
.emplace_back( rFilter
, rType
);
328 m_xFilter_lb
->append_separator(u
""_ustr
);
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
)
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
);
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();
372 // content doesn't exist
373 ErrorHandler::HandleError( ERRCODE_IO_NOTEXISTS
);
379 OUString
RemoteFilesDialog::AddFileExtension(const OUString
& rFileName
)
381 if (m_nCurrentFilter
== -1)
384 OUString sExt
= m_aFilters
[m_nCurrentFilter
].second
;
385 sal_Int32 nDotPos
= rFileName
.lastIndexOf( '.' );
388 return rFileName
+ sExt
.subView( 1 ); // without '*'
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();
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
& )
427 m_xServices_lb
->set_sensitive(false);
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);
439 m_xOk_btn
->set_sensitive(false);
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() )
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
};
486 m_xMasterPasswd
->addPersistent(
487 rURL
, rUser
, aPasswd
, xInteractionHandler
);
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();
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())
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
);
551 IMPL_LINK_NOARG( RemoteFilesDialog
, SelectServiceHdl
, weld::ComboBox
&, void )
553 int nPos
= GetSelectedServicePos();
557 OUString sURL
= m_aServices
[nPos
]->GetUrl();
558 EnableExtraMenuItems(true);
560 m_bServiceChanged
= true;
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();
575 PlaceEditDialog
aDlg(m_xDialog
.get(), m_aServices
[nPos
]);
576 short aRetCode
= aDlg
.run();
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())
592 m_xServices_lb
->insert_text(nSelected
, sPrefix
+ pEditedService
->GetName());
593 m_xServices_lb
->set_active( nSelected
);
599 sIdent
= "delete_service";
608 if( sIdent
== "delete_service" && m_xServices_lb
->get_count() > 0 )
610 int nSelected
= m_xServices_lb
->get_active();
611 int nPos
= GetSelectedServicePos();
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
)
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);
652 m_bIsConnected
= false;
657 else if( sIdent
== "change_password" )
661 if( m_xMasterPasswd
->isPersistentStoringAllowed() && m_xMasterPasswd
->authorizateWithMasterPassword( Reference
< XInteractionHandler
>() ) )
663 int nPos
= GetSelectedServicePos();
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" )
703 IMPL_LINK_NOARG( RemoteFilesDialog
, DoubleClickHdl
, SvtFileView
*, bool )
705 SvtContentEntry
* pData
= m_xFileView
->FirstSelected();
708 if (!pData
->mbIsFolder
)
711 OpenURL(pData
->maURL
);
716 IMPL_LINK_NOARG( RemoteFilesDialog
, SelectHdl
, SvtFileView
*, void )
718 SvtContentEntry
* pData
= m_xFileView
->FirstSelected();
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
) );
737 if( m_eMode
== REMOTEDLG_MODE_OPEN
)
740 m_xName_ed
->set_text( u
""_ustr
);
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())
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() );
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() )
799 aContent
.getTitle( aTitle
);
800 QueryFolderNameDialog
aDlg(m_xDialog
.get(), aTitle
, FpsResId(STR_SVT_NEW_FOLDER
));
801 bool bHandled
= false;
805 if (aDlg
.run() == RET_OK
)
807 OUString aUrl
= aContent
.createFolder(aDlg
.GetName());
808 if( !aUrl
.isEmpty() )
810 m_xFileView
->CreatedFolder(aUrl
, aDlg
.GetName());
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();
829 if( m_eMode
== REMOTEDLG_MODE_SAVE
)
830 sFileName
= AddFileExtension(sUserTypedName
);
832 sFileName
= sUserTypedName
;
834 bool bFileDlg
= ( m_eType
== REMOTEDLG_TYPE_FILEDLG
);
835 bool bSelected
= ( m_xFileView
->GetSelectionCount() > 0 );
837 if( !sCurrentPath
.endsWith("/") )
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
);
847 if( m_eType
== REMOTEDLG_TYPE_PATHDLG
)
848 m_sPath
= sCurrentPath
;
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;
865 bExists
= ContentIsDocument( m_sPath
);
867 bExists
= ContentIsFolder( m_sPath
);
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
)
883 if (ContentIsFolder(sUserSelectedPath
))
885 OpenURL(sUserSelectedPath
);
888 m_xName_ed
->grab_focus();
893 if( m_eMode
== REMOTEDLG_MODE_OPEN
)
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();
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
934 void RemoteFilesDialog::SetStandardDir( const OUString
& rStdDir
)
939 const OUString
& RemoteFilesDialog::GetStandardDir() const
944 void RemoteFilesDialog::SetPath( const OUString
& 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
961 sReturn
= m_xName_ed
->get_text();
965 void RemoteFilesDialog::setCurrentFileText( const OUString
& rText
, bool bSelectAll
)
969 m_xName_ed
->set_text(rText
);
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
990 if (m_nCurrentFilter
!= -1)
992 sFilter
= m_aFilters
[m_nCurrentFilter
].first
;
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();
1012 if ( m_aFilters
[nPos
].first
== rFilter
)
1014 m_nCurrentFilter
= nPos
;
1015 m_xFilter_lb
->set_active( m_nCurrentFilter
);
1021 void RemoteFilesDialog::FilterSelect()
1025 void RemoteFilesDialog::SetFileCallback( ::svt::IFilePickerListener
* )
1029 void RemoteFilesDialog::onAsyncOperationStarted()
1034 void RemoteFilesDialog::onAsyncOperationFinished()
1036 m_pCurrentAsyncAction
= nullptr;
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;
1102 void RemoteFilesDialog::EnableAutocompletion( bool )
1104 // This dialog contains Breadcrumb, not Edit
1107 const OUString
& RemoteFilesDialog::GetPath()
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
) );
1128 if( aList
.empty() && !m_sPath
.isEmpty() )
1129 aList
.push_back( m_sPath
);
1134 bool RemoteFilesDialog::ContentIsFolder( const OUString
& rURL
)
1138 ::ucbhelper::Content
content(rURL
,
1139 ::utl::UCBContentHelper::getDefaultCommandEnvironment(),
1141 return content
.isFolder();
1143 catch (css::uno::Exception
const&)
1149 bool RemoteFilesDialog::ContentIsDocument( const OUString
& rURL
)
1153 ::ucbhelper::Content
content(rURL
,
1154 ::utl::UCBContentHelper::getDefaultCommandEnvironment(),
1156 return content
.isDocument();
1158 catch (css::uno::Exception
const&)
1164 sal_Int32
RemoteFilesDialog::getAvailableWidth()
1166 // This dialog doesn't contain preview
1170 sal_Int32
RemoteFilesDialog::getAvailableHeight()
1172 // This dialog doesn't contain preview
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
1187 weld::Widget
* RemoteFilesDialog::getControl( sal_Int16
, bool) const
1192 void RemoteFilesDialog::enableControl( sal_Int16
, bool )
1196 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */