From 267c6f2ac71f92999e969232431ba04678e7437e Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Mon, 15 Apr 2024 07:54:39 +0200 Subject: Adding upstream version 4:24.2.0. Signed-off-by: Daniel Baumann --- extensions/source/abpilot/abp.component | 26 + extensions/source/abpilot/abpfinalpage.cxx | 227 ++++++++ extensions/source/abpilot/abpfinalpage.hxx | 74 +++ extensions/source/abpilot/abptypes.hxx | 40 ++ extensions/source/abpilot/abspage.cxx | 74 +++ extensions/source/abpilot/abspage.hxx | 56 ++ extensions/source/abpilot/abspilot.cxx | 449 ++++++++++++++++ extensions/source/abpilot/abspilot.hxx | 119 +++++ extensions/source/abpilot/addresssettings.hxx | 56 ++ extensions/source/abpilot/admininvokationimpl.cxx | 117 ++++ extensions/source/abpilot/admininvokationimpl.hxx | 50 ++ extensions/source/abpilot/admininvokationpage.cxx | 90 ++++ extensions/source/abpilot/admininvokationpage.hxx | 52 ++ extensions/source/abpilot/datasourcehandling.cxx | 620 ++++++++++++++++++++++ extensions/source/abpilot/datasourcehandling.hxx | 181 +++++++ extensions/source/abpilot/fieldmappingimpl.cxx | 316 +++++++++++ extensions/source/abpilot/fieldmappingimpl.hxx | 111 ++++ extensions/source/abpilot/fieldmappingpage.cxx | 77 +++ extensions/source/abpilot/fieldmappingpage.hxx | 46 ++ extensions/source/abpilot/moduleabp.cxx | 22 + extensions/source/abpilot/tableselectionpage.cxx | 101 ++++ extensions/source/abpilot/tableselectionpage.hxx | 50 ++ extensions/source/abpilot/typeselectionpage.cxx | 224 ++++++++ extensions/source/abpilot/typeselectionpage.hxx | 81 +++ extensions/source/abpilot/unodialogabp.cxx | 156 ++++++ extensions/source/abpilot/unodialogabp.hxx | 78 +++ 26 files changed, 3493 insertions(+) create mode 100644 extensions/source/abpilot/abp.component create mode 100644 extensions/source/abpilot/abpfinalpage.cxx create mode 100644 extensions/source/abpilot/abpfinalpage.hxx create mode 100644 extensions/source/abpilot/abptypes.hxx create mode 100644 extensions/source/abpilot/abspage.cxx create mode 100644 extensions/source/abpilot/abspage.hxx create mode 100644 extensions/source/abpilot/abspilot.cxx create mode 100644 extensions/source/abpilot/abspilot.hxx create mode 100644 extensions/source/abpilot/addresssettings.hxx create mode 100644 extensions/source/abpilot/admininvokationimpl.cxx create mode 100644 extensions/source/abpilot/admininvokationimpl.hxx create mode 100644 extensions/source/abpilot/admininvokationpage.cxx create mode 100644 extensions/source/abpilot/admininvokationpage.hxx create mode 100644 extensions/source/abpilot/datasourcehandling.cxx create mode 100644 extensions/source/abpilot/datasourcehandling.hxx create mode 100644 extensions/source/abpilot/fieldmappingimpl.cxx create mode 100644 extensions/source/abpilot/fieldmappingimpl.hxx create mode 100644 extensions/source/abpilot/fieldmappingpage.cxx create mode 100644 extensions/source/abpilot/fieldmappingpage.hxx create mode 100644 extensions/source/abpilot/moduleabp.cxx create mode 100644 extensions/source/abpilot/tableselectionpage.cxx create mode 100644 extensions/source/abpilot/tableselectionpage.hxx create mode 100644 extensions/source/abpilot/typeselectionpage.cxx create mode 100644 extensions/source/abpilot/typeselectionpage.hxx create mode 100644 extensions/source/abpilot/unodialogabp.cxx create mode 100644 extensions/source/abpilot/unodialogabp.hxx (limited to 'extensions/source/abpilot') diff --git a/extensions/source/abpilot/abp.component b/extensions/source/abpilot/abp.component new file mode 100644 index 0000000000..91b9638c42 --- /dev/null +++ b/extensions/source/abpilot/abp.component @@ -0,0 +1,26 @@ + + + + + + + + diff --git a/extensions/source/abpilot/abpfinalpage.cxx b/extensions/source/abpilot/abpfinalpage.cxx new file mode 100644 index 0000000000..78756b28b5 --- /dev/null +++ b/extensions/source/abpilot/abpfinalpage.cxx @@ -0,0 +1,227 @@ +/* -*- 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 "abpfinalpage.hxx" +#include "addresssettings.hxx" +#include "abspilot.hxx" +#include +#include +#include +#include +#include +#include +#include +#include + +namespace abp +{ + + using namespace ::svt; + using namespace ::utl; + + static std::shared_ptr lcl_getBaseFilter() + { + std::shared_ptr pFilter = SfxFilter::GetFilterByName("StarOffice XML (Base)"); + OSL_ENSURE(pFilter,"Filter: StarOffice XML (Base) could not be found!"); + return pFilter; + } + + FinalPage::FinalPage(weld::Container* pPage, OAddressBookSourcePilot* pWizard) + : AddressBookSourcePage(pPage, pWizard, "modules/sabpilot/ui/datasourcepage.ui", + "DataSourcePage") + , m_xLocation(new SvtURLBox(m_xBuilder->weld_combo_box("location"))) + , m_xBrowse(m_xBuilder->weld_button("browse")) + , m_xRegisterName(m_xBuilder->weld_check_button("available")) + , m_xEmbed(m_xBuilder->weld_check_button("embed")) + , m_xNameLabel(m_xBuilder->weld_label("nameft")) + , m_xLocationLabel(m_xBuilder->weld_label("locationft")) + , m_xName(m_xBuilder->weld_entry("name")) + , m_xDuplicateNameError(m_xBuilder->weld_label("warning")) + { + m_xLocation->SetSmartProtocol(INetProtocol::File); + m_xLocation->DisableHistory(); + + m_xLocationController.reset( new svx::DatabaseLocationInputController(pWizard->getORB(), + *m_xLocation, *m_xBrowse, *pWizard->getDialog()) ); + + m_xName->connect_changed( LINK(this, FinalPage, OnEntryNameModified) ); + m_xLocation->connect_changed( LINK(this, FinalPage, OnComboNameModified) ); + m_xRegisterName->connect_toggled( LINK( this, FinalPage, OnRegister ) ); + m_xRegisterName->set_active(true); + m_xEmbed->connect_toggled( LINK( this, FinalPage, OnEmbed ) ); + m_xEmbed->set_active(true); + } + + FinalPage::~FinalPage() + { + m_xLocationController.reset(); + } + + bool FinalPage::isValidName() const + { + OUString sCurrentName(m_xName->get_text()); + + if (sCurrentName.isEmpty()) + // the name must not be empty + return false; + + if ( m_aInvalidDataSourceNames.find( sCurrentName ) != m_aInvalidDataSourceNames.end() ) + // there already is a data source with this name + return false; + + return true; + } + + void FinalPage::setFields() + { + AddressSettings& rSettings = getSettings(); + + INetURLObject aURL( rSettings.sDataSourceName ); + if( aURL.GetProtocol() == INetProtocol::NotValid ) + { + OUString sPath = SvtPathOptions().GetWorkPath() + + "/" + rSettings.sDataSourceName; + + std::shared_ptr pFilter = lcl_getBaseFilter(); + if ( pFilter ) + { + OUString sExt = pFilter->GetDefaultExtension(); + sPath += o3tl::getToken(sExt,1,'*'); + } + + aURL.SetURL(sPath); + } + OSL_ENSURE( aURL.GetProtocol() != INetProtocol::NotValid ,"No valid file name!"); + rSettings.sDataSourceName = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ); + m_xLocationController->setURL( rSettings.sDataSourceName ); + OUString sName = aURL.getName( ); + sal_Int32 nPos = sName.indexOf(aURL.GetFileExtension()); + if ( nPos != -1 ) + { + sName = sName.replaceAt(nPos-1, 4, u""); + } + m_xName->set_text(sName); + + OnRegister(*m_xRegisterName); + } + + + void FinalPage::initializePage() + { + AddressBookSourcePage::initializePage(); + + setFields(); + } + + bool FinalPage::commitPage( ::vcl::WizardTypes::CommitPageReason _eReason ) + { + if (!AddressBookSourcePage::commitPage(_eReason)) + return false; + + if ( ( ::vcl::WizardTypes::eTravelBackward != _eReason ) + && ( !m_xLocationController->prepareCommit() ) + ) + return false; + + AddressSettings& rSettings = getSettings(); + rSettings.sDataSourceName = m_xLocationController->getURL(); + rSettings.bRegisterDataSource = m_xRegisterName->get_active(); + if ( rSettings.bRegisterDataSource ) + rSettings.sRegisteredDataSourceName = m_xName->get_text(); + rSettings.bEmbedDataSource = m_xEmbed->get_active(); + + return true; + } + + void FinalPage::Activate() + { + AddressBookSourcePage::Activate(); + + // get the names of all data sources + ODataSourceContext aContext( getORB() ); + aContext.getDataSourceNames( m_aInvalidDataSourceNames ); + + // give the name edit the focus + m_xLocation->grab_focus(); + + // default the finish button + getDialog()->defaultButton( WizardButtonFlags::FINISH ); + + OnEmbed(*m_xEmbed); + } + + void FinalPage::Deactivate() + { + AddressBookSourcePage::Deactivate(); + + // default the "next" button, again + getDialog()->defaultButton( WizardButtonFlags::NEXT ); + // disable the finish button + getDialog()->enableButtons( WizardButtonFlags::FINISH, false ); + } + + + bool FinalPage::canAdvance() const + { + return false; + } + + void FinalPage::implCheckName() + { + bool bValidName = isValidName(); + bool bEmptyName = m_xName->get_text().isEmpty(); + bool bEmptyLocation = m_xLocation->get_active_text().isEmpty(); + + // enable or disable the finish button + getDialog()->enableButtons( WizardButtonFlags::FINISH, !bEmptyLocation && (!m_xRegisterName->get_active() || bValidName) ); + + // show the error message for an invalid name + m_xDuplicateNameError->set_visible(!bValidName && !bEmptyName); + } + + IMPL_LINK_NOARG( FinalPage, OnEntryNameModified, weld::Entry&, void ) + { + implCheckName(); + } + + IMPL_LINK_NOARG( FinalPage, OnComboNameModified, weld::ComboBox&, void ) + { + implCheckName(); + } + + IMPL_LINK_NOARG(FinalPage, OnRegister, weld::Toggleable&, void) + { + bool bEnable = m_xRegisterName->get_active(); + m_xNameLabel->set_sensitive(bEnable); + m_xName->set_sensitive(bEnable); + implCheckName(); + } + + IMPL_LINK_NOARG(FinalPage, OnEmbed, weld::Toggleable&, void) + { + bool bEmbed = m_xEmbed->get_active(); + m_xLocationLabel->set_sensitive(!bEmbed); + m_xLocation->set_sensitive(!bEmbed); + m_xBrowse->set_sensitive(!bEmbed); + } + +} // namespace abp + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/abpilot/abpfinalpage.hxx b/extensions/source/abpilot/abpfinalpage.hxx new file mode 100644 index 0000000000..6c6c5d69d9 --- /dev/null +++ b/extensions/source/abpilot/abpfinalpage.hxx @@ -0,0 +1,74 @@ +/* -*- 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 . + */ + +#pragma once + +#include "abspage.hxx" +#include "abptypes.hxx" + +#include +#include + +namespace abp +{ + + class FinalPage final : public AddressBookSourcePage + { + std::unique_ptr m_xLocation; + std::unique_ptr m_xBrowse; + std::unique_ptr m_xRegisterName; + std::unique_ptr m_xEmbed; + std::unique_ptr m_xNameLabel; + std::unique_ptr m_xLocationLabel; + std::unique_ptr m_xName; + std::unique_ptr m_xDuplicateNameError; + + std::unique_ptr + m_xLocationController; + + StringBag m_aInvalidDataSourceNames; + + public: + explicit FinalPage(weld::Container* pPage, OAddressBookSourcePilot* pController); + virtual ~FinalPage() override; + + private: + // OWizardPage overridables + virtual void initializePage() override; + virtual bool commitPage( ::vcl::WizardTypes::CommitPageReason _eReason ) override; + + // BuilderPage overridables + virtual void Activate() override; + virtual void Deactivate() override; + + // OImportPage overridables + virtual bool canAdvance() const override; + + DECL_LINK(OnEntryNameModified, weld::Entry&, void); + DECL_LINK(OnComboNameModified, weld::ComboBox&, void); + DECL_LINK(OnRegister, weld::Toggleable&, void); + DECL_LINK(OnEmbed, weld::Toggleable&, void); + + bool isValidName() const; + void implCheckName(); + void setFields(); + }; + +} // namespace abp +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/abpilot/abptypes.hxx b/extensions/source/abpilot/abptypes.hxx new file mode 100644 index 0000000000..0339253ffa --- /dev/null +++ b/extensions/source/abpilot/abptypes.hxx @@ -0,0 +1,40 @@ +/* -*- 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 . + */ + +#pragma once + +#include + +#include +#include + +#include + + +namespace abp +{ + + + typedef std::set StringBag; + + typedef std::map MapString2String; + + +} // namespace abp +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/abpilot/abspage.cxx b/extensions/source/abpilot/abspage.cxx new file mode 100644 index 0000000000..4ea1f3dded --- /dev/null +++ b/extensions/source/abpilot/abspage.cxx @@ -0,0 +1,74 @@ +/* -*- 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 "abspage.hxx" +#include "abspilot.hxx" + +namespace abp +{ + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::lang; + + AddressBookSourcePage::AddressBookSourcePage(weld::Container* pPage, OAddressBookSourcePilot* pDialog, const OUString& rUIXMLDescription, const OUString& rID) + : AddressBookSourcePage_Base(pPage, pDialog, rUIXMLDescription, rID) + , m_pDialog(pDialog) + { + } + + void AddressBookSourcePage::Activate() + { + AddressBookSourcePage_Base::Activate(); + m_pDialog->updateTravelUI(); + } + + void AddressBookSourcePage::Deactivate() + { + AddressBookSourcePage_Base::Deactivate(); + m_pDialog->enableButtons(WizardButtonFlags::NEXT, true); + } + + OAddressBookSourcePilot* AddressBookSourcePage::getDialog() + { + return m_pDialog; + } + + const OAddressBookSourcePilot* AddressBookSourcePage::getDialog() const + { + return m_pDialog; + } + + AddressSettings& AddressBookSourcePage::getSettings() + { + return m_pDialog->getSettings(); + } + + const AddressSettings& AddressBookSourcePage::getSettings() const + { + return m_pDialog->getSettings(); + } + + const Reference< XComponentContext > & AddressBookSourcePage::getORB() const + { + return m_pDialog->getORB(); + } + +} // namespace abp + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/abpilot/abspage.hxx b/extensions/source/abpilot/abspage.hxx new file mode 100644 index 0000000000..407713fab9 --- /dev/null +++ b/extensions/source/abpilot/abspage.hxx @@ -0,0 +1,56 @@ +/* -*- 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 . + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace abp +{ + class OAddressBookSourcePilot; + struct AddressSettings; + + typedef ::vcl::OWizardPage AddressBookSourcePage_Base; + /// the base class for all tab pages in the address book source wizard + class AddressBookSourcePage : public AddressBookSourcePage_Base + { + OAddressBookSourcePilot* m_pDialog; + + protected: + AddressBookSourcePage(weld::Container* pPage, OAddressBookSourcePilot* pController, const OUString& rUIXMLDescription, const OUString& rID); + + protected: + // helper + OAddressBookSourcePilot* getDialog(); + const OAddressBookSourcePilot* getDialog() const; + const css::uno::Reference< css::uno::XComponentContext > & + getORB() const; + AddressSettings& getSettings(); + const AddressSettings& getSettings() const; + + // BuilderPage overridables + virtual void Activate() override; + virtual void Deactivate() override; + }; +} // namespace abp +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/abpilot/abspilot.cxx b/extensions/source/abpilot/abspilot.cxx new file mode 100644 index 0000000000..1b04a34ceb --- /dev/null +++ b/extensions/source/abpilot/abspilot.cxx @@ -0,0 +1,449 @@ +/* -*- 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 "abspilot.hxx" +#include +#include +#include +#include +#include "typeselectionpage.hxx" +#include "admininvokationpage.hxx" +#include "tableselectionpage.hxx" +#include +#include +#include +#include "abpfinalpage.hxx" +#include "fieldmappingpage.hxx" +#include "fieldmappingimpl.hxx" + +using vcl::RoadmapWizardTypes::PathId; + +namespace abp +{ + + +#define STATE_SELECT_ABTYPE 0 +#define STATE_INVOKE_ADMIN_DIALOG 1 +#define STATE_TABLE_SELECTION 2 +#define STATE_MANUAL_FIELD_MAPPING 3 +#define STATE_FINAL_CONFIRM 4 + +#define PATH_COMPLETE 1 +#define PATH_NO_SETTINGS 2 +#define PATH_NO_FIELDS 3 +#define PATH_NO_SETTINGS_NO_FIELDS 4 + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::lang; + + OAddressBookSourcePilot::OAddressBookSourcePilot(weld::Window* _pParent, const Reference< XComponentContext >& _rxORB) + :OAddressBookSourcePilot_Base( _pParent ) + ,m_xORB(_rxORB) + ,m_aNewDataSource(_rxORB) + ,m_eNewDataSourceType( AST_INVALID ) + { + declarePath( PATH_COMPLETE, + {STATE_SELECT_ABTYPE, + STATE_INVOKE_ADMIN_DIALOG, + STATE_TABLE_SELECTION, + STATE_MANUAL_FIELD_MAPPING, + STATE_FINAL_CONFIRM} + ); + declarePath( PATH_NO_SETTINGS, + {STATE_SELECT_ABTYPE, + STATE_TABLE_SELECTION, + STATE_MANUAL_FIELD_MAPPING, + STATE_FINAL_CONFIRM} + ); + declarePath( PATH_NO_FIELDS, + {STATE_SELECT_ABTYPE, + STATE_INVOKE_ADMIN_DIALOG, + STATE_TABLE_SELECTION, + STATE_FINAL_CONFIRM} + ); + declarePath( PATH_NO_SETTINGS_NO_FIELDS, + {STATE_SELECT_ABTYPE, + STATE_TABLE_SELECTION, + STATE_FINAL_CONFIRM} + ); + + m_xPrevPage->set_help_id(HID_ABSPILOT_PREVIOUS); + m_xNextPage->set_help_id(HID_ABSPILOT_NEXT); + m_xCancel->set_help_id(HID_ABSPILOT_CANCEL); + m_xFinish->set_help_id(HID_ABSPILOT_FINISH); + m_xHelp->set_help_id(UID_ABSPILOT_HELP); + + // some initial settings +#ifdef UNX +#ifdef MACOSX + m_aSettings.eType = AST_MACAB; +#else +// FIXME: if KDE use KAB instead + m_aSettings.eType = AST_EVOLUTION; +#endif +#else + m_aSettings.eType = AST_OTHER; +#endif + m_aSettings.sDataSourceName = compmodule::ModuleRes(RID_STR_DEFAULT_NAME); + m_aSettings.bRegisterDataSource = false; + m_aSettings.bEmbedDataSource = false; + m_aSettings.bIgnoreNoTable = false; + + defaultButton(WizardButtonFlags::NEXT); + enableButtons(WizardButtonFlags::FINISH, false); + ActivatePage(); + m_xAssistant->set_current_page(0); + + typeSelectionChanged( m_aSettings.eType ); + + OUString sDialogTitle = compmodule::ModuleRes(RID_STR_ABSOURCEDIALOGTITLE); + setTitleBase(sDialogTitle); + m_xAssistant->set_help_id(HID_ABSPILOT); + } + + OUString OAddressBookSourcePilot::getStateDisplayName( WizardState _nState ) const + { + TranslateId pResId; + switch ( _nState ) + { + case STATE_SELECT_ABTYPE: pResId = RID_STR_SELECT_ABTYPE; break; + case STATE_INVOKE_ADMIN_DIALOG: pResId = RID_STR_INVOKE_ADMIN_DIALOG; break; + case STATE_TABLE_SELECTION: pResId = RID_STR_TABLE_SELECTION; break; + case STATE_MANUAL_FIELD_MAPPING: pResId = RID_STR_MANUAL_FIELD_MAPPING; break; + case STATE_FINAL_CONFIRM: pResId = RID_STR_FINAL_CONFIRM; break; + } + DBG_ASSERT( pResId, "OAddressBookSourcePilot::getStateDisplayName: don't know this state!" ); + + OUString sDisplayName; + if (pResId) + { + sDisplayName = compmodule::ModuleRes(pResId); + } + + return sDisplayName; + } + + void OAddressBookSourcePilot::implCommitAll() + { + // in real, the data source already exists in the data source context + // Thus, if the user changed the name, we have to rename the data source + if ( m_aSettings.sDataSourceName != m_aNewDataSource.getName() ) + m_aNewDataSource.rename( m_aSettings.sDataSourceName ); + + // 1. the data source + m_aNewDataSource.store(m_aSettings); + + // 2. check if we need to register the data source + if ( m_aSettings.bRegisterDataSource ) + m_aNewDataSource.registerDataSource(m_aSettings.sRegisteredDataSourceName); + + // 3. write the data source / table names into the configuration + addressconfig::writeTemplateAddressSource( getORB(), m_aSettings.bRegisterDataSource ? m_aSettings.sRegisteredDataSourceName : m_aSettings.sDataSourceName, m_aSettings.sSelectedTable ); + + // 4. write the field mapping + fieldmapping::writeTemplateAddressFieldMapping( getORB(), std::map(m_aSettings.aFieldMapping) ); + } + + void OAddressBookSourcePilot::implCleanup() + { + if ( m_aNewDataSource.isValid() ) + m_aNewDataSource.remove(); + } + + short OAddressBookSourcePilot::run() + { + short nRet = OAddressBookSourcePilot_Base::run(); + + implCleanup(); + + return nRet; + } + + bool OAddressBookSourcePilot::onFinish() + { + if ( !OAddressBookSourcePilot_Base::onFinish() ) + return false; + + implCommitAll(); + + addressconfig::markPilotSuccess( getORB() ); + + return true; + } + + void OAddressBookSourcePilot::enterState( WizardState _nState ) + { + switch ( _nState ) + { + case STATE_SELECT_ABTYPE: + impl_updateRoadmap( static_cast< TypeSelectionPage* >( GetPage( STATE_SELECT_ABTYPE ) )->getSelectedType() ); + break; + + case STATE_FINAL_CONFIRM: + if ( !needManualFieldMapping( ) ) + implDoAutoFieldMapping(); + break; + + case STATE_TABLE_SELECTION: + implDefaultTableName(); + break; + } + + OAddressBookSourcePilot_Base::enterState(_nState); + } + + + bool OAddressBookSourcePilot::prepareLeaveCurrentState( CommitPageReason _eReason ) + { + if ( !OAddressBookSourcePilot_Base::prepareLeaveCurrentState( _eReason ) ) + return false; + + if ( _eReason == vcl::WizardTypes::eTravelBackward ) + return true; + + bool bAllow = true; + + switch ( getCurrentState() ) + { + case STATE_SELECT_ABTYPE: + implCreateDataSource(); + if ( needAdminInvokationPage() ) + break; + [[fallthrough]]; + + case STATE_INVOKE_ADMIN_DIALOG: + if ( !connectToDataSource( false ) ) + { + // connecting did not succeed -> do not allow proceeding + bAllow = false; + break; + } + + + // now that we connected to the data source, check whether we need the "table selection" page + const StringBag& aTables = m_aNewDataSource.getTableNames(); + + if ( aTables.empty() ) + { + std::unique_ptr xBox(Application::CreateMessageDialog(m_xAssistant.get(), + VclMessageType::Question, VclButtonsType::YesNo, + compmodule::ModuleRes(getSettings().eType == AST_EVOLUTION_GROUPWISE ? RID_STR_QRY_NO_EVO_GW : RID_STR_QRY_NOTABLES))); + + if (RET_YES != xBox->run()) + { + // cannot ask the user, or the user chose to use this data source, though there are no tables + bAllow = false; + break; + } + + m_aSettings.bIgnoreNoTable = true; + } + + if ( aTables.size() == 1 ) + // remember the one and only table we have + m_aSettings.sSelectedTable = *aTables.begin(); + + break; + } + + impl_updateRoadmap( m_aSettings.eType ); + return bAllow; + } + + void OAddressBookSourcePilot::implDefaultTableName() + { + const StringBag& rTableNames = getDataSource().getTableNames(); + if ( rTableNames.end() != rTableNames.find( getSettings().sSelectedTable ) ) + // already a valid table selected + return; + + const char* pGuess = nullptr; + switch ( getSettings().eType ) + { + case AST_THUNDERBIRD : pGuess = "Personal Address book"; break; + case AST_EVOLUTION : + case AST_EVOLUTION_GROUPWISE: + case AST_EVOLUTION_LDAP : pGuess = "Personal"; break; + default: + OSL_FAIL( "OAddressBookSourcePilot::implDefaultTableName: unhandled case!" ); + return; + } + const OUString sGuess = OUString::createFromAscii( pGuess ); + if ( rTableNames.end() != rTableNames.find( sGuess ) ) + getSettings().sSelectedTable = sGuess; + } + + void OAddressBookSourcePilot::implDoAutoFieldMapping() + { + DBG_ASSERT( !needManualFieldMapping( ), "OAddressBookSourcePilot::implDoAutoFieldMapping: invalid call!" ); + + fieldmapping::defaultMapping( getORB(), m_aSettings.aFieldMapping ); + } + + void OAddressBookSourcePilot::implCreateDataSource() + { + if (m_aNewDataSource.isValid()) + { // we already have a data source object + if ( m_aSettings.eType == m_eNewDataSourceType ) + // and it already has the correct type + return; + + // it has a wrong type -> remove it + m_aNewDataSource.remove(); + } + + ODataSourceContext aContext( getORB() ); + aContext.disambiguate( m_aSettings.sDataSourceName ); + + switch (m_aSettings.eType) + { + case AST_THUNDERBIRD: + m_aNewDataSource = aContext.createNewThunderbird( m_aSettings.sDataSourceName ); + break; + + case AST_EVOLUTION: + m_aNewDataSource = aContext.createNewEvolution( m_aSettings.sDataSourceName ); + break; + + case AST_EVOLUTION_GROUPWISE: + m_aNewDataSource = aContext.createNewEvolutionGroupwise( m_aSettings.sDataSourceName ); + break; + + case AST_EVOLUTION_LDAP: + m_aNewDataSource = aContext.createNewEvolutionLdap( m_aSettings.sDataSourceName ); + break; + + case AST_KAB: + m_aNewDataSource = aContext.createNewKab( m_aSettings.sDataSourceName ); + break; + + case AST_MACAB: + m_aNewDataSource = aContext.createNewMacab( m_aSettings.sDataSourceName ); + break; + + case AST_OTHER: + m_aNewDataSource = aContext.createNewOther( m_aSettings.sDataSourceName ); + break; + + case AST_INVALID: + OSL_FAIL( "OAddressBookSourcePilot::implCreateDataSource: illegal data source type!" ); + break; + } + m_eNewDataSourceType = m_aSettings.eType; + } + + bool OAddressBookSourcePilot::connectToDataSource( bool _bForceReConnect ) + { + DBG_ASSERT( m_aNewDataSource.isValid(), "OAddressBookSourcePilot::implConnect: invalid current data source!" ); + + weld::WaitObject aWaitCursor(m_xAssistant.get()); + if ( _bForceReConnect && m_aNewDataSource.isConnected( ) ) + m_aNewDataSource.disconnect( ); + + return m_aNewDataSource.connect(m_xAssistant.get()); + } + + std::unique_ptr OAddressBookSourcePilot::createPage(WizardState _nState) + { + OUString sIdent(OUString::number(_nState)); + weld::Container* pPageContainer = m_xAssistant->append_page(sIdent); + + std::unique_ptr xRet; + + switch (_nState) + { + case STATE_SELECT_ABTYPE: + xRet = std::make_unique(pPageContainer, this); + break; + case STATE_INVOKE_ADMIN_DIALOG: + xRet = std::make_unique(pPageContainer, this); + break; + case STATE_TABLE_SELECTION: + xRet = std::make_unique(pPageContainer, this); + break; + case STATE_MANUAL_FIELD_MAPPING: + xRet = std::make_unique(pPageContainer, this); + break; + case STATE_FINAL_CONFIRM: + xRet = std::make_unique(pPageContainer, this); + break; + default: + assert(false && "OAddressBookSourcePilot::createPage: invalid state!"); + break; + } + + m_xAssistant->set_page_title(sIdent, getStateDisplayName(_nState)); + + return xRet; + } + + void OAddressBookSourcePilot::impl_updateRoadmap( AddressSourceType _eType ) + { + bool bSettingsPage = needAdminInvokationPage( _eType ); + bool bTablesPage = needTableSelection( _eType ); + bool bFieldsPage = needManualFieldMapping( _eType ); + + bool bConnected = m_aNewDataSource.isConnected(); + bool bCanSkipTables = + ( m_aNewDataSource.hasTable( m_aSettings.sSelectedTable ) + || m_aSettings.bIgnoreNoTable + ); + + enableState( STATE_INVOKE_ADMIN_DIALOG, bSettingsPage ); + + enableState( STATE_TABLE_SELECTION, + bTablesPage && ( bConnected ? !bCanSkipTables : !bSettingsPage ) + // if we do not need a settings page, we connect upon "Next" on the first page + ); + + enableState( STATE_MANUAL_FIELD_MAPPING, + bFieldsPage && bConnected && m_aNewDataSource.hasTable( m_aSettings.sSelectedTable ) + ); + + enableState( STATE_FINAL_CONFIRM, + bConnected && bCanSkipTables + ); + } + + void OAddressBookSourcePilot::typeSelectionChanged( AddressSourceType _eType ) + { + PathId nCurrentPathID( PATH_COMPLETE ); + bool bSettingsPage = needAdminInvokationPage( _eType ); + bool bFieldsPage = needManualFieldMapping( _eType ); + if ( !bSettingsPage ) + if ( !bFieldsPage ) + nCurrentPathID = PATH_NO_SETTINGS_NO_FIELDS; + else + nCurrentPathID = PATH_NO_SETTINGS; + else + if ( !bFieldsPage ) + nCurrentPathID = PATH_NO_FIELDS; + else + nCurrentPathID = PATH_COMPLETE; + activatePath( nCurrentPathID, true ); + + m_aNewDataSource.disconnect(); + m_aSettings.bIgnoreNoTable = false; + impl_updateRoadmap( _eType ); + } + +} // namespace abp + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/abpilot/abspilot.hxx b/extensions/source/abpilot/abspilot.hxx new file mode 100644 index 0000000000..45c965d2be --- /dev/null +++ b/extensions/source/abpilot/abspilot.hxx @@ -0,0 +1,119 @@ +/* -*- 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 . + */ + +#pragma once + +#include +#include "addresssettings.hxx" +#include "datasourcehandling.hxx" + +using vcl::WizardTypes::WizardState; +using vcl::WizardTypes::CommitPageReason; + +namespace abp +{ + typedef ::vcl::RoadmapWizardMachine OAddressBookSourcePilot_Base; + class OAddressBookSourcePilot final : public OAddressBookSourcePilot_Base + { + css::uno::Reference< css::uno::XComponentContext > + m_xORB; + AddressSettings m_aSettings; + + ODataSource m_aNewDataSource; + AddressSourceType m_eNewDataSourceType; + + public: + /// ctor + OAddressBookSourcePilot( + weld::Window* _pParent, + const css::uno::Reference< css::uno::XComponentContext >& _rxORB); + + virtual short run() override; + + /// get the service factory which was used to create the dialog + const css::uno::Reference< css::uno::XComponentContext >& + getORB() const { return m_xORB; } + AddressSettings& getSettings() { return m_aSettings; } + const AddressSettings& getSettings() const { return m_aSettings; } + + const ODataSource& getDataSource() const { return m_aNewDataSource; } + + bool connectToDataSource( bool _bForceReConnect ); + + void travelNext( ) { OAddressBookSourcePilot_Base::travelNext(); } + + /// to be called when the selected type changed + void typeSelectionChanged( AddressSourceType _eType ); + + private: + // OWizardMachine overridables + virtual std::unique_ptr createPage( WizardState _nState ) override; + virtual void enterState( WizardState _nState ) override; + virtual bool prepareLeaveCurrentState( CommitPageReason _eReason ) override; + virtual bool onFinish() override; + + // RoadmapWizard + virtual OUString getStateDisplayName( WizardState _nState ) const override; + + /** creates a new data source of the type indicated by m_aSettings +

If another data source has been created before, this one is deleted.

+ */ + void implCreateDataSource(); + + /// does an automatic field mapping (possible for all types except AST_OTHER) + void implDoAutoFieldMapping(); + + /// guesses a default for the table name, if no valid table is selected + void implDefaultTableName(); + + static bool needAdminInvokationPage( AddressSourceType _eType ) + { + return ( AST_OTHER == _eType ); + } + /// check if with the current settings, we would need to invoke he administration dialog for more details about the data source + bool needAdminInvokationPage() const + { + return needAdminInvokationPage( m_aSettings.eType ); + } + + static bool needManualFieldMapping( AddressSourceType _eType ) + { + return ( AST_OTHER == _eType ) || ( AST_KAB == _eType ) || + ( AST_EVOLUTION == _eType ) || ( AST_EVOLUTION_GROUPWISE == _eType ) || + ( AST_EVOLUTION_LDAP == _eType ); + } + /// checks if we need a manual (user-guided) field mapping + bool needManualFieldMapping() const + { + return needManualFieldMapping( m_aSettings.eType ); + } + + /// determines whether the given address book type does provide one table only + static bool needTableSelection( AddressSourceType _eType ) + { + return ( AST_KAB != _eType ); + } + + void implCleanup(); + void implCommitAll(); + + void impl_updateRoadmap( AddressSourceType _eType ); + }; +} // namespace abp +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/abpilot/addresssettings.hxx b/extensions/source/abpilot/addresssettings.hxx new file mode 100644 index 0000000000..542a2fe67e --- /dev/null +++ b/extensions/source/abpilot/addresssettings.hxx @@ -0,0 +1,56 @@ +/* -*- 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 . + */ + +#pragma once + +#include +#include "abptypes.hxx" + + +namespace abp +{ + + enum AddressSourceType + { + AST_THUNDERBIRD, + AST_EVOLUTION, + AST_EVOLUTION_GROUPWISE, + AST_EVOLUTION_LDAP, + AST_KAB, + AST_MACAB, + AST_OTHER, + + AST_INVALID + }; + + struct AddressSettings + { + AddressSourceType eType; + OUString sDataSourceName; + OUString sRegisteredDataSourceName; + OUString sSelectedTable; + bool bIgnoreNoTable; + MapString2String aFieldMapping; + bool bRegisterDataSource; + bool bEmbedDataSource; + }; + + +} // namespace abp +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/abpilot/admininvokationimpl.cxx b/extensions/source/abpilot/admininvokationimpl.cxx new file mode 100644 index 0000000000..7f7498cbea --- /dev/null +++ b/extensions/source/abpilot/admininvokationimpl.cxx @@ -0,0 +1,117 @@ +/* -*- 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 "admininvokationimpl.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace abp +{ + + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::awt; + using namespace ::com::sun::star::ui::dialogs; + using namespace ::com::sun::star::sdbc; + + OAdminDialogInvokation::OAdminDialogInvokation(const Reference< XComponentContext >& _rxContext, + css::uno::Reference< css::beans::XPropertySet > _xDataSource, + weld::Window* _pMessageParent) + :m_xContext(_rxContext) + ,m_xDataSource(std::move(_xDataSource)) + ,m_pMessageParent(_pMessageParent) + { + DBG_ASSERT(m_xContext.is(), "OAdminDialogInvokation::OAdminDialogInvokation: invalid service factory!"); + DBG_ASSERT(m_xDataSource.is(), "OAdminDialogInvokation::OAdminDialogInvokation: invalid preferred name!"); + assert(m_pMessageParent && "OAdminDialogInvokation::OAdminDialogInvokation: invalid message parent!"); + } + + + bool OAdminDialogInvokation::invokeAdministration() + { + if (!m_xContext.is()) + return false; + + try + { + // the service name of the administration dialog + static const char16_t s_sAdministrationServiceName[] = u"com.sun.star.sdb.DatasourceAdministrationDialog"; + static constexpr OUStringLiteral s_sDataSourceTypeChangeDialog = u"com.sun.star.sdb.DataSourceTypeChangeDialog"; + + // the parameters for the call + Sequence aArguments(comphelper::InitAnyPropertySequence( + { + {"ParentWindow", Any(m_pMessageParent->GetXWindow())}, + {"Title", Any(compmodule::ModuleRes(RID_STR_ADMINDIALOGTITLE))}, + {"InitialSelection", Any(m_xDataSource)}, // the name of the new data source + })); + + + // create the dialog + Reference< XExecutableDialog > xDialog; + { + // creating the dialog service is potentially expensive (if all the libraries invoked need to be loaded) + // so we display a wait cursor + weld::WaitObject aWaitCursor(m_pMessageParent); + Reference x = m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(s_sDataSourceTypeChangeDialog, aArguments, m_xContext); + xDialog.set( x, UNO_QUERY ); + + // just for a smoother UI: What the dialog does upon execution, is (amongst other things) creating + // the DriverManager service + // If this context has never been accessed before, this may be expensive (it includes loading of + // at least one library). + // As this wizard is intended to run on the first office start, it is very likely that the + // context needs to be freshly created + // Thus, we access the context here (within the WaitCursor), which means the user sees a waitcursor + // while his/her office blocks a few seconds... + DriverManager::create( m_xContext ); + } + + if (xDialog.is()) + { // execute it + if (xDialog->execute()) + return true; + } + else + ShowServiceNotAvailableError(m_pMessageParent, s_sAdministrationServiceName, true); + } + catch(const Exception&) + { + TOOLS_WARN_EXCEPTION("extensions.abpilot", + "caught an exception while executing the dialog!"); + } + return false; + } + + +} // namespace abp + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/abpilot/admininvokationimpl.hxx b/extensions/source/abpilot/admininvokationimpl.hxx new file mode 100644 index 0000000000..fef7a11eb3 --- /dev/null +++ b/extensions/source/abpilot/admininvokationimpl.hxx @@ -0,0 +1,50 @@ +/* -*- 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 . + */ + +#pragma once + +#include +#include + +namespace weld { class Window; } + +namespace abp +{ + /** outsourced from AdminDialogInvokationPage, 'cause this class here, in opposite to + the page, needs exception handling to be enabled. + */ + class OAdminDialogInvokation + { + private: + css::uno::Reference< css::uno::XComponentContext > + m_xContext; + css::uno::Reference< css::beans::XPropertySet > m_xDataSource; + weld::Window* m_pMessageParent; + + public: + OAdminDialogInvokation( + const css::uno::Reference< css::uno::XComponentContext >& _rxContext, + css::uno::Reference< css::beans::XPropertySet > _xDataSource, + weld::Window* _pMessageParent + ); + + bool invokeAdministration(); + }; +} +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/abpilot/admininvokationpage.cxx b/extensions/source/abpilot/admininvokationpage.cxx new file mode 100644 index 0000000000..2f51d86398 --- /dev/null +++ b/extensions/source/abpilot/admininvokationpage.cxx @@ -0,0 +1,90 @@ +/* -*- 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 "admininvokationpage.hxx" +#include "abspilot.hxx" +#include "admininvokationimpl.hxx" + +namespace abp +{ + AdminDialogInvokationPage::AdminDialogInvokationPage(weld::Container* pPage, OAddressBookSourcePilot* pController) + : AddressBookSourcePage(pPage, pController, "modules/sabpilot/ui/invokeadminpage.ui", "InvokeAdminPage") + , m_xInvokeAdminDialog(m_xBuilder->weld_button("settings")) + , m_xErrorMessage(m_xBuilder->weld_label("warning")) + { + m_xInvokeAdminDialog->connect_clicked(LINK(this, AdminDialogInvokationPage, OnInvokeAdminDialog)); + } + + AdminDialogInvokationPage::~AdminDialogInvokationPage() + { + } + + void AdminDialogInvokationPage::Activate() + { + AddressBookSourcePage::Activate(); + m_xInvokeAdminDialog->grab_focus(); + } + + void AdminDialogInvokationPage::implUpdateErrorMessage() + { + const bool bIsConnected = getDialog()->getDataSource().isConnected(); + m_xErrorMessage->set_visible( !bIsConnected ); + } + + void AdminDialogInvokationPage::initializePage() + { + AddressBookSourcePage::initializePage(); + m_xErrorMessage->hide(); + // if we're entering this page, we assume we had no connection trial with this data source + } + + void AdminDialogInvokationPage::implTryConnect() + { + getDialog()->connectToDataSource( true ); + + // show our error message if and only if we could not connect + implUpdateErrorMessage(); + + // the status of the next button may have changed + updateDialogTravelUI(); + + // automatically go to the next page (if successfully connected) + if ( canAdvance() ) + getDialog()->travelNext(); + } + + bool AdminDialogInvokationPage::canAdvance() const + { + return AddressBookSourcePage::canAdvance() && getDialog()->getDataSource().isConnected(); + } + + // davido: Do we need it? + IMPL_LINK_NOARG(AdminDialogInvokationPage, OnInvokeAdminDialog, weld::Button&, void) + { + OAdminDialogInvokation aInvokation(getORB(), getDialog()->getDataSource().getDataSource(), getDialog()->getDialog()); + if ( aInvokation.invokeAdministration() ) + { + // try to connect to this data source + implTryConnect(); + } + } + +} // namespace abp + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/abpilot/admininvokationpage.hxx b/extensions/source/abpilot/admininvokationpage.hxx new file mode 100644 index 0000000000..3d4f676e2d --- /dev/null +++ b/extensions/source/abpilot/admininvokationpage.hxx @@ -0,0 +1,52 @@ +/* -*- 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 . + */ + +#pragma once + +#include "abspage.hxx" + + +namespace abp +{ + class AdminDialogInvokationPage final : public AddressBookSourcePage + { + std::unique_ptr m_xInvokeAdminDialog; + std::unique_ptr m_xErrorMessage; + + public: + explicit AdminDialogInvokationPage(weld::Container* pPage, OAddressBookSourcePilot* pDialog); + virtual ~AdminDialogInvokationPage() override; + private: + // BuilderPage overridables + virtual void Activate() override; + + // OWizard overridables + virtual void initializePage() override; + + // OImportPage overridables + virtual bool canAdvance() const override; + + DECL_LINK( OnInvokeAdminDialog, weld::Button&, void ); + + void implTryConnect(); + void implUpdateErrorMessage(); + }; + +} // namespace abp +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/abpilot/datasourcehandling.cxx b/extensions/source/abpilot/datasourcehandling.cxx new file mode 100644 index 0000000000..fd5820fce1 --- /dev/null +++ b/extensions/source/abpilot/datasourcehandling.cxx @@ -0,0 +1,620 @@ +/* -*- 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 "abptypes.hxx" +#include +#include "datasourcehandling.hxx" +#include "addresssettings.hxx" + +#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 +{ + +/// Returns the URL of this object shell. +OUString lcl_getOwnURL(SfxObjectShell const * pObjectShell) +{ + OUString aRet; + + if (!pObjectShell) + return aRet; + + const INetURLObject& rURLObject = pObjectShell->GetMedium()->GetURLObject(); + aRet = rURLObject.GetMainURL(INetURLObject::DecodeMechanism::NONE); + return aRet; +} + +} + +namespace abp +{ + + + using namespace ::utl; + using namespace ::comphelper; + using namespace ::com::sun::star; + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::sdb; + using namespace ::com::sun::star::sdbc; + using namespace ::com::sun::star::task; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::sdbcx; + using namespace ::com::sun::star::container; + using namespace ::com::sun::star::frame; + + static Reference< XDatabaseContext > lcl_getDataSourceContext( const Reference< XComponentContext >& _rxContext ) + { + Reference xContext = DatabaseContext::create(_rxContext); + return xContext; + } + + + /// creates a new data source and inserts it into the context + static void lcl_implCreateAndInsert( + const Reference< XComponentContext >& _rxContext, const OUString& _rName, + Reference< XPropertySet >& /* [out] */ _rxNewDataSource ) + { + + // get the data source context + Reference< XDatabaseContext > xContext = lcl_getDataSourceContext( _rxContext ); + + DBG_ASSERT( !xContext->hasByName( _rName ), "lcl_implCreateAndInsert: name already used!" ); + + + // create a new data source + Reference< XPropertySet > xNewDataSource; + if (xContext.is()) + xNewDataSource.set( xContext->createInstance(), UNO_QUERY ); + DBG_ASSERT( xNewDataSource.is(), "lcl_implCreateAndInsert: could not create a new data source!" ); + + + // insert the data source into the context + DBG_ASSERT( xContext.is(), "lcl_implCreateAndInsert: missing an interface on the context (XNamingService)!" ); + if (xContext.is()) + { + // xDynamicContext->registerObject( _rName, xNewDataSource ); + _rxNewDataSource = xNewDataSource; + } + } + + + /// creates and inserts a data source, and sets its URL property to the string given + static ODataSource lcl_implCreateAndSetURL( + const Reference< XComponentContext >& _rxORB, const OUString& _rName, + const char* _pInitialAsciiURL ) + { + ODataSource aReturn( _rxORB ); + try + { + // create the new data source + Reference< XPropertySet > xNewDataSource; + lcl_implCreateAndInsert( _rxORB, _rName, xNewDataSource ); + + + // set the URL property + if (xNewDataSource.is()) + { + xNewDataSource->setPropertyValue( + "URL", + Any( OUString::createFromAscii( _pInitialAsciiURL ) ) + ); + } + + aReturn.setDataSource( xNewDataSource, _rName ); + } + catch(const Exception&) + { + TOOLS_WARN_EXCEPTION("extensions.abpilot", + "caught an exception while creating the data source!"); + } + + return aReturn; + } + + static void lcl_registerDataSource( + const Reference< XComponentContext >& _rxORB, const OUString& _sName, + const OUString& _sURL ) + { + OSL_ENSURE( !_sName.isEmpty(), "lcl_registerDataSource: invalid name!" ); + OSL_ENSURE( !_sURL.isEmpty(), "lcl_registerDataSource: invalid URL!" ); + try + { + Reference< XDatabaseContext > xRegistrations( DatabaseContext::create(_rxORB) ); + if ( xRegistrations->hasRegisteredDatabase( _sName ) ) + xRegistrations->changeDatabaseLocation( _sName, _sURL ); + else + xRegistrations->registerDatabaseLocation( _sName, _sURL ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("extensions.abpilot"); + } + } + + struct ODataSourceContextImpl + { + Reference< XComponentContext > xORB; + Reference< XNameAccess > xContext; /// the UNO data source context + StringBag aDataSourceNames; /// for quicker name checks (without the UNO overhead) + + explicit ODataSourceContextImpl(const Reference< XComponentContext >& _rxORB) + : xORB(_rxORB) + { + } + ODataSourceContextImpl(const ODataSourceContextImpl&) = delete; + ODataSourceContextImpl& operator=(const ODataSourceContextImpl&) = delete; + }; + + ODataSourceContext::ODataSourceContext(const Reference< XComponentContext >& _rxORB) + :m_pImpl( new ODataSourceContextImpl( _rxORB ) ) + { + try + { + // create the UNO context + m_pImpl->xContext.set( lcl_getDataSourceContext( _rxORB ), UNO_QUERY_THROW ); + + // collect the data source names + Sequence< OUString > aDSNames = m_pImpl->xContext->getElementNames(); + const OUString* pDSNames = aDSNames.getConstArray(); + const OUString* pDSNamesEnd = pDSNames + aDSNames.getLength(); + + for ( ;pDSNames != pDSNamesEnd; ++pDSNames ) + m_pImpl->aDataSourceNames.insert( *pDSNames ); + } + catch( const Exception& ) + { + TOOLS_WARN_EXCEPTION( "extensions.abpilot", "ODataSourceContext::ODataSourceContext" ); + } + } + ODataSourceContext::~ODataSourceContext() + { + } + + + void ODataSourceContext::disambiguate(OUString& _rDataSourceName) + { + OUString sCheck( _rDataSourceName ); + StringBag::const_iterator aPos = m_pImpl->aDataSourceNames.find( sCheck ); + + sal_Int32 nPostfix = 1; + while ( ( m_pImpl->aDataSourceNames.end() != aPos ) && ( nPostfix < 65535 ) ) + { // there already is a data source with this name + sCheck = _rDataSourceName + OUString::number( nPostfix++ ); + + aPos = m_pImpl->aDataSourceNames.find( sCheck ); + } + + _rDataSourceName = sCheck; + } + + + void ODataSourceContext::getDataSourceNames( StringBag& _rNames ) const + { + _rNames = m_pImpl->aDataSourceNames; + } + + ODataSource ODataSourceContext::createNewThunderbird( const OUString& _rName ) + { + return lcl_implCreateAndSetURL( m_pImpl->xORB, _rName, "sdbc:address:thunderbird" ); + } + + + ODataSource ODataSourceContext::createNewEvolutionLdap( const OUString& _rName) + { + return lcl_implCreateAndSetURL( m_pImpl->xORB, _rName, "sdbc:address:evolution:ldap" ); + } + + ODataSource ODataSourceContext::createNewEvolutionGroupwise( const OUString& _rName) + { + return lcl_implCreateAndSetURL( m_pImpl->xORB, _rName, "sdbc:address:evolution:groupwise" ); + } + + ODataSource ODataSourceContext::createNewEvolution( const OUString& _rName) + { + return lcl_implCreateAndSetURL( m_pImpl->xORB, _rName, "sdbc:address:evolution:local" ); + } + + + ODataSource ODataSourceContext::createNewKab( const OUString& _rName) + { + return lcl_implCreateAndSetURL( m_pImpl->xORB, _rName, "sdbc:address:kab" ); + } + + + ODataSource ODataSourceContext::createNewMacab( const OUString& _rName) + { + return lcl_implCreateAndSetURL( m_pImpl->xORB, _rName, "sdbc:address:macab" ); + } + + + // tdf117101: Spreadsheet by default + ODataSource ODataSourceContext::createNewOther( const OUString& _rName) + { + return lcl_implCreateAndSetURL( m_pImpl->xORB, _rName, "sdbc:calc:" ); + } + + struct ODataSourceImpl + { + public: + Reference< XComponentContext > xORB; /// the service factory + Reference< XPropertySet > xDataSource; /// the UNO data source + ::utl::SharedUNOComponent< XConnection > + xConnection; + StringBag aTables; // the cached table names + OUString sName; + + explicit ODataSourceImpl(const Reference< XComponentContext >& _rxORB) + : xORB(_rxORB) + { + } + }; + + + ODataSource::ODataSource( const ODataSource& _rSource ) + { + *this = _rSource; + } + + ODataSource& ODataSource::operator=( const ODataSource& _rSource ) + { + if( this != &_rSource ) + { + m_pImpl.reset( new ODataSourceImpl( *_rSource.m_pImpl ) ); + } + return *this; + } + + ODataSource& ODataSource::operator=(ODataSource&& _rSource) noexcept + { + m_pImpl = std::move(_rSource.m_pImpl); + return *this; + } + + ODataSource::ODataSource( const Reference< XComponentContext >& _rxORB ) + :m_pImpl(new ODataSourceImpl(_rxORB)) + { + } + + ODataSource::~ODataSource( ) + { + } + + void ODataSource::store(const AddressSettings& rSettings) + { + if (!isValid()) + // nothing to do + return; + try + { + Reference< XDocumentDataSource > xDocAccess( m_pImpl->xDataSource, UNO_QUERY ); + Reference< XStorable > xStorable; + if ( xDocAccess.is() ) + xStorable.set(xDocAccess->getDatabaseDocument(), css::uno::UNO_QUERY); + OSL_ENSURE( xStorable.is(),"DataSource is no XStorable!" ); + if ( xStorable.is() ) + { + SfxViewFrame* pFrame = SfxViewFrame::Current(); + SfxObjectShell* pObjectShell = pFrame ? pFrame->GetObjectShell() : nullptr; + OUString aOwnURL = lcl_getOwnURL(pObjectShell); // empty if pObjectShell is nullptr + if (aOwnURL.isEmpty() || !rSettings.bEmbedDataSource) + { + // Cannot or should not embed. + xStorable->storeAsURL(m_pImpl->sName,Sequence()); + } + else + { + // Embed. + OUString aStreamRelPath = "EmbeddedDatabase"; + auto xContext(comphelper::getProcessComponentContext()); + auto xUri = css::uri::UriReferenceFactory::create(xContext)->parse(aOwnURL); + assert(xUri.is()); + xUri = css::uri::VndSunStarPkgUrlReferenceFactory::create(xContext)->createVndSunStarPkgUrlReference(xUri); + assert(xUri.is()); + OUString const sTmpName = xUri->getUriReference() + "/" + aStreamRelPath; + assert(pObjectShell); + uno::Reference xStorage = pObjectShell->GetStorage(); + uno::Sequence aSequence = comphelper::InitPropertySequence( + { + {"TargetStorage", uno::Any(xStorage)}, + {"StreamRelPath", uno::Any(aStreamRelPath)}, + {"BaseURI", uno::Any(aOwnURL)} + }); + xStorable->storeAsURL(sTmpName, aSequence); + m_pImpl->sName = sTmpName; + + // Refer to the sub-storage name in the document settings, so + // we can load it again next time the file is imported. + uno::Reference xFactory(pObjectShell->GetModel(), uno::UNO_QUERY); + uno::Reference xPropertySet(xFactory->createInstance("com.sun.star.document.Settings"), uno::UNO_QUERY); + xPropertySet->setPropertyValue("EmbeddedDatabaseName", uno::Any(aStreamRelPath)); + } + } + } + catch(const Exception&) + { + TOOLS_WARN_EXCEPTION("extensions.abpilot", + "caught an exception while creating the data source!"); + } + } + + void ODataSource::registerDataSource( const OUString& _sRegisteredDataSourceName) + { + if (!isValid()) + // nothing to do + return; + + try + { + // invalidate ourself + lcl_registerDataSource(m_pImpl->xORB,_sRegisteredDataSourceName,m_pImpl->sName); + } + catch(const Exception&) + { + TOOLS_WARN_EXCEPTION("extensions.abpilot", + "caught an exception while creating the data source!"); + } + } + + + void ODataSource::setDataSource( const Reference< XPropertySet >& _rxDS,const OUString& _sName ) + { + if (m_pImpl->xDataSource.get() == _rxDS.get()) + // nothing to do + return; + + if ( isConnected() ) + disconnect(); + + m_pImpl->sName = _sName; + m_pImpl->xDataSource = _rxDS; + } + + + void ODataSource::remove() + { + if (!isValid()) + // nothing to do + return; + + try + { + // invalidate ourself + m_pImpl->xDataSource.clear(); + } + catch(const Exception&) + { + TOOLS_WARN_EXCEPTION("extensions.abpilot", + "caught an exception while creating the data source!"); + } + } + + + bool ODataSource::rename( const OUString& _rName ) + { + if (!isValid()) + // nothing to do + return false; + + m_pImpl->sName = _rName; + return true; + } + + + OUString ODataSource::getName() const + { + if ( !isValid() ) + return OUString(); + return m_pImpl->sName; + } + + + bool ODataSource::hasTable( const OUString& _rTableName ) const + { + if ( !isConnected() ) + return false; + + const StringBag& aTables( getTableNames() ); + return aTables.find( _rTableName ) != aTables.end(); + } + + + const StringBag& ODataSource::getTableNames() const + { + m_pImpl->aTables.clear(); + if ( !isConnected() ) + { + OSL_FAIL( "ODataSource::getTableNames: not connected!" ); + } + else + { + try + { + // get the tables container from the connection + Reference< XTablesSupplier > xSuppTables( m_pImpl->xConnection.getTyped(), UNO_QUERY ); + Reference< XNameAccess > xTables; + if ( xSuppTables.is( ) ) + xTables = xSuppTables->getTables(); + DBG_ASSERT( xTables.is(), "ODataSource::getTableNames: could not retrieve the tables container!" ); + + // get the names + Sequence< OUString > aTableNames; + if ( xTables.is( ) ) + aTableNames = xTables->getElementNames( ); + + // copy the names + const OUString* pTableNames = aTableNames.getConstArray(); + const OUString* pTableNamesEnd = pTableNames + aTableNames.getLength(); + for (;pTableNames < pTableNamesEnd; ++pTableNames) + m_pImpl->aTables.insert( *pTableNames ); + } + catch(const Exception&) + { + } + } + + // now the table cache is up-to-date + return m_pImpl->aTables; + } + + + bool ODataSource::connect(weld::Window* _pMessageParent) + { + if ( isConnected( ) ) + // nothing to do + return true; + + + // create the interaction handler (needed for authentication and error handling) + Reference< XInteractionHandler > xInteractions; + try + { + xInteractions = InteractionHandler::createWithParent(m_pImpl->xORB, nullptr); + } + catch(const Exception&) + { + } + + + // failure to create the interaction handler is a serious issue ... + if (!xInteractions.is()) + { + if ( _pMessageParent ) + ShowServiceNotAvailableError( _pMessageParent, u"com.sun.star.task.InteractionHandler", true ); + return false; + } + + + // open the connection + Any aError; + Reference< XConnection > xConnection; + try + { + Reference< XCompletedConnection > xComplConn( m_pImpl->xDataSource, UNO_QUERY ); + DBG_ASSERT( xComplConn.is(), "ODataSource::connect: missing the XCompletedConnection interface on the data source!" ); + if ( xComplConn.is() ) + xConnection = xComplConn->connectWithCompletion( xInteractions ); + } + catch( const SQLContext& e ) { aError <<= e; } + catch( const SQLWarning& e ) { aError <<= e; } + catch( const SQLException& e ) { aError <<= e; } + catch( const Exception& ) + { + TOOLS_WARN_EXCEPTION("extensions.abpilot", ""); + } + + + // handle errors + if ( aError.hasValue() && _pMessageParent ) + { + try + { + SQLException aException; + aError >>= aException; + if ( aException.Message.isEmpty() ) + { + // prepend some context info + SQLContext aDetailedError(compmodule::ModuleRes(RID_STR_NOCONNECTION), // message + {}, {}, 0, + aError, // next exception + compmodule::ModuleRes(RID_STR_PLEASECHECKSETTINGS)); // details + // handle (aka display) the new context info + xInteractions->handle( new OInteractionRequest( Any( aDetailedError ) ) ); + } + else + { + // handle (aka display) the original error + xInteractions->handle( new OInteractionRequest( Any( aException ) ) ); + } + } + catch( const Exception& ) + { + TOOLS_WARN_EXCEPTION("extensions.abpilot", + "caught an exception while trying to display the error!"); + } + } + + if ( !xConnection.is() ) + return false; + + + // success + m_pImpl->xConnection.reset( xConnection ); + m_pImpl->aTables.clear(); + + return true; + } + + + void ODataSource::disconnect( ) + { + m_pImpl->xConnection.clear(); + m_pImpl->aTables.clear(); + } + + + bool ODataSource::isConnected( ) const + { + return m_pImpl->xConnection.is(); + } + + + bool ODataSource::isValid() const + { + return m_pImpl && m_pImpl->xDataSource.is(); + } + + Reference< XPropertySet > ODataSource::getDataSource() const + { + return m_pImpl ? m_pImpl->xDataSource : Reference< XPropertySet >(); + } + + +} // namespace abp + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/abpilot/datasourcehandling.hxx b/extensions/source/abpilot/datasourcehandling.hxx new file mode 100644 index 0000000000..c6058e45e3 --- /dev/null +++ b/extensions/source/abpilot/datasourcehandling.hxx @@ -0,0 +1,181 @@ +/* -*- 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 . + */ + +#pragma once + +#include +#include +#include + +#include "abptypes.hxx" + + +namespace com::sun::star { + namespace beans { + class XPropertySet; + } +} + +namespace weld { class Window; } + + +namespace abp +{ + + struct ODataSourceContextImpl; + class ODataSource; + /// a non-UNO wrapper for the data source context + class ODataSourceContext + { + private: + std::unique_ptr m_pImpl; + + public: + explicit ODataSourceContext( + const css::uno::Reference< css::uno::XComponentContext >& _rxORB + ); + ~ODataSourceContext(); + + /// retrieves the names of all data sources + void getDataSourceNames( StringBag& _rNames ) const; + + /// disambiguates the given name by appending successive numbers + void disambiguate(OUString& _rDataSourceName); + + /// creates a new Thunderbird data source + ODataSource createNewThunderbird( const OUString& _rName ); + + /// creates a new Evolution local data source + ODataSource createNewEvolution( const OUString& _rName ); + + /// creates a new Evolution LDAP data source + ODataSource createNewEvolutionLdap( const OUString& _rName ); + + /// creates a new Evolution GROUPWISE data source + ODataSource createNewEvolutionGroupwise( const OUString& _rName ); + + /// creates a new KDE address book data source + ODataSource createNewKab( const OUString& _rName ); + + /// creates a new macOS address book data source + ODataSource createNewMacab( const OUString& _rName ); + + /// creates a new Other data source; tdf117101: Spreadsheet by default + ODataSource createNewOther( const OUString& _rName ); + }; + + struct ODataSourceImpl; + struct AddressSettings; + /** a non-UNO wrapper for a data source +

This class allows to access data sources without the need to compile the respective file with + exception handling enabled (hopefully :).

+

In addition to wrapping a UNO data source, an instance of this class can handle at most + one valid connection, as obtained from the data source.

+ */ + class ODataSource + { + private: + std::unique_ptr m_pImpl; + + public: + + // - ctor/dtor/assignment + + /// constructs an object which is initially invalid + explicit ODataSource( + const css::uno::Reference< css::uno::XComponentContext >& _rxORB + ); + + /// copy ctor + ODataSource( const ODataSource& _rSource ); + + /// dtor + ~ODataSource( ); + + /// copy assignment + ODataSource& operator=( const ODataSource& _rSource ); + + /// move assignment + ODataSource& operator=(ODataSource&& _rSource) noexcept; + + /// checks whether or not the object represents a valid data source + bool isValid() const; + + + /// removes the data source represented by the object from the data source context + void remove(); + // TODO: put this into the context class + + /// returns the name of the data source + OUString + getName() const; + + /// renames the data source + bool rename( const OUString& _rName ); + // TODO: put this into the context class + + + // - connection handling + + /** connects to the data source represented by this object + @param _pMessageParent + the window to use as parent for any error messages. If this is , no messages are displayed + at all. + @see isConnected + */ + bool connect(weld::Window* _pMessageParent); + + /// returns if the object has a valid connection, obtained from its data source + bool isConnected( ) const; + + /// disconnects from the data source (i.e. disposes the UNO connection hold internally) + void disconnect( ); + + /// stores the database file + void store(const AddressSettings& rSettings); + + /// register the data source under the given name in the configuration + void registerDataSource( const OUString& _sRegisteredDataSourceName ); + + + /** retrieves the tables names from the connection +

to be called when isConnected returns only

+ */ + const StringBag& getTableNames() const; + + /** determines whether a given table exists + */ + bool hasTable( const OUString& _rTableName ) const; + + /// return the internal data source object + css::uno::Reference< css::beans::XPropertySet > getDataSource() const; + + + /** set a new data source. +

Available to selected clients only

+ */ + void setDataSource( + const css::uno::Reference< css::beans::XPropertySet >& _rxDS + ,const OUString& _sName + ); + }; + + +} // namespace abp +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/abpilot/fieldmappingimpl.cxx b/extensions/source/abpilot/fieldmappingimpl.cxx new file mode 100644 index 0000000000..b8e8ac5668 --- /dev/null +++ b/extensions/source/abpilot/fieldmappingimpl.cxx @@ -0,0 +1,316 @@ +/* -*- 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 "fieldmappingimpl.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace abp +{ + + + using namespace ::utl; + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::awt; + using namespace ::com::sun::star::util; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::sdb; + using namespace ::com::sun::star::ui; + using namespace ::com::sun::star::ui::dialogs; + + + const char16_t sDriverSettingsNodeName[] = u"/org.openoffice.Office.DataAccess/DriverSettings/com.sun.star.comp.sdbc.MozabDriver"; + constexpr OUString sAddressBookNodeName = u"/org.openoffice.Office.DataAccess/AddressBook"_ustr; + + namespace fieldmapping + { + bool invokeDialog( const Reference< XComponentContext >& _rxORB, class weld::Window* _pParent, + const Reference< XPropertySet >& _rxDataSource, AddressSettings& _rSettings ) + { + _rSettings.aFieldMapping.clear(); + + DBG_ASSERT( _rxORB.is(), "fieldmapping::invokeDialog: invalid service factory!" ); + DBG_ASSERT( _rxDataSource.is(), "fieldmapping::invokeDialog: invalid data source!" ); + if ( !_rxORB.is() || !_rxDataSource.is() ) + return false; + + try + { + + // create an instance of the dialog service + Reference< XWindow > xDialogParent = _pParent->GetXWindow(); + OUString sTitle(compmodule::ModuleRes(RID_STR_FIELDDIALOGTITLE)); + Reference< XExecutableDialog > xDialog = AddressBookSourceDialog::createWithDataSource(_rxORB, + // the parent window + xDialogParent, + _rxDataSource, + _rSettings.bRegisterDataSource ? _rSettings.sRegisteredDataSourceName : _rSettings.sDataSourceName, + // the table to use + _rSettings.sSelectedTable, + sTitle); + + // execute the dialog + if ( xDialog->execute() ) + { + // retrieve the field mapping as set by he user + Reference< XPropertySet > xDialogProps( xDialog, UNO_QUERY ); + + Sequence< AliasProgrammaticPair > aMapping; + bool bSuccess = + xDialogProps->getPropertyValue("FieldMapping") >>= aMapping; + DBG_ASSERT( bSuccess, "fieldmapping::invokeDialog: invalid property type for FieldMapping!" ); + + // and copy it into the map + const AliasProgrammaticPair* pMapping = aMapping.getConstArray(); + const AliasProgrammaticPair* pMappingEnd = pMapping + aMapping.getLength(); + for (;pMapping != pMappingEnd; ++pMapping) + _rSettings.aFieldMapping[ pMapping->ProgrammaticName ] = pMapping->Alias; + + return true; + } + + } + catch(const Exception&) + { + TOOLS_WARN_EXCEPTION("extensions.abpilot", + "caught an exception while executing the dialog!"); + } + return false; + } + + + void defaultMapping( const Reference< XComponentContext >& _rxContext, MapString2String& _rFieldAssignment ) + { + _rFieldAssignment.clear(); + + try + { + // what we have: + // a) For the address data source, we need a mapping from programmatic names (1) to real column names + // b) The SDBC driver has a fixed set of columns, which, when returned, are named according to + // some configuration entries. E.g., the driver displays the field which it knows contains + // the first name as "First Name" - the latter string is stored in the config. + // For this, the driver uses programmatic names, too, but they differ from the programmatic names the + // template documents have. + // So what we need first is a mapping from programmatic names (1) to programmatic names (2) + const char* pMappingProgrammatics[] = + { + "FirstName", "FirstName", + "LastName", "LastName", + "Street", "HomeAddress", + "Zip", "HomeZipCode", + "City", "HomeCity", + "State", "HomeState", + "Country", "HomeCountry", + "PhonePriv", "HomePhone", + "PhoneComp", "WorkPhone", + "PhoneCell", "CellularNumber", + "Pager", "PagerNumber", + "Fax", "FaxNumber", + "EMail", "PrimaryEmail", + "URL", "WebPage1", + "Note", "Notes", + "Altfield1", "Custom1", + "Altfield2", "Custom2", + "Altfield3", "Custom3", + "Altfield4", "Custom4", + "Title", "JobTitle", + "Company", "Company", + "Department", "Department" + }; + // (this list is not complete: both lists of programmatic names are larger in real, + // but this list above is the intersection) + + + // access the configuration information which the driver uses for determining its column names + OUString sDriverAliasesNodeName( + OUString::Concat(sDriverSettingsNodeName) + + "/ColumnAliases"); + + // create a config node for this + OConfigurationTreeRoot aDriverFieldAliasing = OConfigurationTreeRoot::createWithComponentContext( + _rxContext, sDriverAliasesNodeName, -1, OConfigurationTreeRoot::CM_READONLY); + + // loop through all programmatic pairs + DBG_ASSERT( 0 == std::size( pMappingProgrammatics ) % 2, + "fieldmapping::defaultMapping: invalid programmatic map!" ); + // number of pairs + sal_Int32 const nIntersectedProgrammatics = std::size( pMappingProgrammatics ) / 2; + + const char** pProgrammatic = pMappingProgrammatics; + OUString sAddressProgrammatic; + OUString sDriverProgrammatic; + OUString sDriverUI; + for ( sal_Int32 i=0; + i < nIntersectedProgrammatics; + ++i + ) + { + sAddressProgrammatic = OUString::createFromAscii( *pProgrammatic++ ); + sDriverProgrammatic = OUString::createFromAscii( *pProgrammatic++ ); + + if ( aDriverFieldAliasing.hasByName( sDriverProgrammatic ) ) + { + aDriverFieldAliasing.getNodeValue( sDriverProgrammatic ) >>= sDriverUI; + if ( 0 == sDriverUI.getLength() ) + { + OSL_FAIL( "fieldmapping::defaultMapping: invalid driver UI column name!"); + } + else + _rFieldAssignment[ sAddressProgrammatic ] = sDriverUI; + } + else + { + OSL_FAIL( "fieldmapping::defaultMapping: invalid driver programmatic name!" ); + } + } + } + catch( const Exception& ) + { + TOOLS_WARN_EXCEPTION("extensions.abpilot", + "code is assumed to throw no exceptions!"); + // the config nodes we're using herein should not do this... + } + } + + + void writeTemplateAddressFieldMapping( const Reference< XComponentContext >& _rxContext, MapString2String&& aFieldAssignment ) + { + // access the configuration information which the driver uses for determining its column names + + // create a config node for this + OConfigurationTreeRoot aAddressBookSettings = OConfigurationTreeRoot::createWithComponentContext( + _rxContext, sAddressBookNodeName); + + OConfigurationNode aFields = aAddressBookSettings.openNode( OUString( "Fields" ) ); + + // loop through all existent fields + Sequence< OUString > aExistentFields = aFields.getNodeNames(); + const OUString* pExistentFields = aExistentFields.getConstArray(); + const OUString* pExistentFieldsEnd = pExistentFields + aExistentFields.getLength(); + + static constexpr OUString sProgrammaticNodeName( u"ProgrammaticFieldName"_ustr ); + static constexpr OUString sAssignedNodeName( u"AssignedFieldName"_ustr ); + + for ( ; pExistentFields != pExistentFieldsEnd; ++pExistentFields ) + { + SAL_WARN_IF( + ((aFields.openNode(*pExistentFields) + .getNodeValue(sProgrammaticNodeName).get()) + != *pExistentFields), + "extensions.abpilot", + "fieldmapping::writeTemplateAddressFieldMapping: inconsistent config data!"); + // there should be a redundancy in the config data... if this asserts, there isn't anymore! + + // do we have a new alias for the programmatic? + MapString2String::iterator aPos = aFieldAssignment.find( *pExistentFields ); + if ( aFieldAssignment.end() != aPos ) + { // yes + // -> set a new value + OConfigurationNode aExistentField = aFields.openNode( *pExistentFields ); + aExistentField.setNodeValue( sAssignedNodeName, Any( aPos->second ) ); + // and remove the mapping entry + aFieldAssignment.erase( *pExistentFields ); + } + else + { // no + // -> remove it + aFields.removeNode( *pExistentFields ); + } + } + + // now everything remaining in aFieldAssignment marks a mapping entry which was not present + // in the config before + for (auto const& elem : aFieldAssignment) + { + DBG_ASSERT( !aFields.hasByName( elem.first ), + "fieldmapping::writeTemplateAddressFieldMapping: inconsistence!" ); + // in case the config node for the fields already has the node named first>, + // the entry should have been removed from aNewMapping (in the above loop) + OConfigurationNode aNewField = aFields.createNode( elem.first ); + aNewField.setNodeValue( sProgrammaticNodeName, Any( elem.first ) ); + aNewField.setNodeValue( sAssignedNodeName, Any( elem.second ) ); + } + + // commit the changes done + aAddressBookSettings.commit(); + } + + + } // namespace fieldmapping + + + namespace addressconfig + { + + + void writeTemplateAddressSource( const Reference< XComponentContext >& _rxContext, + const OUString& _rDataSourceName, const OUString& _rTableName ) + { + // access the configuration information which the driver uses for determining its column names + + // create a config node for this + OConfigurationTreeRoot aAddressBookSettings = OConfigurationTreeRoot::createWithComponentContext( + _rxContext, sAddressBookNodeName); + + aAddressBookSettings.setNodeValue( OUString( "DataSourceName" ), Any( _rDataSourceName ) ); + aAddressBookSettings.setNodeValue( OUString( "Command" ), Any( _rTableName ) ); + aAddressBookSettings.setNodeValue( OUString( "CommandType" ), Any( sal_Int16(CommandType::TABLE) ) ); + + // commit the changes done + aAddressBookSettings.commit(); + } + + + void markPilotSuccess( const Reference< XComponentContext >& _rxContext ) + { + // access the configuration information which the driver uses for determining its column names + + // create a config node for this + OConfigurationTreeRoot aAddressBookSettings = OConfigurationTreeRoot::createWithComponentContext( + _rxContext, sAddressBookNodeName); + + // set the flag + aAddressBookSettings.setNodeValue( OUString( "AutoPilotCompleted" ), Any( true ) ); + + // commit the changes done + aAddressBookSettings.commit(); + } + + + } // namespace addressconfig + + +} // namespace abp + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/abpilot/fieldmappingimpl.hxx b/extensions/source/abpilot/fieldmappingimpl.hxx new file mode 100644 index 0000000000..e4a2dd1c96 --- /dev/null +++ b/extensions/source/abpilot/fieldmappingimpl.hxx @@ -0,0 +1,111 @@ +/* -*- 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 . + */ + +#pragma once + +#include +#include "abptypes.hxx" +#include +#include "addresssettings.hxx" + +namespace com::sun::star { + namespace lang { + class XMultiServiceFactory; + } + namespace uno { + class XComponentContext; + } + namespace beans { + class XPropertySet; + } +} +namespace weld { class Window; } + +namespace abp +{ + + + namespace fieldmapping + { + + + /** invokes the field mapping dialog + @param _rxORB + service factory to use for creating UNO services + @param _pParent + window to use as parent for the dialog and error messages + @param _rSettings + current settings. Upon return, the field mapping member of this + structure will be filled with the settings the user did in the + field mapping dialog. + */ + bool invokeDialog( + const css::uno::Reference< css::uno::XComponentContext >& _rxORB, + class weld::Window* _pParent, + const css::uno::Reference< css::beans::XPropertySet >& _rxDataSource, + AddressSettings& _rSettings + ); + + + /** creates a default field mapping for usage with the address book SDBC driver +

The column names as used by the SDBC driver for address books is stored in the configuration, + and this function creates a mapping which uses this configuration information.

+ */ + void defaultMapping( + const css::uno::Reference< css::uno::XComponentContext >& _rxContext, + MapString2String& /* [out] */ _rFieldAssignment + ); + + + /** writes a field mapping for the template document address source + */ + void writeTemplateAddressFieldMapping( + const css::uno::Reference< css::uno::XComponentContext >& _rxContext, + MapString2String&& _rFieldAssignment + ); + + + } // namespace fieldmapping + + + namespace addressconfig + { + + + /** writes the data source / table name given into the configuration, to where the template documents + expect it. + */ + void writeTemplateAddressSource( + const css::uno::Reference< css::uno::XComponentContext >& _rxContext, + const OUString& _rDataSourceName, + const OUString& _rTableName + ); + + /** writes the configuration entry which states the pilot has been completed successfully + */ + void markPilotSuccess( + const css::uno::Reference< css::uno::XComponentContext >& _rxContext + ); + + + } // namespace addressconfig + + +} // namespace abp +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/abpilot/fieldmappingpage.cxx b/extensions/source/abpilot/fieldmappingpage.cxx new file mode 100644 index 0000000000..1652723fda --- /dev/null +++ b/extensions/source/abpilot/fieldmappingpage.cxx @@ -0,0 +1,77 @@ +/* -*- 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 "fieldmappingpage.hxx" +#include "fieldmappingimpl.hxx" +#include "addresssettings.hxx" +#include "abspilot.hxx" + + +namespace abp +{ + FieldMappingPage::FieldMappingPage(weld::Container* pPage, OAddressBookSourcePilot* pController) + : AddressBookSourcePage(pPage, pController, "modules/sabpilot/ui/fieldassignpage.ui", "FieldAssignPage") + , m_xInvokeDialog(m_xBuilder->weld_button("assign")) + , m_xHint(m_xBuilder->weld_label("hint")) + { + m_xInvokeDialog->connect_clicked(LINK(this, FieldMappingPage, OnInvokeDialog)); + } + + FieldMappingPage::~FieldMappingPage() + { + } + + void FieldMappingPage::Activate() + { + AddressBookSourcePage::Activate(); + m_xInvokeDialog->grab_focus(); + } + + void FieldMappingPage::initializePage() + { + AddressBookSourcePage::initializePage(); + implUpdateHint(); + } + + void FieldMappingPage::implUpdateHint() + { + const AddressSettings& rSettings = getSettings(); + OUString sHint; + if ( rSettings.aFieldMapping.empty() ) + sHint = compmodule::ModuleRes(RID_STR_NOFIELDSASSIGNED); + m_xHint->set_label(sHint); + } + + IMPL_LINK_NOARG( FieldMappingPage, OnInvokeDialog, weld::Button&, void ) + { + AddressSettings& rSettings = getSettings(); + + // invoke the dialog doing the mapping + if ( fieldmapping::invokeDialog( getORB(), getDialog()->getDialog(), getDialog()->getDataSource().getDataSource(), rSettings ) ) + { + if ( !rSettings.aFieldMapping.empty() ) + getDialog()->travelNext(); + else + implUpdateHint(); + } + } + +} // namespace abp + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/abpilot/fieldmappingpage.hxx b/extensions/source/abpilot/fieldmappingpage.hxx new file mode 100644 index 0000000000..e3ef93794f --- /dev/null +++ b/extensions/source/abpilot/fieldmappingpage.hxx @@ -0,0 +1,46 @@ +/* -*- 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 . + */ + +#pragma once + +#include "abspage.hxx" +#include + +namespace abp +{ + class FieldMappingPage final : public AddressBookSourcePage + { + std::unique_ptr m_xInvokeDialog; + std::unique_ptr m_xHint; + public: + explicit FieldMappingPage(weld::Container* pPage, OAddressBookSourcePilot* pController); + virtual ~FieldMappingPage() override; + private: + // OWizardPage overridables + virtual void initializePage() override; + + // BuilderPage overridables + virtual void Activate() override; + + DECL_LINK(OnInvokeDialog, weld::Button&, void); + + void implUpdateHint(); + }; +} // namespace abp +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/abpilot/moduleabp.cxx b/extensions/source/abpilot/moduleabp.cxx new file mode 100644 index 0000000000..0a8f8fd4d2 --- /dev/null +++ b/extensions/source/abpilot/moduleabp.cxx @@ -0,0 +1,22 @@ +/* -*- 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 + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/abpilot/tableselectionpage.cxx b/extensions/source/abpilot/tableselectionpage.cxx new file mode 100644 index 0000000000..abf8e58296 --- /dev/null +++ b/extensions/source/abpilot/tableselectionpage.cxx @@ -0,0 +1,101 @@ +/* -*- 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 "tableselectionpage.hxx" +#include "abptypes.hxx" +#include "addresssettings.hxx" +#include "abspilot.hxx" +#include + + +namespace abp +{ + + TableSelectionPage::TableSelectionPage(weld::Container* pPage, OAddressBookSourcePilot* pController) + : AddressBookSourcePage(pPage, pController, "modules/sabpilot/ui/selecttablepage.ui", "SelectTablePage") + , m_xTableList(m_xBuilder->weld_tree_view("table")) + { + m_xTableList->connect_changed( LINK( this, TableSelectionPage, OnTableSelected ) ); + m_xTableList->connect_row_activated( LINK( this, TableSelectionPage, OnTableDoubleClicked ) ); + } + + TableSelectionPage::~TableSelectionPage() + { + } + + void TableSelectionPage::Activate() + { + AddressBookSourcePage::Activate(); + + m_xTableList->grab_focus(); + } + + void TableSelectionPage::initializePage() + { + AddressBookSourcePage::initializePage(); + + const AddressSettings& rSettings = getSettings(); + + m_xTableList->clear(); + + // get the table names + const StringBag& aTableNames = getDialog()->getDataSource().getTableNames(); + DBG_ASSERT( aTableNames.size() > 1, "TableSelectionPage::initializePage: to be called for more than one table only!"); + // this page should never bother the user if there is 1 or less tables. + + // fill the list + for (auto const& tableName : aTableNames) + m_xTableList->append_text(tableName); + + // initially select the proper table + m_xTableList->select_text(rSettings.sSelectedTable); + } + + IMPL_LINK_NOARG( TableSelectionPage, OnTableDoubleClicked, weld::TreeView&, bool ) + { + if (m_xTableList->count_selected_rows() == 1) + getDialog()->travelNext(); + return true; + } + + IMPL_LINK_NOARG( TableSelectionPage, OnTableSelected, weld::TreeView&, void ) + { + updateDialogTravelUI(); + } + + bool TableSelectionPage::commitPage( ::vcl::WizardTypes::CommitPageReason _eReason ) + { + if (!AddressBookSourcePage::commitPage(_eReason)) + return false; + + AddressSettings& rSettings = getSettings(); + rSettings.sSelectedTable = m_xTableList->get_selected_text(); + + return true; + } + + bool TableSelectionPage::canAdvance() const + { + return AddressBookSourcePage::canAdvance() + && (m_xTableList->count_selected_rows() > 0); + } + +} // namespace abp + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/abpilot/tableselectionpage.hxx b/extensions/source/abpilot/tableselectionpage.hxx new file mode 100644 index 0000000000..a150bf844f --- /dev/null +++ b/extensions/source/abpilot/tableselectionpage.hxx @@ -0,0 +1,50 @@ +/* -*- 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 . + */ + +#pragma once + +#include "abspage.hxx" +#include + +namespace abp +{ + class TableSelectionPage final : public AddressBookSourcePage + { + std::unique_ptr m_xTableList; + + public: + explicit TableSelectionPage(weld::Container* pPage, OAddressBookSourcePilot* pController); + virtual ~TableSelectionPage() override; + private: + // OWizardPage overridables + virtual void initializePage() override; + virtual bool commitPage( ::vcl::WizardTypes::CommitPageReason _eReason ) override; + + // BuilderPage overridables + virtual void Activate() override; + + // OImportPage overridables + virtual bool canAdvance() const override; + + DECL_LINK(OnTableSelected, weld::TreeView&, void); + DECL_LINK(OnTableDoubleClicked, weld::TreeView&, bool); + }; + +} // namespace abp +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/abpilot/typeselectionpage.cxx b/extensions/source/abpilot/typeselectionpage.cxx new file mode 100644 index 0000000000..79cfd5d6b0 --- /dev/null +++ b/extensions/source/abpilot/typeselectionpage.cxx @@ -0,0 +1,224 @@ +/* -*- 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 "typeselectionpage.hxx" +#include "addresssettings.hxx" +#include "abspilot.hxx" +#include +#include +#include +#include + +namespace abp +{ + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::sdbc; + + // TypeSelectionPage + TypeSelectionPage::TypeSelectionPage(weld::Container* pPage, OAddressBookSourcePilot* pDialog) + : AddressBookSourcePage(pPage, pDialog, "modules/sabpilot/ui/selecttypepage.ui", "SelectTypePage") + , m_xEvolution(m_xBuilder->weld_radio_button("evolution")) + , m_xEvolutionGroupwise(m_xBuilder->weld_radio_button("groupwise")) + , m_xEvolutionLdap(m_xBuilder->weld_radio_button("evoldap")) + , m_xThunderbird(m_xBuilder->weld_radio_button("thunderbird")) + , m_xKab(m_xBuilder->weld_radio_button("kde")) + , m_xMacab(m_xBuilder->weld_radio_button("macosx")) + , m_xOther(m_xBuilder->weld_radio_button("other")) + { + //TODO: For now, try to keep offering the same choices like before the + // Mozilla cleanup, even if the status of what driver actually + // provides which functionality is somewhat unclear, see the discussions + // of fdo#57285 "Address Book Data Source Wizard lists 'macOS address + // book' on Linux" and fdo#57322 "Moz-free LDAP Address Book driver." + // In accordance with ancient OOo 3.3, this is as follows: + // + // On Linux: + // - EVOLUTION, EVOLUTION_GROUPWISE, EVOLUTION_LDAP (if applicable) + // - KAB (if applicable) + // - OTHER + // + // On macOS: + // - MACAB (if applicable) + // - OTHER + // + // On Windows: + // - THUNDERBIRD + // - OTHER + +#if !defined(_WIN32) + bool bHaveEvolution = false; + bool bHaveKab = false; + bool bHaveMacab = false; + + Reference< XDriverManager2 > xManager = DriverManager::create( pDialog->getORB() ); + + try + { + // check whether Evolution is available + Reference< XDriver > xDriver( xManager->getDriverByURL("sdbc:address:evolution:local") ); + if ( xDriver.is() ) + bHaveEvolution = true; + } + catch (...) + { + } + + // check whether KDE address book is available + try + { + Reference< XDriver > xDriver( xManager->getDriverByURL("sdbc:address:kab") ); + if ( xDriver.is() ) + bHaveKab = true; + } + catch (...) + { + } + + try + { + // check whether macOS address book is available + Reference< XDriver > xDriver( xManager->getDriverByURL("sdbc:address:macab") ); + if ( xDriver.is() ) + bHaveMacab = true; + } + catch(...) + { + } +#else + bool const bHaveEvolution = false; + bool const bHaveKab = false; + bool const bHaveMacab = false; +#endif + + // Items are displayed in list order + m_aAllTypes.push_back( ButtonItem( m_xEvolution.get(), AST_EVOLUTION, bHaveEvolution ) ); + m_aAllTypes.push_back( ButtonItem( m_xEvolutionGroupwise.get(), AST_EVOLUTION_GROUPWISE, bHaveEvolution ) ); + m_aAllTypes.push_back( ButtonItem( m_xEvolutionLdap.get(), AST_EVOLUTION_LDAP, bHaveEvolution ) ); + m_aAllTypes.push_back( ButtonItem( m_xThunderbird.get(), AST_THUNDERBIRD, true ) ); + m_aAllTypes.push_back( ButtonItem( m_xKab.get(), AST_KAB, bHaveKab ) ); + m_aAllTypes.push_back( ButtonItem( m_xMacab.get(), AST_MACAB, bHaveMacab ) ); + m_aAllTypes.push_back( ButtonItem( m_xOther.get(), AST_OTHER, true ) ); + + Link aTypeSelectionHandler = LINK(this, TypeSelectionPage, OnTypeSelected ); + for (auto const& elem : m_aAllTypes) + { + if (!elem.m_bVisible) + elem.m_pItem->hide(); + else + { + elem.m_pItem->connect_toggled( aTypeSelectionHandler ); + elem.m_pItem->show(); + } + } + } + + TypeSelectionPage::~TypeSelectionPage() + { + for (auto & elem : m_aAllTypes) + { + elem.m_bVisible = false; + } + } + + void TypeSelectionPage::Activate() + { + AddressBookSourcePage::Activate(); + + for (auto const& elem : m_aAllTypes) + { + if( elem.m_pItem->get_active() && elem.m_bVisible ) + { + elem.m_pItem->grab_focus(); + break; + } + } + + getDialog()->enableButtons(WizardButtonFlags::PREVIOUS, false); + } + + void TypeSelectionPage::Deactivate() + { + AddressBookSourcePage::Deactivate(); + getDialog()->enableButtons(WizardButtonFlags::PREVIOUS, true); + } + + void TypeSelectionPage::selectType( AddressSourceType _eType ) + { + for (auto const& elem : m_aAllTypes) + { + elem.m_pItem->set_active( _eType == elem.m_eType ); + } + } + + AddressSourceType TypeSelectionPage::getSelectedType() const + { + for (auto const& elem : m_aAllTypes) + { + if ( elem.m_pItem->get_active() && elem.m_bVisible ) + return elem.m_eType; + } + + return AST_INVALID; + } + + void TypeSelectionPage::initializePage() + { + AddressBookSourcePage::initializePage(); + + const AddressSettings& rSettings = getSettings(); + selectType(rSettings.eType); + } + + bool TypeSelectionPage::commitPage( ::vcl::WizardTypes::CommitPageReason _eReason ) + { + if (!AddressBookSourcePage::commitPage(_eReason)) + return false; + + if (AST_INVALID == getSelectedType( )) + { + std::unique_ptr xBox(Application::CreateMessageDialog(m_xContainer.get(), + VclMessageType::Warning, VclButtonsType::Ok, + compmodule::ModuleRes(RID_STR_NEEDTYPESELECTION))); + xBox->run(); + return false; + } + + AddressSettings& rSettings = getSettings(); + rSettings.eType = getSelectedType(); + + return true; + } + + bool TypeSelectionPage::canAdvance() const + { + return AddressBookSourcePage::canAdvance() + && (AST_INVALID != getSelectedType()); + } + + IMPL_LINK(TypeSelectionPage, OnTypeSelected, weld::Toggleable&, rButton, void) + { + if (!rButton.get_active()) + return; + getDialog()->typeSelectionChanged( getSelectedType() ); + updateDialogTravelUI(); + } + +} // namespace abp + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/abpilot/typeselectionpage.hxx b/extensions/source/abpilot/typeselectionpage.hxx new file mode 100644 index 0000000000..7c908057d6 --- /dev/null +++ b/extensions/source/abpilot/typeselectionpage.hxx @@ -0,0 +1,81 @@ +/* -*- 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 . + */ + +#pragma once + +#include "abspage.hxx" +#include "addresssettings.hxx" +#include + +namespace abp +{ + + class TypeSelectionPage final : public AddressBookSourcePage + { + std::unique_ptr m_xEvolution; + std::unique_ptr m_xEvolutionGroupwise; + std::unique_ptr m_xEvolutionLdap; + std::unique_ptr m_xThunderbird; + std::unique_ptr m_xKab; + std::unique_ptr m_xMacab; + std::unique_ptr m_xOther; + + struct ButtonItem { + weld::RadioButton* m_pItem; + AddressSourceType m_eType; + bool m_bVisible; + + ButtonItem( weld::RadioButton *pItem, + AddressSourceType eType, + bool bVisible ) : + m_pItem( pItem ), + m_eType( eType ), + m_bVisible( bVisible ) + {} + }; + + std::vector< ButtonItem > m_aAllTypes; + + public: + explicit TypeSelectionPage(weld::Container* pPage, OAddressBookSourcePilot* pController); + virtual ~TypeSelectionPage() override; + + // retrieves the currently selected type + AddressSourceType getSelectedType() const; + + private: + // OWizardPage overridables + virtual void initializePage() override; + virtual bool commitPage( ::vcl::WizardTypes::CommitPageReason _eReason ) override; + + // BuilderPage overridables + virtual void Activate() override; + virtual void Deactivate() override; + + // OImportPage overridables + virtual bool canAdvance() const override; + + DECL_LINK( OnTypeSelected, weld::Toggleable&, void ); + + void selectType( AddressSourceType _eType ); + }; + + +} // namespace abp +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/abpilot/unodialogabp.cxx b/extensions/source/abpilot/unodialogabp.cxx new file mode 100644 index 0000000000..4409a1911f --- /dev/null +++ b/extensions/source/abpilot/unodialogabp.cxx @@ -0,0 +1,156 @@ +/* -*- 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 "unodialogabp.hxx" +#include "abspilot.hxx" +#include +#include +#include +#include +#include + +#define PROPERTY_ID_DATASOURCENAME 3 + +namespace abp +{ + using namespace ::com::sun::star; + 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; + + OABSPilotUno::OABSPilotUno(const Reference< XComponentContext >& _rxORB) + :OGenericUnoDialog(_rxORB) + { + registerProperty( "DataSourceName", PROPERTY_ID_DATASOURCENAME, PropertyAttribute::READONLY , + &m_sDataSourceName, cppu::UnoType::get() ); + } + + Any SAL_CALL OABSPilotUno::queryInterface( const Type& aType ) + { + Any aReturn = svt::OGenericUnoDialog::queryInterface( aType ); + return aReturn.hasValue() ? aReturn : OABSPilotUno_JBase::queryInterface( aType ); + } + + void SAL_CALL OABSPilotUno::acquire( ) noexcept + { + svt::OGenericUnoDialog::acquire(); + } + + void SAL_CALL OABSPilotUno::release( ) noexcept + { + svt::OGenericUnoDialog::release(); + } + + Sequence< Type > SAL_CALL OABSPilotUno::getTypes( ) + { + return ::comphelper::concatSequences( + svt::OGenericUnoDialog::getTypes(), + OABSPilotUno_JBase::getTypes() + ); + } + + Sequence SAL_CALL OABSPilotUno::getImplementationId( ) + { + return css::uno::Sequence(); + } + + OUString SAL_CALL OABSPilotUno::getImplementationName() + { + return "org.openoffice.comp.abp.OAddressBookSourcePilot"; + } + + css::uno::Sequence SAL_CALL OABSPilotUno::getSupportedServiceNames() + { + return { "com.sun.star.ui.dialogs.AddressBookSourcePilot" }; + } + + Reference SAL_CALL OABSPilotUno::getPropertySetInfo() + { + Reference xInfo( createPropertySetInfo( getInfoHelper() ) ); + return xInfo; + } + + + ::cppu::IPropertyArrayHelper& OABSPilotUno::getInfoHelper() + { + return *getArrayHelper(); + } + + + ::cppu::IPropertyArrayHelper* OABSPilotUno::createArrayHelper( ) const + { + Sequence< Property > aProps; + describeProperties(aProps); + return new ::cppu::OPropertyArrayHelper(aProps); + } + + void SAL_CALL OABSPilotUno::initialize( const Sequence< Any >& aArguments ) + { + Reference xParentWindow; + if (aArguments.getLength() == 1 && (aArguments[0] >>= xParentWindow) ) { + Sequence< Any > aNewArgs{ Any(PropertyValue( + "ParentWindow", 0, Any(xParentWindow), PropertyState_DIRECT_VALUE )) }; + OGenericUnoDialog::initialize(aNewArgs); + } else { + OGenericUnoDialog::initialize(aArguments); + } + } + + std::unique_ptr OABSPilotUno::createDialog(const css::uno::Reference& rParent) + { + return std::make_unique(Application::GetFrameWeld(rParent), m_aContext); + } + + Any SAL_CALL OABSPilotUno::execute( const Sequence< NamedValue >& /*lArgs*/ ) + { + // not interested in the context, not interested in the args + // -> call the execute method of the XExecutableDialog + static_cast< XExecutableDialog* >( this )->execute(); + + // result interest not really ... + // We show this dialog one times only! + // User has one chance to accept it or not. + // (or he can start it again by using wizard-menu!) + // So we should deregister it on our general job execution service by using right protocol parameters. + css::uno::Sequence< css::beans::NamedValue > lProtocol { { "Deactivate", css::uno::Any( true ) } }; + return Any( lProtocol ); + } + + void OABSPilotUno::executedDialog(sal_Int16 _nExecutionResult) + { + if ( _nExecutionResult == RET_OK ) + { + const AddressSettings& aSettings = static_cast(m_xDialog.get())->getSettings(); + m_sDataSourceName = aSettings.bRegisterDataSource ? aSettings.sRegisteredDataSourceName : aSettings.sDataSourceName; + } + } + + +} // namespace abp + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +org_openoffice_comp_abp_OAddressBookSourcePilot( + css::uno::XComponentContext *context, + css::uno::Sequence const &) +{ + return cppu::acquire(new abp::OABSPilotUno(context)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/abpilot/unodialogabp.hxx b/extensions/source/abpilot/unodialogabp.hxx new file mode 100644 index 0000000000..b8bd940afa --- /dev/null +++ b/extensions/source/abpilot/unodialogabp.hxx @@ -0,0 +1,78 @@ +/* -*- 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 . + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace abp +{ + class OABSPilotUno; + typedef ::cppu::ImplHelper1< css::task::XJob > OABSPilotUno_JBase; + typedef ::comphelper::OPropertyArrayUsageHelper< OABSPilotUno > OABSPilotUno_PBase; + /// the UNO wrapper for the address book source pilot + class OABSPilotUno + : public svt::OGenericUnoDialog + , public OABSPilotUno_JBase + , public OABSPilotUno_PBase + { + OUString m_sDataSourceName; + + public: + explicit OABSPilotUno(const css::uno::Reference< css::uno::XComponentContext >& _rxORB); + + private: + // XInterface (disambiguation) + virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& aType ) override; + virtual void SAL_CALL acquire( ) noexcept override; + virtual void SAL_CALL release( ) noexcept override; + + // XTypeProvider + virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes( ) override; + virtual css::uno::Sequence SAL_CALL getImplementationId( ) override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual css::uno::Sequence SAL_CALL getSupportedServiceNames() override; + + // XPropertySet + virtual css::uno::Reference< css::beans::XPropertySetInfo> SAL_CALL getPropertySetInfo() override; + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override; + + // OPropertyArrayUsageHelper + virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override; + + // XJob + virtual css::uno::Any SAL_CALL execute( const css::uno::Sequence< css::beans::NamedValue >& lArgs ) override; + + // XInitialisation + virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override; + + using svt::OGenericUnoDialog::execute; + // OGenericUnoDialog overridables + virtual std::unique_ptr createDialog(const css::uno::Reference& rParent) override; + virtual void executedDialog(sal_Int16 _nExecutionResult) override; + }; + +} // namespace abp +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit v1.2.3