From ed5640d8b587fbcfed7dd7967f3de04b37a76f26 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 11:06:44 +0200 Subject: Adding upstream version 4:7.4.7. Signed-off-by: Daniel Baumann --- svtools/source/dialogs/PlaceEditDialog.cxx | 374 ++++++++ svtools/source/dialogs/ServerDetailsControls.cxx | 492 ++++++++++ svtools/source/dialogs/ServerDetailsControls.hxx | 143 +++ svtools/source/dialogs/addresstemplate.cxx | 1122 ++++++++++++++++++++++ svtools/source/dialogs/colrdlg.cxx | 161 ++++ svtools/source/dialogs/insdlg.cxx | 356 +++++++ svtools/source/dialogs/prnsetup.cxx | 351 +++++++ svtools/source/dialogs/restartdialog.cxx | 124 +++ 8 files changed, 3123 insertions(+) create mode 100644 svtools/source/dialogs/PlaceEditDialog.cxx create mode 100644 svtools/source/dialogs/ServerDetailsControls.cxx create mode 100644 svtools/source/dialogs/ServerDetailsControls.hxx create mode 100644 svtools/source/dialogs/addresstemplate.cxx create mode 100644 svtools/source/dialogs/colrdlg.cxx create mode 100644 svtools/source/dialogs/insdlg.cxx create mode 100644 svtools/source/dialogs/prnsetup.cxx create mode 100644 svtools/source/dialogs/restartdialog.cxx (limited to 'svtools/source/dialogs') diff --git a/svtools/source/dialogs/PlaceEditDialog.cxx b/svtools/source/dialogs/PlaceEditDialog.cxx new file mode 100644 index 000000000..b61abd58e --- /dev/null +++ b/svtools/source/dialogs/PlaceEditDialog.cxx @@ -0,0 +1,374 @@ +/* -*- 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 + +#include + +#include +#include +#include +#include +#include + +#include "ServerDetailsControls.hxx" + +using namespace com::sun::star::uno; + +PlaceEditDialog::PlaceEditDialog(weld::Window* pParent) + : GenericDialogController(pParent, "svt/ui/placeedit.ui", "PlaceEditDialog") + , m_xCurrentDetails() + , m_nCurrentType( 0 ) + , m_bLabelChanged( false ) + , m_bShowPassword( true ) + , m_xEDServerName(m_xBuilder->weld_entry("name")) + , m_xLBServerType(m_xBuilder->weld_combo_box("type")) + , m_xEDUsername(m_xBuilder->weld_entry("login")) + , m_xFTUsernameLabel(m_xBuilder->weld_label("loginLabel")) + , m_xBTOk(m_xBuilder->weld_button("ok")) + , m_xBTCancel(m_xBuilder->weld_button("cancel")) + , m_xBTDelete(m_xBuilder->weld_button("delete")) + , m_xBTRepoRefresh(m_xBuilder->weld_button("repositoriesRefresh")) + , m_xCBPassword(m_xBuilder->weld_check_button("rememberPassword")) + , m_xEDPassword(m_xBuilder->weld_entry("password")) + , m_xFTPasswordLabel(m_xBuilder->weld_label("passwordLabel")) + , m_xTypeGrid(m_xBuilder->weld_widget("TypeGrid")) + + , m_xRepositoryBox(m_xBuilder->weld_widget("RepositoryDetails")) + , m_xFTRepository(m_xBuilder->weld_label("repositoryLabel")) + , m_xLBRepository(m_xBuilder->weld_combo_box("repositories")) + + , m_xEDShare(m_xBuilder->weld_entry("share")) + , m_xFTShare(m_xBuilder->weld_label("shareLabel")) + + , m_xDetailsGrid(m_xBuilder->weld_widget("Details")) + , m_xHostBox(m_xBuilder->weld_widget("HostDetails")) + , m_xEDHost(m_xBuilder->weld_entry("host")) + , m_xFTHost(m_xBuilder->weld_label("hostLabel")) + , m_xEDPort(m_xBuilder->weld_spin_button("port")) + , m_xFTPort(m_xBuilder->weld_label("portLabel")) + , m_xEDRoot(m_xBuilder->weld_entry("path")) + , m_xFTRoot(m_xBuilder->weld_label("pathLabel")) + + , m_xCBDavs(m_xBuilder->weld_check_button("webdavs")) +{ + m_xBTOk->connect_clicked( LINK( this, PlaceEditDialog, OKHdl) ); + m_xBTOk->set_sensitive( false ); + + m_xEDServerName->connect_changed( LINK( this, PlaceEditDialog, EditLabelHdl) ); + + // This constructor is called when user request a place creation, so + // delete button is hidden. + m_xBTDelete->hide(); + + m_xLBServerType->connect_changed( LINK( this, PlaceEditDialog, SelectTypeHdl ) ); + m_xEDUsername->connect_changed( LINK( this, PlaceEditDialog, EditUsernameHdl ) ); + m_xEDPassword->connect_changed( LINK( this, PlaceEditDialog, EditUsernameHdl ) ); + + InitDetails( ); +} + +PlaceEditDialog::PlaceEditDialog(weld::Window* pParent, const std::shared_ptr& rPlace) + : GenericDialogController(pParent, "svt/ui/placeedit.ui", "PlaceEditDialog") + , m_xCurrentDetails( ) + , m_bLabelChanged( true ) + , m_bShowPassword( false ) + , m_xEDServerName(m_xBuilder->weld_entry("name")) + , m_xLBServerType(m_xBuilder->weld_combo_box("type")) + , m_xEDUsername(m_xBuilder->weld_entry("login")) + , m_xFTUsernameLabel(m_xBuilder->weld_label("loginLabel")) + , m_xBTOk(m_xBuilder->weld_button("ok")) + , m_xBTCancel(m_xBuilder->weld_button("cancel")) + , m_xBTDelete(m_xBuilder->weld_button("delete")) + , m_xBTRepoRefresh(m_xBuilder->weld_button("repositoriesRefresh")) + , m_xCBPassword(m_xBuilder->weld_check_button("rememberPassword")) + , m_xEDPassword(m_xBuilder->weld_entry("password")) + , m_xFTPasswordLabel(m_xBuilder->weld_label("passwordLabel")) + , m_xTypeGrid(m_xBuilder->weld_widget("TypeGrid")) + + , m_xRepositoryBox(m_xBuilder->weld_widget("RepositoryDetails")) + , m_xFTRepository(m_xBuilder->weld_label("repositoryLabel")) + , m_xLBRepository(m_xBuilder->weld_combo_box("repositories")) + + , m_xEDShare(m_xBuilder->weld_entry("share")) + , m_xFTShare(m_xBuilder->weld_label("shareLabel")) + + , m_xDetailsGrid(m_xBuilder->weld_widget("Details")) + , m_xHostBox(m_xBuilder->weld_widget("HostDetails")) + , m_xEDHost(m_xBuilder->weld_entry("host")) + , m_xFTHost(m_xBuilder->weld_label("hostLabel")) + , m_xEDPort(m_xBuilder->weld_spin_button("port")) + , m_xFTPort(m_xBuilder->weld_label("portLabel")) + , m_xEDRoot(m_xBuilder->weld_entry("path")) + , m_xFTRoot(m_xBuilder->weld_label("pathLabel")) + + , m_xCBDavs(m_xBuilder->weld_check_button("webdavs")) +{ + m_xEDPassword->hide(); + m_xFTPasswordLabel->hide(); + m_xCBPassword->hide(); + + m_xBTOk->connect_clicked( LINK( this, PlaceEditDialog, OKHdl) ); + m_xBTDelete->connect_clicked( LINK( this, PlaceEditDialog, DelHdl) ); + + m_xEDServerName->connect_changed( LINK( this, PlaceEditDialog, ModifyHdl) ); + m_xLBServerType->connect_changed( LINK( this, PlaceEditDialog, SelectTypeHdl ) ); + + InitDetails( ); + + m_xEDServerName->set_text(rPlace->GetName()); + + // Fill the boxes with the URL parts + bool bSuccess = false; + for (size_t i = 0 ; i < m_aDetailsContainers.size( ) && !bSuccess; ++i) + { + INetURLObject& rUrl = rPlace->GetUrlObject(); + bSuccess = m_aDetailsContainers[i]->setUrl( rUrl ); + if ( bSuccess ) + { + // Fill the Username field + if ( rUrl.HasUserData( ) ) + { + m_xEDUsername->set_text( rUrl.GetUser(INetURLObject::DecodeMechanism::WithCharset) ); + m_aDetailsContainers[i]->setUsername( rUrl.GetUser(INetURLObject::DecodeMechanism::WithCharset) ); + } + + m_xLBServerType->set_active(i); + SelectType(true); + } + } + + // In edit mode user can't change connection type + m_xTypeGrid->hide(); +} + +PlaceEditDialog::~PlaceEditDialog() +{ +} + +OUString PlaceEditDialog::GetServerUrl() +{ + OUString sUrl; + if (m_xCurrentDetails) + { + INetURLObject aUrl = m_xCurrentDetails->getUrl(); + OUString sUsername = m_xEDUsername->get_text().trim(); + if ( !sUsername.isEmpty( ) ) + aUrl.SetUser( sUsername ); + if ( !aUrl.HasError( ) ) + sUrl = aUrl.GetMainURL( INetURLObject::DecodeMechanism::NONE ); + } + + return sUrl; +} + +std::shared_ptr PlaceEditDialog::GetPlace() +{ + return std::make_shared(m_xEDServerName->get_text(), GetServerUrl(), true); +} + +void PlaceEditDialog::InitDetails( ) +{ + // Create CMIS controls for each server type + + // Load the ServerType entries + bool bSkipGDrive = OUString( GDRIVE_CLIENT_ID ).isEmpty() || + OUString( GDRIVE_CLIENT_SECRET ).isEmpty(); + bool bSkipAlfresco = OUString( ALFRESCO_CLOUD_CLIENT_ID ).isEmpty() || + OUString( ALFRESCO_CLOUD_CLIENT_SECRET ).isEmpty(); + bool bSkipOneDrive= OUString( ONEDRIVE_CLIENT_ID ).isEmpty() || + OUString( ONEDRIVE_CLIENT_SECRET ).isEmpty(); + + Sequence< OUString > aTypesUrlsList( officecfg::Office::Common::Misc::CmisServersUrls::get() ); + Sequence< OUString > aTypesNamesList( officecfg::Office::Common::Misc::CmisServersNames::get() ); + + int nPos = 0; + auto nSize = std::min(aTypesUrlsList.getLength(), aTypesNamesList.getLength()); + for ( sal_Int32 i = 0; i < nSize; ++i ) + { + OUString sUrl = aTypesUrlsList[i].replaceFirst("", OUStringConcatenation(SvtResId(STR_SVT_PORT) + ">")); + + if ((sUrl == GDRIVE_BASE_URL && bSkipGDrive) || + (sUrl.startsWith( ALFRESCO_CLOUD_BASE_URL) && bSkipAlfresco) || + (sUrl == ONEDRIVE_BASE_URL && bSkipOneDrive)) + { + // this service is not supported + continue; + } + + m_xLBServerType->insert_text(nPos, aTypesNamesList[i].replaceFirst("Other CMIS", SvtResId(STR_SVT_OTHER_CMIS))); + + std::shared_ptr xCmisDetails(std::make_shared(this, sUrl)); + xCmisDetails->setChangeHdl( LINK( this, PlaceEditDialog, EditHdl ) ); + m_aDetailsContainers.push_back(xCmisDetails); + + ++nPos; + } + + // Create WebDAV / FTP / SSH details control + std::shared_ptr xDavDetails(std::make_shared(this)); + xDavDetails->setChangeHdl( LINK( this, PlaceEditDialog, EditHdl ) ); + m_aDetailsContainers.push_back(xDavDetails); + + std::shared_ptr xFtpDetails(std::make_shared(this, 21, "ftp")); + xFtpDetails->setChangeHdl( LINK( this, PlaceEditDialog, EditHdl ) ); + m_aDetailsContainers.push_back(xFtpDetails); + + std::shared_ptr xSshDetails(std::make_shared(this, 22, "sftp")); + xSshDetails->setChangeHdl( LINK( this, PlaceEditDialog, EditHdl ) ); + m_aDetailsContainers.push_back(xSshDetails); + + // Remove Windows Share entry from dialog on Windows OS, where it's non-functional +#if defined(_WIN32) + // nPos is the position of first item that is pre-defined in svtools/uiconfig/ui/placeedit.ui, + // after other CMIS types were inserted + m_xLBServerType->remove(nPos + 3); +#else + // Create Windows Share control + std::shared_ptr xSmbDetails(std::make_shared(this)); + xSmbDetails->setChangeHdl( LINK( this, PlaceEditDialog, EditHdl ) ); + m_aDetailsContainers.push_back(xSmbDetails); +#endif + + // Set default to first value + m_xLBServerType->set_active(0); + + if (m_xLBServerType->get_active_text() == "--------------------" ) + m_xLBServerType->set_active(1); + + SelectType(true); +} + +IMPL_LINK( PlaceEditDialog, OKHdl, weld::Button&, /*rBtn*/, void) +{ + if ( !m_xCurrentDetails ) + return; + + OUString sUrl = m_xCurrentDetails->getUrl().GetHost( INetURLObject::DecodeMechanism::WithCharset ); + + if ( sUrl.startsWith( GDRIVE_BASE_URL ) + || sUrl.startsWith( ALFRESCO_CLOUD_BASE_URL ) + || sUrl.startsWith( ONEDRIVE_BASE_URL ) ) + { + m_xBTRepoRefresh->clicked(); + + sUrl = m_xCurrentDetails->getUrl().GetHost( INetURLObject::DecodeMechanism::WithCharset ); + INetURLObject aHostUrl( sUrl ); + OUString sRepoId = aHostUrl.GetMark(); + + if ( !sRepoId.isEmpty() ) + { + m_xDialog->response(RET_OK); + } + else + { + // TODO: repository id missing. Auth error? + } + } + else + { + m_xDialog->response(RET_OK); + } +} + +IMPL_LINK( PlaceEditDialog, DelHdl, weld::Button&, /*rButton*/, void) +{ + // ReUsing existing symbols... + m_xDialog->response(RET_NO); +} + +IMPL_LINK_NOARG( PlaceEditDialog, EditHdl, DetailsContainer*, void ) +{ + if( !m_bLabelChanged ) + { + if( !m_xEDUsername->get_text().isEmpty( ) ) + { + OUString sLabel = SvtResId( STR_SVT_DEFAULT_SERVICE_LABEL ); + OUString sUser = m_xEDUsername->get_text(); + + int nLength = sUser.indexOf( '@' ); + if( nLength < 0 ) + nLength = sUser.getLength(); + + sLabel = sLabel.replaceFirst( "$user$", sUser.subView( 0, nLength ) ); + sLabel = sLabel.replaceFirst( "$service$", m_xLBServerType->get_active_text() ); + + m_xEDServerName->set_text( sLabel ); + m_bLabelChanged = false; + } + else + { + m_xEDServerName->set_text( m_xLBServerType->get_active_text( ) ); + } + } + + OUString sUrl = GetServerUrl( ); + OUString sName = m_xEDServerName->get_text().trim(); + m_xBTOk->set_sensitive( !sName.isEmpty( ) && !sUrl.isEmpty( ) ); +} + +IMPL_LINK_NOARG( PlaceEditDialog, ModifyHdl, weld::Entry&, void ) +{ + EditHdl(nullptr); +} + +IMPL_LINK_NOARG( PlaceEditDialog, EditLabelHdl, weld::Entry&, void ) +{ + m_bLabelChanged = true; + EditHdl(nullptr); +} + +IMPL_LINK_NOARG( PlaceEditDialog, EditUsernameHdl, weld::Entry&, void ) +{ + for ( auto& rxDetailsContainer : m_aDetailsContainers ) + { + rxDetailsContainer->setUsername( m_xEDUsername->get_text() ); + rxDetailsContainer->setPassword( m_xEDPassword->get_text() ); + } + + EditHdl(nullptr); +} + +IMPL_LINK_NOARG( PlaceEditDialog, SelectTypeHdl, weld::ComboBox&, void ) +{ + SelectType(false); +} + +void PlaceEditDialog::SelectType(bool bSkipSeparator) +{ + if ( m_xLBServerType->get_active_text() == "--------------------" ) + { + if (bSkipSeparator) + m_xLBServerType->set_active(m_nCurrentType); + else + m_xLBServerType->set_active(-1); + return; + } + + if (m_xCurrentDetails) + m_xCurrentDetails->set_visible(false); + + const int nPos = m_xLBServerType->get_active( ); + m_xCurrentDetails = m_aDetailsContainers[nPos]; + m_nCurrentType = nPos; + + m_xCurrentDetails->set_visible(true); + + m_xCBPassword->set_visible( m_bShowPassword && m_xCurrentDetails->enableUserCredentials() ); + m_xEDPassword->set_visible( m_bShowPassword && m_xCurrentDetails->enableUserCredentials() ); + m_xFTPasswordLabel->set_visible( m_bShowPassword && m_xCurrentDetails->enableUserCredentials() ); + m_xEDUsername->set_visible( m_xCurrentDetails->enableUserCredentials() ); + m_xFTUsernameLabel->set_visible( m_xCurrentDetails->enableUserCredentials() ); + + m_xDialog->resize_to_request(); + + EditHdl(nullptr); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svtools/source/dialogs/ServerDetailsControls.cxx b/svtools/source/dialogs/ServerDetailsControls.cxx new file mode 100644 index 000000000..24a6de413 --- /dev/null +++ b/svtools/source/dialogs/ServerDetailsControls.cxx @@ -0,0 +1,492 @@ +/* -*- 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 +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ServerDetailsControls.hxx" + +using namespace com::sun::star::sdbc; +using namespace com::sun::star::task; +using namespace com::sun::star::ucb; +using namespace com::sun::star::uno; + +DetailsContainer::DetailsContainer(PlaceEditDialog* pDialog) + : m_pDialog(pDialog) +{ + m_pDialog->m_xEDPort->connect_output(LINK(this, DetailsContainer, FormatPortHdl)); +} + +//format without thousand separator +IMPL_STATIC_LINK(DetailsContainer, FormatPortHdl, weld::SpinButton&, rSpinButton, void) +{ + rSpinButton.set_text(OUString::number(rSpinButton.get_value())); +} + +DetailsContainer::~DetailsContainer( ) +{ +} + +void DetailsContainer::set_visible( bool ) +{ + m_pDialog->m_xDetailsGrid->set_sensitive(true); + + m_pDialog->m_xEDHost->connect_changed( LINK( this, DetailsContainer, ValueChangeHdl ) ); + m_pDialog->m_xEDPort->connect_changed( LINK( this, DetailsContainer, ValueChangeHdl ) ); + m_pDialog->m_xEDRoot->connect_changed( LINK( this, DetailsContainer, ValueChangeHdl ) ); +} + +INetURLObject DetailsContainer::getUrl( ) +{ + // Don't use that class directly: make it smarter by subclassing it. + return INetURLObject( ); +} + +bool DetailsContainer::setUrl( const INetURLObject& ) +{ + // That class doesn't contain any logic... it defers the dirty work + // to the sub classes. + return false; +} + +void DetailsContainer::notifyChange( ) +{ + m_aChangeHdl.Call( this ); +} + +IMPL_LINK_NOARG( DetailsContainer, ValueChangeHdl, weld::Entry&, void ) +{ + notifyChange( ); +} + +HostDetailsContainer::HostDetailsContainer(PlaceEditDialog* pDialog, sal_uInt16 nPort, const OUString& sScheme) : + DetailsContainer( pDialog ), + m_nDefaultPort( nPort ), + m_sScheme( sScheme ) +{ + set_visible( false ); +} + +void HostDetailsContainer::set_visible( bool bShow ) +{ + m_pDialog->m_xFTHost->set_visible( bShow ); + m_pDialog->m_xHostBox->set_visible( bShow ); + m_pDialog->m_xEDRoot->set_visible( bShow ); + m_pDialog->m_xFTRoot->set_visible( bShow ); + + DetailsContainer::set_visible( bShow ); + + if ( bShow ) + { + if (m_pDialog->m_xEDPort->get_value() == 0) + m_pDialog->m_xEDPort->set_value( m_nDefaultPort ); + m_pDialog->m_xEDHost->set_text( m_sHost ); + } + else + m_pDialog->m_xEDPort->set_value( 0 ); +} + +INetURLObject HostDetailsContainer::getUrl( ) +{ + OUString sHost = m_pDialog->m_xEDHost->get_text().trim(); + sal_Int64 nPort = m_pDialog->m_xEDPort->get_value(); + OUString sPath = m_pDialog->m_xEDRoot->get_text().trim(); + + OUString sUrl; + if ( !sHost.isEmpty( ) ) + { + sUrl = m_sScheme + "://" + sHost; + if ( nPort != m_nDefaultPort ) + sUrl += ":" + OUString::number( nPort ); + if ( !sPath.isEmpty( ) ) + if ( sPath.indexOf( '/' ) != 0 ) + sUrl += "/"; + sUrl += sPath; + } + + return INetURLObject( sUrl ); +} + +bool HostDetailsContainer::setUrl( const INetURLObject& rUrl ) +{ + bool bSuccess = verifyScheme( INetURLObject::GetScheme( rUrl.GetProtocol( ) ) ); + + if ( bSuccess ) + { + m_sHost = rUrl.GetHost( ); + m_pDialog->m_xEDHost->set_text( rUrl.GetHost( ) ); + m_pDialog->m_xEDPort->set_value( rUrl.GetPort( ) ); + m_pDialog->m_xEDRoot->set_text( rUrl.GetURLPath() ); + } + + return bSuccess; +} + +bool HostDetailsContainer::verifyScheme( const OUString& sScheme ) +{ + return sScheme == OUStringConcatenation( m_sScheme + "://" ); +} + +DavDetailsContainer::DavDetailsContainer(PlaceEditDialog* pBuilder) + : HostDetailsContainer(pBuilder, 80, "http") +{ + m_pDialog->m_xCBDavs->connect_toggled(LINK(this, DavDetailsContainer, ToggledDavsHdl)); + + set_visible( false ); +} + +void DavDetailsContainer::set_visible( bool bShow ) +{ + HostDetailsContainer::set_visible( bShow ); + + if ( !bShow ) + m_pDialog->m_xCBDavs->set_active(false); + + m_pDialog->m_xCBDavs->set_visible(bShow); +} + +bool DavDetailsContainer::verifyScheme( const OUString& rScheme ) +{ + bool bValid = false; + if ( rScheme == "http://" ) + { + bValid = true; + m_pDialog->m_xCBDavs->set_active(false); + ToggledDavsHdl(*m_pDialog->m_xCBDavs); + } + else if ( rScheme == "https://" ) + { + bValid = true; + m_pDialog->m_xCBDavs->set_active(true); + ToggledDavsHdl(*m_pDialog->m_xCBDavs); + } + return bValid; +} + +IMPL_LINK( DavDetailsContainer, ToggledDavsHdl, weld::Toggleable&, rCheckBox, void ) +{ + // Change default port if needed + bool bCheckedDavs = rCheckBox.get_active(); + if ( m_pDialog->m_xEDPort->get_value() == 80 && bCheckedDavs ) + m_pDialog->m_xEDPort->set_value( 443 ); + else if ( m_pDialog->m_xEDPort->get_value() == 443 && !bCheckedDavs ) + m_pDialog->m_xEDPort->set_value( 80 ); + + OUString sScheme( "http" ); + if ( bCheckedDavs ) + sScheme = "https"; + setScheme( sScheme ); + + notifyChange( ); +} + +SmbDetailsContainer::SmbDetailsContainer(PlaceEditDialog* pDialog) + : DetailsContainer(pDialog) +{ + m_pDialog->m_xEDShare->connect_changed( LINK( this, DetailsContainer, ValueChangeHdl ) ); + + set_visible( false ); +} + +INetURLObject SmbDetailsContainer::getUrl( ) +{ + OUString sHost = m_pDialog->m_xEDHost->get_text().trim( ); + OUString sShare = m_pDialog->m_xEDShare->get_text().trim( ); + OUString sPath = m_pDialog->m_xEDRoot->get_text().trim( ); + + OUString sUrl; + if ( !sHost.isEmpty( ) ) + { + sUrl = "smb://" + sHost + "/"; + if ( !sShare.isEmpty( ) ) + sUrl += sShare; + if ( !sPath.isEmpty( ) ) + if ( sPath.indexOf( '/' ) != 0 ) + sUrl += "/"; + sUrl += sPath; + } + + return INetURLObject( sUrl ); +} + +bool SmbDetailsContainer::setUrl( const INetURLObject& rUrl ) +{ + bool bSuccess = rUrl.GetProtocol() == INetProtocol::Smb; + + if ( bSuccess ) + { + OUString sShare = rUrl.getName( 0 ); + OUString sFullPath = rUrl.GetURLPath( ); + OUString sPath; + if ( sFullPath.getLength( ) > sShare.getLength( ) ) + { + sal_Int32 nPos = sShare.getLength( ); + if ( nPos != 0 ) + ++nPos; + sPath = sFullPath.copy( nPos ); + } + + m_sHost = rUrl.GetHost( ); + m_pDialog->m_xEDHost->set_text( m_sHost ); + m_pDialog->m_xEDShare->set_text( sShare ); + m_pDialog->m_xEDRoot->set_text( sPath ); + } + + return bSuccess; +} + +void SmbDetailsContainer::set_visible( bool bShow ) +{ + m_pDialog->m_xEDShare->set_visible( bShow ); + m_pDialog->m_xFTShare->set_visible( bShow ); + m_pDialog->m_xEDRoot->set_visible( bShow ); + m_pDialog->m_xFTRoot->set_visible( bShow ); + + m_pDialog->m_xFTHost->set_visible( bShow ); + m_pDialog->m_xHostBox->set_visible( bShow ); + m_pDialog->m_xEDPort->set_sensitive( !bShow ); + m_pDialog->m_xFTPort->set_sensitive( !bShow ); + + if ( bShow ) + m_pDialog->m_xEDHost->set_text( m_sHost ); +} + +CmisDetailsContainer::CmisDetailsContainer(PlaceEditDialog* pParentDialog, OUString const & sBinding) : + DetailsContainer( pParentDialog ), + m_sUsername( ), + m_xCmdEnv( ), + m_aRepoIds( ), + m_sRepoId( ), + m_sBinding( sBinding ), + m_xParentDialog(pParentDialog->getDialog()->GetXWindow()) +{ + Reference< XComponentContext > xContext = ::comphelper::getProcessComponentContext(); + Reference< XInteractionHandler > xGlobalInteractionHandler = + InteractionHandler::createWithParent(xContext, m_xParentDialog); + m_xCmdEnv = new ucbhelper::CommandEnvironment( xGlobalInteractionHandler, Reference< XProgressHandler >() ); + + set_visible( false ); +} + +void CmisDetailsContainer::set_visible( bool bShow ) +{ + m_pDialog->m_xLBRepository->connect_changed( LINK( this, CmisDetailsContainer, SelectRepoHdl ) ); + m_pDialog->m_xBTRepoRefresh->connect_clicked( LINK( this, CmisDetailsContainer, RefreshReposHdl ) ); + + m_pDialog->m_xEDHost->set_text( m_sBinding ); + + if( ( m_sBinding == GDRIVE_BASE_URL ) + || m_sBinding.startsWith( ALFRESCO_CLOUD_BASE_URL ) + || ( m_sBinding == ONEDRIVE_BASE_URL ) ) + { + m_pDialog->m_xFTHost->hide(); + m_pDialog->m_xHostBox->hide(); + m_pDialog->m_xFTRepository->hide(); + m_pDialog->m_xRepositoryBox->hide(); + m_pDialog->m_xEDRoot->hide(); + m_pDialog->m_xFTRoot->hide(); + } + else + { + m_pDialog->m_xFTHost->set_visible( bShow ); + m_pDialog->m_xHostBox->set_visible( bShow ); + m_pDialog->m_xFTRepository->set_visible( bShow ); + m_pDialog->m_xRepositoryBox->set_visible( bShow ); + m_pDialog->m_xEDRoot->set_visible( bShow ); + m_pDialog->m_xFTRoot->set_visible( bShow ); + } + + DetailsContainer::set_visible( bShow ); + m_pDialog->m_xEDPort->set_sensitive( !bShow ); + m_pDialog->m_xFTPort->set_sensitive( !bShow ); +} + +INetURLObject CmisDetailsContainer::getUrl( ) +{ + OUString sBindingUrl = m_pDialog->m_xEDHost->get_text().trim(); + OUString sPath = m_pDialog->m_xEDRoot->get_text().trim(); + + bool bSkip = true; + if( ( m_sBinding == GDRIVE_BASE_URL ) + || m_sBinding.startsWith( ALFRESCO_CLOUD_BASE_URL ) + || ( m_sBinding == ONEDRIVE_BASE_URL ) ) + { + bSkip = m_sUsername.isEmpty(); + } + else + { + bSkip = m_sRepoId.isEmpty(); + } + + OUString sUrl; + if ( !sBindingUrl.isEmpty( ) && !bSkip ) + { + OUString sEncodedBinding = rtl::Uri::encode( + sBindingUrl + "#" + m_sRepoId, + rtl_UriCharClassRelSegment, + rtl_UriEncodeKeepEscapes, + RTL_TEXTENCODING_UTF8 ); + sUrl = "vnd.libreoffice.cmis://" + sEncodedBinding; + } + sUrl += sPath; + + return INetURLObject( sUrl ); +} + +bool CmisDetailsContainer::setUrl( const INetURLObject& rUrl ) +{ + bool bSuccess = rUrl.GetProtocol() == INetProtocol::Cmis; + + if ( bSuccess ) + { + OUString sDecodedHost = rUrl.GetHost( INetURLObject::DecodeMechanism::WithCharset ); + INetURLObject aHostUrl( sDecodedHost ); + m_sBinding = aHostUrl.GetURLNoMark( ); + m_sRepoId = aHostUrl.GetMark( ); + + m_pDialog->m_xEDHost->set_text( m_sBinding ); + m_pDialog->m_xEDRoot->set_text( rUrl.GetURLPath() ); + } + return bSuccess; +} + +void CmisDetailsContainer::setUsername( const OUString& rUsername ) +{ + m_sUsername = rUsername; +} + +void CmisDetailsContainer::setPassword( const OUString& rPass ) +{ + m_sPassword = rPass; +} + +void CmisDetailsContainer::selectRepository( ) +{ + // Get the repo ID and call the Change listener + const int nPos = m_pDialog->m_xLBRepository->get_active(); + if( o3tl::make_unsigned(nPos) < m_aRepoIds.size() ) + { + m_sRepoId = m_aRepoIds[nPos]; + notifyChange( ); + } +} + +IMPL_LINK_NOARG( CmisDetailsContainer, RefreshReposHdl, weld::Button&, void ) +{ + Reference< XComponentContext > xContext = ::comphelper::getProcessComponentContext(); + Reference< XPasswordContainer2 > xMasterPasswd = PasswordContainer::create( xContext ); + + + OUString sBindingUrl = m_pDialog->m_xEDHost->get_text().trim( ); + + OUString sEncodedUsername = ""; + + if ( !m_sUsername.isEmpty( ) ) + { + sEncodedUsername = rtl::Uri::encode(m_sUsername, + rtl_UriCharClassUserinfo, + rtl_UriEncodeKeepEscapes, + RTL_TEXTENCODING_UTF8 ) + + "@"; + } + + // Clean the listbox + m_pDialog->m_xLBRepository->clear(); + m_aRepoIds.clear(); + + // Compute the URL + OUString sUrl; + if ( !sBindingUrl.isEmpty( ) ) + { + OUString sEncodedBinding = rtl::Uri::encode( + sBindingUrl, + rtl_UriCharClassRelSegment, + rtl_UriEncodeKeepEscapes, + RTL_TEXTENCODING_UTF8 ); + sUrl = "vnd.libreoffice.cmis://" + sEncodedUsername + sEncodedBinding; + } + + // temporary remember the password + try + { + if( !sUrl.isEmpty() && !m_sUsername.isEmpty() && !m_sPassword.isEmpty() ) + { + Reference< XInteractionHandler > xInteractionHandler = + InteractionHandler::createWithParent(xContext, m_xParentDialog); + + Sequence aPasswd { m_sPassword }; + + xMasterPasswd->add( + sUrl, m_sUsername, aPasswd, xInteractionHandler ); + } + } + catch( const Exception& ) + {} + + try + { + // Get the Content + ::ucbhelper::Content aCnt( sUrl, m_xCmdEnv, comphelper::getProcessComponentContext() ); + Sequence aProps { "Title" }; + Reference< XResultSet > xResultSet( aCnt.createCursor( aProps ), UNO_SET_THROW ); + Reference< XContentAccess > xAccess( xResultSet, UNO_QUERY_THROW ); + while ( xResultSet->next() ) + { + OUString sURL = xAccess->queryContentIdentifierString( ); + INetURLObject aURL( sURL ); + OUString sId = aURL.GetURLPath( INetURLObject::DecodeMechanism::WithCharset ); + sId = sId.copy( 1 ); + m_aRepoIds.push_back( sId ); + + Reference< XRow > xRow( xResultSet, UNO_QUERY ); + OUString sName = xRow->getString( 1 ); + m_pDialog->m_xLBRepository->append_text(sName); + } + } + catch ( const Exception&) + { + TOOLS_WARN_EXCEPTION( "svtools.dialogs", "RefreshReposHdl" ); + } + + // Auto-select the first one + if (m_pDialog->m_xLBRepository->get_count() > 0) + { + m_pDialog->m_xLBRepository->set_active(0); + selectRepository( ); + } + + // remove temporary password + try + { + xMasterPasswd->remove( sUrl, m_sUsername ); + } + catch( const Exception& ) + {} +} + +IMPL_LINK_NOARG( CmisDetailsContainer, SelectRepoHdl, weld::ComboBox&, void ) +{ + selectRepository( ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svtools/source/dialogs/ServerDetailsControls.hxx b/svtools/source/dialogs/ServerDetailsControls.hxx new file mode 100644 index 000000000..b0f892fe2 --- /dev/null +++ b/svtools/source/dialogs/ServerDetailsControls.hxx @@ -0,0 +1,143 @@ +/* -*- 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/. + */ +#ifndef INCLUDED_SVTOOLS_SERVERDETAILSCONTROLS_HXX +#define INCLUDED_SVTOOLS_SERVERDETAILSCONTROLS_HXX + +#include + +#include + +#include +#include +#include + +namespace com :: sun :: star :: ucb { class XCommandEnvironment; } +namespace com :: sun :: star :: awt { class XWindow; } + +namespace weld { + class Button; + class ComboBox; + class Entry; + class SpinButton; + class ToggleButton; +} + +class PlaceEditDialog; + +class DetailsContainer +{ + protected: + PlaceEditDialog* m_pDialog; + Link m_aChangeHdl; + + public: + DetailsContainer(PlaceEditDialog* pDialog); + virtual ~DetailsContainer( ); + + void setChangeHdl( const Link& rLink ) { m_aChangeHdl = rLink; } + + virtual void set_visible( bool bShow ); + virtual INetURLObject getUrl( ); + + /** Try to split the URL in the controls of that container. + + \param sUrl the URL to split + \return true if the split worked, false otherwise. + */ + virtual bool setUrl( const INetURLObject& rUrl ); + + virtual void setUsername( const OUString& /*rUsername*/ ) { }; + virtual void setPassword( const OUString& ) { }; + + virtual bool enableUserCredentials( ) { return true; }; + + protected: + void notifyChange( ); + DECL_LINK(ValueChangeHdl, weld::Entry&, void); + DECL_STATIC_LINK(DetailsContainer, FormatPortHdl, weld::SpinButton&, void); +}; + +class HostDetailsContainer : public DetailsContainer +{ + private: + sal_uInt16 m_nDefaultPort; + OUString m_sScheme; + OUString m_sHost; + + public: + HostDetailsContainer(PlaceEditDialog* pDialog, sal_uInt16 nPort, const OUString& sScheme); + + virtual void set_visible( bool bShow ) override; + virtual INetURLObject getUrl( ) override; + virtual bool setUrl( const INetURLObject& rUrl ) override; + + protected: + void setScheme( const OUString& sScheme ) { m_sScheme = sScheme; } + + /** Verifies that the scheme split from the URL can be handled by + the container and set the proper controls accordingly if needed. + */ + virtual bool verifyScheme( const OUString& rScheme ); +}; + +class DavDetailsContainer final : public HostDetailsContainer +{ + public: + DavDetailsContainer(PlaceEditDialog* pDialog); + + virtual void set_visible( bool bShow ) override; + virtual bool enableUserCredentials( ) override { return false; }; + + private: + virtual bool verifyScheme( const OUString& rScheme ) override; + + DECL_LINK(ToggledDavsHdl, weld::Toggleable&, void); +}; + +class SmbDetailsContainer final : public DetailsContainer +{ + private: + OUString m_sHost; + + public: + SmbDetailsContainer(PlaceEditDialog* pDialog); + + virtual INetURLObject getUrl( ) override; + virtual bool setUrl( const INetURLObject& rUrl ) override; + virtual void set_visible( bool bShow ) override; +}; + +class CmisDetailsContainer final : public DetailsContainer +{ + private: + OUString m_sUsername; + OUString m_sPassword; + css::uno::Reference< css::ucb::XCommandEnvironment > m_xCmdEnv; + std::vector< OUString > m_aRepoIds; + OUString m_sRepoId; + OUString m_sBinding; + css::uno::Reference< css::awt::XWindow > m_xParentDialog; + + public: + CmisDetailsContainer(PlaceEditDialog* pDialog, OUString const & sBinding); + + virtual void set_visible( bool bShow ) override; + virtual INetURLObject getUrl( ) override; + virtual bool setUrl( const INetURLObject& rUrl ) override; + virtual void setUsername( const OUString& rUsername ) override; + virtual void setPassword( const OUString& rPass ) override; + + private: + void selectRepository( ); + DECL_LINK ( RefreshReposHdl, weld::Button&, void ); + DECL_LINK ( SelectRepoHdl, weld::ComboBox&, void ); +}; + +#endif +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svtools/source/dialogs/addresstemplate.cxx b/svtools/source/dialogs/addresstemplate.cxx new file mode 100644 index 000000000..6f29151e3 --- /dev/null +++ b/svtools/source/dialogs/addresstemplate.cxx @@ -0,0 +1,1122 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace svt +{ + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::container; + using namespace ::com::sun::star::ui::dialogs; + using namespace ::com::sun::star::util; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::sdb; + using namespace ::com::sun::star::sdbc; + using namespace ::com::sun::star::sdbcx; + using namespace ::com::sun::star::task; + using namespace ::comphelper; + using namespace ::utl; + + typedef std::set StringBag; + typedef std::map MapString2String; + + namespace + { + OUString lcl_getSelectedDataSource( const weld::ComboBox& dataSourceCombo ) + { + OUString selectedDataSource = dataSourceCombo.get_active_text(); + if (dataSourceCombo.find_text(selectedDataSource) == -1) + { + // none of the pre-selected entries -> assume a path to a database document + OFileNotation aFileNotation( selectedDataSource, OFileNotation::N_SYSTEM ); + selectedDataSource = aFileNotation.get( OFileNotation::N_URL ); + } + return selectedDataSource; + } + + // = IAssignmentData + + class IAssignmentData + { + public: + virtual ~IAssignmentData(); + + /// the data source to use for the address book + virtual OUString getDatasourceName() const = 0; + + /// the command to use for the address book + virtual OUString getCommand() const = 0; + + /// checks whether or not there is an assignment for a given logical field + virtual bool hasFieldAssignment(const OUString& _rLogicalName) = 0; + /// retrieves the assignment for a given logical field + virtual OUString getFieldAssignment(const OUString& _rLogicalName) = 0; + + /// set the assignment for a given logical field + virtual void setFieldAssignment(const OUString& _rLogicalName, const OUString& _rAssignment) = 0; + + virtual void setDatasourceName(const OUString& _rName) = 0; + virtual void setCommand(const OUString& _rCommand) = 0; + }; + + } + + IAssignmentData::~IAssignmentData() + { + } + + + // = AssignmentTransientData + + namespace { + + class AssignmentTransientData : public IAssignmentData + { + protected: + OUString m_sDSName; + OUString m_sTableName; + MapString2String m_aAliases; + + public: + AssignmentTransientData( + const OUString& _rDataSourceName, + const OUString& _rTableName, + const Sequence< AliasProgrammaticPair >& _rFields + ); + + // IAssignmentData overridables + virtual OUString getDatasourceName() const override; + virtual OUString getCommand() const override; + + virtual bool hasFieldAssignment(const OUString& _rLogicalName) override; + virtual OUString getFieldAssignment(const OUString& _rLogicalName) override; + virtual void setFieldAssignment(const OUString& _rLogicalName, const OUString& _rAssignment) override; + + virtual void setDatasourceName(const OUString& _rName) override; + virtual void setCommand(const OUString& _rCommand) override; + }; + + } + + AssignmentTransientData::AssignmentTransientData( + const OUString& _rDataSourceName, const OUString& _rTableName, + const Sequence< AliasProgrammaticPair >& _rFields ) + :m_sDSName( _rDataSourceName ) + ,m_sTableName( _rTableName ) + { + // fill our aliases structure + // first collect all known programmatic names + StringBag aKnownNames; + + OUString const sLogicalFieldNames(STR_LOGICAL_FIELD_NAMES); + sal_Int32 nIndex = 0; + do + { + OUString aToken = sLogicalFieldNames.getToken(0, ';', nIndex); + aKnownNames.insert(aToken); + } + while ( nIndex >= 0); + + // loop through the given names + for (const AliasProgrammaticPair& rField : _rFields) + { + if ( aKnownNames.end() != aKnownNames.find( rField.ProgrammaticName ) ) + { + m_aAliases[ rField.ProgrammaticName ] = rField.Alias; + } + else + { + SAL_WARN( "svtools", "AssignmentTransientData::AssignmentTransientData: unknown programmatic name: " + << rField.ProgrammaticName ); + } + } + } + + + OUString AssignmentTransientData::getDatasourceName() const + { + return m_sDSName; + } + + + OUString AssignmentTransientData::getCommand() const + { + return m_sTableName; + } + + + bool AssignmentTransientData::hasFieldAssignment(const OUString& _rLogicalName) + { + MapString2String::const_iterator aPos = m_aAliases.find( _rLogicalName ); + return ( m_aAliases.end() != aPos ) + && ( !aPos->second.isEmpty() ); + } + + + OUString AssignmentTransientData::getFieldAssignment(const OUString& _rLogicalName) + { + OUString sReturn; + MapString2String::const_iterator aPos = m_aAliases.find( _rLogicalName ); + if ( m_aAliases.end() != aPos ) + sReturn = aPos->second; + + return sReturn; + } + + + void AssignmentTransientData::setFieldAssignment(const OUString& _rLogicalName, const OUString& _rAssignment) + { + m_aAliases[ _rLogicalName ] = _rAssignment; + } + + + void AssignmentTransientData::setDatasourceName(const OUString&) + { + OSL_FAIL( "AssignmentTransientData::setDatasourceName: cannot be implemented for transient data!" ); + } + + + void AssignmentTransientData::setCommand(const OUString&) + { + OSL_FAIL( "AssignmentTransientData::setCommand: cannot be implemented for transient data!" ); + } + + + // = AssignmentPersistentData + + namespace { + + class AssignmentPersistentData + :public ::utl::ConfigItem + ,public IAssignmentData + { + protected: + StringBag m_aStoredFields; + + protected: + css::uno::Any getProperty(const OUString& _rLocalName) const; + + OUString getStringProperty(const char* _pLocalName) const; + OUString getStringProperty(const OUString& _rLocalName) const; + + void setStringProperty(const char* _pLocalName, const OUString& _rValue); + + public: + AssignmentPersistentData(); + + // IAssignmentData overridables + virtual OUString getDatasourceName() const override; + virtual OUString getCommand() const override; + + virtual bool hasFieldAssignment(const OUString& _rLogicalName) override; + virtual OUString getFieldAssignment(const OUString& _rLogicalName) override; + virtual void setFieldAssignment(const OUString& _rLogicalName, const OUString& _rAssignment) override; + + virtual void setDatasourceName(const OUString& _rName) override; + virtual void setCommand(const OUString& _rCommand) override; + + virtual void Notify( const css::uno::Sequence& aPropertyNames) override; + + private: + virtual void ImplCommit() override; + void clearFieldAssignment(const OUString& _rLogicalName); + }; + + } + +void AssignmentPersistentData::Notify( const css::uno::Sequence& ) +{ +} + +void AssignmentPersistentData::ImplCommit() +{ +} + + + AssignmentPersistentData::AssignmentPersistentData() + :ConfigItem("Office.DataAccess/AddressBook") + { + const Sequence< OUString > aStoredNames = GetNodeNames("Fields"); + m_aStoredFields.insert(aStoredNames.begin(), aStoredNames.end()); + } + + bool AssignmentPersistentData::hasFieldAssignment(const OUString& _rLogicalName) + { + return (m_aStoredFields.end() != m_aStoredFields.find(_rLogicalName)); + } + + + OUString AssignmentPersistentData::getFieldAssignment(const OUString& _rLogicalName) + { + OUString sAssignment; + if (hasFieldAssignment(_rLogicalName)) + { + OUString sFieldPath = "Fields/" + _rLogicalName + "/AssignedFieldName"; + sAssignment = getStringProperty(sFieldPath); + } + return sAssignment; + } + + + Any AssignmentPersistentData::getProperty(const OUString& _rLocalName) const + { + Sequence< OUString > aProperties(&_rLocalName, 1); + Sequence< Any > aValues = const_cast(this)->GetProperties(aProperties); + DBG_ASSERT(aValues.getLength() == 1, "AssignmentPersistentData::getProperty: invalid sequence length!"); + return aValues[0]; + } + + + OUString AssignmentPersistentData::getStringProperty(const OUString& _rLocalName) const + { + OUString sReturn; + getProperty( _rLocalName ) >>= sReturn; + return sReturn; + } + + + OUString AssignmentPersistentData::getStringProperty(const char* _pLocalName) const + { + OUString sReturn; + getProperty(OUString::createFromAscii(_pLocalName)) >>= sReturn; + return sReturn; + } + + + void AssignmentPersistentData::setStringProperty(const char* _pLocalName, const OUString& _rValue) + { + Sequence< OUString > aNames { OUString::createFromAscii(_pLocalName) }; + Sequence< Any > aValues{ Any(_rValue) }; + PutProperties(aNames, aValues); + } + + + void AssignmentPersistentData::setFieldAssignment(const OUString& _rLogicalName, const OUString& _rAssignment) + { + if (_rAssignment.isEmpty()) + { + if (hasFieldAssignment(_rLogicalName)) + { + // the assignment exists but it should be reset + clearFieldAssignment(_rLogicalName); + } + return; + } + + // Fields + OUString sDescriptionNodePath("Fields"); + + // Fields/ + OUString sFieldElementNodePath = sDescriptionNodePath + "/" + _rLogicalName; + + Sequence< PropertyValue > aNewFieldDescription{ + // Fields//ProgrammaticFieldName + comphelper::makePropertyValue(sFieldElementNodePath + "/ProgrammaticFieldName", + _rLogicalName), + // Fields//AssignedFieldName + comphelper::makePropertyValue(sFieldElementNodePath + "/AssignedFieldName", + _rAssignment) + }; + + // just set the new value + bool bSuccess = + SetSetProperties(sDescriptionNodePath, aNewFieldDescription); + DBG_ASSERT(bSuccess, "AssignmentPersistentData::setFieldAssignment: could not commit the changes a field!"); + } + + + void AssignmentPersistentData::clearFieldAssignment(const OUString& _rLogicalName) + { + if (!hasFieldAssignment(_rLogicalName)) + // nothing to do + return; + + Sequence< OUString > aNames(&_rLogicalName, 1); + ClearNodeElements("Fields", aNames); + } + + + OUString AssignmentPersistentData::getDatasourceName() const + { + return getStringProperty( "DataSourceName" ); + } + + + OUString AssignmentPersistentData::getCommand() const + { + return getStringProperty( "Command" ); + } + + + void AssignmentPersistentData::setDatasourceName(const OUString& _rName) + { + setStringProperty( "DataSourceName", _rName ); + } + + + void AssignmentPersistentData::setCommand(const OUString& _rCommand) + { + setStringProperty( "Command", _rCommand ); + } + + + // = AddressBookSourceDialogData + + struct AddressBookSourceDialogData + { + std::array, FIELD_PAIRS_VISIBLE*2> pFieldLabels; + std::array, FIELD_PAIRS_VISIBLE*2> pFields; + + /// when working transient, we need the data source + Reference< XDataSource > + m_xTransientDataSource; + /// current scroll pos in the field list + sal_Int32 nFieldScrollPos; + /// indicates that we've an odd field number. This member is for efficiency only, it's redundant. + bool bOddFieldNumber : 1; + /// indicates that we're working with the real persistent configuration + bool bWorkingPersistent : 1; + + /// the strings to use as labels for the field selection listboxes + std::vector aFieldLabels; + // the current field assignment + std::vector aFieldAssignments; + /// the logical field names + std::vector aLogicalFieldNames; + + std::unique_ptr pConfigData; + + + AddressBookSourceDialogData( ) + :pFieldLabels{{nullptr}} + ,pFields{{nullptr}} + ,nFieldScrollPos(0) + ,bOddFieldNumber(false) + ,bWorkingPersistent( true ) + ,pConfigData( new AssignmentPersistentData ) + { + } + + AddressBookSourceDialogData( const Reference< XDataSource >& _rxTransientDS, const OUString& _rDataSourceName, + const OUString& _rTableName, const Sequence< AliasProgrammaticPair >& _rFields ) + :pFieldLabels{{nullptr}} + ,pFields{{nullptr}} + ,m_xTransientDataSource( _rxTransientDS ) + ,nFieldScrollPos(0) + ,bOddFieldNumber(false) + ,bWorkingPersistent( false ) + ,pConfigData( new AssignmentTransientData( _rDataSourceName, _rTableName, _rFields ) ) + { + } + + // Copy assignment is forbidden and not implemented. + AddressBookSourceDialogData (const AddressBookSourceDialogData &) = delete; + AddressBookSourceDialogData & operator= (const AddressBookSourceDialogData &) = delete; + }; + + // = AddressBookSourceDialog + AddressBookSourceDialog::AddressBookSourceDialog(weld::Window* pParent, + const Reference< XComponentContext >& _rxORB ) + : GenericDialogController(pParent, "svt/ui/addresstemplatedialog.ui", "AddressTemplateDialog") + , m_sNoFieldSelection(SvtResId(STR_NO_FIELD_SELECTION)) + , m_xORB(_rxORB) + , m_pImpl( new AddressBookSourceDialogData ) + { + implConstruct(); + } + + AddressBookSourceDialog::AddressBookSourceDialog(weld::Window* pParent, const Reference< XComponentContext >& _rxORB, + const Reference< XDataSource >& _rxTransientDS, const OUString& _rDataSourceName, + const OUString& _rTable, const Sequence< AliasProgrammaticPair >& _rMapping ) + : GenericDialogController(pParent, "svt/ui/addresstemplatedialog.ui", "AddressTemplateDialog") + , m_sNoFieldSelection(SvtResId(STR_NO_FIELD_SELECTION)) + , m_xORB(_rxORB) + , m_pImpl( new AddressBookSourceDialogData( _rxTransientDS, _rDataSourceName, _rTable, _rMapping ) ) + { + implConstruct(); + } + + void AddressBookSourceDialog::implConstruct() + { + m_xOKButton = m_xBuilder->weld_button("ok"); + m_xDatasource = m_xBuilder->weld_combo_box("datasource"); + m_xAdministrateDatasources = m_xBuilder->weld_button("admin"); + m_xTable = m_xBuilder->weld_combo_box("datatable"); + m_xFieldScroller = m_xBuilder->weld_scrolled_window("scrollwindow", true); + m_xGrid = m_xBuilder->weld_widget("grid"); + + for (sal_Int32 row=0; rowpFieldLabels[row * 2 + column] = m_xBuilder->weld_label("label" + OString::number(row * 2 + column)); + // the listbox + m_pImpl->pFields[row * 2 + column] = m_xBuilder->weld_combo_box("box" + OString::number(row * 2 + column)); + m_pImpl->pFields[row * 2 + column]->connect_changed(LINK(this, AddressBookSourceDialog, OnFieldSelect)); + } + } + + initializeDatasources(); + + // for the moment, we have a hard coded list of all known fields. + // A better solution would be to store all known field translations in the configuration, which could be + // extensible by the user in an arbitrary way. + // But for the moment we need a quick solution ... + // (the main thing would be to store the translations to use here in the user interface, besides that, the code + // should be adjustable with a rather small effort.) + + // initialize the strings for the field labels + m_pImpl->aFieldLabels.push_back( SvtResId( STR_FIELD_FIRSTNAME )); + m_pImpl->aFieldLabels.push_back( SvtResId( STR_FIELD_LASTNAME )); + m_pImpl->aFieldLabels.push_back( SvtResId( STR_FIELD_COMPANY)); + m_pImpl->aFieldLabels.push_back( SvtResId( STR_FIELD_DEPARTMENT )); + m_pImpl->aFieldLabels.push_back( SvtResId( STR_FIELD_STREET )); + m_pImpl->aFieldLabels.push_back( SvtResId( STR_FIELD_ZIPCODE )); + m_pImpl->aFieldLabels.push_back( SvtResId( STR_FIELD_CITY )); + m_pImpl->aFieldLabels.push_back( SvtResId( STR_FIELD_STATE)); + m_pImpl->aFieldLabels.push_back( SvtResId( STR_FIELD_COUNTRY )); + m_pImpl->aFieldLabels.push_back( SvtResId( STR_FIELD_HOMETEL )); + m_pImpl->aFieldLabels.push_back( SvtResId( STR_FIELD_WORKTEL )); + m_pImpl->aFieldLabels.push_back( SvtResId( STR_FIELD_OFFICETEL)); + m_pImpl->aFieldLabels.push_back( SvtResId( STR_FIELD_MOBILE)); + m_pImpl->aFieldLabels.push_back( SvtResId( STR_FIELD_TELOTHER)); + m_pImpl->aFieldLabels.push_back( SvtResId( STR_FIELD_PAGER)); + m_pImpl->aFieldLabels.push_back( SvtResId( STR_FIELD_FAX )); + m_pImpl->aFieldLabels.push_back( SvtResId( STR_FIELD_EMAIL )); + m_pImpl->aFieldLabels.push_back( SvtResId( STR_FIELD_URL )); + m_pImpl->aFieldLabels.push_back( SvtResId( STR_FIELD_TITLE )); + m_pImpl->aFieldLabels.push_back( SvtResId( STR_FIELD_POSITION )); + m_pImpl->aFieldLabels.push_back( SvtResId( STR_FIELD_INITIALS )); + m_pImpl->aFieldLabels.push_back( SvtResId( STR_FIELD_ADDRFORM )); + m_pImpl->aFieldLabels.push_back( SvtResId( STR_FIELD_SALUTATION )); + m_pImpl->aFieldLabels.push_back( SvtResId( STR_FIELD_ID)); + m_pImpl->aFieldLabels.push_back( SvtResId( STR_FIELD_CALENDAR)); + m_pImpl->aFieldLabels.push_back( SvtResId( STR_FIELD_INVITE)); + m_pImpl->aFieldLabels.push_back( SvtResId( STR_FIELD_NOTE)); + m_pImpl->aFieldLabels.push_back( SvtResId( STR_FIELD_USER1)); + m_pImpl->aFieldLabels.push_back( SvtResId( STR_FIELD_USER2)); + m_pImpl->aFieldLabels.push_back( SvtResId( STR_FIELD_USER3)); + m_pImpl->aFieldLabels.push_back( SvtResId( STR_FIELD_USER4)); + + tools::Long nLabelWidth = 0; + tools::Long nListBoxWidth = m_pImpl->pFields[0]->get_approximate_digit_width() * 18; + for (auto const& fieldLabel : m_pImpl->aFieldLabels) + { + m_pImpl->pFieldLabels[0]->set_label(fieldLabel); + nLabelWidth = std::max(nLabelWidth, m_pImpl->pFieldLabels[0]->get_preferred_size().Width()); + } + for (sal_Int32 row=0; rowpFieldLabels[row * 2 + column]->set_size_request(nLabelWidth, -1); + m_pImpl->pFields[row * 2 + column]->set_size_request(nListBoxWidth, -1); + } + } + + // force an even number of known fields + m_pImpl->bOddFieldNumber = (m_pImpl->aFieldLabels.size() % 2) != 0; + if (m_pImpl->bOddFieldNumber) + m_pImpl->aFieldLabels.emplace_back(); + + // limit the scrollbar range accordingly + sal_Int32 nOverallFieldPairs = m_pImpl->aFieldLabels.size() / 2; + m_xFieldScroller->vadjustment_configure(0, 0, nOverallFieldPairs, + 1, FIELD_PAIRS_VISIBLE - 1, FIELD_PAIRS_VISIBLE); + + // reset the current field assignments + m_pImpl->aFieldAssignments.resize(m_pImpl->aFieldLabels.size()); + // (empty strings mean "no assignment") + + // some knittings + m_xFieldScroller->connect_vadjustment_changed(LINK(this, AddressBookSourceDialog, OnFieldScroll)); + m_xAdministrateDatasources->connect_clicked(LINK(this, AddressBookSourceDialog, OnAdministrateDatasources)); + m_xDatasource->set_entry_completion(true); + m_xTable->set_entry_completion(true); + m_xTable->connect_focus_in(LINK(this, AddressBookSourceDialog, OnComboGetFocus)); + m_xDatasource->connect_focus_in(LINK(this, AddressBookSourceDialog, OnComboGetFocus)); + m_xTable->connect_focus_out(LINK(this, AddressBookSourceDialog, OnComboLoseFocus)); + m_xDatasource->connect_focus_out(LINK(this, AddressBookSourceDialog, OnComboLoseFocus)); + m_xTable->connect_changed(LINK(this, AddressBookSourceDialog, OnComboSelect)); + m_xDatasource->connect_changed(LINK(this, AddressBookSourceDialog, OnComboSelect)); + m_xOKButton->connect_clicked(LINK(this, AddressBookSourceDialog, OnOkClicked)); + + // initialize the field controls + resetFields(); + // tdf#136494 wait until contents are filled before getting preferred height + m_xFieldScroller->set_size_request(-1, m_xGrid->get_preferred_size().Height()); + m_xFieldScroller->vadjustment_set_value(0); + m_pImpl->nFieldScrollPos = -1; + implScrollFields(0, false, false); + + // the logical names + OUString sLogicalFieldNames(STR_LOGICAL_FIELD_NAMES); + sal_Int32 nAdjustedTokenCount = comphelper::string::getTokenCount(sLogicalFieldNames, ';') + (m_pImpl->bOddFieldNumber ? 1 : 0); + DBG_ASSERT(nAdjustedTokenCount == static_cast(m_pImpl->aFieldLabels.size()), + "AddressBookSourceDialog::AddressBookSourceDialog: inconsistence between logical and UI field names!"); + m_pImpl->aLogicalFieldNames.reserve(nAdjustedTokenCount); + sal_Int32 nIdx{ 0 }; + for (sal_Int32 i = 0; iaLogicalFieldNames.push_back(sLogicalFieldNames.getToken(0, ';', nIdx)); + + Application::PostUserEvent(LINK(this, AddressBookSourceDialog, OnDelayedInitialize), nullptr, false); + + // so the dialog will at least show up before we do the loading of the + // configuration data and the (maybe time consuming) analysis of the data source/table to select + + if (m_pImpl->bWorkingPersistent) + return; + + m_xAdministrateDatasources->hide(); + } + + void AddressBookSourceDialog::getFieldMapping(Sequence< AliasProgrammaticPair >& _rMapping) const + { + _rMapping.realloc( m_pImpl->aLogicalFieldNames.size() ); + AliasProgrammaticPair* pPair = _rMapping.getArray(); + + for (auto const& logicalFieldName : m_pImpl->aLogicalFieldNames) + { + if ( m_pImpl->pConfigData->hasFieldAssignment(logicalFieldName) ) + { + // the user gave us an assignment for this field + pPair->ProgrammaticName = logicalFieldName; + pPair->Alias = m_pImpl->pConfigData->getFieldAssignment(logicalFieldName); + ++pPair; + } + } + + _rMapping.realloc( pPair - _rMapping.getArray() ); + } + + void AddressBookSourceDialog::loadConfiguration() + { + OUString sName = m_pImpl->pConfigData->getDatasourceName(); + INetURLObject aURL( sName ); + if( aURL.GetProtocol() != INetProtocol::NotValid ) + { + OFileNotation aFileNotation( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); + sName = aFileNotation.get(OFileNotation::N_SYSTEM); + } + + m_xDatasource->set_entry_text(sName); + m_xTable->set_entry_text(m_pImpl->pConfigData->getCommand()); + // we ignore the CommandType: only tables are supported + + // the logical names for the fields + // AddressBookSourceDialog::loadConfiguration: inconsistence between field names and field assignments! + assert(m_pImpl->aLogicalFieldNames.size() == m_pImpl->aFieldAssignments.size()); + + auto aAssignment = m_pImpl->aFieldAssignments.begin(); + for (auto const& logicalFieldName : m_pImpl->aLogicalFieldNames) + { + *aAssignment = m_pImpl->pConfigData->getFieldAssignment(logicalFieldName); + ++aAssignment; + } + } + + AddressBookSourceDialog::~AddressBookSourceDialog() + { + } + + void AddressBookSourceDialog::initializeDatasources() + { + if (!m_xDatabaseContext.is()) + { + DBG_ASSERT(m_xORB.is(), "AddressBookSourceDialog::initializeDatasources: no service factory!"); + if (!m_xORB.is()) + return; + + try + { + m_xDatabaseContext = DatabaseContext::create(m_xORB); + } + catch(const Exception&) { } + if (!m_xDatabaseContext.is()) + { + ShowServiceNotAvailableError(m_xDialog.get(), u"com.sun.star.sdb.DatabaseContext", false); + return; + } + } + m_xDatasource->clear(); + + // fill the datasources listbox + try + { + const css::uno::Sequence aElementNames = m_xDatabaseContext->getElementNames(); + for (const OUString& rDatasourceName : aElementNames) + m_xDatasource->append_text(rDatasourceName); + } + catch(Exception&) + { + TOOLS_WARN_EXCEPTION( "svtools", "AddressBookSourceDialog::initializeDatasources: caught an exception while asking for the data source names!"); + } + } + + IMPL_LINK(AddressBookSourceDialog, OnFieldScroll, weld::ScrolledWindow&, rScrollBar, void) + { + implScrollFields(rScrollBar.vadjustment_get_value(), true, true); + } + + void AddressBookSourceDialog::resetTables() + { + if (!m_xDatabaseContext.is()) + return; + + weld::WaitObject aWaitCursor(m_xDialog.get()); + + // no matter what we do here, we handled the currently selected data source (no matter if successful or not) + m_xDatasource->save_value(); + + // create an interaction handler (may be needed for connecting) + Reference< XInteractionHandler > xHandler; + try + { + xHandler.set( + InteractionHandler::createWithParent(m_xORB, m_xDialog->GetXWindow()), + UNO_QUERY_THROW ); + } + catch(const Exception&) { } + if (!xHandler.is()) + { + ShowServiceNotAvailableError(m_xDialog.get(), u"com.sun.star.task.InteractionHandler", true); + return; + } + + // the currently selected table + OUString sOldTable = m_xTable->get_active_text(); + + m_xTable->clear(); + + m_xCurrentDatasourceTables= nullptr; + + // get the tables of the connection + Sequence< OUString > aTableNames; + Any aException; + try + { + Reference< XCompletedConnection > xDS; + if ( m_pImpl->bWorkingPersistent ) + { + OUString sSelectedDS = lcl_getSelectedDataSource(*m_xDatasource); + + // get the data source the user has chosen and let it build a connection + INetURLObject aURL( sSelectedDS ); + if ( aURL.GetProtocol() != INetProtocol::NotValid || m_xDatabaseContext->hasByName(sSelectedDS) ) + m_xDatabaseContext->getByName( sSelectedDS ) >>= xDS; + } + else + { + xDS.set(m_pImpl->m_xTransientDataSource, css::uno::UNO_QUERY); + } + + // build the connection + Reference< XConnection > xConn; + if (xDS.is()) + xConn = xDS->connectWithCompletion(xHandler); + + // get the table names + Reference< XTablesSupplier > xSupplTables(xConn, UNO_QUERY); + if (xSupplTables.is()) + { + m_xCurrentDatasourceTables = xSupplTables->getTables(); + if (m_xCurrentDatasourceTables.is()) + aTableNames = m_xCurrentDatasourceTables->getElementNames(); + } + } + catch(const SQLContext& e) { aException <<= e; } + catch(const SQLWarning& e) { aException <<= e; } + catch(const SQLException& e) { aException <<= e; } + catch(Exception&) + { + OSL_FAIL("AddressBookSourceDialog::resetTables: could not retrieve the table!"); + } + + if (aException.hasValue()) + { + Reference< XInteractionRequest > xRequest = new OInteractionRequest(aException); + try + { + xHandler->handle(xRequest); + } + catch(Exception&) { } + return; + } + + bool bKnowOldTable = false; + // fill the table list + for (const OUString& rTableName : std::as_const(aTableNames)) + { + m_xTable->append_text(rTableName); + if (rTableName == sOldTable) + bKnowOldTable = true; + } + + // set the old table, if the new data source knows a table with this name, too. Else reset the tables edit field. + if (!bKnowOldTable) + sOldTable.clear(); + m_xTable->set_entry_text(sOldTable); + + resetFields(); + } + + void AddressBookSourceDialog::resetFields() + { + weld::WaitObject aWaitCursor(m_xDialog.get()); + + // no matter what we do here, we handled the currently selected table (no matter if successful or not) + m_xDatasource->save_value(); + + OUString sSelectedTable = m_xTable->get_active_text(); + Sequence< OUString > aColumnNames; + try + { + if (m_xCurrentDatasourceTables.is()) + { + // get the table and the columns + Reference< XColumnsSupplier > xSuppTableCols; + if (m_xCurrentDatasourceTables->hasByName(sSelectedTable)) + xSuppTableCols.set( + m_xCurrentDatasourceTables->getByName(sSelectedTable), + css::uno::UNO_QUERY); + Reference< XNameAccess > xColumns; + if (xSuppTableCols.is()) + xColumns = xSuppTableCols->getColumns(); + if (xColumns.is()) + aColumnNames = xColumns->getElementNames(); + } + } + catch (const Exception&) + { + OSL_FAIL("AddressBookSourceDialog::resetFields: could not retrieve the table columns!"); + } + + + // for quicker access + ::std::set< OUString > aColumnNameSet(std::cbegin(aColumnNames), std::cend(aColumnNames)); + + std::vector::iterator aInitialSelection = m_pImpl->aFieldAssignments.begin() + m_pImpl->nFieldScrollPos; + + OUString sSaveSelection; + for (sal_Int32 i=0; ipFields[i].get(); + sSaveSelection = pListbox->get_active_text(); + + pListbox->clear(); + + // the one entry for "no selection" + pListbox->append_text(m_sNoFieldSelection); + // as it's entry data, set the index of the list box in our array + pListbox->set_id(0, OUString::number(i)); + + // the field names + for (const OUString& rColumnName : std::as_const(aColumnNames)) + pListbox->append_text(rColumnName); + + if (!aInitialSelection->isEmpty() && (aColumnNameSet.end() != aColumnNameSet.find(*aInitialSelection))) + // we can select the entry as specified in our field assignment array + pListbox->set_active_text(*aInitialSelection); + else + // try to restore the selection + if (aColumnNameSet.end() != aColumnNameSet.find(sSaveSelection)) + // the old selection is a valid column name + pListbox->set_active_text(sSaveSelection); + else + // select the entry + pListbox->set_active(0); + } + + // adjust m_pImpl->aFieldAssignments + for (auto & fieldAssignment : m_pImpl->aFieldAssignments) + if (!fieldAssignment.isEmpty()) + if (aColumnNameSet.end() == aColumnNameSet.find(fieldAssignment)) + fieldAssignment.clear(); + } + + IMPL_LINK(AddressBookSourceDialog, OnFieldSelect, weld::ComboBox&, rListbox, void) + { + // the index of the affected list box in our array + sal_Int32 nListBoxIndex = rListbox.get_id(0).toInt32(); + DBG_ASSERT(nListBoxIndex >= 0 && nListBoxIndex < FIELD_CONTROLS_VISIBLE, + "AddressBookSourceDialog::OnFieldScroll: invalid list box entry!"); + + // update the array where we remember the field selections + if (0 == rListbox.get_active()) + // it's the "no field selection" entry + m_pImpl->aFieldAssignments[m_pImpl->nFieldScrollPos * 2 + nListBoxIndex].clear(); + else + // it's a regular field entry + m_pImpl->aFieldAssignments[m_pImpl->nFieldScrollPos * 2 + nListBoxIndex] = rListbox.get_active_text(); + } + + + void AddressBookSourceDialog::implScrollFields(sal_Int32 _nPos, bool _bAdjustFocus, bool _bAdjustScrollbar) + { + if (_nPos == m_pImpl->nFieldScrollPos) + // nothing to do + return; + + // loop through our field control rows and do some adjustments + // for the new texts + auto pLeftLabelControl = m_pImpl->pFieldLabels.begin(); + auto pRightLabelControl = pLeftLabelControl+1; + auto pLeftColumnLabel = m_pImpl->aFieldLabels.cbegin() + 2 * _nPos; + auto pRightColumnLabel = pLeftColumnLabel + 1; + + // for the focus movement and the selection scroll + auto pLeftListControl = m_pImpl->pFields.begin(); + auto pRightListControl = pLeftListControl + 1; + + // for the focus movement + sal_Int32 nOldFocusRow = -1; + sal_Int32 nOldFocusColumn = 0; + + // for the selection scroll + auto pLeftAssignment = m_pImpl->aFieldAssignments.cbegin() + 2 * _nPos; + auto pRightAssignment = pLeftAssignment + 1; + + // loop + for (sal_Int32 i=0; ihas_focus()) + { + nOldFocusRow = i; + nOldFocusColumn = 0; + } + else if ((*pRightListControl)->has_focus()) + { + nOldFocusRow = i; + nOldFocusColumn = 1; + } + + // the new texts of the label controls + (*pLeftLabelControl)->set_label(*pLeftColumnLabel); + (*pRightLabelControl)->set_label(*pRightColumnLabel); + + // we may have to hide the controls in the right column, if we have no label text for it + // (which means we have an odd number of fields, though we forced our internal arrays to + // be even-sized for easier handling) + // (If sometimes we support an arbitrary number of field assignments, we would have to care for + // an invisible left hand side column, too. But right now, the left hand side controls are always + // visible) + bool bHideRightColumn = pRightColumnLabel->isEmpty(); + (*pRightLabelControl)->set_visible(!bHideRightColumn); + (*pRightListControl)->set_visible(!bHideRightColumn); + // the new selections of the listboxes + implSelectField(pLeftListControl->get(), *pLeftAssignment); + implSelectField(pRightListControl->get(), *pRightAssignment); + + // increment ... + if ( i < FIELD_PAIRS_VISIBLE - 1 ) + { // (not in the very last round, here the +=2 could result in an invalid + // iterator position, which causes an abort in a non-product version + pLeftLabelControl += 2; + pRightLabelControl += 2; + pLeftColumnLabel += 2; + pRightColumnLabel += 2; + + pLeftListControl += 2; + pRightListControl += 2; + pLeftAssignment += 2; + pRightAssignment += 2; + } + } + + if (_bAdjustFocus && (nOldFocusRow >= 0)) + { // we have to adjust the focus and one of the list boxes has the focus + sal_Int32 nDelta = m_pImpl->nFieldScrollPos - _nPos; + // the new row for the focus + sal_Int32 nNewFocusRow = nOldFocusRow + nDelta; + // normalize + nNewFocusRow = std::min(nNewFocusRow, sal_Int32(FIELD_PAIRS_VISIBLE - 1), ::std::less< sal_Int32 >()); + nNewFocusRow = std::max(nNewFocusRow, sal_Int32(0), ::std::less< sal_Int32 >()); + // set the new focus (in the same column) + m_pImpl->pFields[nNewFocusRow * 2 + nOldFocusColumn]->grab_focus(); + } + + m_pImpl->nFieldScrollPos = _nPos; + + if (_bAdjustScrollbar) + m_xFieldScroller->vadjustment_set_value(m_pImpl->nFieldScrollPos); + } + + void AddressBookSourceDialog::implSelectField(weld::ComboBox* pBox, const OUString& rText) + { + if (!rText.isEmpty()) + // a valid field name + pBox->set_active_text(rText); + else + // no selection for this item + pBox->set_active(0); + } + + IMPL_LINK_NOARG(AddressBookSourceDialog, OnDelayedInitialize, void*, void) + { + // load the initial data from the configuration + loadConfiguration(); + resetTables(); + // will reset the tables/fields implicitly + + if ( !m_pImpl->bWorkingPersistent ) + if ( m_pImpl->pFields[0] ) + m_pImpl->pFields[0]->grab_focus(); + } + + IMPL_LINK(AddressBookSourceDialog, OnComboSelect, weld::ComboBox&, rBox, void) + { + if (&rBox == m_xDatasource.get()) + resetTables(); + else + resetFields(); + } + + IMPL_STATIC_LINK(AddressBookSourceDialog, OnComboGetFocus, weld::Widget&, rBox, void) + { + dynamic_cast(rBox).save_value(); + } + + IMPL_LINK(AddressBookSourceDialog, OnComboLoseFocus, weld::Widget&, rControl, void) + { + weld::ComboBox& rBox = dynamic_cast(rControl); + if (rBox.get_value_changed_from_saved()) + { + if (&rBox == m_xDatasource.get()) + resetTables(); + else + resetFields(); + } + } + + IMPL_LINK_NOARG(AddressBookSourceDialog, OnOkClicked, weld::Button&, void) + { + OUString sSelectedDS = lcl_getSelectedDataSource(*m_xDatasource); + if ( m_pImpl->bWorkingPersistent ) + { + m_pImpl->pConfigData->setDatasourceName(sSelectedDS); + m_pImpl->pConfigData->setCommand(m_xTable->get_active_text()); + } + + // AddressBookSourceDialog::loadConfiguration: inconsistence between field names and field assignments! + assert(m_pImpl->aLogicalFieldNames.size() == m_pImpl->aFieldAssignments.size()); + + // set the field assignments + auto aAssignment = m_pImpl->aFieldAssignments.cbegin(); + for (auto const& logicalFieldName : m_pImpl->aLogicalFieldNames) + { + m_pImpl->pConfigData->setFieldAssignment(logicalFieldName, *aAssignment); + ++aAssignment; + } + + m_xDialog->response(RET_OK); + } + + IMPL_LINK_NOARG(AddressBookSourceDialog, OnAdministrateDatasources, weld::Button&, void) + { + // create the dialog object + Reference< XExecutableDialog > xAdminDialog; + try + { + xAdminDialog = AddressBookSourcePilot::createWithParent(m_xORB, m_xDialog->GetXWindow()); + } + catch(const Exception&) { } + if (!xAdminDialog.is()) + { + ShowServiceNotAvailableError(m_xDialog.get(), u"com.sun.star.ui.dialogs.AddressBookSourcePilot", true); + return; + } + + // execute the dialog + try + { + if ( xAdminDialog->execute() == RET_OK ) + { + Reference xProp(xAdminDialog,UNO_QUERY); + if ( xProp.is() ) + { + OUString sName; + xProp->getPropertyValue("DataSourceName") >>= sName; + + INetURLObject aURL( sName ); + if( aURL.GetProtocol() != INetProtocol::NotValid ) + { + OFileNotation aFileNotation( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); + sName = aFileNotation.get(OFileNotation::N_SYSTEM); + } + m_xDatasource->append_text(sName); + m_pImpl->pConfigData.reset( new AssignmentPersistentData ); + loadConfiguration(); + resetTables(); + // will reset the fields implicitly + } + } + } + catch(const Exception&) + { + OSL_FAIL("AddressBookSourceDialog::OnAdministrateDatasources: an error occurred while executing the administration dialog!"); + } + + // re-fill the data source list + // try to preserve the current selection + +// initializeDatasources(); + } + +} // namespace svt + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svtools/source/dialogs/colrdlg.cxx b/svtools/source/dialogs/colrdlg.cxx new file mode 100644 index 000000000..27008ccfc --- /dev/null +++ b/svtools/source/dialogs/colrdlg.cxx @@ -0,0 +1,161 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::ui::dialogs; + +const OUStringLiteral sColor = u"Color"; + +SvColorDialog::SvColorDialog() + : meMode(svtools::ColorPickerMode::Select) +{ +} + +SvColorDialog::~SvColorDialog() +{ +} +void SvColorDialog::SetColor( const Color& rColor ) +{ + maColor = rColor; +} + +void SvColorDialog::SetMode( svtools::ColorPickerMode eMode ) +{ + meMode = eMode; +} + +short SvColorDialog::Execute(weld::Window* pParent) +{ + short ret = 0; + try + { + Reference< XComponentContext > xContext( ::comphelper::getProcessComponentContext() ); + + Reference xParent; + if (pParent) + xParent = pParent->GetXWindow(); + + Reference< XExecutableDialog > xDialog = css::cui::ColorPicker::createWithParent(xContext, xParent); + Reference< XPropertyAccess > xPropertyAccess( xDialog, UNO_QUERY_THROW ); + + Sequence< PropertyValue > props{ + comphelper::makePropertyValue(OUString( sColor ), maColor), + comphelper::makePropertyValue("Mode", static_cast(meMode)) + }; + + xPropertyAccess->setPropertyValues( props ); + + ret = xDialog->execute(); + + if( ret ) + { + props = xPropertyAccess->getPropertyValues(); + for( const auto& rProp : std::as_const(props) ) + { + if( rProp.Name == sColor ) + { + rProp.Value >>= maColor; + } + } + } + } + catch(Exception&) + { + OSL_ASSERT(false); + } + + return ret; +} + +void SvColorDialog::ExecuteAsync(weld::Window* pParent, const std::function& func) +{ + m_aResultFunc = func; + + try + { + Reference< XComponentContext > xContext( ::comphelper::getProcessComponentContext() ); + + Reference xParent; + if (pParent) + xParent = pParent->GetXWindow(); + + mxDialog = css::cui::AsynchronousColorPicker::createWithParent(xContext, xParent); + Reference< XPropertyAccess > xPropertyAccess( mxDialog, UNO_QUERY_THROW ); + + Sequence< PropertyValue > props{ + comphelper::makePropertyValue(OUString( sColor ), maColor), + comphelper::makePropertyValue("Mode", static_cast(meMode)) + }; + + xPropertyAccess->setPropertyValues( props ); + + rtl::Reference< ::svt::DialogClosedListener > pListener = new ::svt::DialogClosedListener(); + pListener->SetDialogClosedLink( LINK( this, SvColorDialog, DialogClosedHdl ) ); + + mxDialog->startExecuteModal( pListener ); + } + catch(Exception&) + { + OSL_ASSERT(false); + } +} + +IMPL_LINK( SvColorDialog, DialogClosedHdl, css::ui::dialogs::DialogClosedEvent*, pEvent, void ) +{ + sal_Int32 nResult = 0; + sal_Int16 nDialogRet = pEvent->DialogResult; + if( nDialogRet == ExecutableDialogResults::OK ) + { + nResult = RET_OK; + + Reference< XPropertyAccess > xPropertyAccess( mxDialog, UNO_QUERY_THROW ); + Sequence< PropertyValue > props = xPropertyAccess->getPropertyValues(); + + for( const auto& rProp : std::as_const(props) ) + { + if( rProp.Name == sColor ) + { + rProp.Value >>= maColor; + } + } + } + + m_aResultFunc(nResult); + mxDialog.clear(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svtools/source/dialogs/insdlg.cxx b/svtools/source/dialogs/insdlg.cxx new file mode 100644 index 000000000..adaa1b905 --- /dev/null +++ b/svtools/source/dialogs/insdlg.cxx @@ -0,0 +1,356 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +using namespace ::com::sun::star; + +#if defined _WIN32 +#include +#include +#include +#else +typedef Size SIZEL; +typedef Point POINTL; +#endif + +// this struct conforms to the Microsoft +// OBJECTDESCRIPTOR -> see oleidl.h +// (MS platform sdk) + +namespace { + +struct OleObjectDescriptor +{ + sal_uInt32 cbSize; + ClsId clsid; + sal_uInt32 dwDrawAspect; + SIZEL sizel; + POINTL pointl; + sal_uInt32 dwStatus; + sal_uInt32 dwFullUserTypeName; + sal_uInt32 dwSrcOfCopy; +}; + +#if defined _WIN32 +static_assert(sizeof(OleObjectDescriptor) == sizeof(OBJECTDESCRIPTOR)); +// check the two fields that we use here +static_assert(offsetof(OleObjectDescriptor, dwFullUserTypeName) + == offsetof(OBJECTDESCRIPTOR, dwFullUserTypeName)); +static_assert(offsetof(OleObjectDescriptor, dwSrcOfCopy) + == offsetof(OBJECTDESCRIPTOR, dwSrcOfCopy)); +#endif + +} + +/********************** SvObjectServerList ******************************** +**************************************************************************/ + +const SvObjectServer * SvObjectServerList::Get( std::u16string_view rHumanName ) const +{ + for(const auto & i : aObjectServerList) + { + if( rHumanName == i.GetHumanName() ) + return &i; + } + return nullptr; +} + +const SvObjectServer * SvObjectServerList::Get( const SvGlobalName & rName ) const +{ + for(const auto & i : aObjectServerList) + { + if( rName == i.GetClassName() ) + return &i; + } + return nullptr; +} + +void SvObjectServerList::Remove( const SvGlobalName & rName ) +{ + aObjectServerList.erase(std::remove_if(aObjectServerList.begin(), aObjectServerList.end(), + [rName](const SvObjectServer& rServer) { return rServer.GetClassName() == rName; }), + aObjectServerList.end()); +} + + +void SvObjectServerList::FillInsertObjects() +/* [Description] + + The list is filled with all types which can be selected in the insert-dialog. +*/ +{ + try{ + uno::Reference< uno::XComponentContext > xContext = comphelper::getProcessComponentContext(); + + uno::Reference< lang::XMultiServiceFactory > sProviderMSFactory = + configuration::theDefaultProvider::get(xContext); + + uno::Sequence aArguments(comphelper::InitAnyPropertySequence( + { + {"nodepath", uno::Any(OUString( "/org.openoffice.Office.Embedding/ObjectNames" ))} + })); + uno::Reference< container::XNameAccess > xNameAccess( + sProviderMSFactory->createInstanceWithArguments( "com.sun.star.configuration.ConfigurationAccess", aArguments ), + uno::UNO_QUERY ); + + if( xNameAccess.is()) + { + const uno::Sequence< OUString > seqNames= xNameAccess->getElementNames(); + + OUString aStringProductName( "%PRODUCTNAME" ); + sal_Int32 nStringProductNameLength = aStringProductName.getLength(); + + OUString aStringProductVersion( "%PRODUCTVERSION" ); + sal_Int32 nStringProductVersionLength = aStringProductVersion.getLength(); + + for( const auto& rName : seqNames ) + { + uno::Reference< container::XNameAccess > xEntry ; + xNameAccess->getByName( rName ) >>= xEntry; + if ( xEntry.is() ) + { + OUString aUIName; + OUString aClassID; + xEntry->getByName("ObjectUIName") >>= aUIName; + xEntry->getByName("ClassID") >>= aClassID; + + if ( !aUIName.isEmpty() ) + { + // replace %PRODUCTNAME + sal_Int32 nIndex = aUIName.indexOf( aStringProductName ); + while( nIndex != -1 ) + { + aUIName = aUIName.replaceAt( + nIndex, nStringProductNameLength, + utl::ConfigManager::getProductName() ); + nIndex = aUIName.indexOf( aStringProductName ); + } + + // replace %PRODUCTVERSION + nIndex = aUIName.indexOf( aStringProductVersion ); + while( nIndex != -1 ) + { + aUIName = aUIName.replaceAt( + nIndex, nStringProductVersionLength, + utl::ConfigManager::getProductVersion() ); + nIndex = aUIName.indexOf( aStringProductVersion ); + } + } + + SvGlobalName aClassName; + if( aClassName.MakeId( aClassID) ) + { + if( !Get( aClassName ) ) + // not entered yet + aObjectServerList.emplace_back( aClassName, aUIName ); + } + } + } + } + + +#ifdef _WIN32 + SvGlobalName aOleFact( SO3_OUT_CLASSID ); + OUString aOleObj( SvtResId( STR_FURTHER_OBJECT ) ); + aObjectServerList.push_back( SvObjectServer( aOleFact, aOleObj ) ); +#endif + + }catch(const container::NoSuchElementException&) + { + }catch(const uno::Exception&) + { + } + catch(...) + { + } +} + +OUString SvPasteObjectHelper::GetSotFormatUIName( SotClipboardFormatId nId ) +{ + struct SotResourcePair + { + SotClipboardFormatId mnSotId; + TranslateId mpResId; + }; + + static const SotResourcePair aSotResourcePairs[] = + { + { SotClipboardFormatId::STRING, STR_FORMAT_STRING }, + { SotClipboardFormatId::BITMAP, STR_FORMAT_BITMAP }, + { SotClipboardFormatId::GDIMETAFILE, STR_FORMAT_GDIMETAFILE }, + { SotClipboardFormatId::RTF, STR_FORMAT_RTF }, + { SotClipboardFormatId::DRAWING, STR_FORMAT_ID_DRAWING }, + { SotClipboardFormatId::SVXB, STR_FORMAT_ID_SVXB }, + { SotClipboardFormatId::INTERNALLINK_STATE, STR_FORMAT_ID_INTERNALLINK_STATE }, + { SotClipboardFormatId::SOLK, STR_FORMAT_ID_SOLK }, + { SotClipboardFormatId::NETSCAPE_BOOKMARK, STR_FORMAT_ID_NETSCAPE_BOOKMARK }, + { SotClipboardFormatId::STARSERVER, STR_FORMAT_ID_STARSERVER }, + { SotClipboardFormatId::STAROBJECT, STR_FORMAT_ID_STAROBJECT }, + { SotClipboardFormatId::APPLETOBJECT, STR_FORMAT_ID_APPLETOBJECT }, + { SotClipboardFormatId::PLUGIN_OBJECT, STR_FORMAT_ID_PLUGIN_OBJECT }, + { SotClipboardFormatId::STARWRITER_30, STR_FORMAT_ID_STARWRITER_30 }, + { SotClipboardFormatId::STARWRITER_40, STR_FORMAT_ID_STARWRITER_40 }, + { SotClipboardFormatId::STARWRITER_50, STR_FORMAT_ID_STARWRITER_50 }, + { SotClipboardFormatId::STARWRITERWEB_40, STR_FORMAT_ID_STARWRITERWEB_40 }, + { SotClipboardFormatId::STARWRITERWEB_50, STR_FORMAT_ID_STARWRITERWEB_50 }, + { SotClipboardFormatId::STARWRITERGLOB_40, STR_FORMAT_ID_STARWRITERGLOB_40 }, + { SotClipboardFormatId::STARWRITERGLOB_50, STR_FORMAT_ID_STARWRITERGLOB_50 }, + { SotClipboardFormatId::STARDRAW, STR_FORMAT_ID_STARDRAW }, + { SotClipboardFormatId::STARDRAW_40, STR_FORMAT_ID_STARDRAW_40 }, + { SotClipboardFormatId::STARIMPRESS_50, STR_FORMAT_ID_STARIMPRESS_50 }, + { SotClipboardFormatId::STARDRAW_50, STR_FORMAT_ID_STARDRAW_50 }, + { SotClipboardFormatId::STARCALC, STR_FORMAT_ID_STARCALC }, + { SotClipboardFormatId::STARCALC_40, STR_FORMAT_ID_STARCALC_40 }, + { SotClipboardFormatId::STARCALC_50, STR_FORMAT_ID_STARCALC_50 }, + { SotClipboardFormatId::STARCHART, STR_FORMAT_ID_STARCHART }, + { SotClipboardFormatId::STARCHART_40, STR_FORMAT_ID_STARCHART_40 }, + { SotClipboardFormatId::STARCHART_50, STR_FORMAT_ID_STARCHART_50 }, + { SotClipboardFormatId::STARIMAGE, STR_FORMAT_ID_STARIMAGE }, + { SotClipboardFormatId::STARIMAGE_40, STR_FORMAT_ID_STARIMAGE_40 }, + { SotClipboardFormatId::STARIMAGE_50, STR_FORMAT_ID_STARIMAGE_50 }, + { SotClipboardFormatId::STARMATH, STR_FORMAT_ID_STARMATH }, + { SotClipboardFormatId::STARMATH_40, STR_FORMAT_ID_STARMATH_40 }, + { SotClipboardFormatId::STARMATH_50, STR_FORMAT_ID_STARMATH_50 }, + { SotClipboardFormatId::STAROBJECT_PAINTDOC, STR_FORMAT_ID_STAROBJECT_PAINTDOC }, + { SotClipboardFormatId::HTML, STR_FORMAT_ID_HTML }, + { SotClipboardFormatId::HTML_SIMPLE, STR_FORMAT_ID_HTML_SIMPLE }, + { SotClipboardFormatId::BIFF_5, STR_FORMAT_ID_BIFF_5 }, + { SotClipboardFormatId::BIFF_8, STR_FORMAT_ID_BIFF_8 }, + { SotClipboardFormatId::SYLK, STR_FORMAT_ID_SYLK }, + { SotClipboardFormatId::LINK, STR_FORMAT_ID_LINK }, + { SotClipboardFormatId::DIF, STR_FORMAT_ID_DIF }, + { SotClipboardFormatId::MSWORD_DOC, STR_FORMAT_ID_MSWORD_DOC }, + { SotClipboardFormatId::STAR_FRAMESET_DOC, STR_FORMAT_ID_STAR_FRAMESET_DOC }, + { SotClipboardFormatId::OFFICE_DOC, STR_FORMAT_ID_OFFICE_DOC }, + { SotClipboardFormatId::NOTES_DOCINFO, STR_FORMAT_ID_NOTES_DOCINFO }, + { SotClipboardFormatId::SFX_DOC, STR_FORMAT_ID_SFX_DOC }, + { SotClipboardFormatId::STARCHARTDOCUMENT_50,STR_FORMAT_ID_STARCHARTDOCUMENT_50 }, + { SotClipboardFormatId::GRAPHOBJ, STR_FORMAT_ID_GRAPHOBJ }, + { SotClipboardFormatId::STARWRITER_60, STR_FORMAT_ID_STARWRITER_60 }, + { SotClipboardFormatId::STARWRITERWEB_60, STR_FORMAT_ID_STARWRITERWEB_60 }, + { SotClipboardFormatId::STARWRITERGLOB_60, STR_FORMAT_ID_STARWRITERGLOB_60 }, + { SotClipboardFormatId::STARDRAW_60, STR_FORMAT_ID_STARDRAW_60 }, + { SotClipboardFormatId::STARIMPRESS_60, STR_FORMAT_ID_STARIMPRESS_60 }, + { SotClipboardFormatId::STARCALC_60, STR_FORMAT_ID_STARCALC_60 }, + { SotClipboardFormatId::STARCHART_60, STR_FORMAT_ID_STARCHART_60 }, + { SotClipboardFormatId::STARMATH_60, STR_FORMAT_ID_STARMATH_60 }, + { SotClipboardFormatId::WMF, STR_FORMAT_ID_WMF }, + { SotClipboardFormatId::DBACCESS_QUERY, STR_FORMAT_ID_DBACCESS_QUERY }, + { SotClipboardFormatId::DBACCESS_TABLE, STR_FORMAT_ID_DBACCESS_TABLE }, + { SotClipboardFormatId::DBACCESS_COMMAND, STR_FORMAT_ID_DBACCESS_COMMAND }, + { SotClipboardFormatId::DIALOG_60, STR_FORMAT_ID_DIALOG_60 }, + { SotClipboardFormatId::FILEGRPDESCRIPTOR, STR_FORMAT_ID_FILEGRPDESCRIPTOR }, + { SotClipboardFormatId::HTML_NO_COMMENT, STR_FORMAT_ID_HTML_NO_COMMENT }, + { SotClipboardFormatId::RICHTEXT, STR_FORMAT_ID_RICHTEXT }, + { SotClipboardFormatId::STRING_TSVC, STR_FORMAT_ID_STRING_TSVC }, + { SotClipboardFormatId::PNG, STR_FORMAT_ID_PNG_BITMAP }, + }; + + TranslateId pResId; + + sal_uInt32 const nCount = SAL_N_ELEMENTS( aSotResourcePairs ); + for (sal_uInt32 i = 0; ( i < nCount ) && !pResId; ++i) + { + if( aSotResourcePairs[ i ].mnSotId == nId ) + pResId = aSotResourcePairs[ i ].mpResId; + } + + OUString aUIName; + if (pResId) + aUIName = SvtResId(pResId); + else + aUIName = SotExchange::GetFormatName( nId ); + + return aUIName; +} + +bool SvPasteObjectHelper::GetEmbeddedName(const TransferableDataHelper& rData, OUString& _rName, OUString& _rSource, SotClipboardFormatId const & _nFormat) +{ + if( _nFormat != SotClipboardFormatId::EMBED_SOURCE_OLE && _nFormat != SotClipboardFormatId::EMBEDDED_OBJ_OLE ) + return false; + + datatransfer::DataFlavor aFlavor; + SotExchange::GetFormatDataFlavor( SotClipboardFormatId::OBJECTDESCRIPTOR_OLE, aFlavor ); + + if( !rData.HasFormat( aFlavor ) ) + return false; + + uno::Any aAny = rData.GetAny(aFlavor, OUString()); + if (!aAny.hasValue()) + return false; + + uno::Sequence< sal_Int8 > anySequence; + aAny >>= anySequence; + + OleObjectDescriptor* pOleObjDescr = + reinterpret_cast< OleObjectDescriptor* >( anySequence.getArray( ) ); + + // determine the user friendly description of the embedded object + if ( pOleObjDescr->dwFullUserTypeName ) + { + // we set the pointer to the start of user friendly description + // string. it starts at &OleObjectDescriptor + dwFullUserTypeName. + // dwFullUserTypeName is the offset in bytes. + // the user friendly description string is '\0' terminated. + const sal_Unicode* pUserTypeName = + reinterpret_cast< sal_Unicode* >( + reinterpret_cast< char* >( pOleObjDescr ) + + pOleObjDescr->dwFullUserTypeName ); + + _rName += pUserTypeName; + // the following statement was here for historical reasons, it is commented out since it causes bug i49460 + // _nFormat = SotClipboardFormatId::EMBED_SOURCE_OLE; + } + + // determine the source of the embedded object + if ( pOleObjDescr->dwSrcOfCopy ) + { + // we set the pointer to the start of source string + // it starts at &OleObjectDescriptor + dwSrcOfCopy. + // dwSrcOfCopy is the offset in bytes. + // the source string is '\0' terminated. + const sal_Unicode* pSrcOfCopy = + reinterpret_cast< sal_Unicode* >( + reinterpret_cast< char* >( pOleObjDescr ) + + pOleObjDescr->dwSrcOfCopy ); + + _rSource += pSrcOfCopy; + } + else + _rSource = SvtResId(STR_UNKNOWN_SOURCE); + + return true; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svtools/source/dialogs/prnsetup.cxx b/svtools/source/dialogs/prnsetup.cxx new file mode 100644 index 000000000..60dba4348 --- /dev/null +++ b/svtools/source/dialogs/prnsetup.cxx @@ -0,0 +1,351 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +void ImplFillPrnDlgListBox( const Printer* pPrinter, + weld::ComboBox* pBox, weld::Button* pPropBtn ) +{ + ImplFreePrnDlgListBox( pBox ); + + const std::vector& rPrinters = Printer::GetPrinterQueues(); + unsigned int nCount = rPrinters.size(); + if ( nCount ) + { + for( unsigned int i = 0; i < nCount; i++ ) + pBox->append_text( rPrinters[i] ); + pBox->set_active_text(pPrinter->GetName()); + } + + pBox->set_sensitive(nCount != 0); + pPropBtn->set_visible( pPrinter->HasSupport( PrinterSupport::SetupDialog ) ); +} + + +void ImplFreePrnDlgListBox( weld::ComboBox* pBox, bool bClear ) +{ + if ( bClear ) + pBox->clear(); +} + + +Printer* ImplPrnDlgListBoxSelect( const weld::ComboBox* pBox, weld::Button* pPropBtn, + Printer const * pPrinter, Printer* pTempPrinterIn ) +{ + VclPtr pTempPrinter( pTempPrinterIn ); + if ( pBox->get_active() != -1 ) + { + const QueueInfo* pInfo = Printer::GetQueueInfo( pBox->get_active_text(), true ); + if( pInfo) + { + if ( !pTempPrinter ) + { + if ( (pPrinter->GetName() == pInfo->GetPrinterName()) && + (pPrinter->GetDriverName() == pInfo->GetDriver()) ) + pTempPrinter = VclPtr::Create( pPrinter->GetJobSetup() ); + else + pTempPrinter = VclPtr::Create( *pInfo ); + } + else + { + if ( (pTempPrinter->GetName() != pInfo->GetPrinterName()) || + (pTempPrinter->GetDriverName() != pInfo->GetDriver()) ) + { + pTempPrinter.disposeAndClear(); + pTempPrinter = VclPtr::Create( *pInfo ); + } + } + + pPropBtn->set_sensitive(pTempPrinter->HasSupport(PrinterSupport::SetupDialog)); + } + else + pPropBtn->set_sensitive(false); + } + else + pPropBtn->set_sensitive(false); + + return pTempPrinter; +} + + +Printer* ImplPrnDlgUpdatePrinter( Printer const * pPrinter, Printer* pTempPrinterIn ) +{ + VclPtr pTempPrinter( pTempPrinterIn ); + OUString aPrnName; + if ( pTempPrinter ) + aPrnName = pTempPrinter->GetName(); + else + aPrnName = pPrinter->GetName(); + + if ( ! Printer::GetQueueInfo( aPrnName, false ) ) + { + pTempPrinter.disposeAndClear(); + pTempPrinter = VclPtr::Create(); + } + + return pTempPrinter; +} + + +void ImplPrnDlgUpdateQueueInfo( const weld::ComboBox* pBox, QueueInfo& rInfo ) +{ + if ( pBox->get_active() != -1 ) + { + const QueueInfo* pInfo = Printer::GetQueueInfo( pBox->get_active_text(), true ); + if( pInfo ) + rInfo = *pInfo; + } +} + + +static OUString ImplPrnDlgAddString(const OUString& rStr, std::u16string_view rAddStr) +{ + OUString aStr(rStr); + if (!aStr.isEmpty()) + aStr += "; " ; + return aStr + rAddStr; +} + + +static OUString ImplPrnDlgAddResString(const OUString& rStr, TranslateId pResId) +{ + return ImplPrnDlgAddString(rStr, SvtResId(pResId)); +} + + +OUString ImplPrnDlgGetStatusText( const QueueInfo& rInfo ) +{ + OUString aStr; + PrintQueueFlags nStatus = rInfo.GetStatus(); + + // Default-Printer + if ( !rInfo.GetPrinterName().isEmpty() && + (rInfo.GetPrinterName() == Printer::GetDefaultPrinterName()) ) + aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_DEFPRINTER ); + + // Status + if ( nStatus & PrintQueueFlags::Ready ) + aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_READY ); + if ( nStatus & PrintQueueFlags::Paused ) + aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_PAUSED ); + if ( nStatus & PrintQueueFlags::PendingDeletion ) + aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_PENDING ); + if ( nStatus & PrintQueueFlags::Busy ) + aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_BUSY ); + if ( nStatus & PrintQueueFlags::Initializing ) + aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_INITIALIZING ); + if ( nStatus & PrintQueueFlags::Waiting ) + aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_WAITING ); + if ( nStatus & PrintQueueFlags::WarmingUp ) + aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_WARMING_UP ); + if ( nStatus & PrintQueueFlags::Processing ) + aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_PROCESSING ); + if ( nStatus & PrintQueueFlags::Printing ) + aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_PRINTING ); + if ( nStatus & PrintQueueFlags::Offline ) + aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_OFFLINE ); + if ( nStatus & PrintQueueFlags::Error ) + aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_ERROR ); + if ( nStatus & PrintQueueFlags::StatusUnknown ) + aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_SERVER_UNKNOWN ); + if ( nStatus & PrintQueueFlags::PaperJam ) + aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_PAPER_JAM ); + if ( nStatus & PrintQueueFlags::PaperOut ) + aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_PAPER_OUT ); + if ( nStatus & PrintQueueFlags::ManualFeed ) + aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_MANUAL_FEED ); + if ( nStatus & PrintQueueFlags::PaperProblem ) + aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_PAPER_PROBLEM ); + if ( nStatus & PrintQueueFlags::IOActive ) + aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_IO_ACTIVE ); + if ( nStatus & PrintQueueFlags::OutputBinFull ) + aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_OUTPUT_BIN_FULL ); + if ( nStatus & PrintQueueFlags::TonerLow ) + aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_TONER_LOW ); + if ( nStatus & PrintQueueFlags::NoToner ) + aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_NO_TONER ); + if ( nStatus & PrintQueueFlags::PagePunt ) + aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_PAGE_PUNT ); + if ( nStatus & PrintQueueFlags::UserIntervention ) + aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_USER_INTERVENTION ); + if ( nStatus & PrintQueueFlags::OutOfMemory ) + aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_OUT_OF_MEMORY ); + if ( nStatus & PrintQueueFlags::DoorOpen ) + aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_DOOR_OPEN ); + if ( nStatus & PrintQueueFlags::PowerSave ) + aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_POWER_SAVE ); + + // Number of jobs + sal_uInt32 nJobs = rInfo.GetJobs(); + if ( nJobs && (nJobs != QUEUE_JOBS_DONTKNOW) ) + { + OUString aJobStr( SvtResId( STR_SVT_PRNDLG_JOBCOUNT ) ); + OUString aJobs( OUString::number( nJobs ) ); + aStr = ImplPrnDlgAddString(aStr, aJobStr.replaceAll("%d", aJobs)); + } + + return aStr; +} + +PrinterSetupDialog::PrinterSetupDialog(weld::Window* pParent) + : GenericDialogController(pParent, "svt/ui/printersetupdialog.ui", "PrinterSetupDialog") + , m_xLbName(m_xBuilder->weld_combo_box("name")) + , m_xBtnProperties(m_xBuilder->weld_button("properties")) + , m_xBtnOptions(m_xBuilder->weld_button("options")) + , m_xFiStatus(m_xBuilder->weld_label("status")) + , m_xFiType(m_xBuilder->weld_label("type")) + , m_xFiLocation(m_xBuilder->weld_label("location")) + , m_xFiComment(m_xBuilder->weld_label("comment")) + , maStatusTimer("PrinterSetupDialog maStatusTimer") +{ + m_xLbName->make_sorted(); + + // show options button only if link is set + m_xBtnOptions->hide(); + + mpPrinter = nullptr; + mpTempPrinter = nullptr; + + maStatusTimer.SetTimeout( IMPL_PRINTDLG_STATUS_UPDATE ); + maStatusTimer.SetInvokeHandler( LINK( this, PrinterSetupDialog, ImplStatusHdl ) ); + m_xBtnProperties->connect_clicked( LINK( this, PrinterSetupDialog, ImplPropertiesHdl ) ); + m_xLbName->connect_changed( LINK( this, PrinterSetupDialog, ImplChangePrinterHdl ) ); + m_xDialog->connect_focus_in( LINK( this, PrinterSetupDialog, ImplGetFocusHdl ) ); + Application::AddEventListener(LINK( this, PrinterSetupDialog, ImplDataChangedHdl ) ); +} + +PrinterSetupDialog::~PrinterSetupDialog() +{ + Application::RemoveEventListener(LINK( this, PrinterSetupDialog, ImplDataChangedHdl ) ); + ImplFreePrnDlgListBox(m_xLbName.get(), false); +} + +void PrinterSetupDialog::SetOptionsHdl(const Link& rLink) +{ + m_xBtnOptions->connect_clicked(rLink); + m_xBtnOptions->set_accessible_description(SvtResId(STR_A11Y_DESC_OPTIONS)); + m_xBtnOptions->set_visible(rLink.IsSet()); +} + +void PrinterSetupDialog::ImplSetInfo() +{ + const QueueInfo* pInfo = Printer::GetQueueInfo(m_xLbName->get_active_text(), true); + if ( pInfo ) + { + m_xFiType->set_label( pInfo->GetDriver() ); + m_xFiLocation->set_label( pInfo->GetLocation() ); + m_xFiComment->set_label( pInfo->GetComment() ); + m_xFiStatus->set_label( ImplPrnDlgGetStatusText( *pInfo ) ); + } + else + { + const OUString aTempStr; + m_xFiType->set_label( aTempStr ); + m_xFiLocation->set_label( aTempStr ); + m_xFiComment->set_label( aTempStr ); + m_xFiStatus->set_label( aTempStr ); + } +} + +IMPL_LINK_NOARG(PrinterSetupDialog, ImplStatusHdl, Timer *, void) +{ + QueueInfo aInfo; + ImplPrnDlgUpdateQueueInfo(m_xLbName.get(), aInfo); + m_xFiStatus->set_label( ImplPrnDlgGetStatusText( aInfo ) ); +} + + +IMPL_LINK_NOARG(PrinterSetupDialog, ImplPropertiesHdl, weld::Button&, void) +{ + if ( !mpTempPrinter ) + mpTempPrinter = VclPtr::Create( mpPrinter->GetJobSetup() ); + mpTempPrinter->Setup(m_xDialog.get()); +} + +IMPL_LINK_NOARG(PrinterSetupDialog, ImplChangePrinterHdl, weld::ComboBox&, void) +{ + mpTempPrinter = ImplPrnDlgListBoxSelect(m_xLbName.get(), m_xBtnProperties.get(), + mpPrinter, mpTempPrinter); + ImplSetInfo(); +} + +IMPL_LINK(PrinterSetupDialog, ImplGetFocusHdl, weld::Widget&, rWidget, void) +{ + if (rWidget.is_visible()) + ImplStatusHdl(&maStatusTimer); +} + +IMPL_LINK(PrinterSetupDialog, ImplDataChangedHdl, VclSimpleEvent&, rEvt, void) +{ + VclEventId nEvent = rEvt.GetId(); + if (nEvent != VclEventId::ApplicationDataChanged) + return; + + DataChangedEvent* pData = static_cast(static_cast(rEvt).GetData()); + if (!pData || pData->GetType() != DataChangedEventType::PRINTER) + return; + + mpTempPrinter = ImplPrnDlgUpdatePrinter(mpPrinter, mpTempPrinter); + Printer* pPrn; + if (mpTempPrinter) + pPrn = mpTempPrinter; + else + pPrn = mpPrinter; + ImplFillPrnDlgListBox(pPrn, m_xLbName.get(), m_xBtnProperties.get()); + ImplSetInfo(); +} + +short PrinterSetupDialog::run() +{ + if ( !mpPrinter || mpPrinter->IsPrinting() || mpPrinter->IsJobActive() ) + { + SAL_WARN( "svtools.dialogs", "PrinterSetupDialog::execute() - No Printer or printer is printing" ); + return RET_CANCEL; + } + + Printer::updatePrinters(); + + ImplFillPrnDlgListBox(mpPrinter, m_xLbName.get(), m_xBtnProperties.get()); + ImplSetInfo(); + maStatusTimer.Start(); + + // start dialog + short nRet = GenericDialogController::run(); + + // update data if the dialog was terminated with OK + if ( nRet == RET_OK && mpTempPrinter ) + mpPrinter->SetPrinterProps( mpTempPrinter ); + + maStatusTimer.Stop(); + + return nRet; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svtools/source/dialogs/restartdialog.cxx b/svtools/source/dialogs/restartdialog.cxx new file mode 100644 index 000000000..30954f176 --- /dev/null +++ b/svtools/source/dialogs/restartdialog.cxx @@ -0,0 +1,124 @@ +/* -*- 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 + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace { + +class RestartDialog : public weld::GenericDialogController{ +public: + RestartDialog(weld::Window* parent, svtools::RestartReason reason) + : GenericDialogController(parent, "svt/ui/restartdialog.ui", "RestartDialog") + , btnYes_(m_xBuilder->weld_button("yes")) + , btnNo_(m_xBuilder->weld_button("no")) + { + switch (reason) { + case svtools::RESTART_REASON_JAVA: + reason_ = m_xBuilder->weld_widget("reason_java"); + break; + case svtools::RESTART_REASON_PDF_AS_STANDARD_JOB_FORMAT: + reason_ = m_xBuilder->weld_widget("reason_pdf"); + break; + case svtools::RESTART_REASON_BIBLIOGRAPHY_INSTALL: + reason_ = m_xBuilder->weld_widget("reason_bibliography_install"); + break; + case svtools::RESTART_REASON_MAILMERGE_INSTALL: + reason_ = m_xBuilder->weld_widget("reason_mailmerge_install"); + break; + case svtools::RESTART_REASON_LANGUAGE_CHANGE: + reason_ = m_xBuilder->weld_widget("reason_language_change"); + break; + case svtools::RESTART_REASON_ADDING_PATH: + reason_ = m_xBuilder->weld_widget("reason_adding_path"); + break; + case svtools::RESTART_REASON_ASSIGNING_JAVAPARAMETERS: + reason_ = m_xBuilder->weld_widget("reason_assigning_javaparameters"); + break; + case svtools::RESTART_REASON_ASSIGNING_FOLDERS: + reason_ = m_xBuilder->weld_widget("reason_assigning_folders"); + break; + case svtools::RESTART_REASON_EXP_FEATURES: + reason_ = m_xBuilder->weld_widget("reason_exp_features"); + break; + case svtools::RESTART_REASON_EXTENSION_INSTALL: + reason_ = m_xBuilder->weld_widget("reason_extension_install"); + break; + case svtools::RESTART_REASON_SKIA: + reason_ = m_xBuilder->weld_widget("reason_skia"); + break; + case svtools::RESTART_REASON_OPENCL: + reason_ = m_xBuilder->weld_widget("reason_opencl"); + break; + case svtools::RESTART_REASON_THREADING: + reason_ = m_xBuilder->weld_widget("reason_threading"); + break; + case svtools::RESTART_REASON_MSCOMPATIBLE_FORMS_MENU: + reason_ = m_xBuilder->weld_widget("reason_mscompatible_formsmenu"); + break; + case svtools::RESTART_REASON_SAVE: + reason_ = m_xBuilder->weld_widget("reason_save"); + break; + case svtools::RESTART_REASON_UI_CHANGE: + reason_ = m_xBuilder->weld_widget("reason_uichange"); + break; + default: + assert(false); // this cannot happen + } + reason_->show(); + btnYes_->connect_clicked(LINK(this, RestartDialog, hdlYes)); + btnNo_->connect_clicked(LINK(this, RestartDialog, hdlNo)); + } +private: + DECL_LINK(hdlYes, weld::Button&, void); + DECL_LINK(hdlNo, weld::Button&, void); + + std::unique_ptr reason_; + std::unique_ptr btnYes_; + std::unique_ptr btnNo_; +}; + +IMPL_LINK_NOARG(RestartDialog, hdlYes, weld::Button&, void) +{ + m_xDialog->response(RET_OK); +} + +IMPL_LINK_NOARG(RestartDialog, hdlNo, weld::Button&, void) +{ + m_xDialog->response(RET_CANCEL); +} + +} + +bool svtools::executeRestartDialog( + css::uno::Reference< css::uno::XComponentContext > const & context, + weld::Window* parent, RestartReason reason) +{ + auto xRestartManager = css::task::OfficeRestartManager::get(context); + if (xRestartManager->isRestartRequested(false)) + return true; // don't try to show another dialog when restart is already in progress + RestartDialog aDlg(parent, reason); + if (aDlg.run()) { + xRestartManager->requestRestart( + css::uno::Reference< css::task::XInteractionHandler >()); + return true; + } + return false; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit v1.2.3