summaryrefslogtreecommitdiffstats
path: root/fpicker/source/office/RemoteFilesDialog.cxx
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--fpicker/source/office/RemoteFilesDialog.cxx1232
1 files changed, 1232 insertions, 0 deletions
diff --git a/fpicker/source/office/RemoteFilesDialog.cxx b/fpicker/source/office/RemoteFilesDialog.cxx
new file mode 100644
index 000000000..fcbd203b5
--- /dev/null
+++ b/fpicker/source/office/RemoteFilesDialog.cxx
@@ -0,0 +1,1232 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <config_oauth2.h>
+
+#include "fpsmartcontent.hxx"
+#include "QueryFolderName.hxx"
+#include "RemoteFilesDialog.hxx"
+#include <fpsofficeResMgr.hxx>
+#include <fpicker/strings.hrc>
+#include <strings.hrc>
+#include <comphelper/docpasswordrequest.hxx>
+#include <comphelper/stillreadwriteinteraction.hxx>
+#include <com/sun/star/task/InteractionHandler.hpp>
+#include <com/sun/star/task/PasswordContainer.hpp>
+#include <svtools/PlaceEditDialog.hxx>
+#include <tools/debug.hxx>
+#include <ucbhelper/commandenvironment.hxx>
+#include <vcl/errinf.hxx>
+#include <bitmaps.hlst>
+#include <officecfg/Office/Common.hxx>
+
+RemoteFilesDialog::RemoteFilesDialog( weld::Window* pParent, PickerFlags nBits )
+ : SvtFileDialog_Base( pParent, "fps/ui/remotefilesdialog.ui", "RemoteFilesDialog" )
+ , m_xContext( comphelper::getProcessComponentContext() )
+ , m_xMasterPasswd( PasswordContainer::create( m_xContext ) )
+ , m_bIsInExecute( false )
+ , m_xCancel_btn(m_xBuilder->weld_button("cancel"))
+ , m_xManageServices(m_xBuilder->weld_menu_button("add_service_btn"))
+ , m_xServices_lb(m_xBuilder->weld_combo_box("services_lb"))
+ , m_xPathContainer(m_xBuilder->weld_container("breadcrumb_container"))
+ , m_xNewFolder(m_xBuilder->weld_button("new_folder"))
+ , m_xListView_btn(m_xBuilder->weld_toggle_button("list_view"))
+ , m_xIconView_btn(m_xBuilder->weld_toggle_button("icon_view"))
+ , m_xFilter_lb(m_xBuilder->weld_combo_box("filter_lb"))
+ , m_xName_ed(new AutocompleteEdit(m_xBuilder->weld_entry("filename")))
+{
+ m_eMode = ( nBits & PickerFlags::SaveAs ) ? REMOTEDLG_MODE_SAVE : REMOTEDLG_MODE_OPEN;
+ m_eType = ( nBits & PickerFlags::PathDialog ) ? REMOTEDLG_TYPE_PATHDLG : REMOTEDLG_TYPE_FILEDLG;
+ bool bMultiselection = bool( nBits & PickerFlags::MultiSelection );
+ m_bIsUpdated = false;
+ m_bIsConnected = false;
+ m_bServiceChanged = false;
+ m_nCurrentFilter = -1;
+
+ m_xName_ed->show();
+
+ // limit width due to super wide strings that may end up here
+ m_xFilter_lb->set_size_request(m_xFilter_lb->get_approximate_digit_width() * 60, -1);
+
+ m_xFilter_lb->set_sensitive(false);
+ m_xName_ed->set_sensitive(false);
+ m_xNewFolder->set_sensitive(false);
+
+ if( m_eMode == REMOTEDLG_MODE_OPEN )
+ {
+ m_xOk_btn = m_xBuilder->weld_button("open");
+
+ m_xNewFolder->hide();
+ }
+ else
+ {
+ m_xOk_btn = m_xBuilder->weld_button("save");
+ m_xNewFolder->connect_clicked( LINK( this, RemoteFilesDialog, NewFolderHdl ) );
+ }
+
+ m_xListView_btn->set_active(true);
+ m_xIconView_btn->connect_clicked( LINK( this, RemoteFilesDialog, IconViewHdl ) );
+ m_xListView_btn->connect_clicked( LINK( this, RemoteFilesDialog, ListViewHdl ) );
+
+ m_xOk_btn->show();
+ m_xOk_btn->set_sensitive(false);
+
+ m_xOk_btn->connect_clicked( LINK( this, RemoteFilesDialog, OkHdl ) );
+ m_xCancel_btn->connect_clicked( LINK( this, RemoteFilesDialog, CancelHdl ) );
+
+ m_sRootLabel = FpsResId( STR_SVT_ROOTLABEL );
+ m_xPath.reset(new Breadcrumb(m_xPathContainer.get()));
+ m_xPath->connect_clicked( LINK( this, RemoteFilesDialog, SelectBreadcrumbHdl ) );
+ m_xPath->SetMode( SvtBreadcrumbMode::ALL_VISITED );
+
+ m_xContainer = m_xBuilder->weld_container("container");
+ m_xContainer->set_size_request(m_xContainer->get_approximate_digit_width() * 82, -1);
+
+ m_xFileView.reset(new SvtFileView(m_xDialog.get(),
+ m_xBuilder->weld_tree_view("fileview"),
+ m_xBuilder->weld_icon_view("iconview"),
+ REMOTEDLG_TYPE_PATHDLG == m_eType,
+ bMultiselection, false));
+
+ m_xFileView->SetDoubleClickHdl( LINK( this, RemoteFilesDialog, DoubleClickHdl ) );
+ m_xFileView->SetSelectHdl( LINK( this, RemoteFilesDialog, SelectHdl ) );
+ m_xFileView->EnableDelete( true );
+
+ m_xTreeView.reset(new FolderTree(m_xBuilder->weld_tree_view("foldertree"), m_xDialog.get()));
+ m_xTreeView->connect_changed(LINK(this, RemoteFilesDialog, TreeSelectHdl));
+
+ m_xContainer->set_sensitive(false);
+
+ m_sIniKey = "RemoteFilesDialog";
+ InitSize();
+
+ m_xName_ed->connect_focus_in(LINK(this, RemoteFilesDialog, FileNameGetFocusHdl));
+ m_xName_ed->connect_changed(LINK(this, RemoteFilesDialog, FileNameModifyHdl));
+
+ m_xManageServices->connect_selected(LINK(this, RemoteFilesDialog, EditServiceMenuHdl));
+
+ FillServicesListbox();
+
+ m_xServices_lb->connect_changed( LINK( this, RemoteFilesDialog, SelectServiceHdl ) );
+
+ m_xFilter_lb->connect_changed( LINK( this, RemoteFilesDialog, SelectFilterHdl ) );
+}
+
+RemoteFilesDialog::~RemoteFilesDialog()
+{
+ m_xFileView->SetSelectHdl(Link<SvtFileView*,void>());
+
+ // save window state
+ if( !m_sIniKey.isEmpty() )
+ {
+ SvtViewOptions aDlgOpt( EViewType::Dialog, m_sIniKey );
+ aDlgOpt.SetWindowState(OStringToOUString(m_xDialog->get_window_state(WindowStateMask::All), RTL_TEXTENCODING_UTF8));
+
+ Size aSize(m_xDialog->get_size());
+
+ OUString sSize = OUString::number( aSize.Width() ) + "|";
+ sSize = sSize + OUString::number( aSize.Height() ) + "|";
+
+ OUString sUserData = m_xFileView->GetConfigString();
+ aDlgOpt.SetUserItem( "UserData",
+ makeAny( sSize + sUserData ) );
+ }
+
+ // save services
+ std::shared_ptr< comphelper::ConfigurationChanges > batch( comphelper::ConfigurationChanges::create( m_xContext ) );
+
+ officecfg::Office::Common::Misc::FilePickerLastService::set( m_sLastServiceUrl, batch );
+
+ if( m_bIsUpdated )
+ {
+ Sequence< OUString > placesUrlsList( m_aServices.size() );
+ Sequence< OUString > placesNamesList( m_aServices.size() );
+
+ int i = 0;
+ for (auto const& service : m_aServices)
+ {
+ placesUrlsList[i] = service->GetUrl();
+ placesNamesList[i] = service->GetName();
+ ++i;
+ }
+
+ officecfg::Office::Common::Misc::FilePickerPlacesUrls::set( placesUrlsList, batch );
+ officecfg::Office::Common::Misc::FilePickerPlacesNames::set( placesNamesList, batch );
+ }
+
+ batch->commit();
+}
+
+void RemoteFilesDialog::EnableExtraMenuItems(bool bEnable)
+{
+ m_xManageServices->set_item_visible("change_password", bEnable);
+ m_xManageServices->set_item_visible("edit_service", bEnable);
+ m_xManageServices->set_item_visible("delete_service", bEnable);
+ m_xManageServices->set_item_visible("change_password", bEnable);
+}
+
+short RemoteFilesDialog::run()
+{
+ if (m_xServices_lb->get_count() > 0)
+ {
+ m_xDialog->show();
+ SelectServiceHdl(*m_xServices_lb);
+ }
+ if (!m_bIsConnected)
+ {
+ m_xServices_lb->set_active(-1);
+ EnableExtraMenuItems(false);
+ }
+
+ m_bIsInExecute = true;
+ short nRet = SvtFileDialog_Base::run();
+ m_bIsInExecute = false;
+ return nRet;
+}
+
+static OUString lcl_GetServiceType( const ServicePtr& pService )
+{
+ INetProtocol aProtocol = pService->GetUrlObject().GetProtocol();
+ switch( aProtocol )
+ {
+ case INetProtocol::Ftp:
+ return "FTP";
+ case INetProtocol::Cmis:
+ {
+ OUString sHost = pService->GetUrlObject().GetHost( INetURLObject::DecodeMechanism::WithCharset );
+
+ if( sHost.startsWith( GDRIVE_BASE_URL ) )
+ return "Google Drive";
+ else if( sHost.startsWith( ALFRESCO_CLOUD_BASE_URL ) )
+ return "Alfresco Cloud";
+ else if( sHost.startsWith( ONEDRIVE_BASE_URL ) )
+ return "OneDrive";
+
+ return "CMIS";
+ }
+ case INetProtocol::Smb:
+ return "Windows Share";
+ case INetProtocol::File:
+ return "SSH";
+ case INetProtocol::Http:
+ return "WebDAV";
+ case INetProtocol::Https:
+ return "WebDAV";
+ case INetProtocol::Generic:
+ return "SSH";
+ default:
+ return OUString();
+ }
+}
+
+void RemoteFilesDialog::InitSize()
+{
+ if( m_sIniKey.isEmpty() )
+ return;
+
+ // initialize from config
+ SvtViewOptions aDlgOpt( EViewType::Dialog, m_sIniKey );
+
+ if( !aDlgOpt.Exists() )
+ return;
+
+ m_xDialog->set_window_state(OUStringToOString(aDlgOpt.GetWindowState(), RTL_TEXTENCODING_UTF8));
+
+ Any aUserData = aDlgOpt.GetUserItem( "UserData" );
+ OUString sCfgStr;
+ if( aUserData >>= sCfgStr )
+ {
+ sal_Int32 nPos1{ sCfgStr.indexOf('|') };
+ if (nPos1<0)
+ return;
+ sal_Int32 nPos2{ sCfgStr.indexOf('|', nPos1+1 ) };
+ if (nPos2<0)
+ return;
+ m_xFileView->SetConfigString( sCfgStr.copy(nPos2+1) );
+ }
+}
+
+void RemoteFilesDialog::FillServicesListbox()
+{
+ m_xServices_lb->clear();
+ m_aServices.clear();
+
+ // Load from user settings
+ Sequence< OUString > placesUrlsList( officecfg::Office::Common::Misc::FilePickerPlacesUrls::get( m_xContext ) );
+ Sequence< OUString > placesNamesList( officecfg::Office::Common::Misc::FilePickerPlacesNames::get( m_xContext ) );
+
+ unsigned int nPos = 0;
+ unsigned int i = 0;
+
+ m_sLastServiceUrl = officecfg::Office::Common::Misc::FilePickerLastService::get( m_xContext );
+
+ for( sal_Int32 nPlace = 0; nPlace < placesUrlsList.getLength() && nPlace < placesNamesList.getLength(); ++nPlace )
+ {
+ ServicePtr pService = std::make_shared<Place>( placesNamesList[nPlace], placesUrlsList[nPlace], true );
+ m_aServices.push_back( pService );
+
+ // Add to the listbox only remote services, not local bookmarks
+ if( !pService->IsLocal() )
+ {
+ OUString sPrefix = lcl_GetServiceType( pService );
+
+ if( !sPrefix.isEmpty() )
+ sPrefix += ": ";
+
+ if( placesUrlsList[nPlace] == m_sLastServiceUrl )
+ nPos = i;
+
+ m_xServices_lb->append_text(sPrefix + placesNamesList[nPlace]);
+
+ i++;
+ }
+ }
+
+ if (m_xServices_lb->get_count() > 0)
+ {
+ m_xServices_lb->set_active(nPos);
+ EnableExtraMenuItems(true);
+ }
+ else
+ EnableExtraMenuItems(false);
+
+ EnableControls();
+}
+
+int RemoteFilesDialog::GetSelectedServicePos()
+{
+ if( m_aServices.empty() )
+ return -1;
+
+ int nPos = 0;
+ int i = -1;
+
+ int nSelected = m_xServices_lb->get_active();
+
+ int nServices = static_cast<int>(m_aServices.size());
+ while( nPos < nServices )
+ {
+ while( (nPos < nServices) && m_aServices[nPos]->IsLocal() )
+ nPos++;
+ i++;
+ if( i == nSelected )
+ break;
+ nPos++;
+ }
+
+ return nPos;
+}
+
+void RemoteFilesDialog::AddFilter( const OUString& rFilter, const OUString& rType )
+{
+ OUString sName = rFilter;
+
+ m_aFilters.emplace_back( rFilter, rType );
+ if (rType.isEmpty())
+ m_xFilter_lb->append_separator("");
+ else
+ m_xFilter_lb->append_text(sName);
+
+ if (m_xFilter_lb->get_active() == -1)
+ m_xFilter_lb->set_active(0);
+}
+
+void RemoteFilesDialog::OpenURL( OUString const & sURL )
+{
+ if( !m_xFileView )
+ return;
+
+ DisableControls();
+
+ auto xWait = std::make_unique<weld::WaitObject>(m_xDialog.get());
+
+ if( !sURL.isEmpty() )
+ {
+ OUString sFilter = FILEDIALOG_FILTER_ALL;
+
+ if( m_nCurrentFilter != -1)
+ {
+ sFilter = m_aFilters[m_nCurrentFilter].second;
+ }
+
+ m_xFileView->EndInplaceEditing();
+
+ DBG_ASSERT( !m_pCurrentAsyncAction.is(), "SvtFileDialog::executeAsync: previous async action not yet finished!" );
+
+ m_pCurrentAsyncAction = new AsyncPickerAction( this, m_xFileView.get(), AsyncPickerAction::Action::eOpenURL );
+
+ // -1 timeout - sync
+ m_pCurrentAsyncAction->execute( sURL, sFilter, -1, -1, GetBlackList() );
+
+ if( m_eMode != REMOTEDLG_MODE_SAVE )
+ m_xName_ed->set_text( "" );
+
+ m_xFileView->grab_focus();
+ }
+ else
+ {
+ xWait.reset();
+
+ // content doesn't exist
+ ErrorHandler::HandleError( ERRCODE_IO_NOTEXISTS );
+
+ EnableControls();
+ }
+}
+
+void RemoteFilesDialog::AddFileExtension()
+{
+ if (m_nCurrentFilter == -1)
+ return;
+
+ OUString sExt = m_aFilters[m_nCurrentFilter].second;
+ OUString sFileName = m_xName_ed->get_text();
+
+ sal_Int32 nDotPos = sFileName.lastIndexOf( '.' );
+
+ if ( nDotPos == -1 )
+ {
+ sFileName += sExt.copy( 1 ); // without '*'
+ m_xName_ed->set_text( sFileName );
+ }
+}
+
+void RemoteFilesDialog::EnableControls()
+{
+ if (m_xServices_lb->get_count() > 0)
+ {
+ m_xServices_lb->set_sensitive(true);
+
+ if (m_xServices_lb->get_active() != -1)
+ {
+ m_xManageServices->set_item_sensitive("change_password", false);
+
+ try
+ {
+ if( m_xMasterPasswd->isPersistentStoringAllowed() )
+ {
+ int nPos = GetSelectedServicePos();
+
+ if( nPos >= 0 )
+ {
+ OUString sUrl( m_aServices[nPos]->GetUrl() );
+
+ UrlRecord aURLEntries = m_xMasterPasswd->find( sUrl, Reference< XInteractionHandler>() );
+
+ if( aURLEntries.UserList.hasElements() )
+ {
+ m_xManageServices->set_item_sensitive("change_password", true);
+ }
+ }
+ }
+ }
+ catch( const Exception& )
+ {}
+ }
+ }
+ else
+ m_xServices_lb->set_sensitive(false);
+
+ if( m_bIsConnected )
+ {
+ m_xFilter_lb->set_sensitive(true);
+ m_xName_ed->set_sensitive(true);
+ m_xContainer->set_sensitive(true);
+ m_xNewFolder->set_sensitive(true);
+
+ if (!m_xName_ed->get_text().isEmpty())
+ m_xOk_btn->set_sensitive(true);
+ else
+ m_xOk_btn->set_sensitive(false);
+ }
+ else
+ {
+ m_xFilter_lb->set_sensitive(false);
+ m_xName_ed->set_sensitive(false);
+ m_xContainer->set_sensitive(false);
+ m_xNewFolder->set_sensitive(false);
+ m_xOk_btn->set_sensitive(false);
+ }
+
+ m_xPath->EnableFields( true );
+ m_xManageServices->set_sensitive(true);
+}
+
+void RemoteFilesDialog::DisableControls()
+{
+ m_xServices_lb->set_sensitive(false);
+ m_xFilter_lb->set_sensitive(false);
+ m_xManageServices->set_sensitive(false);
+ m_xName_ed->set_sensitive(false);
+ m_xContainer->set_sensitive(false);
+ m_xOk_btn->set_sensitive(false);
+ m_xPath->EnableFields( false );
+
+ m_xCancel_btn->set_sensitive(true);
+}
+
+void RemoteFilesDialog::SavePassword(const OUString& rURL, const OUString& rUser,
+ const OUString& rPassword, bool bPersistent)
+{
+ if( rURL.isEmpty() || rUser.isEmpty() || rPassword.isEmpty() )
+ return;
+
+ try
+ {
+ if( !bPersistent ||
+ ( m_xMasterPasswd->isPersistentStoringAllowed()
+ && m_xMasterPasswd->authorizateWithMasterPassword( Reference< XInteractionHandler>() ) )
+ )
+ {
+ Reference< XInteractionHandler > xInteractionHandler =
+ InteractionHandler::createWithParent( m_xContext, nullptr );
+
+ Sequence<OUString> aPasswd { rPassword };
+
+ if( bPersistent )
+ m_xMasterPasswd->addPersistent(
+ rURL, rUser, aPasswd, xInteractionHandler );
+ else
+ m_xMasterPasswd->add( rURL, rUser, aPasswd, xInteractionHandler );
+ }
+ }
+ catch( const Exception& )
+ {}
+}
+
+IMPL_LINK_NOARG ( RemoteFilesDialog, IconViewHdl, weld::Button&, void )
+{
+ m_xListView_btn->set_active(false);
+ m_xFileView->SetViewMode( eIcon );
+}
+
+IMPL_LINK_NOARG ( RemoteFilesDialog, ListViewHdl, weld::Button&, void )
+{
+ m_xIconView_btn->set_active(false);
+ m_xFileView->SetViewMode( eDetailedList );
+}
+
+void RemoteFilesDialog::AddService()
+{
+ PlaceEditDialog aDlg(m_xDialog.get());
+ aDlg.ShowPasswordControl();
+ short aRetCode = aDlg.run();
+
+ switch( aRetCode )
+ {
+ case RET_OK :
+ {
+ ServicePtr newService = aDlg.GetPlace();
+ m_aServices.push_back( newService );
+
+ OUString sPassword = aDlg.GetPassword();
+ OUString sUser = aDlg.GetUser();
+ if( !sUser.isEmpty() && !sPassword.isEmpty() )
+ {
+ bool bPersistent = aDlg.IsRememberChecked();
+ SavePassword( newService->GetUrl(), sUser, sPassword, bPersistent );
+ }
+
+ OUString sPrefix = lcl_GetServiceType( newService );
+
+ if(!sPrefix.isEmpty())
+ sPrefix += ": ";
+
+ m_xServices_lb->append_text( sPrefix + newService->GetName() );
+ m_xServices_lb->set_active( m_xServices_lb->get_count() - 1 );
+ EnableExtraMenuItems(true);
+ SelectServiceHdl( *m_xServices_lb );
+
+ m_bIsUpdated = true;
+
+ EnableControls();
+ break;
+ }
+ case RET_CANCEL :
+ default :
+ // Do Nothing
+ break;
+ }
+}
+
+IMPL_LINK_NOARG( RemoteFilesDialog, SelectServiceHdl, weld::ComboBox&, void )
+{
+ int nPos = GetSelectedServicePos();
+
+ if( nPos >= 0 )
+ {
+ OUString sURL = m_aServices[nPos]->GetUrl();
+ EnableExtraMenuItems(true);
+
+ m_bServiceChanged = true;
+ OpenURL( sURL );
+ }
+}
+
+IMPL_LINK ( RemoteFilesDialog, EditServiceMenuHdl, const OString&, rIdent, void )
+{
+ OString sIdent(rIdent);
+ if( sIdent == "edit_service" && m_xServices_lb->get_count() > 0 )
+ {
+ int nSelected = m_xServices_lb->get_active();
+ int nPos = GetSelectedServicePos();
+
+ if( nPos >= 0 )
+ {
+ PlaceEditDialog aDlg(m_xDialog.get(), m_aServices[nPos]);
+ short aRetCode = aDlg.run();
+
+ switch( aRetCode )
+ {
+ case RET_OK :
+ {
+ ServicePtr pEditedService = aDlg.GetPlace();
+
+ m_aServices[nPos] = pEditedService;
+ m_xServices_lb->remove( nSelected );
+
+ OUString sPrefix = lcl_GetServiceType( pEditedService );
+
+ if(!sPrefix.isEmpty())
+ sPrefix += ": ";
+
+ m_xServices_lb->insert_text(nSelected, sPrefix + pEditedService->GetName());
+ m_xServices_lb->set_active( nSelected );
+
+ m_bIsUpdated = true;
+ break;
+ }
+ case RET_NO:
+ sIdent = "delete_service";
+ break;
+ case RET_CANCEL :
+ default :
+ // Do Nothing
+ break;
+ }
+ }
+ }
+ if( sIdent == "delete_service" && m_xServices_lb->get_count() > 0 )
+ {
+ int nSelected = m_xServices_lb->get_active();
+ int nPos = GetSelectedServicePos();
+
+ if( nPos >= 0 )
+ {
+ OUString sMsg = FpsResId( STR_SVT_DELETESERVICE );
+ sMsg = sMsg.replaceFirst( "$servicename$", m_xServices_lb->get_active_text() );
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
+ VclMessageType::Question, VclButtonsType::YesNo, sMsg));
+ if (xBox->run() == RET_YES)
+ {
+ // remove password
+ try
+ {
+ if( m_xMasterPasswd->isPersistentStoringAllowed() )
+ {
+ OUString sUrl( m_aServices[nPos]->GetUrl() );
+
+ Reference< XInteractionHandler > xInteractionHandler =
+ InteractionHandler::createWithParent( m_xContext, nullptr );
+
+ UrlRecord aURLEntries = m_xMasterPasswd->find( sUrl, xInteractionHandler );
+
+ if( aURLEntries.Url == sUrl && aURLEntries.UserList.hasElements() )
+ {
+ OUString sUserName = aURLEntries.UserList[0].UserName;
+
+ m_xMasterPasswd->removePersistent( sUrl, sUserName );
+ }
+ }
+ }
+ catch( const Exception& )
+ {}
+
+ m_aServices.erase( m_aServices.begin() + nPos );
+ m_xServices_lb->remove( nSelected );
+
+ m_xServices_lb->set_active(-1);
+ EnableExtraMenuItems(false);
+
+ m_bIsUpdated = true;
+
+ m_bIsConnected = false;
+ EnableControls();
+ }
+ }
+ }
+ else if( sIdent == "change_password" )
+ {
+ try
+ {
+ if( m_xMasterPasswd->isPersistentStoringAllowed() && m_xMasterPasswd->authorizateWithMasterPassword( Reference< XInteractionHandler>() ) )
+ {
+ int nPos = GetSelectedServicePos();
+
+ if( nPos >= 0 )
+ {
+ OUString sUrl( m_aServices[nPos]->GetUrl() );
+
+ Reference< XInteractionHandler > xInteractionHandler =
+ InteractionHandler::createWithParent( m_xContext, nullptr );
+
+ UrlRecord aURLEntries = m_xMasterPasswd->find( sUrl, xInteractionHandler );
+
+ if( aURLEntries.Url == sUrl && aURLEntries.UserList.hasElements() )
+ {
+ OUString sUserName = aURLEntries.UserList[0].UserName;
+
+ ::comphelper::SimplePasswordRequest* pPasswordRequest
+ = new ::comphelper::SimplePasswordRequest;
+ Reference< XInteractionRequest > rRequest( pPasswordRequest );
+
+ xInteractionHandler->handle( rRequest );
+
+ if ( pPasswordRequest->isPassword() )
+ {
+ OUString aNewPass = pPasswordRequest->getPassword();
+ Sequence<OUString> aPasswd { aNewPass };
+
+ m_xMasterPasswd->addPersistent(
+ sUrl, sUserName, aPasswd, xInteractionHandler );
+ }
+ }
+ }
+ }
+ }
+ catch( const Exception& )
+ {}
+ }
+ else if( sIdent == "add_service" )
+ AddService();
+
+ EnableControls();
+}
+
+IMPL_LINK_NOARG( RemoteFilesDialog, DoubleClickHdl, SvtFileView*, bool )
+{
+ SvtContentEntry* pData = m_xFileView->FirstSelected();
+ if (pData)
+ {
+ if (!pData->mbIsFolder)
+ m_xDialog->response(RET_OK);
+ else
+ OpenURL(pData->maURL);
+ }
+ return true;
+}
+
+IMPL_LINK_NOARG( RemoteFilesDialog, SelectHdl, SvtFileView*, void )
+{
+ SvtContentEntry* pData = m_xFileView->FirstSelected();
+ if (!pData)
+ return;
+
+ if( ( pData->mbIsFolder && ( m_eType == REMOTEDLG_TYPE_PATHDLG ) )
+ || ( !pData->mbIsFolder && ( m_eType == REMOTEDLG_TYPE_FILEDLG ) ) )
+ {
+ // url must contain user info, because we need this info in recent files entry
+ // (to fill user field in login box by default)
+ INetURLObject aURL( pData->maURL );
+ INetURLObject aCurrentURL( m_sLastServiceUrl );
+ aURL.SetUser( aCurrentURL.GetUser() );
+
+ m_sPath = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+
+ m_xName_ed->set_text( aURL.GetLastName(INetURLObject::DecodeMechanism::WithCharset) );
+ }
+ else
+ {
+ if( m_eMode == REMOTEDLG_MODE_OPEN )
+ {
+ m_sPath.clear();
+ m_xName_ed->set_text( "" );
+ }
+ }
+
+ EnableControls();
+}
+
+IMPL_LINK_NOARG(RemoteFilesDialog, FileNameGetFocusHdl, weld::Widget&, void)
+{
+ m_xFileView->SetNoSelection();
+}
+
+IMPL_LINK_NOARG(RemoteFilesDialog, FileNameModifyHdl, weld::Entry&, void)
+{
+ m_xFileView->SetNoSelection();
+ if (!m_xOk_btn->get_sensitive())
+ EnableControls();
+}
+
+IMPL_LINK_NOARG( RemoteFilesDialog, SelectFilterHdl, weld::ComboBox&, void )
+{
+ int nPos = m_xFilter_lb->get_active();
+
+ if( nPos != -1 && !m_aFilters[nPos].second.isEmpty() )
+ {
+ m_nCurrentFilter = nPos;
+
+ OUString sCurrentURL = m_xFileView->GetViewURL();
+
+ if( !sCurrentURL.isEmpty() && m_bIsConnected )
+ OpenURL( sCurrentURL );
+ }
+}
+
+IMPL_LINK(RemoteFilesDialog, TreeSelectHdl, weld::TreeView&, rBox, void)
+{
+ OpenURL(rBox.get_selected_id());
+ m_xFileView->grab_focus();
+}
+
+IMPL_LINK(RemoteFilesDialog, SelectBreadcrumbHdl, Breadcrumb*, pPtr, bool)
+{
+ OpenURL( pPtr->GetHdlURL() );
+ return true;
+}
+
+IMPL_LINK_NOARG ( RemoteFilesDialog, NewFolderHdl, weld::Button&, void )
+{
+ m_xFileView->EndInplaceEditing();
+
+ // will be bound after InteractionHandler is enabled
+ SmartContent aContent;
+ aContent.enableDefaultInteractionHandler();
+ // now it can be bound
+ aContent.bindTo( m_xFileView->GetViewURL() );
+ if( !aContent.canCreateFolder() )
+ return;
+
+ OUString aTitle;
+ aContent.getTitle( aTitle );
+ QueryFolderNameDialog aDlg(m_xDialog.get(), aTitle, FpsResId(STR_SVT_NEW_FOLDER));
+ bool bHandled = false;
+
+ while( !bHandled )
+ {
+ if (aDlg.run() == RET_OK)
+ {
+ OUString aUrl = aContent.createFolder(aDlg.GetName());
+ if( !aUrl.isEmpty() )
+ {
+ m_xFileView->CreatedFolder(aUrl, aDlg.GetName());
+ bHandled = true;
+ }
+ }
+ else
+ bHandled = true;
+ }
+}
+
+IMPL_LINK_NOARG ( RemoteFilesDialog, OkHdl, weld::Button&, void )
+{
+ OUString sNameNoExt = m_xName_ed->get_text();
+ OUString sPathNoExt;
+
+ // auto extension
+ if( m_eMode == REMOTEDLG_MODE_SAVE )
+ AddFileExtension();
+
+ // check if file/path exists
+
+ OUString sCurrentPath = m_xFileView->GetViewURL();
+ OUString sSelectedItem = m_xFileView->GetCurrentURL();
+ OUString sName = m_xName_ed->get_text();
+
+ bool bFileDlg = ( m_eType == REMOTEDLG_TYPE_FILEDLG );
+ bool bSelected = ( m_xFileView->GetSelectionCount() > 0 );
+
+ if( !sCurrentPath.endsWith("/") )
+ sCurrentPath += "/";
+
+ if( !bSelected )
+ {
+ m_sPath = sCurrentPath + INetURLObject::encode( sName, INetURLObject::PART_FPATH, INetURLObject::EncodeMechanism::All );
+ sPathNoExt = sCurrentPath + INetURLObject::encode( sNameNoExt, INetURLObject::PART_FPATH, INetURLObject::EncodeMechanism::All );
+ }
+ else
+ {
+ if( m_eType == REMOTEDLG_TYPE_PATHDLG )
+ m_sPath = sCurrentPath;
+ else
+ m_sPath = sSelectedItem;
+
+ // url must contain user info, because we need this info in recent files entry
+ // (to fill user field in login box by default)
+ INetURLObject aURL( m_sPath );
+ INetURLObject aCurrentURL( m_sLastServiceUrl );
+ aURL.SetUser( aCurrentURL.GetUser() );
+
+ m_sPath = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ }
+
+ bool bExists = false;
+
+ if( bFileDlg )
+ bExists = ContentIsDocument( m_sPath );
+ else
+ bExists = ContentIsFolder( m_sPath );
+
+ if( bExists )
+ {
+ if( m_eMode == REMOTEDLG_MODE_SAVE )
+ {
+ OUString sMsg = FpsResId( STR_SVT_ALREADYEXISTOVERWRITE );
+ sMsg = sMsg.replaceFirst( "$filename$", sName );
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
+ VclMessageType::Question, VclButtonsType::YesNo, sMsg));
+ if (xBox->run() != RET_YES)
+ return;
+ }
+ }
+ else
+ {
+ if( ContentIsFolder( sPathNoExt ) )
+ {
+ OpenURL( sPathNoExt );
+ m_xName_ed->set_text( "" );
+
+ if (!bSelected)
+ m_xName_ed->grab_focus();
+
+ return;
+ }
+
+ if( m_eMode == REMOTEDLG_MODE_OPEN )
+ return;
+ }
+
+ m_xDialog->response(RET_OK);
+}
+
+IMPL_LINK_NOARG ( RemoteFilesDialog, CancelHdl, weld::Button&, void )
+{
+ if( m_pCurrentAsyncAction.is() )
+ {
+ m_pCurrentAsyncAction->cancel();
+ onAsyncOperationFinished();
+ }
+ else
+ {
+ m_xDialog->response(RET_CANCEL);
+ }
+}
+
+// SvtFileDialog_Base
+SvtFileView* RemoteFilesDialog::GetView()
+{
+ return m_xFileView.get();
+}
+
+void RemoteFilesDialog::SetHasFilename( bool )
+{
+}
+
+void RemoteFilesDialog::SetBlackList( const css::uno::Sequence< OUString >& rBlackList )
+{
+ m_aBlackList = rBlackList;
+ m_xTreeView->SetBlackList( rBlackList );
+}
+
+const css::uno::Sequence< OUString >& RemoteFilesDialog::GetBlackList() const
+{
+ return m_aBlackList;
+}
+
+void RemoteFilesDialog::SetStandardDir( const OUString& rStdDir )
+{
+ m_sStdDir = rStdDir;
+}
+
+const OUString& RemoteFilesDialog::GetStandardDir() const
+{
+ return m_sStdDir;
+}
+
+void RemoteFilesDialog::SetPath( const OUString& rNewURL )
+{
+ m_sPath = rNewURL;
+
+ if( m_eMode == REMOTEDLG_MODE_SAVE )
+ {
+ INetURLObject aUrl( m_sPath );
+ OUString sFileName = aUrl.GetLastName( INetURLObject::DecodeMechanism::WithCharset );
+
+ m_xName_ed->set_text( sFileName );
+ }
+}
+
+OUString RemoteFilesDialog::getCurrentFileText() const
+{
+ OUString sReturn;
+ if( m_xName_ed )
+ sReturn = m_xName_ed->get_text();
+ return sReturn;
+}
+
+void RemoteFilesDialog::setCurrentFileText( const OUString& rText, bool bSelectAll )
+{
+ if (m_xName_ed)
+ {
+ m_xName_ed->set_text(rText);
+ if( bSelectAll )
+ m_xName_ed->select_region(0, -1);
+ }
+}
+
+void RemoteFilesDialog::AddFilterGroup(
+ const OUString& rFilter,
+ const css::uno::Sequence< css::beans::StringPair >& rFilters )
+{
+ AddFilter( rFilter, OUString() );
+ const StringPair* pSubFilters = rFilters.getConstArray();
+ const StringPair* pSubFiltersEnd = pSubFilters + rFilters.getLength();
+ for ( ; pSubFilters != pSubFiltersEnd; ++pSubFilters )
+ AddFilter( pSubFilters->First, pSubFilters->Second );
+}
+
+OUString RemoteFilesDialog::GetCurFilter() const
+{
+ OUString sFilter;
+
+ if (m_nCurrentFilter != -1)
+ {
+ sFilter = m_aFilters[m_nCurrentFilter].first;
+ }
+
+ return sFilter;
+}
+
+OUString RemoteFilesDialog::getCurFilter( ) const
+{
+ return GetCurFilter();
+}
+
+void RemoteFilesDialog::SetCurFilter( const OUString& rFilter )
+{
+ DBG_ASSERT( !m_bIsInExecute, "SvtFileDialog::SetCurFilter: currently executing!" );
+
+ // look for corresponding filter
+ sal_uInt16 nPos = m_aFilters.size();
+
+ while ( nPos-- )
+ {
+ if ( m_aFilters[nPos].first == rFilter )
+ {
+ m_nCurrentFilter = nPos;
+ m_xFilter_lb->set_active( m_nCurrentFilter );
+ break;
+ }
+ }
+}
+
+void RemoteFilesDialog::FilterSelect()
+{
+}
+
+void RemoteFilesDialog::SetFileCallback( ::svt::IFilePickerListener * )
+{
+}
+
+void RemoteFilesDialog::onAsyncOperationStarted()
+{
+ DisableControls();
+}
+
+void RemoteFilesDialog::onAsyncOperationFinished()
+{
+ m_pCurrentAsyncAction = nullptr;
+ EnableControls();
+}
+
+void RemoteFilesDialog::UpdateControls( const OUString& rURL )
+{
+ int nPos = GetSelectedServicePos();
+
+ if( nPos >= 0 && m_bServiceChanged && rURL == m_aServices[nPos]->GetUrl() )
+ {
+ OUString sURL = m_aServices[nPos]->GetUrl();
+
+ m_xPath->SetRootName( m_sRootLabel );
+ m_xTreeView->clear();
+
+ m_xTreeView->InsertRootEntry(rURL, m_sRootLabel);
+
+ m_xName_ed->grab_focus();
+
+ m_sLastServiceUrl = sURL;
+
+ m_bServiceChanged = false;
+ }
+
+ m_xPath->SetURL( rURL );
+
+ m_xTreeView->connect_changed(Link<weld::TreeView&,void>());
+
+ // read cached data for this url and fill the tree
+ const ::std::vector< SvtContentEntry >& rFolders = m_xFileView->GetContent();
+ ::std::vector< std::pair< OUString, OUString > > aFolders;
+
+ m_xName_ed->ClearEntries();
+
+ for(const auto & rFolder : rFolders)
+ {
+ //WebDAV folders path ends in '/', so strip it
+ OUString aFolderName = rFolder.maURL;
+ if( rFolder.mbIsFolder && ( ( aFolderName.lastIndexOf( '/' ) + 1 ) == aFolderName.getLength() ) )
+ aFolderName = aFolderName.copy( 0, aFolderName.getLength() - 1 );
+
+ int nTitleStart = aFolderName.lastIndexOf( '/' );
+ if( nTitleStart != -1 )
+ {
+ OUString sTitle( INetURLObject::decode(
+ aFolderName.copy( nTitleStart + 1 ),
+ INetURLObject::DecodeMechanism::WithCharset ) );
+
+ if( rFolder.mbIsFolder )
+ {
+ aFolders.emplace_back( sTitle, aFolderName );
+ }
+
+ // add entries to the autocompletion mechanism
+ m_xName_ed->AddEntry( sTitle );
+ }
+ }
+
+ m_xTreeView->FillTreeEntry( rURL, aFolders );
+
+ m_xTreeView->connect_changed( LINK( this, RemoteFilesDialog, TreeSelectHdl ) );
+
+ m_bIsConnected = true;
+ EnableControls();
+}
+
+void RemoteFilesDialog::EnableAutocompletion( bool )
+{
+ // This dialog contains Breadcrumb, not Edit
+}
+
+const OUString& RemoteFilesDialog::GetPath()
+{
+ return m_sPath;
+}
+
+std::vector<OUString> RemoteFilesDialog::GetPathList() const
+{
+ std::vector<OUString> aList;
+
+ m_xFileView->selected_foreach([this, &aList](weld::TreeIter& rCurEntry){
+ // url must contain user info, because we need this info in recent files entry
+ // (to fill user field in login box by default)
+ INetURLObject aURL(m_xFileView->GetURL(rCurEntry));
+ INetURLObject aCurrentURL( m_sLastServiceUrl );
+ aURL.SetUser( aCurrentURL.GetUser() );
+
+ aList.push_back( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
+
+ return false;
+ });
+
+ if( aList.empty() && !m_sPath.isEmpty() )
+ aList.push_back( m_sPath );
+
+ return aList;
+}
+
+bool RemoteFilesDialog::ContentIsFolder( const OUString& rURL )
+{
+ try
+ {
+ Reference< XInteractionHandler > xInteractionHandler(
+ InteractionHandler::createWithParent( m_xContext, nullptr ), UNO_QUERY_THROW );
+ Reference< XCommandEnvironment > xEnv = new ::ucbhelper::CommandEnvironment( xInteractionHandler, Reference< XProgressHandler >() );
+ ::ucbhelper::Content aContent( rURL, xEnv, m_xContext );
+
+ return aContent.isFolder();
+ }
+ catch( const Exception& )
+ {
+ // a content doesn't exist
+ }
+
+ return false;
+}
+
+bool RemoteFilesDialog::ContentIsDocument( const OUString& rURL )
+{
+ try
+ {
+ Reference< XInteractionHandler > xInteractionHandler(
+ InteractionHandler::createWithParent( m_xContext, nullptr ), UNO_QUERY_THROW );
+ //check if WebDAV or not
+ if ( !INetURLObject( rURL ).isAnyKnownWebDAVScheme() )
+ {
+ // no webdav, use the interaction handler as is
+ Reference< XCommandEnvironment > xEnv = new ::ucbhelper::CommandEnvironment( xInteractionHandler, Reference< XProgressHandler >() );
+ ::ucbhelper::Content aContent( rURL, xEnv, m_xContext );
+
+ return aContent.isDocument();
+ }
+ else
+ {
+ // It's a webdav URL, so use the same open sequence as in normal open process.
+ // Let's use a comphelper::StillReadWriteInteraction to trap errors here without showing the user.
+ // This sequence will result in an exception if the target URL resource is not present
+ comphelper::StillReadWriteInteraction* pInteraction = new comphelper::StillReadWriteInteraction(xInteractionHandler,xInteractionHandler);
+ css::uno::Reference< css::task::XInteractionHandler > xInteraction(static_cast< css::task::XInteractionHandler* >(pInteraction), css::uno::UNO_QUERY);
+
+ Reference< XCommandEnvironment > xEnv = new ::ucbhelper::CommandEnvironment( xInteraction, Reference< XProgressHandler >() );
+ ::ucbhelper::Content aContent( rURL, xEnv, m_xContext );
+
+ aContent.openStream();
+ return aContent.isDocument();
+ }
+ }
+ catch( const Exception& )
+ {
+ // a content doesn't exist
+ }
+
+ return false;
+}
+
+sal_Int32 RemoteFilesDialog::getAvailableWidth()
+{
+ // This dialog doesn't contain preview
+ return 0;
+}
+
+sal_Int32 RemoteFilesDialog::getAvailableHeight()
+{
+ // This dialog doesn't contain preview
+ return 0;
+}
+
+void RemoteFilesDialog::setImage( const css::uno::Any& )
+{
+ // This dialog doesn't contain preview
+}
+
+bool RemoteFilesDialog::getShowState()
+{
+ // This dialog doesn't contain preview
+ return false;
+}
+
+weld::Widget* RemoteFilesDialog::getControl( sal_Int16, bool) const
+{
+ return nullptr;
+}
+
+void RemoteFilesDialog::enableControl( sal_Int16, bool )
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */