diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
commit | 940b4d1848e8c70ab7642901a68594e8016caffc (patch) | |
tree | eb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /dbaccess/source/ui/dlg | |
parent | Initial commit. (diff) | |
download | libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.tar.xz libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.zip |
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dbaccess/source/ui/dlg')
60 files changed, 17408 insertions, 0 deletions
diff --git a/dbaccess/source/ui/dlg/CollectionView.cxx b/dbaccess/source/ui/dlg/CollectionView.cxx new file mode 100644 index 000000000..6b978bc30 --- /dev/null +++ b/dbaccess/source/ui/dlg/CollectionView.cxx @@ -0,0 +1,318 @@ +/* -*- 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 <CollectionView.hxx> +#include <tools/diagnose_ex.h> +#include <core_resource.hxx> +#include <strings.hrc> +#include <comphelper/interaction.hxx> +#include <comphelper/propertysequence.hxx> +#include <cppuhelper/exc_hlp.hxx> +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> +#include <UITools.hxx> +#include <com/sun/star/container/XHierarchicalNameContainer.hpp> +#include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp> +#include <com/sun/star/ucb/IOErrorCode.hpp> +#include <com/sun/star/ucb/XDynamicResultSet.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/task/InteractionHandler.hpp> +#include <com/sun/star/task/InteractionClassification.hpp> +#include <com/sun/star/sdbc/SQLException.hpp> +#include <comphelper/processfactory.hxx> +#include <ucbhelper/commandenvironment.hxx> +#include <ucbhelper/content.hxx> +#include <connectivity/dbexception.hxx> + +namespace dbaui +{ + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ucb; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::task; +using namespace ::com::sun::star::sdbc; +using namespace comphelper; + +OCollectionView::OCollectionView(weld::Window* pParent, + const Reference< XContent>& _xContent, + const OUString& _sDefaultName, + const css::uno::Reference< css::uno::XComponentContext >& _rxContext) + : GenericDialogController(pParent, "dbaccess/ui/collectionviewdialog.ui", "CollectionView") + , m_xContent(_xContent) + , m_xContext(_rxContext) + , m_bCreateForm(true) + , m_xFTCurrentPath(m_xBuilder->weld_label("currentPathLabel")) + , m_xNewFolder(m_xBuilder->weld_button("newFolderButton")) + , m_xUp(m_xBuilder->weld_button("upButton")) + , m_xView(m_xBuilder->weld_tree_view("viewTreeview")) + , m_xName(m_xBuilder->weld_entry("fileNameEntry")) + , m_xPB_OK(m_xBuilder->weld_button("ok")) +{ + Reference<XInteractionHandler2> xHandler( + InteractionHandler::createWithParent(m_xContext, m_xDialog->GetXWindow())); + m_xCmdEnv = new ::ucbhelper::CommandEnvironment(xHandler, nullptr); + + OSL_ENSURE(m_xContent.is(),"No valid content!"); + m_xView->set_size_request(m_xView->get_approximate_digit_width() * 60, m_xView->get_height_rows(8)); + m_xView->make_sorted(); + Initialize(); + initCurrentPath(); + + m_xName->set_text(_sDefaultName); + m_xName->grab_focus(); + + m_xView->connect_row_activated( LINK( this, OCollectionView, Dbl_Click_FileView ) ); + m_xUp->connect_clicked( LINK( this, OCollectionView, Up_Click ) ); + m_xNewFolder->connect_clicked( LINK( this, OCollectionView, NewFolder_Click ) ); + m_xPB_OK->connect_clicked( LINK( this, OCollectionView, Save_Click ) ); +} + +OCollectionView::~OCollectionView() +{ +} + +IMPL_LINK_NOARG(OCollectionView, Save_Click, weld::Button&, void) +{ + OUString sName = m_xName->get_text(); + if (sName.isEmpty()) + return; + try + { + sal_Int32 nIndex = sName.lastIndexOf('/') + 1; + if ( nIndex ) + { + if ( nIndex == 1 ) // special handling for root + { + Reference<XChild> xChild(m_xContent,UNO_QUERY); + Reference<XNameAccess> xNameAccess(xChild,UNO_QUERY); + while( xNameAccess.is() ) + { + xNameAccess.set(xChild->getParent(),UNO_QUERY); + if ( xNameAccess.is() ) + { + m_xContent.set(xNameAccess,UNO_QUERY); + xChild.set(m_xContent,UNO_QUERY); + } + } + Initialize(); + initCurrentPath(); + } + OUString sSubFolder = sName.copy(0,nIndex-1); + sName = sName.copy(nIndex); + Reference<XHierarchicalNameContainer> xHier(m_xContent,UNO_QUERY); + OSL_ENSURE(xHier.is(),"XHierarchicalNameContainer not supported!"); + if ( !sSubFolder.isEmpty() && xHier.is() ) + { + if ( xHier->hasByHierarchicalName(sSubFolder) ) + { + m_xContent.set(xHier->getByHierarchicalName(sSubFolder),UNO_QUERY); + } + else // sub folder doesn't exist + { + Sequence<Any> aValues(comphelper::InitAnyPropertySequence( + { + {"ResourceName", Any(sSubFolder)}, + {"ResourceType", Any(OUString("folder"))} + })); + InteractiveAugmentedIOException aException(OUString(),Reference<XInterface>(), + InteractionClassification_ERROR, + IOErrorCode_NOT_EXISTING_PATH,aValues); + + Reference<XInteractionHandler2> xHandler( + InteractionHandler::createWithParent(m_xContext, m_xDialog->GetXWindow())); + OInteractionRequest* pRequest = new OInteractionRequest(makeAny(aException)); + Reference< XInteractionRequest > xRequest(pRequest); + + OInteractionApprove* pApprove = new OInteractionApprove; + pRequest->addContinuation(pApprove); + xHandler->handle(xRequest); + + return; + } + } + } + Reference<XNameContainer> xNameContainer(m_xContent,UNO_QUERY); + if ( xNameContainer.is() ) + { + if ( xNameContainer->hasByName(sName) ) + { + std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Question, VclButtonsType::YesNo, + DBA_RES(STR_ALREADYEXISTOVERWRITE))); + if (xQueryBox->run() != RET_YES) + return; + } + m_xName->set_text(sName); + m_xDialog->response(RET_OK); + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("dbaccess"); + } +} + +IMPL_LINK_NOARG(OCollectionView, NewFolder_Click, weld::Button&, void) +{ + try + { + Reference<XHierarchicalNameContainer> xNameContainer(m_xContent,UNO_QUERY); + if ( dbaui::insertHierachyElement(m_xDialog.get(),m_xContext,xNameContainer,OUString(),m_bCreateForm) ) + Initialize(); + } + catch( const SQLException& ) + { + showError(::dbtools::SQLExceptionInfo(::cppu::getCaughtException()), m_xDialog->GetXWindow(), m_xContext); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("dbaccess"); + } +} + +IMPL_LINK_NOARG(OCollectionView, Up_Click, weld::Button&, void) +{ + try + { + Reference<XChild> xChild(m_xContent,UNO_QUERY); + if ( xChild.is() ) + { + Reference<XNameAccess> xNameAccess(xChild->getParent(),UNO_QUERY); + if ( xNameAccess.is() ) + { + m_xContent.set(xNameAccess,UNO_QUERY); + Initialize(); + initCurrentPath(); + } + else + m_xUp->set_sensitive(false); + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("dbaccess"); + } +} + +IMPL_LINK_NOARG(OCollectionView, Dbl_Click_FileView, weld::TreeView&, bool) +{ + try + { + Reference<XNameAccess> xNameAccess(m_xContent,UNO_QUERY); + if ( xNameAccess.is() ) + { + OUString sSubFolder = m_xView->get_selected_text(); + if (!sSubFolder.isEmpty()) + { + Reference< XContent> xContent; + if ( xNameAccess->hasByName(sSubFolder) ) + xContent.set(xNameAccess->getByName(sSubFolder),UNO_QUERY); + if ( xContent.is() ) + { + m_xContent = xContent; + Initialize(); + initCurrentPath(); + } + } + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("dbaccess"); + } + + return true; +} + +void OCollectionView::initCurrentPath() +{ + bool bEnable = false; + try + { + if ( m_xContent.is() ) + { + const OUString sCID = m_xContent->getIdentifier()->getContentIdentifier(); + static const char s_sFormsCID[] = "private:forms"; + static const char s_sReportsCID[] = "private:reports"; + m_bCreateForm = s_sFormsCID == sCID; + OUString sPath("/"); + if ( m_bCreateForm && sCID.getLength() != static_cast<sal_Int32>(strlen(s_sFormsCID))) + sPath = sCID.copy(strlen(s_sFormsCID)); + else if ( !m_bCreateForm && sCID.getLength() != static_cast<sal_Int32>(strlen(s_sReportsCID)) ) + sPath = sCID.copy(strlen(s_sReportsCID) - 2); + + m_xFTCurrentPath->set_label(sPath); + Reference<XChild> xChild(m_xContent,UNO_QUERY); + bEnable = xChild.is() && Reference<XNameAccess>(xChild->getParent(),UNO_QUERY).is(); + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("dbaccess"); + } + m_xUp->set_sensitive(bEnable); +} + +OUString OCollectionView::getName() const +{ + return m_xName->get_text(); +} + +#define ROW_TITLE 1 +#define ROW_IS_FOLDER 2 + +void OCollectionView::Initialize() +{ + weld::WaitObject aWaitCursor(m_xDialog.get()); + + m_xView->clear(); + + try + { + ::ucbhelper::Content aContent(m_xContent, m_xCmdEnv, comphelper::getProcessComponentContext()); + Sequence<OUString> aProps(2); + aProps[0] = "Title"; + aProps[1] = "IsFolder"; + auto xDynResultSet = aContent.createDynamicCursor(aProps, ucbhelper::INCLUDE_FOLDERS_ONLY); + if (!xDynResultSet.is()) + return; + + Reference<XResultSet> xResultSet = xDynResultSet->getStaticResultSet(); + Reference<XRow> xRow(xResultSet, UNO_QUERY); + while (xResultSet->next()) + { + if (!xRow->getBoolean(ROW_IS_FOLDER)) + continue; + m_xView->append_text(xRow->getString(ROW_TITLE)); + } + } + catch (const Exception&) + { + DBG_UNHANDLED_EXCEPTION("dbaccess"); + } +} + +} // namespace dbaui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/ConnectionHelper.cxx b/dbaccess/source/ui/dlg/ConnectionHelper.cxx new file mode 100644 index 000000000..a9f4418a2 --- /dev/null +++ b/dbaccess/source/ui/dlg/ConnectionHelper.cxx @@ -0,0 +1,726 @@ +/* -*- 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 <core_resource.hxx> +#include "dsnItem.hxx" +#include "ConnectionHelper.hxx" +#include <IItemSetHelper.hxx> +#include <strings.hrc> +#include <svl/itemset.hxx> +#include <unotools/moduleoptions.hxx> +#include <unotools/pathoptions.hxx> +#include <svl/stritem.hxx> +#include <dsitems.hxx> +#include <osl/diagnose.h> +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> +#include <sfx2/filedlghelper.hxx> +#include <vcl/stdtext.hxx> +#include <sqlmessage.hxx> +#include "dsselect.hxx" +#include <svl/filenotation.hxx> +#include <com/sun/star/awt/XSystemDependentWindowPeer.hpp> +#include <com/sun/star/ui/dialogs/FolderPicker.hpp> +#include <com/sun/star/ui/dialogs/TemplateDescription.hpp> +#include <com/sun/star/lang/SystemDependent.hpp> +#include <com/sun/star/mozilla/MozillaBootstrap.hpp> +#include <com/sun/star/task/InteractionHandler.hpp> +#include <com/sun/star/ucb/XProgressHandler.hpp> +#include <ucbhelper/commandenvironment.hxx> +#include <ucbhelper/content.hxx> +#include "finteraction.hxx" +#include <tools/urlobj.hxx> +#include <tools/diagnose_ex.h> + +#if defined _WIN32 +#include <rtl/process.h> +#include <vcl/sysdata.hxx> +#include "adodatalinks.hxx" +#endif + +#include <com/sun/star/mozilla/XMozillaBootstrap.hpp> +#include <comphelper/processfactory.hxx> +#include <comphelper/string.hxx> + +namespace dbaui +{ + using namespace ::com::sun::star; + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::ucb; + using namespace ::com::sun::star::ui::dialogs; + using namespace ::com::sun::star::sdbc; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::container; + using namespace ::com::sun::star::mozilla; + using namespace ::dbtools; + using namespace ::svt; + + OConnectionHelper::OConnectionHelper(weld::Container* pPage, weld::DialogController* pController, const OUString& _rUIXMLDescription, const OString& _rId, const SfxItemSet& _rCoreAttrs) + : OGenericAdministrationPage(pPage, pController, _rUIXMLDescription, _rId, _rCoreAttrs) + , m_bUserGrabFocus(false) + , m_pCollection(nullptr) + , m_xFT_Connection(m_xBuilder->weld_label("browseurllabel")) + , m_xPB_Connection(m_xBuilder->weld_button("browse")) + , m_xPB_CreateDB(m_xBuilder->weld_button("create")) + , m_xConnectionURL(new OConnectionURLEdit(m_xBuilder->weld_entry("browseurl"), m_xBuilder->weld_label("browselabel"))) + { + // extract the datasource type collection from the item set + const DbuTypeCollectionItem* pCollectionItem = dynamic_cast<const DbuTypeCollectionItem*>( _rCoreAttrs.GetItem(DSID_TYPECOLLECTION) ); + if (pCollectionItem) + m_pCollection = pCollectionItem->getCollection(); + m_xPB_Connection->connect_clicked(LINK(this, OConnectionHelper, OnBrowseConnections)); + m_xPB_CreateDB->connect_clicked(LINK(this, OConnectionHelper, OnCreateDatabase)); + OSL_ENSURE(m_pCollection, "OConnectionHelper::OConnectionHelper : really need a DSN type collection !"); + m_xConnectionURL->SetTypeCollection(m_pCollection); + + m_xConnectionURL->connect_focus_in(LINK(this, OConnectionHelper, GetFocusHdl)); + m_xConnectionURL->connect_focus_out(LINK(this, OConnectionHelper, LoseFocusHdl)); + } + + OConnectionHelper::~OConnectionHelper() + { + m_xConnectionURL.reset(); + } + + void OConnectionHelper::implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) + { + // check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa) + bool bValid, bReadonly; + getFlags(_rSet, bValid, bReadonly); + + m_xFT_Connection->show(); + m_xConnectionURL->show(); + m_xConnectionURL->ShowPrefix( ::dbaccess::DST_JDBC == m_pCollection->determineType(m_eType) ); + + bool bEnableBrowseButton = m_pCollection->supportsBrowsing( m_eType ); + m_xPB_Connection->set_visible( bEnableBrowseButton ); + + bool bEnableCreateButton = m_pCollection->supportsDBCreation( m_eType ); + m_xPB_CreateDB->set_visible( bEnableCreateButton ); + + const SfxStringItem* pUrlItem = _rSet.GetItem<SfxStringItem>(DSID_CONNECTURL); + + // forward the values to the controls + if ( bValid ) + { + OUString sUrl = pUrlItem->GetValue(); + setURL( sUrl ); + + checkTestConnection(); + m_xConnectionURL->save_value(); + } + + OGenericAdministrationPage::implInitControls(_rSet, _bSaveValue); + } + + void OConnectionHelper::implUpdateURLDependentStates() const + { + OSL_PRECOND( m_pAdminDialog && m_pCollection, "OConnectionHelper::implUpdateURLDependentStates: no admin dialog!" ); + if ( !m_pAdminDialog || !m_pCollection ) + return; + + if ( m_pCollection->isFileSystemBased(m_eType) ) + m_pAdminDialog->enableConfirmSettings( !getURLNoPrefix().isEmpty() ); + } + + IMPL_LINK_NOARG(OConnectionHelper, OnBrowseConnections, weld::Button&, void) + { + OSL_ENSURE(m_pAdminDialog,"No Admin dialog set! ->GPF"); + const ::dbaccess::DATASOURCE_TYPE eType = m_pCollection->determineType(m_eType); + switch ( eType ) + { + case ::dbaccess::DST_DBASE: + case ::dbaccess::DST_FLAT: + { + try + { + Reference< XFolderPicker2 > xFolderPicker = FolderPicker::create(m_xORB); + + bool bDoBrowse = false; + OUString sOldPath = getURLNoPrefix(); + do + { + if (!sOldPath.isEmpty()) + xFolderPicker->setDisplayDirectory(sOldPath); + if (0 == xFolderPicker->execute()) + // cancelled by the user + return; + + sOldPath = xFolderPicker->getDirectory(); + switch (checkPathExistence(sOldPath)) + { + case RET_RETRY: + bDoBrowse = true; + break; + case RET_CANCEL: + return; + default: + break; + } + } + while (bDoBrowse); + + OUString sSelectedDirectory = xFolderPicker->getDirectory(); + INetURLObject aSelectedDirectory( sSelectedDirectory, INetURLObject::EncodeMechanism::WasEncoded, RTL_TEXTENCODING_UTF8 ); + + // for UI purpose, we don't want to have the path encoded + sSelectedDirectory = aSelectedDirectory.GetMainURL( INetURLObject::DecodeMechanism::WithCharset ); + + setURLNoPrefix( sSelectedDirectory ); + SetRoadmapStateValue(true); + callModifiedHdl(); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("dbaccess"); + } + } + break; + case ::dbaccess::DST_CALC: + { + SvtModuleOptions aModule; + ::sfx2::FileDialogHelper aFileDlg( + ui::dialogs::TemplateDescription::FILEOPEN_READONLY_VERSION, + FileDialogFlags::NONE, + aModule.GetFactoryEmptyDocumentURL(SvtModuleOptions::EFactory::CALC) + ,SfxFilterFlags::IMPORT, SfxFilterFlags::NONE, GetFrameWeld()); + askForFileName(aFileDlg); + } + break; + case ::dbaccess::DST_WRITER: + { + SvtModuleOptions aModule; + ::sfx2::FileDialogHelper aFileDlg( + ui::dialogs::TemplateDescription::FILEOPEN_READONLY_VERSION, + FileDialogFlags::NONE, + aModule.GetFactoryEmptyDocumentURL(SvtModuleOptions::EFactory::WRITER), + SfxFilterFlags::IMPORT, SfxFilterFlags::NONE, GetFrameWeld()); + askForFileName(aFileDlg); + } + break; + case ::dbaccess::DST_MSACCESS: + { + const OUString sExt("*.mdb;*.mde"); + OUString sFilterName(DBA_RES (STR_MSACCESS_FILTERNAME)); + ::sfx2::FileDialogHelper aFileDlg( + ui::dialogs::TemplateDescription::FILEOPEN_READONLY_VERSION, + FileDialogFlags::NONE, GetFrameWeld()); + aFileDlg.AddFilter(sFilterName,sExt); + aFileDlg.SetCurrentFilter(sFilterName); + askForFileName(aFileDlg); + } + break; + case ::dbaccess::DST_MSACCESS_2007: + { + const OUString sAccdb("*.accdb;*.accde"); + OUString sFilterName2(DBA_RES (STR_MSACCESS_2007_FILTERNAME)); + ::sfx2::FileDialogHelper aFileDlg( + ui::dialogs::TemplateDescription::FILEOPEN_READONLY_VERSION, + FileDialogFlags::NONE, GetFrameWeld()); + aFileDlg.AddFilter(sFilterName2,sAccdb); + aFileDlg.SetCurrentFilter(sFilterName2); + askForFileName(aFileDlg); + } + break; + case ::dbaccess::DST_MYSQL_ODBC: + case ::dbaccess::DST_ODBC: + { + // collect all ODBC data source names + OUString sCurrDatasource = getURLNoPrefix(); + OUString sDataSource; + if ( getSelectedDataSource(sDataSource,sCurrDatasource) && !sDataSource.isEmpty() ) + { + setURLNoPrefix(sDataSource); + SetRoadmapStateValue(true); + callModifiedHdl(); + } + else + return; + } + break; +#if defined _WIN32 + case ::dbaccess::DST_ADO: + { + OUString sOldDataSource=getURLNoPrefix(); + OUString sNewDataSource; + HWND hWnd = nullptr; + + weld::Window* pDialog = GetFrameWeld(); + css::uno::Reference<css::awt::XSystemDependentWindowPeer> xSysDepWin(pDialog->GetXWindow(), css::uno::UNO_QUERY); + if (xSysDepWin.is()) + { + css::uno::Sequence<sal_Int8> aProcessIdent(16); + rtl_getGlobalProcessId(reinterpret_cast<sal_uInt8*>(aProcessIdent.getArray())); + css::uno::Any aAny = xSysDepWin->getWindowHandle(aProcessIdent, css::lang::SystemDependent::SYSTEM_WIN32); + sal_Int64 tmp(0); + aAny >>= tmp; + hWnd = reinterpret_cast<HWND>(tmp); + } + + sNewDataSource = getAdoDatalink(reinterpret_cast<LONG_PTR>(hWnd),sOldDataSource); + if ( !sNewDataSource.isEmpty() ) + { + setURLNoPrefix(sNewDataSource); + SetRoadmapStateValue(true); + callModifiedHdl(); + } + } + break; +#endif + case ::dbaccess::DST_MOZILLA: + case ::dbaccess::DST_THUNDERBIRD: + { + MozillaProductType profileType = MozillaProductType_Mozilla; + if (eType == ::dbaccess::DST_THUNDERBIRD) + profileType = MozillaProductType_Thunderbird; + + Reference<XComponentContext> xContext = ::comphelper::getProcessComponentContext(); + Reference<XMozillaBootstrap> xMozillaBootstrap = MozillaBootstrap::create(xContext); + + // collect all Mozilla Profiles + css::uno::Sequence< OUString > list; + + xMozillaBootstrap->getProfileList( profileType, list ); + const OUString * pArray = list.getConstArray(); + + sal_Int32 count = list.getLength(); + + std::set<OUString> aProfiles; + for (sal_Int32 index=0; index < count; index++) + aProfiles.insert(pArray[index]); + + // execute the select dialog + ODatasourceSelectDialog aSelector(GetFrameWeld(), aProfiles); + OUString sOldProfile=getURLNoPrefix(); + + if (!sOldProfile.isEmpty()) + aSelector.Select(sOldProfile); + else + aSelector.Select(xMozillaBootstrap->getDefaultProfile(profileType)); + + if (RET_OK == aSelector.run()) + setURLNoPrefix(aSelector.GetSelected()); + break; + } + case ::dbaccess::DST_FIREBIRD: + { + const OUString sExt("*.fdb"); + OUString sFilterName(DBA_RES (STR_FIREBIRD_FILTERNAME)); + ::sfx2::FileDialogHelper aFileDlg( + ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE, + FileDialogFlags::NONE, GetFrameWeld()); + aFileDlg.AddFilter(sFilterName,sExt); + aFileDlg.SetCurrentFilter(sFilterName); + askForFileName(aFileDlg); + break; + } + default: + break; + } + + checkTestConnection(); + } + + IMPL_LINK_NOARG(OConnectionHelper, OnCreateDatabase, weld::Button&, void) + { + OSL_ENSURE(m_pAdminDialog,"No Admin dialog set! ->GPF"); + const ::dbaccess::DATASOURCE_TYPE eType = m_pCollection->determineType(m_eType); + switch ( eType ) + { + case ::dbaccess::DST_FIREBIRD: + { + const OUString sExt("*.fdb"); + OUString sFilterName(DBA_RES (STR_FIREBIRD_FILTERNAME)); + ::sfx2::FileDialogHelper aFileDlg( + ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION, + FileDialogFlags::NONE, GetFrameWeld()); + aFileDlg.AddFilter(sFilterName,sExt); + aFileDlg.SetCurrentFilter(sFilterName); + askForFileName(aFileDlg); + break; + } + default: + break; + } + + checkTestConnection(); + } + + bool OConnectionHelper::checkTestConnection() + { + return true; + } + + void OConnectionHelper::impl_setURL( const OUString& _rURL, bool _bPrefix ) + { + OUString sURL( comphelper::string::stripEnd(_rURL, '*') ); + OSL_ENSURE( m_pCollection, "OConnectionHelper::impl_setURL: have no interpreter for the URLs!" ); + + if ( m_pCollection && !sURL.isEmpty() ) + { + if ( m_pCollection->isFileSystemBased( m_eType ) ) + { + // get the two parts: prefix and file URL + OUString sTypePrefix, sFileURLEncoded; + if ( _bPrefix ) + { + sTypePrefix = m_pCollection->getPrefix( m_eType ); + sFileURLEncoded = m_pCollection->cutPrefix( sURL ); + } + else + { + sFileURLEncoded = sURL; + } + + // substitute any variables + sFileURLEncoded = SvtPathOptions().SubstituteVariable( sFileURLEncoded ); + + // decode the URL + sURL = sTypePrefix; + if ( !sFileURLEncoded.isEmpty() ) + { + OFileNotation aFileNotation(sFileURLEncoded); + // set this decoded URL as text + sURL += aFileNotation.get(OFileNotation::N_SYSTEM); + } + } + } + + if ( _bPrefix ) + m_xConnectionURL->SetText( sURL ); + else + m_xConnectionURL->SetTextNoPrefix( sURL ); + + implUpdateURLDependentStates(); + } + + OUString OConnectionHelper::impl_getURL() const + { + // get the pure text + OUString sURL = m_xConnectionURL->GetTextNoPrefix(); + + OSL_ENSURE( m_pCollection, "OConnectionHelper::impl_getURL: have no interpreter for the URLs!" ); + + if ( m_pCollection && !sURL.isEmpty() ) + { + if ( m_pCollection->isFileSystemBased( m_eType ) ) + { + // get the two parts: prefix and file URL + OUString sFileURLDecoded = sURL; + + sURL = OUString(); + if ( !sFileURLDecoded.isEmpty() ) + { + OFileNotation aFileNotation( sFileURLDecoded, OFileNotation::N_SYSTEM ); + sURL += aFileNotation.get( OFileNotation::N_URL ); + } + + // encode the URL + INetURLObject aFileURL( sFileURLDecoded, INetURLObject::EncodeMechanism::All, RTL_TEXTENCODING_UTF8 ); + sFileURLDecoded = aFileURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ); + } + } + return sURL; + } + + void OConnectionHelper::setURL( const OUString& _rURL ) + { + impl_setURL( _rURL, true ); + } + + OUString OConnectionHelper::getURLNoPrefix( ) const + { + return impl_getURL(); + } + + void OConnectionHelper::setURLNoPrefix( const OUString& _rURL ) + { + impl_setURL( _rURL, false ); + } + + sal_Int32 OConnectionHelper::checkPathExistence(const OUString& _rURL) + { + IS_PATH_EXIST e_exists = pathExists(_rURL, false); + if (!m_pCollection->supportsDBCreation(m_eType) && + (( e_exists == PATH_NOT_EXIST) || ( e_exists == PATH_NOT_KNOWN))) + { + OUString sQuery(DBA_RES(STR_ASK_FOR_DIRECTORY_CREATION)); + OFileNotation aTransformer(_rURL); + sQuery = sQuery.replaceFirst("$path$", aTransformer.get(OFileNotation::N_SYSTEM)); + + m_bUserGrabFocus = false; + std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(GetFrameWeld(), + VclMessageType::Question, VclButtonsType::YesNo, + sQuery)); + xQueryBox->set_default_response(RET_YES); + sal_Int32 nQueryResult = xQueryBox->run(); + m_bUserGrabFocus = true; + + switch (nQueryResult) + { + case RET_YES: + { + bool bTryCreate = false; + do + { + if ( !createDirectoryDeep(_rURL) ) + { // could not create the directory + sQuery = DBA_RES(STR_COULD_NOT_CREATE_DIRECTORY); + sQuery = sQuery.replaceFirst("$name$", aTransformer.get(OFileNotation::N_SYSTEM)); + + m_bUserGrabFocus = false; + + std::unique_ptr<weld::MessageDialog> xWhatToDo(Application::CreateMessageDialog(GetFrameWeld(), + VclMessageType::Question, VclButtonsType::NONE, + sQuery)); + xWhatToDo->add_button(GetStandardText(StandardButtonType::Retry), RET_RETRY); + xWhatToDo->add_button(GetStandardText(StandardButtonType::Cancel), RET_CANCEL); + xWhatToDo->set_default_response(RET_RETRY); + nQueryResult = xWhatToDo->run(); + m_bUserGrabFocus = true; + + if (RET_RETRY == nQueryResult) + bTryCreate = true; + else + { + SetRoadmapStateValue(false); + callModifiedHdl(); + return RET_RETRY; + } + } + } + while (bTryCreate); + } + break; + + case RET_NO: + callModifiedHdl(); + return RET_OK; + + default: + // cancelled + SetRoadmapStateValue(false); + callModifiedHdl(); + return RET_CANCEL; + } + } +/* else + { + // TODO: error msg + return RET_CANCEL; + } */ + SetRoadmapStateValue(true); + callModifiedHdl(); + return RET_OK; + } + + IS_PATH_EXIST OConnectionHelper::pathExists(const OUString& _rURL, bool bIsFile) const + { + ::ucbhelper::Content aCheckExistence; + IS_PATH_EXIST eExists = PATH_NOT_EXIST; + Reference< css::task::XInteractionHandler > xInteractionHandler = + task::InteractionHandler::createWithParent(m_xORB, nullptr); + OFilePickerInteractionHandler* pHandler = new OFilePickerInteractionHandler(xInteractionHandler); + xInteractionHandler = pHandler; + + Reference< XCommandEnvironment > xCmdEnv = new ::ucbhelper::CommandEnvironment( xInteractionHandler, Reference< XProgressHandler >() ); + try + { + aCheckExistence = ::ucbhelper::Content(_rURL, xCmdEnv, comphelper::getProcessComponentContext()); + const bool bExists = bIsFile? aCheckExistence.isDocument(): aCheckExistence.isFolder(); + eExists = bExists? PATH_EXIST: PATH_NOT_EXIST; + } + catch (const Exception&) + { + eExists = pHandler->isDoesNotExist() ? PATH_NOT_EXIST : (bIsFile ? PATH_NOT_EXIST : PATH_NOT_KNOWN); + } + return eExists; + } + + IMPL_LINK_NOARG(OConnectionHelper, GetFocusHdl, weld::Widget&, void) + { + if (!m_pCollection->isFileSystemBased(m_eType)) + return; + if (!m_bUserGrabFocus) + return; + // URL edit field got the focus + m_xConnectionURL->SaveValueNoPrefix(); + } + + IMPL_LINK_NOARG(OConnectionHelper, LoseFocusHdl, weld::Widget&, void) + { + if (!m_pCollection->isFileSystemBased(m_eType)) + return; + if (!m_bUserGrabFocus) + return; + // URL edit field lost the focus + commitURL(); + } + + bool OConnectionHelper::createDirectoryDeep(const OUString& _rPathURL) + { + // get a URL object analyzing the URL for us ... + INetURLObject aParser; + aParser.SetURL(_rPathURL); + + INetProtocol eProtocol = aParser.GetProtocol(); + + std::vector< OUString > aToBeCreated; // the to-be-created levels + + // search a level which exists + IS_PATH_EXIST eParentExists = PATH_NOT_EXIST; + while ( eParentExists == PATH_NOT_EXIST && aParser.getSegmentCount()) + { + aToBeCreated.push_back(aParser.getName()); // remember the local name for creation + aParser.removeSegment(); // cut the local name + eParentExists = pathExists(aParser.GetMainURL(INetURLObject::DecodeMechanism::NONE), false); + } + + if (!aParser.getSegmentCount()) + return false; + + // create all the missing levels + try + { + // the parent content + Reference< XCommandEnvironment > xEmptyEnv; + ::ucbhelper::Content aParent(aParser.GetMainURL(INetURLObject::DecodeMechanism::NONE), xEmptyEnv, comphelper::getProcessComponentContext()); + + OUString sContentType; + if ( INetProtocol::File == eProtocol ) + { + sContentType = "application/vnd.sun.staroffice.fsys-folder"; + // the file UCP currently does not support the ContentType property + } + else + { + Any aContentType = aParent.getPropertyValue("ContentType"); + aContentType >>= sContentType; + } + + // the properties which need to be set on the new content + Sequence< OUString > aNewDirectoryProperties { "Title" }; + + // the values to be set + Sequence< Any > aNewDirectoryAttributes(1); + + // loop + for ( std::vector< OUString >::const_reverse_iterator aLocalName = aToBeCreated.rbegin(); + aLocalName != aToBeCreated.rend(); + ++aLocalName + ) + { + aNewDirectoryAttributes[0] <<= *aLocalName; + if (!aParent.insertNewContent(sContentType, aNewDirectoryProperties, aNewDirectoryAttributes, aParent)) + return false; + } + } + catch ( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("dbaccess"); + return false; + } + + return true; + } + + void OConnectionHelper::fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) + { + _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFT_Connection.get())); + _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Button>(m_xPB_Connection.get())); + _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Button>(m_xPB_CreateDB.get())); + } + + void OConnectionHelper::fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) + { + _rControlList.emplace_back( new OSaveValueWidgetWrapper<OConnectionURLEdit>( m_xConnectionURL.get() ) ); + } + + bool OConnectionHelper::commitURL() + { + OUString sOldPath = m_xConnectionURL->GetSavedValueNoPrefix(); + OUString sURL = m_xConnectionURL->GetTextNoPrefix(); + + if ( m_pCollection->isFileSystemBased(m_eType) ) + { + if ( ( sURL != sOldPath ) && !sURL.isEmpty() ) + { // the text changed since entering the control + + // the path may be in system notation... + OFileNotation aTransformer(sURL); + sURL = aTransformer.get(OFileNotation::N_URL); + + const ::dbaccess::DATASOURCE_TYPE eType = m_pCollection->determineType(m_eType); + + if ( ( ::dbaccess::DST_CALC == eType) || ( ::dbaccess::DST_WRITER == eType) || ( ::dbaccess::DST_MSACCESS == eType) || ( ::dbaccess::DST_MSACCESS_2007 == eType) ) + { + if( pathExists(sURL, true) == PATH_NOT_EXIST ) + { + OUString sFile = DBA_RES( STR_FILE_DOES_NOT_EXIST ); + sFile = sFile.replaceFirst("$file$", aTransformer.get(OFileNotation::N_SYSTEM)); + OSQLWarningBox aWarning(GetFrameWeld(), sFile); + aWarning.run(); + setURLNoPrefix(sOldPath); + SetRoadmapStateValue(false); + callModifiedHdl(); + return false; + } + } + else + { + switch (checkPathExistence(sURL)) + { + case RET_RETRY: + m_bUserGrabFocus = false; + m_xConnectionURL->grab_focus(); + m_bUserGrabFocus = true; + return false; + + case RET_CANCEL: + setURLNoPrefix(sOldPath); + return false; + } + } + } + } + + setURLNoPrefix(sURL); + m_xConnectionURL->SaveValueNoPrefix(); + return true; + } + + void OConnectionHelper::askForFileName(::sfx2::FileDialogHelper& _aFileOpen) + { + OUString sOldPath = getURLNoPrefix(); + if ( !sOldPath.isEmpty() ) + _aFileOpen.SetDisplayDirectory(sOldPath); + else + _aFileOpen.SetDisplayDirectory( SvtPathOptions().GetWorkPath() ); + if (ERRCODE_NONE == _aFileOpen.Execute()) + { + setURLNoPrefix(_aFileOpen.GetPath()); + SetRoadmapStateValue(checkTestConnection()); + callModifiedHdl(); + } + } + +} // namespace dbaui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/ConnectionHelper.hxx b/dbaccess/source/ui/dlg/ConnectionHelper.hxx new file mode 100644 index 000000000..ed58eac07 --- /dev/null +++ b/dbaccess/source/ui/dlg/ConnectionHelper.hxx @@ -0,0 +1,106 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_DBACCESS_SOURCE_UI_DLG_CONNECTIONHELPER_HXX +#define INCLUDED_DBACCESS_SOURCE_UI_DLG_CONNECTIONHELPER_HXX + +#include "adminpages.hxx" +#include <curledit.hxx> +#include <sfx2/filedlghelper.hxx> + +namespace dbaui +{ + + enum IS_PATH_EXIST + { + PATH_NOT_EXIST = 0, + PATH_EXIST, + PATH_NOT_KNOWN + }; + + class OConnectionHelper : public OGenericAdministrationPage + { + bool m_bUserGrabFocus; + + public: + OConnectionHelper(weld::Container* pPage, weld::DialogController* pController, const OUString& _rUIXMLDescription, const OString& _rId, const SfxItemSet& _rCoreAttrs); + virtual ~OConnectionHelper() override; + + OUString m_eType; // the type can't be changed in this class, so we hold it as member. + // setting/retrieving the current connection URL + // necessary because for some types, the URL must be decoded for display purposes + ::dbaccess::ODsnTypeCollection* m_pCollection; /// the DSN type collection instance + + std::unique_ptr<weld::Label> m_xFT_Connection; + std::unique_ptr<weld::Button> m_xPB_Connection; + std::unique_ptr<weld::Button> m_xPB_CreateDB; + std::unique_ptr<OConnectionURLEdit> m_xConnectionURL; + + public: + + // <method>OGenericAdministrationPage::fillControls</method> + virtual void fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override; + // <method>OGenericAdministrationPage::fillWindows</method> + virtual void fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override; + virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override; + + // setting/retrieving the current connection URL + // necessary because for some types, the URL must be decoded for display purposes + //String getURL( OConnectionURLEdit* _m_pConnection ) const; + //void setURL( const OUString& _rURL, OConnectionURLEdit* _m_pConnection ); + + OUString getURLNoPrefix( ) const; + void setURLNoPrefix( const OUString& _rURL ); + + /** checks if the path is existence + @param _rURL + The URL to check. + */ + sal_Int32 checkPathExistence(const OUString& _rURL); + + IS_PATH_EXIST pathExists(const OUString& _rURL, bool bIsFile) const; + bool createDirectoryDeep(const OUString& _rPathNormalized); + bool commitURL(); + + /** opens the FileOpen dialog and asks for a FileName + @param _aFileOpen + Executes the file open dialog, which must be filled from caller. + */ + void askForFileName(::sfx2::FileDialogHelper& _aFileOpen); + + protected: + void setURL( const OUString& _rURL ); + virtual bool checkTestConnection(); + + private: + DECL_LINK(OnBrowseConnections, weld::Button&, void); + DECL_LINK(OnCreateDatabase, weld::Button&, void); + DECL_LINK(GetFocusHdl, weld::Widget&, void); + DECL_LINK(LoseFocusHdl, weld::Widget&, void); + OUString impl_getURL() const; + void impl_setURL( const OUString& _rURL, bool _bPrefix ); + void implUpdateURLDependentStates() const; + }; + + +} // namespace dbaui + +#endif // INCLUDED_DBACCESS_SOURCE_UI_DLG_CONNECTIONHELPER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/ConnectionPage.cxx b/dbaccess/source/ui/dlg/ConnectionPage.cxx new file mode 100644 index 000000000..5082abf9e --- /dev/null +++ b/dbaccess/source/ui/dlg/ConnectionPage.cxx @@ -0,0 +1,283 @@ +/* -*- 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 <config_java.h> +#include "ConnectionPage.hxx" +#include <core_resource.hxx> +#include <IItemSetHelper.hxx> +#include <strings.hrc> +#include <dsmeta.hxx> +#if HAVE_FEATURE_JAVA +#include <jvmaccess/virtualmachine.hxx> +#endif +#include <svl/itemset.hxx> +#include <svl/stritem.hxx> +#include <svl/eitem.hxx> +#include <dsitems.hxx> +#include <helpids.h> +#include <sqlmessage.hxx> +#include <svl/filenotation.hxx> +#include <com/sun/star/ucb/XProgressHandler.hpp> +#include <connectivity/CommonTools.hxx> + +namespace dbaui +{ + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::ucb; + using namespace ::com::sun::star::ui::dialogs; + using namespace ::com::sun::star::sdbc; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::container; + using namespace ::dbtools; + using namespace ::svt; + + std::unique_ptr<SfxTabPage> OConnectionTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet) + { + return std::make_unique<OConnectionTabPage>(pPage, pController, *_rAttrSet); + } + + // OConnectionTabPage + OConnectionTabPage::OConnectionTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rCoreAttrs) + : OConnectionHelper(pPage, pController, "dbaccess/ui/connectionpage.ui", "ConnectionPage", _rCoreAttrs) + , m_xFL2(m_xBuilder->weld_label("userlabel")) + , m_xUserNameLabel(m_xBuilder->weld_label("userNameLabel")) + , m_xUserName(m_xBuilder->weld_entry("userNameEntry")) + , m_xPasswordRequired(m_xBuilder->weld_check_button("passCheckbutton")) + , m_xFL3(m_xBuilder->weld_label("JDBCLabel")) + , m_xJavaDriverLabel(m_xBuilder->weld_label("javaDriverLabel")) + , m_xJavaDriver(m_xBuilder->weld_entry("driverEntry")) + , m_xTestJavaDriver(m_xBuilder->weld_button("driverButton")) + , m_xTestConnection(m_xBuilder->weld_button("connectionButton")) + { + m_xConnectionURL->connect_changed(LINK(this, OConnectionTabPage, OnEditModified)); + m_xJavaDriver->connect_changed(LINK(this, OConnectionTabPage, OnEditModified)); + m_xUserName->connect_changed(LINK(this, OGenericAdministrationPage, OnControlEntryModifyHdl)); + m_xPasswordRequired->connect_toggled(LINK(this, OGenericAdministrationPage, OnControlModifiedButtonClick)); + + m_xTestConnection->connect_clicked(LINK(this,OGenericAdministrationPage,OnTestConnectionButtonClickHdl)); + m_xTestJavaDriver->connect_clicked(LINK(this,OConnectionTabPage,OnTestJavaClickHdl)); + } + + OConnectionTabPage::~OConnectionTabPage() + { + } + + void OConnectionTabPage::implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) + { + // check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa) + bool bValid, bReadonly; + getFlags(_rSet, bValid, bReadonly); + + m_eType = m_pAdminDialog->getDatasourceType(_rSet); + OConnectionHelper::implInitControls( _rSet, _bSaveValue); + + ::dbaccess::DATASOURCE_TYPE eType = m_pCollection->determineType(m_eType); + switch( eType ) + { + case ::dbaccess::DST_DBASE: + m_xFT_Connection->set_label(DBA_RES(STR_DBASE_PATH_OR_FILE)); + m_xConnectionURL->set_help_id(HID_DSADMIN_DBASE_PATH); + break; + case ::dbaccess::DST_FLAT: + m_xFT_Connection->set_label(DBA_RES(STR_FLAT_PATH_OR_FILE)); + m_xConnectionURL->set_help_id(HID_DSADMIN_FLAT_PATH); + break; + case ::dbaccess::DST_CALC: + m_xFT_Connection->set_label(DBA_RES(STR_CALC_PATH_OR_FILE)); + m_xConnectionURL->set_help_id(HID_DSADMIN_CALC_PATH); + break; + case ::dbaccess::DST_WRITER: + m_xFT_Connection->set_label(DBA_RES(STR_WRITER_PATH_OR_FILE)); + m_xConnectionURL->set_help_id(HID_DSADMIN_WRITER_PATH); + break; + case ::dbaccess::DST_ADO: + m_xFT_Connection->set_label(DBA_RES(STR_COMMONURL)); + break; + case ::dbaccess::DST_MSACCESS: + case ::dbaccess::DST_MSACCESS_2007: + m_xFT_Connection->set_label(DBA_RES(STR_MSACCESS_MDB_FILE)); + m_xConnectionURL->set_help_id(HID_DSADMIN_MSACCESS_MDB_FILE); + break; + case ::dbaccess::DST_MYSQL_NATIVE: + case ::dbaccess::DST_MYSQL_JDBC: + m_xFT_Connection->set_label(DBA_RES(STR_MYSQL_DATABASE_NAME)); + m_xConnectionURL->set_help_id( HID_DSADMIN_MYSQL_DATABASE ); + break; + case ::dbaccess::DST_ORACLE_JDBC: + m_xFT_Connection->set_label(DBA_RES(STR_ORACLE_DATABASE_NAME)); + m_xConnectionURL->set_help_id(HID_DSADMIN_ORACLE_DATABASE); + break; + case ::dbaccess::DST_MYSQL_ODBC: + case ::dbaccess::DST_ODBC: + m_xFT_Connection->set_label(DBA_RES(STR_NAME_OF_ODBC_DATASOURCE)); + m_xConnectionURL->set_help_id( eType == ::dbaccess::DST_MYSQL_ODBC ? HID_DSADMIN_MYSQL_ODBC_DATASOURCE : HID_DSADMIN_ODBC_DATASOURCE); + break; + case ::dbaccess::DST_LDAP: + m_xFT_Connection->set_label(DBA_RES(STR_HOSTNAME)); + m_xConnectionURL->set_help_id( HID_DSADMIN_LDAP_HOSTNAME ); + break; + case ::dbaccess::DST_MOZILLA: + m_xFT_Connection->set_label(DBA_RES(STR_MOZILLA_PROFILE_NAME)); + m_xConnectionURL->set_help_id( HID_DSADMIN_MOZILLA_PROFILE_NAME ); + break; + case ::dbaccess::DST_THUNDERBIRD: + m_xFT_Connection->set_label(DBA_RES(STR_THUNDERBIRD_PROFILE_NAME)); + m_xConnectionURL->set_help_id( HID_DSADMIN_THUNDERBIRD_PROFILE_NAME ); + break; + case ::dbaccess::DST_OUTLOOK: + case ::dbaccess::DST_OUTLOOKEXP: + case ::dbaccess::DST_EVOLUTION: + case ::dbaccess::DST_EVOLUTION_GROUPWISE: + case ::dbaccess::DST_EVOLUTION_LDAP: + case ::dbaccess::DST_KAB: + case ::dbaccess::DST_MACAB: + m_xFT_Connection->set_label(DBA_RES(STR_NO_ADDITIONAL_SETTINGS)); + { + OUString sText = m_xFT_Connection->get_label(); + sText = sText.replaceAll("%test",m_xTestConnection->get_label()); + sText = sText.replaceAll("~",""); + m_xFT_Connection->set_label(sText); + } + m_xConnectionURL->hide(); + break; + case ::dbaccess::DST_JDBC: + default: + m_xFT_Connection->set_label(DBA_RES(STR_COMMONURL)); + break; + } + + AuthenticationMode eAuthMode( DataSourceMetaData::getAuthentication( m_eType ) ); + bool bShowUserAuthenfication = ( eAuthMode != AuthNone ); + bool bShowUser = ( eAuthMode == AuthUserPwd ); + + m_xPB_Connection->set_help_id(HID_DSADMIN_BROWSECONN); + m_xFL2->set_visible( bShowUserAuthenfication ); + m_xUserNameLabel->set_visible( bShowUser && bShowUserAuthenfication ); + m_xUserName->set_visible( bShowUser && bShowUserAuthenfication ); + m_xPasswordRequired->set_visible( bShowUserAuthenfication ); + + // collect the items + const SfxStringItem* pUidItem = _rSet.GetItem<SfxStringItem>(DSID_USER); + + const SfxStringItem* pJdbcDrvItem = _rSet.GetItem<SfxStringItem>(DSID_JDBCDRIVERCLASS); + const SfxStringItem* pUrlItem = _rSet.GetItem<SfxStringItem>(DSID_CONNECTURL); + const SfxBoolItem* pAllowEmptyPwd = _rSet.GetItem<SfxBoolItem>(DSID_PASSWORDREQUIRED); + + // forward the values to the controls + if ( !bValid ) + return; + + m_xUserName->set_text(pUidItem->GetValue()); + m_xPasswordRequired->set_active(pAllowEmptyPwd->GetValue()); + + const OUString& sUrl = pUrlItem->GetValue(); + setURL( sUrl ); + + const bool bEnableJDBC = m_pCollection->determineType(m_eType) == ::dbaccess::DST_JDBC; + if ( !pJdbcDrvItem->GetValue().getLength() ) + { + OUString sDefaultJdbcDriverName = m_pCollection->getJavaDriverClass(m_eType); + if ( !sDefaultJdbcDriverName.isEmpty() ) + m_xJavaDriver->set_text(sDefaultJdbcDriverName); + } + else + m_xJavaDriver->set_text(pJdbcDrvItem->GetValue()); + + m_xJavaDriverLabel->set_visible(bEnableJDBC); + m_xJavaDriver->set_visible(bEnableJDBC); + m_xTestJavaDriver->set_visible(bEnableJDBC); + m_xTestJavaDriver->set_sensitive( !m_xJavaDriver->get_text().trim().isEmpty() ); + m_xFL3->set_visible(bEnableJDBC); + + checkTestConnection(); + + m_xUserName->save_value(); + m_xConnectionURL->save_value(); + m_xJavaDriver->save_value(); + m_xPasswordRequired->save_state(); + } + + bool OConnectionTabPage::FillItemSet(SfxItemSet* _rSet) + { + bool bChangedSomething = false; + + if (m_xUserName->get_value_changed_from_saved()) + { + _rSet->Put(SfxStringItem(DSID_USER, m_xUserName->get_text())); + _rSet->Put(SfxStringItem(DSID_PASSWORD, OUString())); + bChangedSomething = true; + } + + fillBool(*_rSet,m_xPasswordRequired.get(),DSID_PASSWORDREQUIRED,false, bChangedSomething); + + if ( m_pCollection->determineType(m_eType) == ::dbaccess::DST_JDBC ) + { + fillString(*_rSet,m_xJavaDriver.get(), DSID_JDBCDRIVERCLASS, bChangedSomething); + } + + fillString(*_rSet,m_xConnectionURL.get(), DSID_CONNECTURL, bChangedSomething); + + return bChangedSomething; + } + IMPL_LINK_NOARG(OConnectionTabPage, OnTestJavaClickHdl, weld::Button&, void) + { + OSL_ENSURE(m_pAdminDialog,"No Admin dialog set! ->GPF"); + bool bSuccess = false; +#if HAVE_FEATURE_JAVA + try + { + if ( !m_xJavaDriver->get_text().trim().isEmpty() ) + { + ::rtl::Reference< jvmaccess::VirtualMachine > xJVM = ::connectivity::getJavaVM( m_pAdminDialog->getORB() ); + m_xJavaDriver->set_text(m_xJavaDriver->get_text().trim()); // fdo#68341 + bSuccess = ::connectivity::existsJavaClassByName(xJVM,m_xJavaDriver->get_text().trim()); + } + } + catch(Exception&) + { + } +#endif + + const char* pMessage = bSuccess ? STR_JDBCDRIVER_SUCCESS : STR_JDBCDRIVER_NO_SUCCESS; + const MessageType mt = bSuccess ? MessageType::Info : MessageType::Error; + OSQLMessageBox aMsg(GetFrameWeld(), DBA_RES(pMessage), OUString(), MessBoxStyle::Ok | MessBoxStyle::DefaultOk, mt); + aMsg.run(); + } + bool OConnectionTabPage::checkTestConnection() + { + OSL_ENSURE(m_pAdminDialog,"No Admin dialog set! ->GPF"); + bool bEnableTestConnection = !m_xConnectionURL->get_visible() || !m_xConnectionURL->GetTextNoPrefix().isEmpty(); + if ( m_pCollection->determineType(m_eType) == ::dbaccess::DST_JDBC ) + bEnableTestConnection = bEnableTestConnection && (!m_xJavaDriver->get_text().trim().isEmpty()); + m_xTestConnection->set_sensitive(bEnableTestConnection); + return true; + } + IMPL_LINK(OConnectionTabPage, OnEditModified, weld::Entry&, rEdit, void) + { + if (&rEdit == m_xJavaDriver.get()) + m_xTestJavaDriver->set_sensitive( !m_xJavaDriver->get_text().trim().isEmpty() ); + + checkTestConnection(); + // tell the listener we were modified + callModifiedHdl(); + } +} // namespace dbaui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/ConnectionPage.hxx b/dbaccess/source/ui/dlg/ConnectionPage.hxx new file mode 100644 index 000000000..3b514f866 --- /dev/null +++ b/dbaccess/source/ui/dlg/ConnectionPage.hxx @@ -0,0 +1,75 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_DBACCESS_SOURCE_UI_DLG_CONNECTIONPAGE_HXX +#define INCLUDED_DBACCESS_SOURCE_UI_DLG_CONNECTIONPAGE_HXX + +#include "ConnectionHelper.hxx" + +namespace dbaui +{ + + // OConnectionTabPage + + /** implements the connection page of the data source properties dialog. + */ + class OConnectionTabPage final : public OConnectionHelper + { + private: + // user authentication + std::unique_ptr<weld::Label> m_xFL2; + std::unique_ptr<weld::Label> m_xUserNameLabel; + std::unique_ptr<weld::Entry> m_xUserName; + std::unique_ptr<weld::CheckButton> m_xPasswordRequired; + + // jdbc driver + std::unique_ptr<weld::Label> m_xFL3; + std::unique_ptr<weld::Label> m_xJavaDriverLabel; + std::unique_ptr<weld::Entry> m_xJavaDriver; + std::unique_ptr<weld::Button> m_xTestJavaDriver; + + // connection test + std::unique_ptr<weld::Button> m_xTestConnection; + + // called when the test connection button was clicked + DECL_LINK(OnTestJavaClickHdl, weld::Button&, void); + DECL_LINK(OnEditModified, weld::Entry&, void); + + public: + OConnectionTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rCoreAttrs); + static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet); + virtual ~OConnectionTabPage() override; + virtual bool FillItemSet (SfxItemSet* _rCoreAttrs) override; + + virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override; + + /** changes the connection URL. + <p>The new URL must be of the type which is currently selected, only the parts which do not + affect the type may be changed (compared to the previous URL).</p> + */ + private: + /** enables the test connection button, if allowed + */ + virtual bool checkTestConnection() override; + }; +} // namespace dbaui + +#endif // INCLUDED_DBACCESS_SOURCE_UI_DLG_CONNECTIONPAGE_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/ConnectionPageSetup.cxx b/dbaccess/source/ui/dlg/ConnectionPageSetup.cxx new file mode 100644 index 000000000..bee1b1f11 --- /dev/null +++ b/dbaccess/source/ui/dlg/ConnectionPageSetup.cxx @@ -0,0 +1,153 @@ +/* -*- 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 "ConnectionPageSetup.hxx" +#include <strings.hrc> +#include <core_resource.hxx> +#include <IItemSetHelper.hxx> +#include <svl/itemset.hxx> +#include <dsitems.hxx> +#include <svl/filenotation.hxx> +#include <com/sun/star/ucb/XProgressHandler.hpp> + +namespace dbaui +{ + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::ucb; + using namespace ::com::sun::star::ui::dialogs; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::container; + using namespace ::svt; + + std::unique_ptr<OGenericAdministrationPage> OConnectionTabPageSetup::CreateDbaseTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet) + { + return std::make_unique<OConnectionTabPageSetup>( pPage, pController, "dbaccess/ui/dbwizconnectionpage.ui", "ConnectionPage", _rAttrSet, STR_DBASE_HELPTEXT, STR_DBASE_HEADERTEXT, STR_DBASE_PATH_OR_FILE ); + } + + std::unique_ptr<OGenericAdministrationPage> OConnectionTabPageSetup::CreateMSAccessTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet) + { + return std::make_unique<OConnectionTabPageSetup>( pPage, pController, "dbaccess/ui/dbwizconnectionpage.ui", "ConnectionPage", _rAttrSet, STR_MSACCESS_HELPTEXT, STR_MSACCESS_HEADERTEXT, STR_MSACCESS_MDB_FILE ); + } + + std::unique_ptr<OGenericAdministrationPage> OConnectionTabPageSetup::CreateADOTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet) + { + return std::make_unique<OConnectionTabPageSetup>( pPage, pController, "dbaccess/ui/dbwizconnectionpage.ui", "ConnectionPage", _rAttrSet, STR_ADO_HELPTEXT, STR_ADO_HEADERTEXT, STR_COMMONURL ); + } + + std::unique_ptr<OGenericAdministrationPage> OConnectionTabPageSetup::CreateODBCTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet) + { + return std::make_unique<OConnectionTabPageSetup>( pPage, pController, "dbaccess/ui/dbwizconnectionpage.ui", "ConnectionPage", _rAttrSet, STR_ODBC_HELPTEXT, STR_ODBC_HEADERTEXT, STR_NAME_OF_ODBC_DATASOURCE ); + } + + std::unique_ptr<OGenericAdministrationPage> OConnectionTabPageSetup::CreateUserDefinedTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet) + { + return std::make_unique<OConnectionTabPageSetup>(pPage, pController, "dbaccess/ui/dbwizconnectionpage.ui", "ConnectionPage", _rAttrSet, nullptr, nullptr, STR_COMMONURL); + } + + OConnectionTabPageSetup::OConnectionTabPageSetup(weld::Container* pPage, weld::DialogController* pController, const OUString& _rUIXMLDescription, const OString& _rId, const SfxItemSet& _rCoreAttrs, const char* pHelpTextResId, const char* pHeaderResId, const char* pUrlResId) + : OConnectionHelper(pPage, pController, _rUIXMLDescription, _rId, _rCoreAttrs) + , m_xHelpText(m_xBuilder->weld_label("helptext")) + , m_xHeaderText(m_xBuilder->weld_label("header")) + { + + if (pHelpTextResId != nullptr) + { + OUString sHelpText = DBA_RES(pHelpTextResId); + m_xHelpText->set_label(sHelpText); + } + else + m_xHelpText->hide(); + + if (pHeaderResId != nullptr) + m_xHeaderText->set_label(DBA_RES(pHeaderResId)); + + if (pUrlResId != nullptr) + { + OUString sLabelText = DBA_RES(pUrlResId); + m_xFT_Connection->set_label(sLabelText); + } + else + m_xFT_Connection->hide(); + + m_xConnectionURL->connect_changed(LINK(this, OConnectionTabPageSetup, OnEditModified)); + + SetRoadmapStateValue(false); + } + + OConnectionTabPageSetup::~OConnectionTabPageSetup() + { + } + + void OConnectionTabPageSetup::implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) + { + m_eType = m_pAdminDialog->getDatasourceType(_rSet); + // special handling for oracle, this can only happen + // if the user enters the same url as used for Oracle and we are on the JDBC path + //! TODO + //if ( ::dbaccess::DST_ORACLE_JDBC == m_eType ) + // m_eType = ::dbaccess::DST_JDBC; + if(m_pCollection->determineType(m_eType) == ::dbaccess::DST_POSTGRES){ + SetRoadmapStateValue(true); + } + + OConnectionHelper::implInitControls(_rSet, _bSaveValue); + + //! TODO + //if ( m_eType >= ::dbaccess::DST_USERDEFINE1 ) + //{ + // OUString sDisplayName = m_pCollection->getTypeDisplayName(m_eType); + // FixedText* ppTextControls[] ={&m_aFT_Connection}; + // for (size_t i = 0; i < sizeof(ppTextControls)/sizeof(ppTextControls[0]); ++i) + // { + // ppTextControls[i]->SetText(sDisplayName); + // } + //} + + callModifiedHdl(); + } + + bool OConnectionTabPageSetup::commitPage( ::vcl::WizardTypes::CommitPageReason /*_eReason*/ ) + { + return commitURL(); + } + + bool OConnectionTabPageSetup::FillItemSet(SfxItemSet* _rSet) + { + bool bChangedSomething = false; + fillString(*_rSet,m_xConnectionURL.get(), DSID_CONNECTURL, bChangedSomething); + return bChangedSomething; + } + + bool OConnectionTabPageSetup::checkTestConnection() + { + if ( m_pCollection->determineType(m_eType) == ::dbaccess::DST_POSTGRES ) + return true; + return !m_xConnectionURL->get_visible() || !m_xConnectionURL->GetTextNoPrefix().isEmpty(); + } + + IMPL_LINK_NOARG(OConnectionTabPageSetup, OnEditModified, weld::Entry&, void) + { + SetRoadmapStateValue(checkTestConnection()); + callModifiedHdl(); + } + +} // namespace dbaui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/ConnectionPageSetup.hxx b/dbaccess/source/ui/dlg/ConnectionPageSetup.hxx new file mode 100644 index 000000000..f7cfe37ad --- /dev/null +++ b/dbaccess/source/ui/dlg/ConnectionPageSetup.hxx @@ -0,0 +1,65 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_DBACCESS_SOURCE_UI_DLG_CONNECTIONPAGESETUP_HXX +#define INCLUDED_DBACCESS_SOURCE_UI_DLG_CONNECTIONPAGESETUP_HXX +#include "ConnectionHelper.hxx" + +#include "adminpages.hxx" + +namespace dbaui +{ + + // OConnectionTabPageSetup + + /** implements the connection page of the data source properties dialog. + */ + class OConnectionTabPageSetup : public OConnectionHelper + { + std::unique_ptr<weld::Label> m_xHelpText; + std::unique_ptr<weld::Label> m_xHeaderText; + + // called when the test connection button was clicked + DECL_LINK(OnEditModified, weld::Entry&, void); + + public: + OConnectionTabPageSetup(weld::Container* pPage, weld::DialogController* pController, const OUString& _rUIXMLDescription, const OString& _rId, const SfxItemSet& _rCoreAttrs, const char* pHelpTextResId, const char* pHeaderResId, const char* pUrlResId); + virtual ~OConnectionTabPageSetup() override; + + static std::unique_ptr<OGenericAdministrationPage> CreateDbaseTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet); + static std::unique_ptr<OGenericAdministrationPage> CreateMSAccessTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet); + static std::unique_ptr<OGenericAdministrationPage> CreateADOTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet); + static std::unique_ptr<OGenericAdministrationPage> CreateODBCTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet); + static std::unique_ptr<OGenericAdministrationPage> CreateUserDefinedTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet); + + virtual bool FillItemSet (SfxItemSet* _rCoreAttrs) override; + + virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override; + virtual bool commitPage( ::vcl::WizardTypes::CommitPageReason _eReason ) override; + + protected: + virtual bool checkTestConnection() override; + }; + + +} // namespace dbaui + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/DBSetupConnectionPages.cxx b/dbaccess/source/ui/dlg/DBSetupConnectionPages.cxx new file mode 100644 index 000000000..9c8d0fdd8 --- /dev/null +++ b/dbaccess/source/ui/dlg/DBSetupConnectionPages.cxx @@ -0,0 +1,786 @@ +/* -*- 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 <config_java.h> + +#include "DBSetupConnectionPages.hxx" +#include <core_resource.hxx> +#include <sqlmessage.hxx> +#include <strings.hrc> +#include <svl/itemset.hxx> +#include <svl/stritem.hxx> +#include <svl/eitem.hxx> +#include <svl/intitem.hxx> +#include <dsitems.hxx> +#include "dsnItem.hxx" + +#if HAVE_FEATURE_JAVA + #include <jvmaccess/virtualmachine.hxx> +#endif + +#include <connectivity/CommonTools.hxx> +#include <dbwizsetup.hxx> +#include "TextConnectionHelper.hxx" +#include <osl/diagnose.h> + +namespace dbaui +{ +using namespace ::com::sun::star; + + std::unique_ptr<OGenericAdministrationPage> OTextConnectionPageSetup::CreateTextTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet) + { + return std::make_unique<OTextConnectionPageSetup>(pPage, pController, _rAttrSet); + } + + // OTextConnectionPageSetup + OTextConnectionPageSetup::OTextConnectionPageSetup(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs) + : OConnectionTabPageSetup(pPage, pController, "dbaccess/ui/dbwiztextpage.ui", "DBWizTextPage", + rCoreAttrs, STR_TEXT_HELPTEXT, STR_TEXT_HEADERTEXT, STR_TEXT_PATH_OR_FILE) + , m_xSubContainer(m_xBuilder->weld_widget("TextPageContainer")) + , m_xTextConnectionHelper(new OTextConnectionHelper(m_xSubContainer.get(), TC_EXTENSION | TC_SEPARATORS)) + { + m_xTextConnectionHelper->SetClickHandler(LINK( this, OTextConnectionPageSetup, ImplGetExtensionHdl ) ); + } + + OTextConnectionPageSetup::~OTextConnectionPageSetup() + { + m_xTextConnectionHelper.reset(); + } + + IMPL_LINK_NOARG(OTextConnectionPageSetup, ImplGetExtensionHdl, OTextConnectionHelper*, void) + { + SetRoadmapStateValue(!m_xTextConnectionHelper->GetExtension().isEmpty() && OConnectionTabPageSetup::checkTestConnection()); + callModifiedHdl(); + } + + bool OTextConnectionPageSetup::checkTestConnection() + { + bool bDoEnable = OConnectionTabPageSetup::checkTestConnection(); + bDoEnable = !m_xTextConnectionHelper->GetExtension().isEmpty() && bDoEnable; + return bDoEnable; + } + + void OTextConnectionPageSetup::fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) + { + OConnectionTabPageSetup::fillControls(_rControlList); + m_xTextConnectionHelper->fillControls(_rControlList); + } + + void OTextConnectionPageSetup::fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) + { + OConnectionTabPageSetup::fillWindows(_rControlList); + m_xTextConnectionHelper->fillWindows(_rControlList); + } + + void OTextConnectionPageSetup::implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) + { + // first check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa) + bool bValid, bReadonly; + getFlags(_rSet, bValid, bReadonly); + OConnectionTabPageSetup::implInitControls( _rSet, _bSaveValue); + m_xTextConnectionHelper->implInitControls(_rSet, bValid); + } + + bool OTextConnectionPageSetup::FillItemSet( SfxItemSet* _rSet ) + { + bool bChangedSomething = OConnectionTabPageSetup::FillItemSet(_rSet); + bChangedSomething = m_xTextConnectionHelper->FillItemSet(*_rSet, bChangedSomething); + return bChangedSomething; + } + + bool OTextConnectionPageSetup::prepareLeave() + { + return m_xTextConnectionHelper->prepareLeave(); + } + + std::unique_ptr<OGenericAdministrationPage> OLDAPConnectionPageSetup::CreateLDAPTabPage( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet ) + { + return std::make_unique<OLDAPConnectionPageSetup>(pPage, pController, _rAttrSet); + } + + // OLDAPPageSetup + OLDAPConnectionPageSetup::OLDAPConnectionPageSetup( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rCoreAttrs ) + : OGenericAdministrationPage(pPage, pController, "dbaccess/ui/ldapconnectionpage.ui", "LDAPConnectionPage", _rCoreAttrs) + , m_xFTHelpText(m_xBuilder->weld_label("helpLabel")) + , m_xFTHostServer(m_xBuilder->weld_label("hostNameLabel")) + , m_xETHostServer(m_xBuilder->weld_entry("hostNameEntry")) + , m_xFTBaseDN(m_xBuilder->weld_label("baseDNLabel")) + , m_xETBaseDN(m_xBuilder->weld_entry("baseDNEntry")) + , m_xFTPortNumber(m_xBuilder->weld_label("portNumLabel")) + , m_xNFPortNumber(m_xBuilder->weld_spin_button("portNumEntry")) + , m_xFTDefaultPortNumber(m_xBuilder->weld_label("portNumDefLabel")) + , m_xCBUseSSL(m_xBuilder->weld_check_button("useSSLCheckbutton")) + { + m_xETHostServer->connect_changed(LINK(this, OGenericAdministrationPage, OnControlEntryModifyHdl)); + m_xETBaseDN->connect_changed(LINK(this, OGenericAdministrationPage, OnControlEntryModifyHdl)); + m_xNFPortNumber->connect_value_changed(LINK(this, OGenericAdministrationPage, OnControlSpinButtonModifyHdl)); + m_xCBUseSSL->connect_toggled( LINK(this, OGenericAdministrationPage, OnControlModifiedButtonClick) ); + SetRoadmapStateValue(false); + } + + OLDAPConnectionPageSetup::~OLDAPConnectionPageSetup() + { + } + + bool OLDAPConnectionPageSetup::FillItemSet( SfxItemSet* _rSet ) + { + bool bChangedSomething = false; + fillString(*_rSet,m_xETBaseDN.get(),DSID_CONN_LDAP_BASEDN, bChangedSomething); + fillInt32(*_rSet,m_xNFPortNumber.get(),DSID_CONN_LDAP_PORTNUMBER,bChangedSomething); + + if ( m_xETHostServer->get_value_changed_from_saved() ) + { + const DbuTypeCollectionItem* pCollectionItem = dynamic_cast<const DbuTypeCollectionItem*>( _rSet->GetItem(DSID_TYPECOLLECTION) ); + ::dbaccess::ODsnTypeCollection* pCollection = nullptr; + if (pCollectionItem) + pCollection = pCollectionItem->getCollection(); + OSL_ENSURE(pCollection, "OLDAPConnectionPageSetup::FillItemSet : really need a DSN type collection !"); + if (pCollection) + { + OUString sUrl = pCollection->getPrefix( "sdbc:address:ldap:") + m_xETHostServer->get_text(); + _rSet->Put(SfxStringItem(DSID_CONNECTURL, sUrl)); + bChangedSomething = true; + } + } + + fillBool(*_rSet,m_xCBUseSSL.get(),DSID_CONN_LDAP_USESSL,false,bChangedSomething); + return bChangedSomething; + } + void OLDAPConnectionPageSetup::fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) + { + _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::Entry>(m_xETHostServer.get())); + _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::Entry>(m_xETBaseDN.get())); + _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::SpinButton>(m_xNFPortNumber.get())); + _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::ToggleButton>(m_xCBUseSSL.get())); + } + void OLDAPConnectionPageSetup::fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) + { + _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFTHelpText.get())); + _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFTHostServer.get())); + _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFTBaseDN.get())); + _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFTPortNumber.get())); + _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFTDefaultPortNumber.get())); + } + void OLDAPConnectionPageSetup::implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) + { + // check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa) + bool bValid, bReadonly; + getFlags(_rSet, bValid, bReadonly); + + const SfxStringItem* pBaseDN = _rSet.GetItem<SfxStringItem>(DSID_CONN_LDAP_BASEDN); + const SfxInt32Item* pPortNumber = _rSet.GetItem<SfxInt32Item>(DSID_CONN_LDAP_PORTNUMBER); + + if ( bValid ) + { + m_xETBaseDN->set_text(pBaseDN->GetValue()); + m_xNFPortNumber->set_value(pPortNumber->GetValue()); + } + OGenericAdministrationPage::implInitControls(_rSet, _bSaveValue); + callModifiedHdl(); + } + + void OLDAPConnectionPageSetup::callModifiedHdl(weld::Widget*) + { + bool bRoadmapState = ((!m_xETHostServer->get_text().isEmpty() ) && ( !m_xETBaseDN->get_text().isEmpty() ) && (!m_xFTPortNumber->get_label().isEmpty() )); + SetRoadmapStateValue(bRoadmapState); + OGenericAdministrationPage::callModifiedHdl(); + } + + std::unique_ptr<OMySQLIntroPageSetup> OMySQLIntroPageSetup::CreateMySQLIntroTabPage(weld::Container* pPage, ODbTypeWizDialogSetup* pController, const SfxItemSet& rAttrSet) + { + return std::make_unique<OMySQLIntroPageSetup>(pPage, pController, rAttrSet); + } + + OMySQLIntroPageSetup::OMySQLIntroPageSetup(weld::Container* pPage, ODbTypeWizDialogSetup* pController, const SfxItemSet& _rCoreAttrs) + : OGenericAdministrationPage(pPage, pController, "dbaccess/ui/dbwizmysqlintropage.ui", "DBWizMysqlIntroPage", _rCoreAttrs) + , m_xODBCDatabase(m_xBuilder->weld_radio_button("odbc")) + , m_xJDBCDatabase(m_xBuilder->weld_radio_button("jdbc")) + , m_xNATIVEDatabase(m_xBuilder->weld_radio_button("directly")) + { + m_xODBCDatabase->connect_toggled(LINK(this, OMySQLIntroPageSetup, OnSetupModeSelected)); + m_xJDBCDatabase->connect_toggled(LINK(this, OMySQLIntroPageSetup, OnSetupModeSelected)); + m_xNATIVEDatabase->connect_toggled(LINK(this, OMySQLIntroPageSetup, OnSetupModeSelected)); + pController->SetIntroPage(this); + } + + OMySQLIntroPageSetup::~OMySQLIntroPageSetup() + { + } + + IMPL_LINK_NOARG(OMySQLIntroPageSetup, OnSetupModeSelected, weld::ToggleButton&, void) + { + maClickHdl.Call( this ); + } + + void OMySQLIntroPageSetup::implInitControls(const SfxItemSet& _rSet, bool /*_bSaveValue*/) + { + // show the "Connect directly" option only if the driver is installed + const DbuTypeCollectionItem* pCollectionItem = dynamic_cast<const DbuTypeCollectionItem*>( _rSet.GetItem(DSID_TYPECOLLECTION) ); + bool bHasMySQLNative = ( pCollectionItem != nullptr ) && pCollectionItem->getCollection()->hasDriver( "sdbc:mysql:mysqlc:" ); + if ( bHasMySQLNative ) + m_xNATIVEDatabase->show(); + + // if any of the options is checked, then there's nothing to do + if ( m_xODBCDatabase->get_active() || m_xJDBCDatabase->get_active() || m_xNATIVEDatabase->get_active() ) + return; + + // prefer "native" or "JDBC" + if ( bHasMySQLNative ) + m_xNATIVEDatabase->set_active(true); + else + m_xJDBCDatabase->set_active(true); + } + + void OMySQLIntroPageSetup::fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& /*_rControlList*/) + { + } + + void OMySQLIntroPageSetup::fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& /*_rControlList*/) + { + } + + bool OMySQLIntroPageSetup::FillItemSet(SfxItemSet* /*_rSet*/) + { + OSL_FAIL("Who called me?! Please ask oj for more information."); + return true; + } + + OMySQLIntroPageSetup::ConnectionType OMySQLIntroPageSetup::getMySQLMode() const + { + if (m_xJDBCDatabase->get_active()) + return VIA_JDBC; + else if (m_xNATIVEDatabase->get_active()) + return VIA_NATIVE; + else + return VIA_ODBC; + } + + // MySQLNativeSetupPage + MySQLNativeSetupPage::MySQLNativeSetupPage( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs ) + : OGenericAdministrationPage(pPage, pController, "dbaccess/ui/dbwizmysqlnativepage.ui", "DBWizMysqlNativePage", rCoreAttrs) + , m_xHelpText(m_xBuilder->weld_label("helptext")) + , m_xSettingsContainer(m_xBuilder->weld_container("MySQLSettingsContainer")) + , m_xMySQLSettings(new MySQLNativeSettings(m_xSettingsContainer.get(), LINK(this, OGenericAdministrationPage, OnControlModified))) + { + SetRoadmapStateValue(false); + } + + MySQLNativeSetupPage::~MySQLNativeSetupPage() + { + m_xMySQLSettings.reset(); + } + + std::unique_ptr<OGenericAdministrationPage> MySQLNativeSetupPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rAttrSet) + { + return std::make_unique<MySQLNativeSetupPage>(pPage, pController, rAttrSet); + } + + void MySQLNativeSetupPage::fillControls( std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList ) + { + m_xMySQLSettings->fillControls( _rControlList ); + } + + void MySQLNativeSetupPage::fillWindows(std::vector<std::unique_ptr<ISaveValueWrapper>>& rControlList) + { + rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xHelpText.get())); + m_xMySQLSettings->fillWindows(rControlList); + } + + bool MySQLNativeSetupPage::FillItemSet( SfxItemSet* _rSet ) + { + return m_xMySQLSettings->FillItemSet( _rSet ); + } + + void MySQLNativeSetupPage::implInitControls( const SfxItemSet& _rSet, bool _bSaveValue ) + { + m_xMySQLSettings->implInitControls( _rSet ); + + OGenericAdministrationPage::implInitControls( _rSet, _bSaveValue ); + + callModifiedHdl(); + } + + void MySQLNativeSetupPage::callModifiedHdl(weld::Widget*) + { + SetRoadmapStateValue( m_xMySQLSettings->canAdvance() ); + + OGenericAdministrationPage::callModifiedHdl(); + } + + // OMySQLJDBCConnectionPageSetup + OGeneralSpecialJDBCConnectionPageSetup::OGeneralSpecialJDBCConnectionPageSetup( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rCoreAttrs ,sal_uInt16 _nPortId, const char* pDefaultPortResId, const char* pHelpTextResId, const char* pHeaderTextResId, const char* pDriverClassId) + : OGenericAdministrationPage(pPage, pController, "dbaccess/ui/specialjdbcconnectionpage.ui", "SpecialJDBCConnectionPage", _rCoreAttrs) + , m_nPortId(_nPortId) + , m_xHeaderText(m_xBuilder->weld_label("header")) + , m_xFTHelpText(m_xBuilder->weld_label("helpLabel")) + , m_xFTDatabasename(m_xBuilder->weld_label("dbNameLabel")) + , m_xETDatabasename(m_xBuilder->weld_entry("dbNameEntry")) + , m_xFTHostname(m_xBuilder->weld_label("hostNameLabel")) + , m_xETHostname(m_xBuilder->weld_entry("hostNameEntry")) + , m_xFTPortNumber(m_xBuilder->weld_label("portNumLabel")) + , m_xFTDefaultPortNumber(m_xBuilder->weld_label("portNumDefLabel")) + , m_xNFPortNumber(m_xBuilder->weld_spin_button("portNumEntry")) + , m_xFTDriverClass(m_xBuilder->weld_label("jdbcDriverLabel")) + , m_xETDriverClass(m_xBuilder->weld_entry("jdbcDriverEntry")) + , m_xPBTestJavaDriver(m_xBuilder->weld_button("testDriverButton")) + { + m_xFTDriverClass->set_label(DBA_RES(pDriverClassId)); + + m_xFTDefaultPortNumber->set_label(DBA_RES(pDefaultPortResId)); + OUString sHelpText = DBA_RES(pHelpTextResId); + m_xFTHelpText->set_label(sHelpText); + //TODO this code snippet is redundant + m_xHeaderText->set_label(DBA_RES(pHeaderTextResId)); + + m_xETDatabasename->connect_changed(LINK(this, OGenericAdministrationPage, OnControlEntryModifyHdl)); + m_xETHostname->connect_changed(LINK(this, OGenericAdministrationPage, OnControlEntryModifyHdl)); + m_xNFPortNumber->connect_value_changed(LINK(this, OGenericAdministrationPage, OnControlSpinButtonModifyHdl)); + + m_xETDriverClass->connect_changed(LINK(this, OGenericAdministrationPage, OnControlEntryModifyHdl)); + m_xPBTestJavaDriver->connect_clicked(LINK(this,OGeneralSpecialJDBCConnectionPageSetup,OnTestJavaClickHdl)); + + const SfxStringItem* pUrlItem = _rCoreAttrs.GetItem<SfxStringItem>(DSID_CONNECTURL); + const DbuTypeCollectionItem* pTypesItem = _rCoreAttrs.GetItem<DbuTypeCollectionItem>(DSID_TYPECOLLECTION); + ::dbaccess::ODsnTypeCollection* pTypeCollection = pTypesItem ? pTypesItem->getCollection() : nullptr; + if (pTypeCollection && pUrlItem && pUrlItem->GetValue().getLength() ) + { + m_sDefaultJdbcDriverName = pTypeCollection->getJavaDriverClass(pUrlItem->GetValue()); + } + + SetRoadmapStateValue(false); + } + + OGeneralSpecialJDBCConnectionPageSetup::~OGeneralSpecialJDBCConnectionPageSetup() + { + } + + std::unique_ptr<OGenericAdministrationPage> OGeneralSpecialJDBCConnectionPageSetup::CreateMySQLJDBCTabPage( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet ) + { + return std::make_unique<OGeneralSpecialJDBCConnectionPageSetup>(pPage, pController, + _rAttrSet, + DSID_MYSQL_PORTNUMBER , + STR_MYSQL_DEFAULT, + STR_MYSQLJDBC_HELPTEXT, + STR_MYSQLJDBC_HEADERTEXT, + STR_MYSQL_DRIVERCLASSTEXT); + } + + std::unique_ptr<OGenericAdministrationPage> OGeneralSpecialJDBCConnectionPageSetup::CreateOracleJDBCTabPage( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet ) + { + return std::make_unique<OGeneralSpecialJDBCConnectionPageSetup>(pPage, pController, + _rAttrSet, + DSID_ORACLE_PORTNUMBER, + STR_ORACLE_DEFAULT, + STR_ORACLE_HELPTEXT, + STR_ORACLE_HEADERTEXT, + STR_ORACLE_DRIVERCLASSTEXT); + } + + void OGeneralSpecialJDBCConnectionPageSetup::fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) + { + _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::Entry>(m_xETDatabasename.get())); + _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::Entry>(m_xETDriverClass.get())); + _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::Entry>(m_xETHostname.get())); + _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::SpinButton>(m_xNFPortNumber.get())); + } + + void OGeneralSpecialJDBCConnectionPageSetup::fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) + { + _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFTHelpText.get())); + _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFTDatabasename.get())); + _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFTHostname.get())); + _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFTPortNumber.get())); + _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFTDefaultPortNumber.get())); + _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFTDriverClass.get())); + } + + bool OGeneralSpecialJDBCConnectionPageSetup::FillItemSet( SfxItemSet* _rSet ) + { + bool bChangedSomething = false; + fillString(*_rSet,m_xETDriverClass.get(),DSID_JDBCDRIVERCLASS,bChangedSomething); + fillString(*_rSet,m_xETHostname.get(),DSID_CONN_HOSTNAME,bChangedSomething); + fillString(*_rSet,m_xETDatabasename.get(),DSID_DATABASENAME,bChangedSomething); + fillInt32(*_rSet,m_xNFPortNumber.get(),m_nPortId,bChangedSomething ); + return bChangedSomething; + } + + void OGeneralSpecialJDBCConnectionPageSetup::implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) + { + // check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa) + bool bValid, bReadonly; + getFlags(_rSet, bValid, bReadonly); + + const SfxStringItem* pDatabaseName = _rSet.GetItem<SfxStringItem>(DSID_DATABASENAME); + const SfxStringItem* pDrvItem = _rSet.GetItem<SfxStringItem>(DSID_JDBCDRIVERCLASS); + const SfxStringItem* pHostName = _rSet.GetItem<SfxStringItem>(DSID_CONN_HOSTNAME); + const SfxInt32Item* pPortNumber = _rSet.GetItem<SfxInt32Item>(m_nPortId); + + if ( bValid ) + { + m_xETDatabasename->set_text(pDatabaseName->GetValue()); + m_xETDatabasename->save_value(); + + m_xETDriverClass->set_text(pDrvItem->GetValue()); + m_xETDriverClass->save_value(); + + m_xETHostname->set_text(pHostName->GetValue()); + m_xETHostname->save_value(); + + m_xNFPortNumber->set_value(pPortNumber->GetValue()); + m_xNFPortNumber->save_value(); + } + OGenericAdministrationPage::implInitControls(_rSet, _bSaveValue); + + // to get the correct value when saveValue was called by base class + if ( m_xETDriverClass->get_text().trim().isEmpty() ) + { + m_xETDriverClass->set_text(m_sDefaultJdbcDriverName); + m_xETDriverClass->save_value(); + } + callModifiedHdl(); + + bool bRoadmapState = ((!m_xETDatabasename->get_text().isEmpty() ) && (!m_xETHostname->get_text().isEmpty()) && (!m_xNFPortNumber->get_text().isEmpty() ) && ( !m_xETDriverClass->get_text().isEmpty() )); + SetRoadmapStateValue(bRoadmapState); + } + + IMPL_LINK_NOARG(OGeneralSpecialJDBCConnectionPageSetup, OnTestJavaClickHdl, weld::Button&, void) + { + OSL_ENSURE(m_pAdminDialog,"No Admin dialog set! ->GPF"); + + bool bSuccess = false; +#if HAVE_FEATURE_JAVA + try + { + if ( !m_xETDriverClass->get_text().trim().isEmpty() ) + { +// TODO change jvmaccess + ::rtl::Reference< jvmaccess::VirtualMachine > xJVM = ::connectivity::getJavaVM( m_pAdminDialog->getORB() ); + m_xETDriverClass->set_text(m_xETDriverClass->get_text().trim()); // fdo#68341 + bSuccess = ::connectivity::existsJavaClassByName(xJVM,m_xETDriverClass->get_text()); + } + } + catch(css::uno::Exception&) + { + } +#endif + const char *pMessage = bSuccess ? STR_JDBCDRIVER_SUCCESS : STR_JDBCDRIVER_NO_SUCCESS; + const MessageType mt = bSuccess ? MessageType::Info : MessageType::Error; + OSQLMessageBox aMsg(GetFrameWeld(), DBA_RES(pMessage), OUString(), MessBoxStyle::Ok | MessBoxStyle::DefaultOk, mt); + aMsg.run(); + } + + void OGeneralSpecialJDBCConnectionPageSetup::callModifiedHdl(weld::Widget* pControl) + { + if (pControl == m_xETDriverClass.get()) + m_xPBTestJavaDriver->set_sensitive( !m_xETDriverClass->get_text().trim().isEmpty() ); + bool bRoadmapState = ((!m_xETDatabasename->get_text().isEmpty() ) && ( !m_xETHostname->get_text().isEmpty() ) && (!m_xNFPortNumber->get_text().isEmpty() ) && ( !m_xETDriverClass->get_text().trim().isEmpty() )); + SetRoadmapStateValue(bRoadmapState); + OGenericAdministrationPage::callModifiedHdl(); + } + + std::unique_ptr<OGenericAdministrationPage> OJDBCConnectionPageSetup::CreateJDBCTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet) + { + return std::make_unique<OJDBCConnectionPageSetup>(pPage, pController, _rAttrSet); + } + + // OMySQLJDBCConnectionPageSetup + OJDBCConnectionPageSetup::OJDBCConnectionPageSetup(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs) + : OConnectionTabPageSetup(pPage, pController, "dbaccess/ui/jdbcconnectionpage.ui", "JDBCConnectionPage", rCoreAttrs, + STR_JDBC_HELPTEXT, STR_JDBC_HEADERTEXT, STR_COMMONURL) + , m_xFTDriverClass(m_xBuilder->weld_label("jdbcLabel")) + , m_xETDriverClass(m_xBuilder->weld_entry("jdbcEntry")) + , m_xPBTestJavaDriver(m_xBuilder->weld_button("jdbcButton")) + { + m_xETDriverClass->connect_changed(LINK(this, OJDBCConnectionPageSetup, OnEditModified)); + m_xPBTestJavaDriver->connect_clicked(LINK(this,OJDBCConnectionPageSetup,OnTestJavaClickHdl)); + } + + OJDBCConnectionPageSetup::~OJDBCConnectionPageSetup() + { + } + + void OJDBCConnectionPageSetup::fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) + { + _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::Entry>(m_xETDriverClass.get())); + } + + void OJDBCConnectionPageSetup::fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) + { + _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFTDriverClass.get())); + } + + bool OJDBCConnectionPageSetup::FillItemSet( SfxItemSet* _rSet ) + { + bool bChangedSomething = OConnectionTabPageSetup::FillItemSet(_rSet); + fillString(*_rSet,m_xETDriverClass.get(),DSID_JDBCDRIVERCLASS,bChangedSomething); + return bChangedSomething; + } + + void OJDBCConnectionPageSetup::implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) + { + // check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa) + bool bValid, bReadonly; + getFlags(_rSet, bValid, bReadonly); + + const SfxStringItem* pDrvItem = _rSet.GetItem<SfxStringItem>(DSID_JDBCDRIVERCLASS); + + if ( bValid ) + { + if ( !pDrvItem->GetValue().getLength() ) + { + OUString sDefaultJdbcDriverName = m_pCollection->getJavaDriverClass(m_eType); + if ( !sDefaultJdbcDriverName.isEmpty() ) + { + m_xETDriverClass->set_text(sDefaultJdbcDriverName); + m_xETDriverClass->save_value(); + } + } + else + { + m_xETDriverClass->set_text(pDrvItem->GetValue()); + m_xETDriverClass->save_value(); + } + } + bool bEnable = pDrvItem->GetValue().getLength() != 0; + m_xPBTestJavaDriver->set_sensitive(bEnable); + OConnectionTabPageSetup::implInitControls(_rSet, _bSaveValue); + + SetRoadmapStateValue(checkTestConnection()); + } + + bool OJDBCConnectionPageSetup::checkTestConnection() + { + OSL_ENSURE(m_pAdminDialog,"No Admin dialog set! ->GPF"); + bool bEnableTestConnection = !m_xConnectionURL->get_visible() || !m_xConnectionURL->GetTextNoPrefix().isEmpty(); + bEnableTestConnection = bEnableTestConnection && (!m_xETDriverClass->get_text().isEmpty()); + return bEnableTestConnection; + } + + IMPL_LINK_NOARG(OJDBCConnectionPageSetup, OnTestJavaClickHdl, weld::Button&, void) + { + OSL_ENSURE(m_pAdminDialog,"No Admin dialog set! ->GPF"); + bool bSuccess = false; +#if HAVE_FEATURE_JAVA + try + { + if ( !m_xETDriverClass->get_text().isEmpty() ) + { +// TODO change jvmaccess + ::rtl::Reference< jvmaccess::VirtualMachine > xJVM = ::connectivity::getJavaVM( m_pAdminDialog->getORB() ); + m_xETDriverClass->set_text(m_xETDriverClass->get_text().trim()); // fdo#68341 + bSuccess = xJVM.is() && ::connectivity::existsJavaClassByName(xJVM,m_xETDriverClass->get_text()); + } + } + catch(css::uno::Exception&) + { + } +#endif + const char* pMessage = bSuccess ? STR_JDBCDRIVER_SUCCESS : STR_JDBCDRIVER_NO_SUCCESS; + const MessageType mt = bSuccess ? MessageType::Info : MessageType::Error; + OSQLMessageBox aMsg(GetFrameWeld(), DBA_RES(pMessage), OUString(), MessBoxStyle::Ok | MessBoxStyle::DefaultOk, mt); + aMsg.run(); + } + + IMPL_LINK(OJDBCConnectionPageSetup, OnEditModified, weld::Entry&, rEdit, void) + { + if (&rEdit == m_xETDriverClass.get()) + m_xPBTestJavaDriver->set_sensitive(!m_xETDriverClass->get_text().isEmpty()); + SetRoadmapStateValue(checkTestConnection()); + // tell the listener we were modified + callModifiedHdl(); + } + + std::unique_ptr<OGenericAdministrationPage> OSpreadSheetConnectionPageSetup::CreateDocumentOrSpreadSheetTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet) + { + return std::make_unique<OSpreadSheetConnectionPageSetup>(pPage, pController, _rAttrSet); + } + + OSpreadSheetConnectionPageSetup::OSpreadSheetConnectionPageSetup(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs) + : OConnectionTabPageSetup(pPage, pController, "dbaccess/ui/dbwizspreadsheetpage.ui", "DBWizSpreadsheetPage", + rCoreAttrs, STR_SPREADSHEET_HELPTEXT, STR_SPREADSHEET_HEADERTEXT, STR_SPREADSHEETPATH) + , m_xPasswordrequired(m_xBuilder->weld_check_button("passwordrequired")) + { + m_xPasswordrequired->connect_toggled(LINK(this, OGenericAdministrationPage, OnControlModifiedButtonClick)); + } + + OSpreadSheetConnectionPageSetup::~OSpreadSheetConnectionPageSetup() + { + } + + void OSpreadSheetConnectionPageSetup::fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& /*_rControlList*/) + { + } + + void OSpreadSheetConnectionPageSetup::fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) + { + OConnectionTabPageSetup::fillControls(_rControlList); + _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::ToggleButton>(m_xPasswordrequired.get())); + + } + + bool OSpreadSheetConnectionPageSetup::FillItemSet( SfxItemSet* _rSet ) + { + bool bChangedSomething = OConnectionTabPageSetup::FillItemSet(_rSet); + fillBool(*_rSet,m_xPasswordrequired.get(),DSID_PASSWORDREQUIRED,false,bChangedSomething); + return bChangedSomething; + } + + std::unique_ptr<OGenericAdministrationPage> OAuthentificationPageSetup::CreateAuthentificationTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet) + { + return std::make_unique<OAuthentificationPageSetup>(pPage, pController, _rAttrSet); + } + + OAuthentificationPageSetup::OAuthentificationPageSetup(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rCoreAttrs) + : OGenericAdministrationPage(pPage, pController, "dbaccess/ui/authentificationpage.ui", "AuthentificationPage", _rCoreAttrs) + , m_xFTHelpText(m_xBuilder->weld_label("helptext")) + , m_xFTUserName(m_xBuilder->weld_label("generalUserNameLabel")) + , m_xETUserName(m_xBuilder->weld_entry("generalUserNameEntry")) + , m_xCBPasswordRequired(m_xBuilder->weld_check_button("passRequiredCheckbutton")) + , m_xPBTestConnection(m_xBuilder->weld_button("testConnectionButton")) + { + m_xETUserName->connect_changed(LINK(this,OGenericAdministrationPage,OnControlEntryModifyHdl)); + m_xCBPasswordRequired->connect_toggled(LINK(this,OGenericAdministrationPage,OnControlModifiedButtonClick)); + m_xPBTestConnection->connect_clicked(LINK(this,OGenericAdministrationPage,OnTestConnectionButtonClickHdl)); + } + + OAuthentificationPageSetup::~OAuthentificationPageSetup() + { + } + + void OAuthentificationPageSetup::fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) + { + _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFTHelpText.get())); + _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFTUserName.get())); + _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Button>(m_xPBTestConnection.get())); + } + + void OAuthentificationPageSetup::fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) + { + _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::Entry>(m_xETUserName.get())); + _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::ToggleButton>(m_xCBPasswordRequired.get())); + } + + void OAuthentificationPageSetup::implInitControls(const SfxItemSet& _rSet, bool /*_bSaveValue*/) + { + // check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa) + bool bValid, bReadonly; + getFlags(_rSet, bValid, bReadonly); + const SfxStringItem* pUidItem = _rSet.GetItem<SfxStringItem>(DSID_USER); + const SfxBoolItem* pAllowEmptyPwd = _rSet.GetItem<SfxBoolItem>(DSID_PASSWORDREQUIRED); + + m_xETUserName->set_text(pUidItem->GetValue()); + m_xCBPasswordRequired->set_active(pAllowEmptyPwd->GetValue()); + + m_xETUserName->save_value(); + } + + bool OAuthentificationPageSetup::FillItemSet( SfxItemSet* _rSet ) + { + bool bChangedSomething = false; + + if (m_xETUserName->get_value_changed_from_saved()) + { + _rSet->Put(SfxStringItem(DSID_USER, m_xETUserName->get_text())); + _rSet->Put(SfxStringItem(DSID_PASSWORD, OUString())); + bChangedSomething = true; + } + fillBool(*_rSet, m_xCBPasswordRequired.get(), DSID_PASSWORDREQUIRED, false, bChangedSomething); + return bChangedSomething; + } + + std::unique_ptr<OGenericAdministrationPage> OFinalDBPageSetup::CreateFinalDBTabPageSetup(weld::Container* pPage, ODbTypeWizDialogSetup* pController, const SfxItemSet& _rAttrSet) + { + return std::make_unique<OFinalDBPageSetup>(pPage, pController, _rAttrSet); + } + + OFinalDBPageSetup::OFinalDBPageSetup(weld::Container* pPage, ODbTypeWizDialogSetup* pController, const SfxItemSet& _rCoreAttrs) + : OGenericAdministrationPage(pPage, pController, "dbaccess/ui/finalpagewizard.ui", "PageFinal", _rCoreAttrs) + , m_xFTFinalHeader(m_xBuilder->weld_label("headerText")) + , m_xFTFinalHelpText(m_xBuilder->weld_label("helpText")) + , m_xRBRegisterDataSource(m_xBuilder->weld_radio_button("yesregister")) + , m_xRBDontregisterDataSource(m_xBuilder->weld_radio_button("noregister")) + , m_xFTAdditionalSettings(m_xBuilder->weld_label("additionalText")) + , m_xCBOpenAfterwards(m_xBuilder->weld_check_button("openediting")) + , m_xCBStartTableWizard(m_xBuilder->weld_check_button("usewizard")) + , m_xFTFinalText(m_xBuilder->weld_label("finishText")) + { + m_xCBOpenAfterwards->connect_toggled(LINK(this, OFinalDBPageSetup, OnOpenSelected)); + m_xRBRegisterDataSource->set_active(true); + pController->SetFinalPage(this); + } + + OFinalDBPageSetup::~OFinalDBPageSetup() + { + } + + bool OFinalDBPageSetup::IsDatabaseDocumentToBeRegistered() const + { + return m_xRBRegisterDataSource->get_active() && m_xRBRegisterDataSource->get_sensitive(); + } + + bool OFinalDBPageSetup::IsDatabaseDocumentToBeOpened() const + { + return m_xCBOpenAfterwards->get_active() && m_xCBOpenAfterwards->get_sensitive(); + } + + bool OFinalDBPageSetup::IsTableWizardToBeStarted() const + { + return m_xCBStartTableWizard->get_active() && m_xCBStartTableWizard->get_sensitive(); + } + + void OFinalDBPageSetup::fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) + { + _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFTFinalHeader.get())); + _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFTFinalHelpText.get())); + _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFTAdditionalSettings.get())); + _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFTFinalText.get())); + } + + void OFinalDBPageSetup::fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) + { + _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::ToggleButton>(m_xCBOpenAfterwards.get())); + _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::ToggleButton>(m_xCBStartTableWizard.get())); + _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::ToggleButton>(m_xRBRegisterDataSource.get())); + _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::ToggleButton>(m_xRBDontregisterDataSource.get())); + } + + void OFinalDBPageSetup::implInitControls(const SfxItemSet& /*_rSet*/, bool /*_bSaveValue*/) + { + m_xCBOpenAfterwards->set_active(true); + } + + void OFinalDBPageSetup::enableTableWizardCheckBox( bool _bSupportsTableCreation) + { + m_xCBStartTableWizard->set_sensitive(_bSupportsTableCreation); + } + + bool OFinalDBPageSetup::FillItemSet( SfxItemSet* /*_rSet*/ ) + { + return true; + } + + IMPL_LINK(OFinalDBPageSetup, OnOpenSelected, weld::ToggleButton&, rBox, void) + { + m_xCBStartTableWizard->set_sensitive(rBox.get_sensitive() && rBox.get_active()); + } +} + +// namespace dbaui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/DBSetupConnectionPages.hxx b/dbaccess/source/ui/dlg/DBSetupConnectionPages.hxx new file mode 100644 index 000000000..057e7e584 --- /dev/null +++ b/dbaccess/source/ui/dlg/DBSetupConnectionPages.hxx @@ -0,0 +1,273 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_DBACCESS_SOURCE_UI_DLG_DBSETUPCONNECTIONPAGES_HXX +#define INCLUDED_DBACCESS_SOURCE_UI_DLG_DBSETUPCONNECTIONPAGES_HXX + +#include "ConnectionPageSetup.hxx" + +#include "adminpages.hxx" +#include "admincontrols.hxx" +#include "TextConnectionHelper.hxx" + +namespace dbaui +{ + class ODbTypeWizDialogSetup; + + // OSpreadSheetConnectionPageSetup + class OSpreadSheetConnectionPageSetup final : public OConnectionTabPageSetup + { + public: + virtual bool FillItemSet ( SfxItemSet* _rCoreAttrs ) override; + static std::unique_ptr<OGenericAdministrationPage> CreateDocumentOrSpreadSheetTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet); + OSpreadSheetConnectionPageSetup(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rCoreAttrs); + virtual ~OSpreadSheetConnectionPageSetup() override; + + private: + std::unique_ptr<weld::CheckButton> m_xPasswordrequired; + + virtual void fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override; + virtual void fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override; + }; + + // OTextConnectionPage + class OTextConnectionPageSetup : public OConnectionTabPageSetup + { + public: + virtual bool FillItemSet ( SfxItemSet* _rCoreAttrs ) override; + static std::unique_ptr<OGenericAdministrationPage> CreateTextTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet ); + OTextConnectionPageSetup(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rCoreAttrs); + virtual ~OTextConnectionPageSetup() override; + protected: + virtual bool prepareLeave() override; + virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override; + virtual void fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override; + virtual void fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override; + bool checkTestConnection() override; + private: + DECL_LINK(ImplGetExtensionHdl, OTextConnectionHelper*, void); + std::unique_ptr<weld::Widget> m_xSubContainer; + std::unique_ptr<OTextConnectionHelper> m_xTextConnectionHelper; + }; + + // OLDAPConnectionPageSetup + class OLDAPConnectionPageSetup : public OGenericAdministrationPage + { + public: + virtual bool FillItemSet ( SfxItemSet* _rCoreAttrs ) override; + static std::unique_ptr<OGenericAdministrationPage> CreateLDAPTabPage( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet ); + OLDAPConnectionPageSetup( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rCoreAttrs ); + virtual ~OLDAPConnectionPageSetup() override; + virtual void callModifiedHdl(weld::Widget* pControl = nullptr) override; + + protected: + virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override; + virtual void fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override; + virtual void fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override; + + private: + std::unique_ptr<weld::Label> m_xFTHelpText; + std::unique_ptr<weld::Label> m_xFTHostServer; + std::unique_ptr<weld::Entry> m_xETHostServer; + std::unique_ptr<weld::Label> m_xFTBaseDN; + std::unique_ptr<weld::Entry> m_xETBaseDN; + std::unique_ptr<weld::Label> m_xFTPortNumber; + std::unique_ptr<weld::SpinButton> m_xNFPortNumber; + std::unique_ptr<weld::Label> m_xFTDefaultPortNumber; + std::unique_ptr<weld::CheckButton> m_xCBUseSSL; + }; + + // MySQLNativeSetupPage + class MySQLNativeSetupPage : public OGenericAdministrationPage + { + private: + std::unique_ptr<weld::Label> m_xHelpText; + std::unique_ptr<weld::Container> m_xSettingsContainer; + std::unique_ptr<MySQLNativeSettings> m_xMySQLSettings; + + public: + MySQLNativeSetupPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs); + virtual ~MySQLNativeSetupPage() override; + + static std::unique_ptr<OGenericAdministrationPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rAttrSet); + + protected: + virtual void fillControls( std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList ) override; + virtual void fillWindows( std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList ) override; + + virtual bool FillItemSet( SfxItemSet* _rCoreAttrs ) override; + virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override; + + virtual void callModifiedHdl(weld::Widget* pControl = nullptr) override; + }; + + // OGeneralSpecialJDBCConnectionPageSetup + class OGeneralSpecialJDBCConnectionPageSetup final : public OGenericAdministrationPage + { + public: + OGeneralSpecialJDBCConnectionPageSetup(weld::Container* pPage, weld::DialogController* pController + , const SfxItemSet& _rCoreAttrs + , sal_uInt16 _nPortId + , const char* pDefaultPortResId + , const char* pHelpTextResId + , const char* pHeaderTextResId + , const char* pDriverClassId ); + virtual ~OGeneralSpecialJDBCConnectionPageSetup() override; + static std::unique_ptr<OGenericAdministrationPage> CreateMySQLJDBCTabPage( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet ); + static std::unique_ptr<OGenericAdministrationPage> CreateOracleJDBCTabPage( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet ); + + private: + virtual bool FillItemSet( SfxItemSet* _rCoreAttrs ) override; + virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override; + virtual void fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override; + virtual void fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override; + virtual void callModifiedHdl(weld::Widget* pControl = nullptr) override; + + DECL_LINK(OnTestJavaClickHdl, weld::Button&, void); + + OUString m_sDefaultJdbcDriverName; + sal_uInt16 m_nPortId; + + std::unique_ptr<weld::Label> m_xHeaderText; + std::unique_ptr<weld::Label> m_xFTHelpText; + std::unique_ptr<weld::Label> m_xFTDatabasename; + std::unique_ptr<weld::Entry> m_xETDatabasename; + std::unique_ptr<weld::Label> m_xFTHostname; + std::unique_ptr<weld::Entry> m_xETHostname; + std::unique_ptr<weld::Label> m_xFTPortNumber; + std::unique_ptr<weld::Label> m_xFTDefaultPortNumber; + std::unique_ptr<weld::SpinButton> m_xNFPortNumber; + + std::unique_ptr<weld::Label> m_xFTDriverClass; + std::unique_ptr<weld::Entry> m_xETDriverClass; + std::unique_ptr<weld::Button> m_xPBTestJavaDriver; + }; + + // OJDBCConnectionPageSetup + class OJDBCConnectionPageSetup final : public OConnectionTabPageSetup + { + public: + OJDBCConnectionPageSetup(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rCoreAttrs); + virtual ~OJDBCConnectionPageSetup() override; + static std::unique_ptr<OGenericAdministrationPage> CreateJDBCTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rAttrSet); + + private: + virtual bool checkTestConnection() override; + + virtual bool FillItemSet( SfxItemSet* _rCoreAttrs ) override; + virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override; + virtual void fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override; + virtual void fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override; + + DECL_LINK(OnTestJavaClickHdl, weld::Button&, void); + DECL_LINK(OnEditModified, weld::Entry&, void); + std::unique_ptr<weld::Label> m_xFTDriverClass; + std::unique_ptr<weld::Entry> m_xETDriverClass; + std::unique_ptr<weld::Button> m_xPBTestJavaDriver; + }; + + // OMySQLIntroPageSetup + class OMySQLIntroPageSetup : public OGenericAdministrationPage + { + public: + enum ConnectionType + { + VIA_ODBC, + VIA_JDBC, + VIA_NATIVE + }; + + OMySQLIntroPageSetup(weld::Container* pPage, ODbTypeWizDialogSetup* pController, const SfxItemSet& rCoreAttrs); + virtual ~OMySQLIntroPageSetup() override; + + static std::unique_ptr<OMySQLIntroPageSetup> CreateMySQLIntroTabPage(weld::Container* pPage, ODbTypeWizDialogSetup* pController, const SfxItemSet& rAttrSet); + ConnectionType getMySQLMode() const; + void SetClickHdl( const Link<OMySQLIntroPageSetup *, void>& rLink ) { maClickHdl = rLink; } + + protected: + virtual bool FillItemSet(SfxItemSet* _rSet) override; + virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override; + virtual void fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override; + virtual void fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override; + + private: + std::unique_ptr<weld::RadioButton> m_xODBCDatabase; + std::unique_ptr<weld::RadioButton> m_xJDBCDatabase; + std::unique_ptr<weld::RadioButton> m_xNATIVEDatabase; + Link<OMySQLIntroPageSetup *, void> maClickHdl; + + DECL_LINK(OnSetupModeSelected, weld::ToggleButton&, void); + }; + + // OAuthentificationPageSetup + class OAuthentificationPageSetup final : public OGenericAdministrationPage + { + public: + virtual bool FillItemSet ( SfxItemSet* _rCoreAttrs ) override; + static std::unique_ptr<OGenericAdministrationPage> CreateAuthentificationTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet); + OAuthentificationPageSetup(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rCoreAttrs); + virtual ~OAuthentificationPageSetup() override; + + private: + std::unique_ptr<weld::Label> m_xFTHelpText; + std::unique_ptr<weld::Label> m_xFTUserName; + std::unique_ptr<weld::Entry> m_xETUserName; + std::unique_ptr<weld::CheckButton> m_xCBPasswordRequired; + std::unique_ptr<weld::Button> m_xPBTestConnection; + + virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override; + virtual void fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override; + virtual void fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override; + }; + + // OFinalDBPageSetup + class OFinalDBPageSetup : public OGenericAdministrationPage + { + public: + virtual bool FillItemSet ( SfxItemSet* _rCoreAttrs ) override; + static std::unique_ptr<OGenericAdministrationPage> CreateFinalDBTabPageSetup(weld::Container* pPage, ODbTypeWizDialogSetup* pController, const SfxItemSet& _rAttrSet); + + OFinalDBPageSetup(weld::Container* pPage, ODbTypeWizDialogSetup* pController, const SfxItemSet& _rCoreAttrs); + virtual ~OFinalDBPageSetup() override; + bool IsDatabaseDocumentToBeRegistered() const; + bool IsDatabaseDocumentToBeOpened() const; + bool IsTableWizardToBeStarted() const; + void enableTableWizardCheckBox( bool _bSupportsTableCreation); + + DECL_LINK(OnOpenSelected, weld::ToggleButton&, void); + protected: + virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override; + virtual void fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override; + virtual void fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override; + private: + std::unique_ptr<weld::Label> m_xFTFinalHeader; + std::unique_ptr<weld::Label> m_xFTFinalHelpText; + std::unique_ptr<weld::RadioButton> m_xRBRegisterDataSource; + std::unique_ptr<weld::RadioButton> m_xRBDontregisterDataSource; + std::unique_ptr<weld::Label> m_xFTAdditionalSettings; + std::unique_ptr<weld::CheckButton> m_xCBOpenAfterwards; + std::unique_ptr<weld::CheckButton> m_xCBStartTableWizard; + std::unique_ptr<weld::Label> m_xFTFinalText; + }; + +} // namespace dbaui + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/DbAdminImpl.cxx b/dbaccess/source/ui/dlg/DbAdminImpl.cxx new file mode 100644 index 000000000..2437196f1 --- /dev/null +++ b/dbaccess/source/ui/dlg/DbAdminImpl.cxx @@ -0,0 +1,1076 @@ +/* -*- 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 "DbAdminImpl.hxx" +#include <dsmeta.hxx> + +#include <svl/poolitem.hxx> +#include <svl/itempool.hxx> +#include <svl/stritem.hxx> +#include <svl/intitem.hxx> +#include <svl/eitem.hxx> +#include <IItemSetHelper.hxx> +#include <UITools.hxx> +#include <core_resource.hxx> +#include <strings.hrc> +#include <strings.hxx> +#include <dsitems.hxx> +#include "dsnItem.hxx" +#include "optionalboolitem.hxx" +#include <stringlistitem.hxx> +#include <OAuthenticationContinuation.hxx> + +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/frame/XStorable.hpp> +#include <com/sun/star/sdb/DatabaseContext.hpp> +#include <com/sun/star/sdb/SQLContext.hpp> +#include <com/sun/star/sdbc/ConnectionPool.hpp> +#include <com/sun/star/sdbc/XDriver.hpp> +#include <com/sun/star/task/InteractionHandler.hpp> +#include <com/sun/star/task/XInteractionRequest.hpp> +#include <com/sun/star/ucb/AuthenticationRequest.hpp> + +#include <comphelper/interaction.hxx> +#include <comphelper/sequence.hxx> +#include <connectivity/DriversConfig.hxx> +#include <connectivity/dbexception.hxx> +#include <osl/file.hxx> +#include <tools/diagnose_ex.h> +#include <osl/diagnose.h> +#include <sal/log.hxx> +#include <typelib/typedescription.hxx> +#include <vcl/svapp.hxx> +#include <vcl/stdtext.hxx> +#include <vcl/weld.hxx> + +#include <algorithm> +#include <iterator> +#include <functional> +#include <o3tl/functional.hxx> + +namespace dbaui +{ +using namespace ::dbtools; +using namespace com::sun::star::uno; +using namespace com::sun::star; +using namespace com::sun::star::ucb; +using namespace com::sun::star::task; +using namespace com::sun::star::sdbc; +using namespace com::sun::star::sdb; +using namespace com::sun::star::lang; +using namespace com::sun::star::beans; +using namespace com::sun::star::util; +using namespace com::sun::star::container; +using namespace com::sun::star::frame; + +namespace +{ + bool implCheckItemType( SfxItemSet const & _rSet, const sal_uInt16 _nId, const std::function<bool ( const SfxPoolItem* )>& isItemType ) + { + bool bCorrectType = false; + + SfxItemPool* pPool = _rSet.GetPool(); + OSL_ENSURE( pPool, "implCheckItemType: invalid item pool!" ); + if ( pPool ) + { + const SfxPoolItem& rDefItem = pPool->GetDefaultItem( _nId ); + bCorrectType = isItemType(&rDefItem); + } + return bCorrectType; + } + + void lcl_putProperty(const Reference< XPropertySet >& _rxSet, const OUString& _rName, const Any& _rValue) + { + try + { + if ( _rxSet.is() ) + _rxSet->setPropertyValue(_rName, _rValue); + } + catch(Exception&) + { + SAL_WARN("dbaccess", "ODbAdminDialog::implTranslateProperty: could not set the property " + << _rName); + } + + } + + OUString lcl_createHostWithPort(const SfxStringItem* _pHostName,const SfxInt32Item* _pPortNumber) + { + OUString sNewUrl; + + if ( _pHostName && _pHostName->GetValue().getLength() ) + sNewUrl = _pHostName->GetValue(); + + if ( _pPortNumber ) + { + sNewUrl += ":" + OUString::number(_pPortNumber->GetValue()); + } + + return sNewUrl; + } +} + + // ODbDataSourceAdministrationHelper +ODbDataSourceAdministrationHelper::ODbDataSourceAdministrationHelper(const Reference< XComponentContext >& _xORB, weld::Window* pParent, weld::Window* pTopParent, IItemSetHelper* _pItemSetHelper) + : m_xContext(_xORB) + , m_pParent(pParent) + , m_pItemSetHelper(_pItemSetHelper) +{ + /// initialize the property translation map + // direct properties of a data source + m_aDirectPropTranslator.emplace( DSID_CONNECTURL, PROPERTY_URL ); + m_aDirectPropTranslator.emplace( DSID_NAME, PROPERTY_NAME ); + m_aDirectPropTranslator.emplace( DSID_USER, PROPERTY_USER ); + m_aDirectPropTranslator.emplace( DSID_PASSWORD, PROPERTY_PASSWORD ); + m_aDirectPropTranslator.emplace( DSID_PASSWORDREQUIRED, PROPERTY_ISPASSWORDREQUIRED ); + m_aDirectPropTranslator.emplace( DSID_TABLEFILTER, PROPERTY_TABLEFILTER ); + m_aDirectPropTranslator.emplace( DSID_READONLY, PROPERTY_ISREADONLY ); + m_aDirectPropTranslator.emplace( DSID_SUPPRESSVERSIONCL, PROPERTY_SUPPRESSVERSIONCL ); + + // implicit properties, to be found in the direct property "Info" + m_aIndirectPropTranslator.emplace( DSID_JDBCDRIVERCLASS, INFO_JDBCDRIVERCLASS ); + m_aIndirectPropTranslator.emplace( DSID_TEXTFILEEXTENSION, INFO_TEXTFILEEXTENSION ); + m_aIndirectPropTranslator.emplace( DSID_CHARSET, INFO_CHARSET ); + m_aIndirectPropTranslator.emplace( DSID_TEXTFILEHEADER, INFO_TEXTFILEHEADER ); + m_aIndirectPropTranslator.emplace( DSID_FIELDDELIMITER, INFO_FIELDDELIMITER ); + m_aIndirectPropTranslator.emplace( DSID_TEXTDELIMITER, INFO_TEXTDELIMITER ); + m_aIndirectPropTranslator.emplace( DSID_DECIMALDELIMITER, INFO_DECIMALDELIMITER ); + m_aIndirectPropTranslator.emplace( DSID_THOUSANDSDELIMITER, INFO_THOUSANDSDELIMITER ); + m_aIndirectPropTranslator.emplace( DSID_SHOWDELETEDROWS, INFO_SHOWDELETEDROWS ); + m_aIndirectPropTranslator.emplace( DSID_ALLOWLONGTABLENAMES, INFO_ALLOWLONGTABLENAMES ); + m_aIndirectPropTranslator.emplace( DSID_ADDITIONALOPTIONS, INFO_ADDITIONALOPTIONS ); + m_aIndirectPropTranslator.emplace( DSID_SQL92CHECK, PROPERTY_ENABLESQL92CHECK ); + m_aIndirectPropTranslator.emplace( DSID_AUTOINCREMENTVALUE, PROPERTY_AUTOINCREMENTCREATION ); + m_aIndirectPropTranslator.emplace( DSID_AUTORETRIEVEVALUE, INFO_AUTORETRIEVEVALUE ); + m_aIndirectPropTranslator.emplace( DSID_AUTORETRIEVEENABLED, INFO_AUTORETRIEVEENABLED ); + m_aIndirectPropTranslator.emplace( DSID_APPEND_TABLE_ALIAS, INFO_APPEND_TABLE_ALIAS ); + m_aIndirectPropTranslator.emplace( DSID_AS_BEFORE_CORRNAME, INFO_AS_BEFORE_CORRELATION_NAME ); + m_aIndirectPropTranslator.emplace( DSID_CHECK_REQUIRED_FIELDS, INFO_FORMS_CHECK_REQUIRED_FIELDS ); + m_aIndirectPropTranslator.emplace( DSID_ESCAPE_DATETIME, INFO_ESCAPE_DATETIME ); + m_aIndirectPropTranslator.emplace( DSID_PRIMARY_KEY_SUPPORT, OUString("PrimaryKeySupport") ); + m_aIndirectPropTranslator.emplace( DSID_PARAMETERNAMESUBST, INFO_PARAMETERNAMESUBST ); + m_aIndirectPropTranslator.emplace( DSID_IGNOREDRIVER_PRIV, INFO_IGNOREDRIVER_PRIV ); + m_aIndirectPropTranslator.emplace( DSID_BOOLEANCOMPARISON, PROPERTY_BOOLEANCOMPARISONMODE ); + m_aIndirectPropTranslator.emplace( DSID_ENABLEOUTERJOIN, PROPERTY_ENABLEOUTERJOIN ); + m_aIndirectPropTranslator.emplace( DSID_CATALOG, PROPERTY_USECATALOGINSELECT ); + m_aIndirectPropTranslator.emplace( DSID_SCHEMA, PROPERTY_USESCHEMAINSELECT ); + m_aIndirectPropTranslator.emplace( DSID_INDEXAPPENDIX, OUString("AddIndexAppendix") ); + m_aIndirectPropTranslator.emplace( DSID_DOSLINEENDS, OUString("PreferDosLikeLineEnds") ); + m_aIndirectPropTranslator.emplace( DSID_CONN_SOCKET, OUString("LocalSocket") ); + m_aIndirectPropTranslator.emplace( DSID_NAMED_PIPE, OUString("NamedPipe") ); + m_aIndirectPropTranslator.emplace( DSID_RESPECTRESULTSETTYPE, OUString("RespectDriverResultSetType") ); + m_aIndirectPropTranslator.emplace( DSID_MAX_ROW_SCAN, OUString("MaxRowScan") ); + + // extra settings for ODBC + m_aIndirectPropTranslator.emplace( DSID_USECATALOG, INFO_USECATALOG ); + // extra settings for an LDAP address book + m_aIndirectPropTranslator.emplace( DSID_CONN_LDAP_BASEDN, INFO_CONN_LDAP_BASEDN ); + m_aIndirectPropTranslator.emplace( DSID_CONN_LDAP_ROWCOUNT, INFO_CONN_LDAP_ROWCOUNT ); + m_aIndirectPropTranslator.emplace( DSID_CONN_LDAP_USESSL, OUString("UseSSL") ); + m_aIndirectPropTranslator.emplace( DSID_DOCUMENT_URL, PROPERTY_URL ); + + // Oracle + m_aIndirectPropTranslator.emplace( DSID_IGNORECURRENCY, OUString("IgnoreCurrency") ); + + try + { + m_xDatabaseContext = DatabaseContext::create(m_xContext); + } + catch(const Exception&) + { + ShowServiceNotAvailableError(pTopParent, "com.sun.star.sdb.DatabaseContext", true); + } +} + +bool ODbDataSourceAdministrationHelper::getCurrentSettings(Sequence< PropertyValue >& _rDriverParam) +{ + OSL_ENSURE(m_pItemSetHelper->getOutputSet(), "ODbDataSourceAdministrationHelper::getCurrentSettings : not to be called without an example set!"); + if (!m_pItemSetHelper->getOutputSet()) + return false; + + std::vector< PropertyValue > aReturn; + // collecting this in a vector because it has a push_back, in opposite to sequences + + // user: DSID_USER -> "user" + const SfxStringItem* pUser = m_pItemSetHelper->getOutputSet()->GetItem<SfxStringItem>(DSID_USER); + if (pUser && pUser->GetValue().getLength()) + aReturn.emplace_back( "user", 0, + makeAny(pUser->GetValue()), PropertyState_DIRECT_VALUE); + + // check if the connection type requires a password + if (hasAuthentication(*m_pItemSetHelper->getOutputSet())) + { + // password: DSID_PASSWORD -> password + const SfxStringItem* pPassword = m_pItemSetHelper->getOutputSet()->GetItem<SfxStringItem>(DSID_PASSWORD); + OUString sPassword = pPassword ? pPassword->GetValue() : OUString(); + const SfxBoolItem* pPasswordRequired = m_pItemSetHelper->getOutputSet()->GetItem<SfxBoolItem>(DSID_PASSWORDREQUIRED); + // if the set does not contain a password, but the item set says it requires one, ask the user + if ((!pPassword || !pPassword->GetValue().getLength()) && (pPasswordRequired && pPasswordRequired->GetValue())) + { + const SfxStringItem* pName = m_pItemSetHelper->getOutputSet()->GetItem<SfxStringItem>(DSID_NAME); + + Reference< XModel > xModel( getDataSourceOrModel( m_xDatasource ), UNO_QUERY_THROW ); + ::comphelper::NamedValueCollection aArgs( xModel->getArgs() ); + Reference< XInteractionHandler > xHandler( aArgs.getOrDefault( "InteractionHandler", Reference< XInteractionHandler >() ) ); + + if ( !xHandler.is() ) + { + // instantiate the default SDB interaction handler + xHandler = task::InteractionHandler::createWithParent(m_xContext, nullptr); + } + + OUString sName = pName ? pName->GetValue() : OUString(); + OUString sLoginRequest(DBA_RES(STR_ENTER_CONNECTION_PASSWORD)); + OUString sTemp = sName; + sName = ::dbaui::getStrippedDatabaseName(nullptr,sTemp); + if ( !sName.isEmpty() ) + sLoginRequest = sLoginRequest.replaceAll("$name$", sName); + else + { + sLoginRequest = sLoginRequest.replaceAll("\"$name$\"", ""); + // ensure that in other languages the string will be deleted + sLoginRequest = sLoginRequest.replaceAll("$name$", ""); + } + + // the request + AuthenticationRequest aRequest; + aRequest.ServerName = sName; + aRequest.Diagnostic = sLoginRequest; + aRequest.HasRealm = false; + // aRequest.Realm + aRequest.HasUserName = pUser != nullptr; + aRequest.UserName = pUser ? pUser->GetValue() : OUString(); + aRequest.HasPassword = true; + //aRequest.Password + aRequest.HasAccount = false; + // aRequest.Account + + comphelper::OInteractionRequest* pRequest = new comphelper::OInteractionRequest(makeAny(aRequest)); + uno::Reference< XInteractionRequest > xRequest(pRequest); + + // build an interaction request + // two continuations (Ok and Cancel) + ::rtl::Reference< comphelper::OInteractionAbort > pAbort = new comphelper::OInteractionAbort; + ::rtl::Reference< dbaccess::OAuthenticationContinuation > pAuthenticate = new dbaccess::OAuthenticationContinuation; + pAuthenticate->setCanChangeUserName( false ); + pAuthenticate->setRememberPassword( RememberAuthentication_SESSION ); + + // some knittings + pRequest->addContinuation(pAbort.get()); + pRequest->addContinuation(pAuthenticate.get()); + + // handle the request + try + { + SolarMutexGuard aSolarGuard; + // release the mutex when calling the handler, it may need to lock the SolarMutex + xHandler->handle(xRequest); + } + catch(Exception&) + { + DBG_UNHANDLED_EXCEPTION("dbaccess"); + } + if (!pAuthenticate->wasSelected()) + return false; + + sPassword = pAuthenticate->getPassword(); + if (pAuthenticate->getRememberPassword()) + m_pItemSetHelper->getWriteOutputSet()->Put(SfxStringItem(DSID_PASSWORD, sPassword)); + } + + if (!sPassword.isEmpty()) + aReturn.emplace_back( "password", 0, + makeAny(sPassword), PropertyState_DIRECT_VALUE); + } + + if ( !aReturn.empty() ) + _rDriverParam = comphelper::containerToSequence(aReturn); + + // append all the other stuff (charset etc.) + fillDatasourceInfo(*m_pItemSetHelper->getOutputSet(), _rDriverParam); + + return true; +} + +void ODbDataSourceAdministrationHelper::successfullyConnected() +{ + OSL_ENSURE(m_pItemSetHelper->getOutputSet(), "ODbDataSourceAdministrationHelper::successfullyConnected: not to be called without an example set!"); + if (!m_pItemSetHelper->getOutputSet()) + return; + + if (hasAuthentication(*m_pItemSetHelper->getOutputSet())) + { + const SfxStringItem* pPassword = m_pItemSetHelper->getOutputSet()->GetItem<SfxStringItem>(DSID_PASSWORD); + if (pPassword && (0 != pPassword->GetValue().getLength())) + { + OUString sPassword = pPassword->GetValue(); + + Reference< XPropertySet > xCurrentDatasource = getCurrentDataSource(); + lcl_putProperty(xCurrentDatasource,m_aDirectPropTranslator[DSID_PASSWORD], makeAny(sPassword)); + } + } +} + +void ODbDataSourceAdministrationHelper::clearPassword() +{ + if (m_pItemSetHelper->getWriteOutputSet()) + m_pItemSetHelper->getWriteOutputSet()->ClearItem(DSID_PASSWORD); +} + +std::pair< Reference<XConnection>,bool> ODbDataSourceAdministrationHelper::createConnection() +{ + std::pair< Reference<XConnection>,bool> aRet; + aRet.second = false; + Sequence< PropertyValue > aConnectionParams; + if ( getCurrentSettings(aConnectionParams) ) + { + // the current DSN + // fill the table list with this connection information + SQLExceptionInfo aErrorInfo; + try + { + weld::WaitObject aWaitCursor(m_pParent); + aRet.first = getDriver()->connect(getConnectionURL(), aConnectionParams); + aRet.second = true; + } + catch (const SQLContext& e) { aErrorInfo = SQLExceptionInfo(e); } + catch (const SQLWarning& e) { aErrorInfo = SQLExceptionInfo(e); } + catch (const SQLException& e) { aErrorInfo = SQLExceptionInfo(e); } + + showError(aErrorInfo,m_pParent->GetXWindow(),getORB()); + } + if ( aRet.first.is() ) + successfullyConnected();// notify the admindlg to save the password + + return aRet; +} + +Reference< XDriver > ODbDataSourceAdministrationHelper::getDriver() +{ + return getDriver(getConnectionURL()); +} + +Reference< XDriver > ODbDataSourceAdministrationHelper::getDriver(const OUString& _sURL) +{ + // get the global DriverManager + Reference< XConnectionPool > xDriverManager; + + OUString sCurrentActionError = DBA_RES(STR_COULDNOTCREATE_DRIVERMANAGER); + sCurrentActionError = sCurrentActionError.replaceFirst("#servicename#", "com.sun.star.sdbc.ConnectionPool"); + + try + { + xDriverManager.set( ConnectionPool::create( getORB() ) ); + } + catch (const Exception&) + { + css::uno::Any anyEx = cppu::getCaughtException(); + // wrap the exception into an SQLException + throw SQLException(sCurrentActionError, getORB(), "S1000", 0, anyEx); + } + + Reference< XDriver > xDriver = xDriverManager->getDriverByURL(_sURL); + if (!xDriver.is()) + { + sCurrentActionError = DBA_RES(STR_NOREGISTEREDDRIVER); + sCurrentActionError = sCurrentActionError.replaceFirst("#connurl#", _sURL); + // will be caught and translated into an SQLContext exception + throw SQLException(sCurrentActionError, getORB(), "S1000", 0, Any()); + } + return xDriver; +} + +Reference< XPropertySet > const & ODbDataSourceAdministrationHelper::getCurrentDataSource() +{ + if ( !m_xDatasource.is() ) + { + Reference<XInterface> xIn(m_aDataSourceOrName,UNO_QUERY); + if ( !xIn.is() ) + { + OUString sCurrentDatasource; + m_aDataSourceOrName >>= sCurrentDatasource; + OSL_ENSURE(!sCurrentDatasource.isEmpty(),"No datasource name given!"); + try + { + if ( m_xDatabaseContext.is() ) + m_xDatasource.set(m_xDatabaseContext->getByName(sCurrentDatasource),UNO_QUERY); + xIn = m_xDatasource; + } + catch(const Exception&) + { + } + } + m_xModel.set(getDataSourceOrModel(xIn),UNO_QUERY); + if ( m_xModel.is() ) + m_xDatasource.set(xIn,UNO_QUERY); + else + { + m_xDatasource.set(getDataSourceOrModel(xIn),UNO_QUERY); + m_xModel.set(xIn,UNO_QUERY); + } + } + + OSL_ENSURE(m_xDatasource.is(), "ODbDataSourceAdministrationHelper::getCurrentDataSource: no data source!"); + return m_xDatasource; +} + +OUString ODbDataSourceAdministrationHelper::getDatasourceType( const SfxItemSet& _rSet ) +{ + const SfxStringItem* pConnectURL = _rSet.GetItem<SfxStringItem>(DSID_CONNECTURL); + OSL_ENSURE( pConnectURL , "ODbDataSourceAdministrationHelper::getDatasourceType: invalid items in the source set!" ); + const DbuTypeCollectionItem* pTypeCollection = _rSet.GetItem<DbuTypeCollectionItem>(DSID_TYPECOLLECTION); + OSL_ENSURE(pTypeCollection, "ODbDataSourceAdministrationHelper::getDatasourceType: invalid items in the source set!"); + ::dbaccess::ODsnTypeCollection* pCollection = pTypeCollection->getCollection(); + return pCollection->getType(pConnectURL->GetValue()); +} + +bool ODbDataSourceAdministrationHelper::hasAuthentication(const SfxItemSet& _rSet) +{ + return DataSourceMetaData::getAuthentication( getDatasourceType( _rSet ) ) != AuthNone; +} + +OUString ODbDataSourceAdministrationHelper::getConnectionURL() const +{ + OUString sNewUrl; + + OUString eType = getDatasourceType(*m_pItemSetHelper->getOutputSet()); + + const SfxStringItem* pUrlItem = m_pItemSetHelper->getOutputSet()->GetItem<SfxStringItem>(DSID_CONNECTURL); + const DbuTypeCollectionItem* pTypeCollection = m_pItemSetHelper->getOutputSet()->GetItem<DbuTypeCollectionItem>(DSID_TYPECOLLECTION); + + OSL_ENSURE(pUrlItem,"Connection URL is NULL. -> GPF!"); + OSL_ENSURE(pTypeCollection, "ODbDataSourceAdministrationHelper::getDatasourceType: invalid items in the source set!"); + ::dbaccess::ODsnTypeCollection* pCollection = pTypeCollection->getCollection(); + OSL_ENSURE(pCollection, "ODbDataSourceAdministrationHelper::getDatasourceType: invalid type collection!"); + + switch( pCollection->determineType(eType) ) + { + case ::dbaccess::DST_DBASE: + case ::dbaccess::DST_FLAT: + case ::dbaccess::DST_CALC: + case ::dbaccess::DST_WRITER: + break; + case ::dbaccess::DST_MSACCESS: + case ::dbaccess::DST_MSACCESS_2007: + { + OUString sFileName = pCollection->cutPrefix(pUrlItem->GetValue()); + OUString sNewFileName; + if ( ::osl::FileBase::getSystemPathFromFileURL( sFileName, sNewFileName ) == ::osl::FileBase::E_None ) + { + sNewUrl += sNewFileName; + } + } + break; + case ::dbaccess::DST_MYSQL_NATIVE: + case ::dbaccess::DST_MYSQL_JDBC: + { + const SfxStringItem* pHostName = m_pItemSetHelper->getOutputSet()->GetItem<SfxStringItem>(DSID_CONN_HOSTNAME); + const SfxInt32Item* pPortNumber = m_pItemSetHelper->getOutputSet()->GetItem<SfxInt32Item>(DSID_MYSQL_PORTNUMBER); + const SfxStringItem* pDatabaseName = m_pItemSetHelper->getOutputSet()->GetItem<SfxStringItem>(DSID_DATABASENAME); + sNewUrl = lcl_createHostWithPort(pHostName,pPortNumber); + OUString sDatabaseName = pDatabaseName ? pDatabaseName->GetValue() : OUString(); + if ( !sDatabaseName.getLength() && pUrlItem ) + sDatabaseName = pCollection->cutPrefix( pUrlItem->GetValue() ); + // TODO: what's that? Why is the database name transported via the URL Item? + // Huh? Anybody there? + // OJ: It is needed when the connection properties are changed. There the URL is used for every type. + + if ( !sDatabaseName.isEmpty() ) + { + sNewUrl += "/" + sDatabaseName; + } + } + break; + case ::dbaccess::DST_ORACLE_JDBC: + { + const SfxStringItem* pHostName = m_pItemSetHelper->getOutputSet()->GetItem<SfxStringItem>(DSID_CONN_HOSTNAME); + const SfxInt32Item* pPortNumber = m_pItemSetHelper->getOutputSet()->GetItem<SfxInt32Item>(DSID_ORACLE_PORTNUMBER); + const SfxStringItem* pDatabaseName = m_pItemSetHelper->getOutputSet()->GetItem<SfxStringItem>(DSID_DATABASENAME); + if ( pHostName && pHostName->GetValue().getLength() ) + { + sNewUrl = "@" + lcl_createHostWithPort(pHostName,pPortNumber); + OUString sDatabaseName = pDatabaseName ? pDatabaseName->GetValue() : OUString(); + if ( sDatabaseName.isEmpty() && pUrlItem ) + sDatabaseName = pCollection->cutPrefix( pUrlItem->GetValue() ); + if ( !sDatabaseName.isEmpty() ) + { + sNewUrl += ":" + sDatabaseName; + } + } + else + { // here someone entered a JDBC url which looks like oracle, so we have to use the url property + + } + } + break; + case ::dbaccess::DST_LDAP: + { + const SfxInt32Item* pPortNumber = m_pItemSetHelper->getOutputSet()->GetItem<SfxInt32Item>(DSID_CONN_LDAP_PORTNUMBER); + sNewUrl = pCollection->cutPrefix(pUrlItem->GetValue()) + lcl_createHostWithPort(nullptr,pPortNumber); + } + break; + case ::dbaccess::DST_JDBC: + // run through + default: + break; + } + if ( !sNewUrl.isEmpty() ) + sNewUrl = pCollection->getPrefix(eType) + sNewUrl; + else + sNewUrl = pUrlItem->GetValue(); + + return sNewUrl; +} + +namespace { + +struct PropertyValueLess +{ + bool operator() (const PropertyValue& x, const PropertyValue& y) const + { return x.Name < y.Name; } // construct prevents a MSVC6 warning +}; + +} + +typedef std::set<PropertyValue, PropertyValueLess> PropertyValueSet; + +void ODbDataSourceAdministrationHelper::translateProperties(const Reference< XPropertySet >& _rxSource, SfxItemSet& _rDest) +{ + if (_rxSource.is()) + { + for (auto const& elem : m_aDirectPropTranslator) + { + // get the property value + Any aValue; + try + { + aValue = _rxSource->getPropertyValue(elem.second); + } + catch(Exception&) + { + SAL_WARN("dbaccess", "ODbDataSourceAdministrationHelper::translateProperties: could not extract the property " + << elem.second); + } + // transfer it into an item + implTranslateProperty(_rDest, elem.first, aValue); + } + + // get the additional information + Sequence< PropertyValue > aAdditionalInfo; + try + { + _rxSource->getPropertyValue(PROPERTY_INFO) >>= aAdditionalInfo; + } + catch(Exception&) { } + + // collect the names of the additional settings + PropertyValueSet aInfos; + for (const PropertyValue& rAdditionalInfo : std::as_const(aAdditionalInfo)) + { + if( rAdditionalInfo.Name == "JDBCDRV" ) + { // compatibility + PropertyValue aCompatibility(rAdditionalInfo); + aCompatibility.Name = "JavaDriverClass"; + aInfos.insert(aCompatibility); + } + else + aInfos.insert(rAdditionalInfo); + } + + // go through all known translations and check if we have such a setting + if ( !aInfos.empty() ) + { + PropertyValue aSearchFor; + for (auto const& elem : m_aIndirectPropTranslator) + { + aSearchFor.Name = elem.second; + PropertyValueSet::const_iterator aInfoPos = aInfos.find(aSearchFor); + if (aInfos.end() != aInfoPos) + // the property is contained in the info sequence + // -> transfer it into an item + implTranslateProperty(_rDest, elem.first, aInfoPos->Value); + } + } + + convertUrl(_rDest); + } + + try + { + Reference<XStorable> xStore(getDataSourceOrModel(_rxSource),UNO_QUERY); + _rDest.Put(SfxBoolItem(DSID_READONLY, !xStore.is() || xStore->isReadonly() )); + } + catch(Exception&) + { + TOOLS_WARN_EXCEPTION("dbaccess", "IsReadOnly throws"); + } +} + +void ODbDataSourceAdministrationHelper::translateProperties(const SfxItemSet& _rSource, const Reference< XPropertySet >& _rxDest) +{ + OSL_ENSURE(_rxDest.is(), "ODbDataSourceAdministrationHelper::translateProperties: invalid property set!"); + if (!_rxDest.is()) + return; + + // the property set info + Reference< XPropertySetInfo > xInfo; + try { xInfo = _rxDest->getPropertySetInfo(); } + catch(Exception&) { } + + const OUString sUrlProp("URL"); + // transfer the direct properties + for (auto const& elem : m_aDirectPropTranslator) + { + const SfxPoolItem* pCurrentItem = _rSource.GetItem(static_cast<sal_uInt16>(elem.first)); + if (pCurrentItem) + { + sal_Int16 nAttributes = PropertyAttribute::READONLY; + if (xInfo.is()) + { + try { nAttributes = xInfo->getPropertyByName(elem.second).Attributes; } + catch(Exception&) { } + } + if ((nAttributes & PropertyAttribute::READONLY) == 0) + { + if ( sUrlProp == elem.second ) + { + Any aValue(makeAny(getConnectionURL())); + // aValue <<= OUString(); + lcl_putProperty(_rxDest, elem.second,aValue); + } + else + implTranslateProperty(_rxDest, elem.second, pCurrentItem); + } + } + } + + // now for the indirect properties + + Sequence< PropertyValue > aInfo; + // the original properties + try + { + _rxDest->getPropertyValue(PROPERTY_INFO) >>= aInfo; + } + catch(Exception&) { } + + // overwrite and extend them + fillDatasourceInfo(_rSource, aInfo); + // and propagate the (newly composed) sequence to the set + lcl_putProperty(_rxDest,PROPERTY_INFO, makeAny(aInfo)); +} + +void ODbDataSourceAdministrationHelper::fillDatasourceInfo(const SfxItemSet& _rSource, Sequence< css::beans::PropertyValue >& _rInfo) +{ + // within the current "Info" sequence, replace the ones we can examine from the item set + // (we don't just fill a completely new sequence with our own items, but we preserve any properties unknown to + // us) + + // first determine which of all the items are relevant for the data source (depends on the connection url) + const OUString eType = getDatasourceType(_rSource); + const ::connectivity::DriversConfig aDriverConfig(getORB()); + const ::comphelper::NamedValueCollection& aProperties = aDriverConfig.getProperties(eType); + + // collect the translated property values for the relevant items + PropertyValueSet aRelevantSettings; + MapInt2String::const_iterator aTranslation; + for (ItemID detailId = DSID_FIRST_ITEM_ID ; detailId <= DSID_LAST_ITEM_ID; ++detailId) + { + const SfxPoolItem* pCurrent = _rSource.GetItem(static_cast<sal_uInt16>(detailId)); + aTranslation = m_aIndirectPropTranslator.find(detailId); + if ( pCurrent && (m_aIndirectPropTranslator.end() != aTranslation) && + aProperties.has(aTranslation->second) ) + { + if ( aTranslation->second == INFO_CHARSET ) + { + OUString sCharSet; + implTranslateProperty(pCurrent) >>= sCharSet; + if ( !sCharSet.isEmpty() ) + aRelevantSettings.insert(PropertyValue(aTranslation->second, 0, makeAny(sCharSet), PropertyState_DIRECT_VALUE)); + } + else + aRelevantSettings.insert(PropertyValue(aTranslation->second, 0, implTranslateProperty(pCurrent), PropertyState_DIRECT_VALUE)); + } + } + + // settings to preserve + MapInt2String aPreservedSettings; + + // now aRelevantSettings contains all the property values relevant for the current data source type, + // check the original sequence if it already contains any of these values (which have to be overwritten, then) + PropertyValue* pInfo = _rInfo.getArray(); + PropertyValue aSearchFor; + sal_Int32 nObsoleteSetting = -1; + sal_Int32 nCount = _rInfo.getLength(); + for (sal_Int32 i = 0; i < nCount; ++i, ++pInfo) + { + aSearchFor.Name = pInfo->Name; + PropertyValueSet::const_iterator aOverwrittenSetting = aRelevantSettings.find(aSearchFor); + if (aRelevantSettings.end() != aOverwrittenSetting) + { // the setting was present in the original sequence, and it is to be overwritten -> replace it + if ( pInfo->Value != aOverwrittenSetting->Value ) + *pInfo = *aOverwrittenSetting; + aRelevantSettings.erase(aOverwrittenSetting); + } + else if( pInfo->Name == "JDBCDRV" ) + { // this is a compatibility setting, remove it from the sequence (it's replaced by JavaDriverClass) + nObsoleteSetting = i; + } + else + aPreservedSettings[i] = pInfo->Name; + } + if (-1 != nObsoleteSetting) + ::comphelper::removeElementAt(_rInfo, nObsoleteSetting); + + if ( !aPreservedSettings.empty() ) + { // check if there are settings which + // * are known as indirect properties + // * but not relevant for the current data source type + // These settings have to be removed: If they're not relevant, we have no UI for changing them. + + // for this, we need a string-controlled quick access to m_aIndirectPropTranslator + std::set<OUString> aIndirectProps; + std::transform(m_aIndirectPropTranslator.begin(), + m_aIndirectPropTranslator.end(), + std::inserter(aIndirectProps,aIndirectProps.begin()), + ::o3tl::select2nd< MapInt2String::value_type >()); + + // now check the to-be-preserved props + std::vector< sal_Int32 > aRemoveIndexes; + sal_Int32 nPositionCorrector = 0; + for (auto const& preservedSetting : aPreservedSettings) + { + if (aIndirectProps.end() != aIndirectProps.find(preservedSetting.second)) + { + aRemoveIndexes.push_back(preservedSetting.first - nPositionCorrector); + ++nPositionCorrector; + } + } + // now finally remove all such props + for (auto const& removeIndex : aRemoveIndexes) + ::comphelper::removeElementAt(_rInfo, removeIndex); + } + + Sequence< Any> aTypeSettings; + aTypeSettings = aProperties.getOrDefault("TypeInfoSettings",aTypeSettings); + // here we have a special entry for types from oracle + if ( aTypeSettings.hasElements() ) + { + aRelevantSettings.insert(PropertyValue("TypeInfoSettings", 0, makeAny(aTypeSettings), PropertyState_DIRECT_VALUE)); + } + + // check which values are still left ('cause they were not present in the original sequence, but are to be set) + if ( aRelevantSettings.empty() ) + return; + + sal_Int32 nOldLength = _rInfo.getLength(); + _rInfo.realloc(nOldLength + aRelevantSettings.size()); + PropertyValue* pAppendValues = _rInfo.getArray() + nOldLength; + for (auto const& relevantSetting : aRelevantSettings) + { + if ( relevantSetting.Name == INFO_CHARSET ) + { + OUString sCharSet; + relevantSetting.Value >>= sCharSet; + if ( !sCharSet.isEmpty() ) + *pAppendValues = relevantSetting; + } + else + *pAppendValues = relevantSetting; + ++pAppendValues; + } +} + +Any ODbDataSourceAdministrationHelper::implTranslateProperty(const SfxPoolItem* _pItem) +{ + // translate the SfxPoolItem + Any aValue; + + const SfxStringItem* pStringItem = dynamic_cast<const SfxStringItem*>( _pItem ); + const SfxBoolItem* pBoolItem = dynamic_cast<const SfxBoolItem*>( _pItem ); + const OptionalBoolItem* pOptBoolItem = dynamic_cast<const OptionalBoolItem*>( _pItem ); + const SfxInt32Item* pInt32Item = dynamic_cast< const SfxInt32Item* >( _pItem ); + const OStringListItem* pStringListItem = dynamic_cast<const OStringListItem*>( _pItem ); + + if ( pStringItem ) + { + aValue <<= pStringItem->GetValue(); + } + else if ( pBoolItem ) + { + aValue <<= pBoolItem->GetValue(); + } + else if ( pOptBoolItem ) + { + if ( !pOptBoolItem->HasValue() ) + aValue.clear(); + else + aValue <<= pOptBoolItem->GetValue(); + } + else if ( pInt32Item ) + { + aValue <<= pInt32Item->GetValue(); + } + else if ( pStringListItem ) + { + aValue <<= pStringListItem->getList(); + } + else + { + OSL_FAIL("ODbDataSourceAdministrationHelper::implTranslateProperty: unsupported item type!"); + return aValue; + } + + return aValue; +} + +void ODbDataSourceAdministrationHelper::implTranslateProperty(const Reference< XPropertySet >& _rxSet, const OUString& _rName, const SfxPoolItem* _pItem) +{ + Any aValue = implTranslateProperty(_pItem); + lcl_putProperty(_rxSet, _rName,aValue); +} + +OString ODbDataSourceAdministrationHelper::translatePropertyId( sal_Int32 _nId ) +{ + OUString aString; + + MapInt2String::const_iterator aPos = m_aDirectPropTranslator.find( _nId ); + if ( m_aDirectPropTranslator.end() != aPos ) + { + aString = aPos->second; + } + else + { + MapInt2String::const_iterator indirectPos = m_aIndirectPropTranslator.find( _nId ); + if ( m_aIndirectPropTranslator.end() != indirectPos ) + aString = indirectPos->second; + } + + OString aReturn( aString.getStr(), aString.getLength(), RTL_TEXTENCODING_ASCII_US ); + return aReturn; +} +template<class T> static bool checkItemType(const SfxPoolItem* pItem){ return dynamic_cast<const T*>(pItem) != nullptr;} + +void ODbDataSourceAdministrationHelper::implTranslateProperty( SfxItemSet& _rSet, sal_Int32 _nId, const Any& _rValue ) +{ + switch ( _rValue.getValueType().getTypeClass() ) + { + case TypeClass_STRING: + if ( implCheckItemType( _rSet, _nId, checkItemType<SfxStringItem> ) ) + { + OUString sValue; + _rValue >>= sValue; + _rSet.Put(SfxStringItem(_nId, sValue)); + } + else { + SAL_WARN( "dbaccess", "ODbDataSourceAdministrationHelper::implTranslateProperty: invalid property value (" + << translatePropertyId(_nId) << " should be no string)!"); + } + break; + + case TypeClass_BOOLEAN: + if ( implCheckItemType( _rSet, _nId, checkItemType<SfxBoolItem> ) ) + { + bool bVal = false; + _rValue >>= bVal; + _rSet.Put(SfxBoolItem(_nId, bVal)); + } + else if ( implCheckItemType( _rSet, _nId, checkItemType<OptionalBoolItem> ) ) + { + OptionalBoolItem aItem( _nId ); + if ( _rValue.hasValue() ) + { + bool bValue = false; + _rValue >>= bValue; + aItem.SetValue( bValue ); + } + else + aItem.ClearValue(); + _rSet.Put( aItem ); + } + else { + SAL_WARN( "dbaccess", "ODbDataSourceAdministrationHelper::implTranslateProperty: invalid property value (" + << translatePropertyId(_nId) + << " should be no boolean)!"); + } + break; + + case TypeClass_LONG: + if ( implCheckItemType( _rSet, _nId, checkItemType<SfxInt32Item> ) ) + { + sal_Int32 nValue = 0; + _rValue >>= nValue; + _rSet.Put( SfxInt32Item( _nId, nValue ) ); + } + else { + SAL_WARN( "dbaccess", "ODbDataSourceAdministrationHelper::implTranslateProperty: invalid property value (" + << translatePropertyId(_nId) + << " should be no int)!"); + } + break; + + case TypeClass_SEQUENCE: + if ( implCheckItemType( _rSet, _nId, checkItemType<OStringListItem> ) ) + { + // determine the element type + TypeDescription aTD(_rValue.getValueType()); + typelib_IndirectTypeDescription* pSequenceTD = + reinterpret_cast< typelib_IndirectTypeDescription* >(aTD.get()); + OSL_ENSURE(pSequenceTD && pSequenceTD->pType, "ODbDataSourceAdministrationHelper::implTranslateProperty: invalid sequence type!"); + + Type aElementType(pSequenceTD->pType); + switch (aElementType.getTypeClass()) + { + case TypeClass_STRING: + { + Sequence< OUString > aStringList; + _rValue >>= aStringList; + _rSet.Put(OStringListItem(_nId, aStringList)); + } + break; + default: + OSL_FAIL("ODbDataSourceAdministrationHelper::implTranslateProperty: unsupported property value type!"); + } + } + else { + SAL_WARN( "dbaccess", "ODbDataSourceAdministrationHelper::implTranslateProperty: invalid property value (" + << translatePropertyId(_nId) + << " should be no string sequence)!"); + } + break; + + case TypeClass_VOID: + _rSet.ClearItem(_nId); + break; + + default: + OSL_FAIL("ODbDataSourceAdministrationHelper::implTranslateProperty: unsupported property value type!"); + } +} + +OUString ODbDataSourceAdministrationHelper::getDocumentUrl(SfxItemSet const & _rDest) +{ + const SfxStringItem* pUrlItem = _rDest.GetItem<SfxStringItem>(DSID_DOCUMENT_URL); + OSL_ENSURE(pUrlItem,"Document URL is NULL. -> GPF!"); + return pUrlItem->GetValue(); +} + +void ODbDataSourceAdministrationHelper::convertUrl(SfxItemSet& _rDest) +{ + OUString eType = getDatasourceType(_rDest); + + const SfxStringItem* pUrlItem = _rDest.GetItem<SfxStringItem>(DSID_CONNECTURL); + const DbuTypeCollectionItem* pTypeCollection = _rDest.GetItem<DbuTypeCollectionItem>(DSID_TYPECOLLECTION); + + OSL_ENSURE(pUrlItem,"Connection URL is NULL. -> GPF!"); + OSL_ENSURE(pTypeCollection, "ODbAdminDialog::getDatasourceType: invalid items in the source set!"); + ::dbaccess::ODsnTypeCollection* pCollection = pTypeCollection->getCollection(); + OSL_ENSURE(pCollection, "ODbAdminDialog::getDatasourceType: invalid type collection!"); + + sal_uInt16 nPortNumberId = 0; + sal_Int32 nPortNumber = -1; + OUString sNewHostName; + OUString sUrlPart; + + pCollection->extractHostNamePort(pUrlItem->GetValue(),sUrlPart,sNewHostName,nPortNumber); + const ::dbaccess::DATASOURCE_TYPE eTy = pCollection->determineType(eType); + + switch( eTy ) + { + case ::dbaccess::DST_MYSQL_NATIVE: + case ::dbaccess::DST_MYSQL_JDBC: + nPortNumberId = DSID_MYSQL_PORTNUMBER; + break; + case ::dbaccess::DST_ORACLE_JDBC: + nPortNumberId = DSID_ORACLE_PORTNUMBER; + break; + case ::dbaccess::DST_LDAP: + nPortNumberId = DSID_CONN_LDAP_PORTNUMBER; + break; + default: + break; + } + + if ( !sUrlPart.isEmpty() ) + { + if ( eTy == ::dbaccess::DST_MYSQL_NATIVE ) + { + _rDest.Put( SfxStringItem( DSID_DATABASENAME, sUrlPart ) ); + } + else + { + OUString sNewUrl = pCollection->getPrefix(eType) + sUrlPart; + _rDest.Put( SfxStringItem( DSID_CONNECTURL, sNewUrl ) ); + } + } + + if ( !sNewHostName.isEmpty() ) + _rDest.Put(SfxStringItem(DSID_CONN_HOSTNAME, sNewHostName)); + + if ( nPortNumber != -1 && nPortNumberId != 0 ) + _rDest.Put(SfxInt32Item(nPortNumberId, nPortNumber)); + +} + +bool ODbDataSourceAdministrationHelper::saveChanges(const SfxItemSet& _rSource) +{ + // put the remembered settings into the property set + Reference<XPropertySet> xDatasource = getCurrentDataSource(); + if ( !xDatasource.is() ) + return false; + + translateProperties(_rSource,xDatasource ); + + return true; +} + +void ODbDataSourceAdministrationHelper::setDataSourceOrName( const Any& _rDataSourceOrName ) +{ + OSL_ENSURE( !m_aDataSourceOrName.hasValue(), "ODbDataSourceAdministrationHelper::setDataSourceOrName: already have one!" ); + // hmm. We could reset m_xDatasource/m_xModel, probably, and continue working + m_aDataSourceOrName = _rDataSourceOrName; +} + +// DbuTypeCollectionItem +DbuTypeCollectionItem::DbuTypeCollectionItem(sal_Int16 _nWhich, ::dbaccess::ODsnTypeCollection* _pCollection) + :SfxPoolItem(_nWhich) + ,m_pCollection(_pCollection) +{ +} + +DbuTypeCollectionItem::DbuTypeCollectionItem(const DbuTypeCollectionItem& _rSource) + :SfxPoolItem(_rSource) + ,m_pCollection(_rSource.getCollection()) +{ +} + +bool DbuTypeCollectionItem::operator==(const SfxPoolItem& _rItem) const +{ + return SfxPoolItem::operator==(_rItem) && + static_cast<const DbuTypeCollectionItem&>( _rItem ).getCollection() == getCollection(); +} + +DbuTypeCollectionItem* DbuTypeCollectionItem::Clone(SfxItemPool* /*_pPool*/) const +{ + return new DbuTypeCollectionItem(*this); +} + +} // namespace dbaui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/DbAdminImpl.hxx b/dbaccess/source/ui/dlg/DbAdminImpl.hxx new file mode 100644 index 000000000..c7fbcdc6d --- /dev/null +++ b/dbaccess/source/ui/dlg/DbAdminImpl.hxx @@ -0,0 +1,170 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_DBACCESS_SOURCE_UI_DLG_DBADMINIMPL_HXX +#define INCLUDED_DBACCESS_SOURCE_UI_DLG_DBADMINIMPL_HXX + +#include <sal/config.h> + +#include <map> + +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/sdb/XDatabaseContext.hpp> +#include <com/sun/star/sdbc/XConnection.hpp> +#include <com/sun/star/sdbc/XDriver.hpp> +#include <dsntypes.hxx> +#include <svl/itemset.hxx> +#include <com/sun/star/frame/XModel.hpp> +#include <svl/poolitem.hxx> +#include <vcl/weld.hxx> + +namespace dbaui +{ + namespace DataSourceInfoConverter + { + void convert(const css::uno::Reference< css::uno::XComponentContext> & xContext, + const ::dbaccess::ODsnTypeCollection* _pCollection, + const OUString& _sOldURLPrefix, + const OUString& _sNewURLPrefix, + const css::uno::Reference< css::beans::XPropertySet >& _xDatasource); + }; + class IItemSetHelper; + // ODbDataSourceAdministrationHelper + class ODbDataSourceAdministrationHelper final + { + public: + typedef std::map<sal_Int32, OUString> MapInt2String; + + private: + css::uno::Reference< css::uno::XComponentContext > + m_xContext; /// service factory + css::uno::Reference< css::sdb::XDatabaseContext > + m_xDatabaseContext; /// database context we're working in + css::uno::Reference< css::beans::XPropertySet > m_xDatasource; + css::uno::Reference< css::frame::XModel > m_xModel; + + css::uno::Any m_aDataSourceOrName; + + MapInt2String m_aDirectPropTranslator; /// translating property id's into names (direct properties of a data source) + MapInt2String m_aIndirectPropTranslator; /// translating property id's into names (indirect properties of a data source) + weld::Window* m_pParent; + IItemSetHelper* m_pItemSetHelper; + public: + + ODbDataSourceAdministrationHelper(const css::uno::Reference< css::uno::XComponentContext >& _xORB, + weld::Window* pParent, weld::Window* pTopParent, + IItemSetHelper* _pItemSetHelper); + + /** translate the current dialog SfxItems into driver relevant PropertyValues + @see successfullyConnected + */ + bool getCurrentSettings(css::uno::Sequence< css::beans::PropertyValue >& _rDriverParams); + + /** to be called if the settings got from getCurrentSettings have been used for successfully connecting + @see getCurrentSettings + */ + void successfullyConnected(); + + /// clear the password in the current data source's item set + void clearPassword(); + + const css::uno::Reference< css::uno::XComponentContext >& getORB() const { return m_xContext; } + + /** creates a new connection. The caller is responsible to dispose it !!!! + */ + std::pair< css::uno::Reference< css::sdbc::XConnection >,bool> createConnection(); + + /** return the corresponding driver for the selected URL + */ + css::uno::Reference< css::sdbc::XDriver > getDriver(); + css::uno::Reference< css::sdbc::XDriver > getDriver(const OUString& _sURL); + + /** returns the data source the dialog is currently working with + */ + css::uno::Reference< css::beans::XPropertySet > const & getCurrentDataSource(); + // returns the Url of a database document + static OUString getDocumentUrl(SfxItemSet const & _rDest); + + void setDataSourceOrName( const css::uno::Any& _rDataSourceOrName ); + + /** extracts the connection type from the given set<p/> + The connection type is determined by the value of the DSN item, analyzed by the TypeCollection item. + */ + static OUString getDatasourceType( const SfxItemSet& _rSet ); + + /** returns the connection URL + @return + The connection URL + */ + OUString getConnectionURL() const; + + /// fill the necessary information from the url line + static void convertUrl(SfxItemSet& _rDest); + + const MapInt2String& getIndirectProperties() const { return m_aIndirectPropTranslator; } + + /** translates properties of a UNO data source into SfxItems + @param _rxSource + The data source + @param _rDest + The item set to fill. + */ + void translateProperties( + const css::uno::Reference< css::beans::XPropertySet >& _rxSource, + SfxItemSet& _rDest); + + /** translate SfxItems into properties of a UNO data source + @param _rSource + The item set to read from. + @param _rxDest + The data source to fill. + */ + void translateProperties( + const SfxItemSet& _rSource, + const css::uno::Reference< css::beans::XPropertySet >& _rxDest); + + bool saveChanges(const SfxItemSet& _rSource); + private: + /** fill a data source info array with the settings from a given item set + */ + void fillDatasourceInfo(const SfxItemSet& _rSource, css::uno::Sequence< css::beans::PropertyValue >& _rInfo); + + /// translate the given value into an SfxPoolItem, put this into the given set under the given id + void implTranslateProperty(SfxItemSet& _rSet, sal_Int32 _nId, const css::uno::Any& _rValue); + + /// translate the given SfxPoolItem into an <type scope="com.sun.star.Any">uno</type> + static css::uno::Any implTranslateProperty(const SfxPoolItem* _pItem); + + /// translate the given SfxPoolItem into an <type scope="com.sun.star.Any">uno</type>, set it (under the given name) on the given property set + static void implTranslateProperty(const css::uno::Reference< css::beans::XPropertySet >& _rxSet, const OUString& _rName, const SfxPoolItem* _pItem); + + /** check if the data source described by the given set needs authentication<p/> + The return value depends on the data source type only. + */ + static bool hasAuthentication(const SfxItemSet& _rSet); + + OString translatePropertyId( sal_Int32 _nId ); + }; + +} // namespace dbaui + +#endif // INCLUDED_DBACCESS_SOURCE_UI_DLG_DBADMINIMPL_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/DriverSettings.hxx b/dbaccess/source/ui/dlg/DriverSettings.hxx new file mode 100644 index 000000000..3fc4e9792 --- /dev/null +++ b/dbaccess/source/ui/dlg/DriverSettings.hxx @@ -0,0 +1,82 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_DBACCESS_SOURCE_UI_DLG_DRIVERSETTINGS_HXX +#define INCLUDED_DBACCESS_SOURCE_UI_DLG_DRIVERSETTINGS_HXX + +#include <sfx2/tabdlg.hxx> + +class SfxTabPage; +namespace vcl { class Window; } +namespace dbaui +{ + /// a collection class for all details a driver needs + class ODriversSettings + { + public: + + /** Creates the detail page for ado + */ + static std::unique_ptr<SfxTabPage> CreateDbase( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet ); + + /** Creates the detail page for ado + */ + static std::unique_ptr<SfxTabPage> CreateAdo( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet ); + + /** Creates the detail page for ODBC + */ + static std::unique_ptr<SfxTabPage> CreateODBC( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet ); + + /** Creates the detail page for user + */ + static std::unique_ptr<SfxTabPage> CreateUser( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet ); + + /** Creates the detail page for MySQLODBC + */ + static std::unique_ptr<SfxTabPage> CreateMySQLODBC( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet ); + + /** Creates the detail page for MySQLJDBC + */ + static std::unique_ptr<SfxTabPage> CreateMySQLJDBC( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet ); + + /** Creates the detail page for MySQLNATIVE + */ + static std::unique_ptr<SfxTabPage> CreateMySQLNATIVE( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet ); + + /** Creates the detail page for Oracle JDBC + */ + static std::unique_ptr<SfxTabPage> CreateOracleJDBC( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet ); + + /** Creates the detail page for LDAP + */ + static std::unique_ptr<SfxTabPage> CreateLDAP( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet ); + + /// Creates the detail page for Text + static std::unique_ptr<SfxTabPage> CreateText( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet ); + + /// creates the GeneratedValues page + static std::unique_ptr<SfxTabPage> CreateGeneratedValuesPage( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet ); + + /// creates the "Special Settings" page of the "Advanced Settings" dialog + static std::unique_ptr<SfxTabPage> CreateSpecialSettingsPage( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet ); + }; +} + +#endif // INCLUDED_DBACCESS_SOURCE_UI_DLG_DRIVERSETTINGS_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/QueryPropertiesDialog.cxx b/dbaccess/source/ui/dlg/QueryPropertiesDialog.cxx new file mode 100644 index 000000000..41ed0e867 --- /dev/null +++ b/dbaccess/source/ui/dlg/QueryPropertiesDialog.cxx @@ -0,0 +1,63 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <QueryPropertiesDialog.hxx> +#include <strings.hrc> +#include <core_resource.hxx> + +#define ALL_STRING DBA_RES(STR_QUERY_LIMIT_ALL) +#define ALL_INT -1 + +namespace dbaui +{ + +QueryPropertiesDialog::QueryPropertiesDialog( + weld::Window* pParent, const bool bDistinct, const sal_Int64 nLimit ) + : GenericDialogController(pParent, "dbaccess/ui/querypropertiesdialog.ui", "QueryPropertiesDialog") + , m_xRB_Distinct(m_xBuilder->weld_radio_button("distinct")) + , m_xRB_NonDistinct(m_xBuilder->weld_radio_button("nondistinct")) + , m_xLB_Limit(m_xBuilder->weld_combo_box("limitbox")) +{ + m_xRB_Distinct->set_active(bDistinct); + m_xRB_NonDistinct->set_active(!bDistinct); + + m_xLB_Limit->append(OUString::number(ALL_INT), ALL_STRING); + /// Default values + sal_Int64 const aDefLimitAry[] = + { + 5, + 10, + 20, + 50 + }; + for (auto a : aDefLimitAry) + m_xLB_Limit->append(OUString::number(a), OUString::number(a)); + OUString sInitial = OUString::number(nLimit); + auto nPos = m_xLB_Limit->find_id(sInitial); + if (nPos != -1) + m_xLB_Limit->set_active(nPos); + else + m_xLB_Limit->set_entry_text(OUString::number(nLimit)); +} + +sal_Int64 QueryPropertiesDialog::getLimit() const +{ + OUString sSelectedId = m_xLB_Limit->get_active_id(); + if (!sSelectedId.isEmpty()) + return sSelectedId.toInt64(); + return m_xLB_Limit->get_active_text().toInt64(); +} + +QueryPropertiesDialog::~QueryPropertiesDialog() +{ +} + +} ///dbaui namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/RelationDlg.cxx b/dbaccess/source/ui/dlg/RelationDlg.cxx new file mode 100644 index 000000000..cc449d9b7 --- /dev/null +++ b/dbaccess/source/ui/dlg/RelationDlg.cxx @@ -0,0 +1,215 @@ +/* -*- 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 <RelationDlg.hxx> + +#include <com/sun/star/sdbc/KeyRule.hpp> +#include <com/sun/star/sdbc/SQLException.hpp> + +#include <tools/diagnose_ex.h> +#include <JoinDesignView.hxx> +#include <JoinController.hxx> +#include <connectivity/dbexception.hxx> +#include <connectivity/dbtools.hxx> +#include <RTableConnectionData.hxx> +#include <RelationControl.hxx> +#include <cppuhelper/exc_hlp.hxx> + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::beans; +using namespace ::dbaui; +using namespace ::dbtools; + +ORelationDialog::ORelationDialog( OJoinTableView* pParent, + const TTableConnectionData::value_type& pConnectionData, + bool bAllowTableSelect ) + : GenericDialogController(pParent->GetFrameWeld(), + "dbaccess/ui/relationdialog.ui", "RelationDialog") + , m_pParent(pParent) + , m_pOrigConnData(pConnectionData) + , m_bTriedOneUpdate(false) + , m_xRB_NoCascUpd(m_xBuilder->weld_radio_button("addaction")) + , m_xRB_CascUpd(m_xBuilder->weld_radio_button("addcascade")) + , m_xRB_CascUpdNull(m_xBuilder->weld_radio_button("addnull")) + , m_xRB_CascUpdDefault(m_xBuilder->weld_radio_button("adddefault")) + , m_xRB_NoCascDel(m_xBuilder->weld_radio_button("delaction")) + , m_xRB_CascDel(m_xBuilder->weld_radio_button("delcascade")) + , m_xRB_CascDelNull(m_xBuilder->weld_radio_button("delnull")) + , m_xRB_CascDelDefault(m_xBuilder->weld_radio_button("deldefault")) + , m_xPB_OK(m_xBuilder->weld_button("ok")) +{ + // Copy connection + m_pConnData = pConnectionData->NewInstance(); + m_pConnData->CopyFrom( *pConnectionData ); + + Init(m_pConnData); + m_xTableControl.reset(new OTableListBoxControl(m_xBuilder.get(), &pParent->GetTabWinMap(), this)); + + m_xPB_OK->connect_clicked(LINK(this, ORelationDialog, OKClickHdl)); + + m_xTableControl->Init( m_pConnData ); + if ( bAllowTableSelect ) + m_xTableControl->fillListBoxes(); + else + m_xTableControl->fillAndDisable(pConnectionData); + + m_xTableControl->lateInit(); + + m_xTableControl->NotifyCellChange(); +} + +ORelationDialog::~ORelationDialog() +{ +} + +void ORelationDialog::Init(const TTableConnectionData::value_type& _pConnectionData) +{ + ORelationTableConnectionData* pConnData = static_cast<ORelationTableConnectionData*>(_pConnectionData.get()); + // Update Rules + switch (pConnData->GetUpdateRules()) + { + case KeyRule::NO_ACTION: + case KeyRule::RESTRICT: + m_xRB_NoCascUpd->set_active(true); + break; + + case KeyRule::CASCADE: + m_xRB_CascUpd->set_active(true); + break; + + case KeyRule::SET_NULL: + m_xRB_CascUpdNull->set_active(true); + break; + case KeyRule::SET_DEFAULT: + m_xRB_CascUpdDefault->set_active(true); + break; + } + + // Delete Rules + switch (pConnData->GetDeleteRules()) + { + case KeyRule::NO_ACTION: + case KeyRule::RESTRICT: + m_xRB_NoCascDel->set_active(true); + break; + + case KeyRule::CASCADE: + m_xRB_CascDel->set_active(true); + break; + + case KeyRule::SET_NULL: + m_xRB_CascDelNull->set_active(true); + break; + case KeyRule::SET_DEFAULT: + m_xRB_CascDelDefault->set_active(true); + break; + } +} + +IMPL_LINK_NOARG(ORelationDialog, OKClickHdl, weld::Button&, void) +{ + // Read out RadioButtons + sal_uInt16 nAttrib = 0; + + // Delete Rules + if( m_xRB_NoCascDel->get_active() ) + nAttrib |= KeyRule::NO_ACTION; + if( m_xRB_CascDel->get_active() ) + nAttrib |= KeyRule::CASCADE; + if( m_xRB_CascDelNull->get_active() ) + nAttrib |= KeyRule::SET_NULL; + if( m_xRB_CascDelDefault->get_active() ) + nAttrib |= KeyRule::SET_DEFAULT; + + ORelationTableConnectionData* pConnData = static_cast<ORelationTableConnectionData*>(m_pConnData.get()); + pConnData->SetDeleteRules( nAttrib ); + + // Update Rules + nAttrib = 0; + if( m_xRB_NoCascUpd->get_active() ) + nAttrib |= KeyRule::NO_ACTION; + if( m_xRB_CascUpd->get_active() ) + nAttrib |= KeyRule::CASCADE; + if( m_xRB_CascUpdNull->get_active() ) + nAttrib |= KeyRule::SET_NULL; + if( m_xRB_CascUpdDefault->get_active() ) + nAttrib |= KeyRule::SET_DEFAULT; + pConnData->SetUpdateRules( nAttrib ); + + m_xTableControl->SaveModified(); + + //// if the ComboBoxes for the table selection are enabled (constructor with bAllowTableSelect==sal_True), + //// then I must also put the table names into the connection + //m_pConnData->SetSourceWinName(m_xTableControl->getSourceWinName()); + //m_pConnData->SetDestWinName(m_xTableControl->getDestWinName()); + + // try to create the relation + try + { + ORelationTableConnectionData* pOrigConnData = static_cast<ORelationTableConnectionData*>(m_pOrigConnData.get()); + if ( *pConnData == *pOrigConnData || pConnData->Update()) + { + m_pOrigConnData->CopyFrom( *m_pConnData ); + m_xDialog->response(RET_OK); + return; + } + } + catch( const SQLException& ) + { + ::dbtools::showError(SQLExceptionInfo(::cppu::getCaughtException()), + m_xDialog->GetXWindow(), + m_pParent->getDesignView()->getController().getORB()); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("dbaccess"); + } + + m_bTriedOneUpdate = true; + // this means that the original connection may be lost (if m_pConnData was not a newly created but an + // existent conn to be modified), which we reflect by returning RET_NO (see ::Execute) + + // try again + Init(m_pConnData); + m_xTableControl->Init( m_pConnData ); + m_xTableControl->lateInit(); +} + +short ORelationDialog::run() +{ + short nResult = GenericDialogController::run(); + if ((nResult != RET_OK) && m_bTriedOneUpdate) + return RET_NO; + + return nResult; +} + +void ORelationDialog::setValid(bool _bValid) +{ + m_xPB_OK->set_sensitive(_bValid); +} + +void ORelationDialog::notifyConnectionChange() +{ + Init(m_pConnData); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/TablesSingleDlg.cxx b/dbaccess/source/ui/dlg/TablesSingleDlg.cxx new file mode 100644 index 000000000..52babf2b1 --- /dev/null +++ b/dbaccess/source/ui/dlg/TablesSingleDlg.cxx @@ -0,0 +1,110 @@ +/* -*- 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 <TablesSingleDlg.hxx> +#include "DbAdminImpl.hxx" +#include "tablespage.hxx" + +namespace dbaui +{ +using namespace com::sun::star::uno; +using namespace com::sun::star::sdbc; +using namespace com::sun::star::lang; +using namespace com::sun::star::beans; +using namespace com::sun::star::container; + + // OTableSubscriptionDialog +OTableSubscriptionDialog::OTableSubscriptionDialog(weld::Window* pParent + ,const SfxItemSet* _pItems + ,const Reference< XComponentContext >& _rxORB + ,const css::uno::Any& _aDataSourceName) + : SfxSingleTabDialogController(pParent, _pItems, + "dbaccess/ui/tablesfilterdialog.ui", "TablesFilterDialog") + , m_pImpl(new ODbDataSourceAdministrationHelper(_rxORB, m_xDialog.get(), pParent, this)) + , m_bStopExecution(false) +{ + m_pImpl->setDataSourceOrName(_aDataSourceName); + Reference< XPropertySet > xDatasource = m_pImpl->getCurrentDataSource(); + m_pOutSet.reset(new SfxItemSet( *_pItems )); + + m_pImpl->translateProperties(xDatasource, *m_pOutSet); + SetInputSet(m_pOutSet.get()); + + auto xTabPage = std::make_unique<OTableSubscriptionPage>(get_content_area(), this, *m_pOutSet); + xTabPage->SetServiceFactory(_rxORB); + SetTabPage(std::move(xTabPage)); +} + +OTableSubscriptionDialog::~OTableSubscriptionDialog() +{ +} + +short OTableSubscriptionDialog::run() +{ + short nRet = RET_CANCEL; + if ( !m_bStopExecution ) + { + nRet = SfxSingleTabDialogController::run(); + if ( nRet == RET_OK ) + { + m_pOutSet->Put(*GetOutputItemSet()); + m_pImpl->saveChanges(*m_pOutSet); + } + } + return nRet; +} + +bool OTableSubscriptionDialog::getCurrentSettings(Sequence< PropertyValue >& _rDriverParams) +{ + return m_pImpl->getCurrentSettings(_rDriverParams); +} + +void OTableSubscriptionDialog::successfullyConnected() +{ + m_pImpl->successfullyConnected(); +} + +void OTableSubscriptionDialog::clearPassword() +{ + m_pImpl->clearPassword(); +} + +OUString OTableSubscriptionDialog::getConnectionURL() const +{ + return m_pImpl->getConnectionURL(); +} + +Reference< XPropertySet > const & OTableSubscriptionDialog::getCurrentDataSource() +{ + return m_pImpl->getCurrentDataSource(); +} + +const SfxItemSet* OTableSubscriptionDialog::getOutputSet() const +{ + return m_pOutSet.get(); +} + +SfxItemSet* OTableSubscriptionDialog::getWriteOutputSet() +{ + return m_pOutSet.get(); +} + +} // namespace dbaui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/TextConnectionHelper.cxx b/dbaccess/source/ui/dlg/TextConnectionHelper.cxx new file mode 100644 index 000000000..bacc0f7cb --- /dev/null +++ b/dbaccess/source/ui/dlg/TextConnectionHelper.cxx @@ -0,0 +1,391 @@ +/* -*- 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 <core_resource.hxx> +#include "TextConnectionHelper.hxx" +#include <strings.hrc> +#include <strings.hxx> +#include <svl/itemset.hxx> +#include <svl/stritem.hxx> +#include <svl/eitem.hxx> +#include <dsitems.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> +#include <vcl/mnemonic.hxx> + +namespace +{ + +OUString lcl_getListEntry(const OUString& rStr, sal_Int32& rIdx) +{ + const OUString sTkn {rStr.getToken( 0, '\t', rIdx )}; + if (rIdx>=0) + { + rIdx = rStr.indexOf('\t', rIdx); + if (rIdx>=0 && ++rIdx>=rStr.getLength()) + rIdx = -1; + } + return sTkn; +} + +} + +namespace dbaui +{ + + OTextConnectionHelper::OTextConnectionHelper(weld::Widget* pParent, const short _nAvailableSections) + : m_aFieldSeparatorList (DBA_RES(STR_AUTOFIELDSEPARATORLIST)) + , m_aTextSeparatorList (STR_AUTOTEXTSEPARATORLIST) + , m_aTextNone (DBA_RES(STR_AUTOTEXT_FIELD_SEP_NONE)) + , m_nAvailableSections( _nAvailableSections ) + , m_xBuilder(Application::CreateBuilder(pParent, "dbaccess/ui/textpage.ui")) + , m_xContainer(m_xBuilder->weld_widget("TextPage")) + , m_xExtensionHeader(m_xBuilder->weld_widget("extensionframe")) + , m_xAccessTextFiles(m_xBuilder->weld_radio_button("textfile")) + , m_xAccessCSVFiles(m_xBuilder->weld_radio_button("csvfile")) + , m_xAccessOtherFiles(m_xBuilder->weld_radio_button("custom")) + , m_xOwnExtension(m_xBuilder->weld_entry("extension")) + , m_xExtensionExample(m_xBuilder->weld_label("example")) + , m_xFormatHeader(m_xBuilder->weld_widget("formatframe")) + , m_xFieldSeparatorLabel(m_xBuilder->weld_label("fieldlabel")) + , m_xFieldSeparator(m_xBuilder->weld_combo_box("fieldseparator")) + , m_xTextSeparatorLabel(m_xBuilder->weld_label("textlabel")) + , m_xTextSeparator(m_xBuilder->weld_combo_box("textseparator")) + , m_xDecimalSeparatorLabel(m_xBuilder->weld_label("decimallabel")) + , m_xDecimalSeparator(m_xBuilder->weld_combo_box("decimalseparator")) + , m_xThousandsSeparatorLabel(m_xBuilder->weld_label("thousandslabel")) + , m_xThousandsSeparator(m_xBuilder->weld_combo_box("thousandsseparator")) + , m_xRowHeader(m_xBuilder->weld_check_button("containsheaders")) + , m_xCharSetHeader(m_xBuilder->weld_widget("charsetframe")) + , m_xCharSetLabel(m_xBuilder->weld_label("charsetlabel")) + , m_xCharSet(new CharSetListBox(m_xBuilder->weld_combo_box("charset"))) + { + for(sal_Int32 nIdx {0}; nIdx>=0;) + m_xFieldSeparator->append_text( lcl_getListEntry(m_aFieldSeparatorList, nIdx) ); + + for(sal_Int32 nIdx {0}; nIdx>=0;) + m_xTextSeparator->append_text( lcl_getListEntry(m_aTextSeparatorList, nIdx) ); + m_xTextSeparator->append_text(m_aTextNone); + + m_xOwnExtension->connect_changed(LINK(this, OTextConnectionHelper, OnEditModified)); + m_xAccessTextFiles->connect_toggled(LINK(this, OTextConnectionHelper, OnSetExtensionHdl)); + m_xAccessCSVFiles->connect_toggled(LINK(this, OTextConnectionHelper, OnSetExtensionHdl)); + m_xAccessOtherFiles->connect_toggled(LINK(this, OTextConnectionHelper, OnSetExtensionHdl)); + m_xAccessCSVFiles->set_active(true); + + struct SectionDescriptor + { + short nFlag; + weld::Widget* pFrame; + } aSections[] = { + { TC_EXTENSION, m_xExtensionHeader.get() }, + { TC_SEPARATORS, m_xFormatHeader.get() }, + { TC_HEADER, m_xRowHeader.get() }, + { TC_CHARSET, m_xCharSetHeader.get() }, + { 0, nullptr } + }; + + for ( size_t section=0; section < SAL_N_ELEMENTS( aSections ) - 1; ++section ) + { + if ( ( m_nAvailableSections & aSections[section].nFlag ) != 0 ) + { + // the section is visible, no need to do anything here + continue; + } + + // hide all elements from this section + aSections[section].pFrame->hide(); + } + + m_xContainer->show(); + } + + IMPL_LINK_NOARG(OTextConnectionHelper, OnEditModified, weld::Entry&, void) + { + m_aGetExtensionHandler.Call(this); + } + + IMPL_LINK_NOARG(OTextConnectionHelper, OnSetExtensionHdl, weld::ToggleButton&, void) + { + bool bDoEnable = m_xAccessOtherFiles->get_active(); + m_xOwnExtension->set_sensitive(bDoEnable); + m_xExtensionExample->set_sensitive(bDoEnable); + m_aGetExtensionHandler.Call(this); + } + + void OTextConnectionHelper::fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) + { + _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::ComboBox>(m_xFieldSeparator.get())); + _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::ComboBox>(m_xTextSeparator.get())); + _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::ComboBox>(m_xDecimalSeparator.get())); + _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::ComboBox>(m_xThousandsSeparator.get())); + _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::ToggleButton>(m_xRowHeader.get())); + _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::ComboBox>(m_xCharSet->get_widget())); + } + + void OTextConnectionHelper::fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) + { + _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFieldSeparatorLabel.get())); + _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xTextSeparatorLabel.get())); + _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xDecimalSeparatorLabel.get())); + _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xThousandsSeparatorLabel.get())); + _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Widget>(m_xCharSetHeader.get())); + _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xCharSetLabel.get())); + _rControlList.emplace_back(new ODisableWidgetWrapper<weld::ComboBox>(m_xCharSet->get_widget())); + } + + void OTextConnectionHelper::implInitControls(const SfxItemSet& _rSet, bool _bValid) + { + if ( !_bValid ) + return; + + const SfxStringItem* pDelItem = _rSet.GetItem<SfxStringItem>(DSID_FIELDDELIMITER); + const SfxStringItem* pStrItem = _rSet.GetItem<SfxStringItem>(DSID_TEXTDELIMITER); + const SfxStringItem* pDecdelItem = _rSet.GetItem<SfxStringItem>(DSID_DECIMALDELIMITER); + const SfxStringItem* pThodelItem = _rSet.GetItem<SfxStringItem>(DSID_THOUSANDSDELIMITER); + const SfxStringItem* pExtensionItem = _rSet.GetItem<SfxStringItem>(DSID_TEXTFILEEXTENSION); + const SfxStringItem* pCharsetItem = _rSet.GetItem<SfxStringItem>(DSID_CHARSET); + + if ( ( m_nAvailableSections & TC_EXTENSION ) != 0 ) + { + m_aOldExtension = pExtensionItem->GetValue(); + SetExtension( m_aOldExtension ); + } + + if ( ( m_nAvailableSections & TC_HEADER ) != 0 ) + { + const SfxBoolItem* pHdrItem = _rSet.GetItem<SfxBoolItem>(DSID_TEXTFILEHEADER); + m_xRowHeader->set_active(pHdrItem->GetValue()); + } + + if ( ( m_nAvailableSections & TC_SEPARATORS ) != 0 ) + { + SetSeparator(*m_xFieldSeparator, m_aFieldSeparatorList, pDelItem->GetValue()); + SetSeparator(*m_xTextSeparator, m_aTextSeparatorList, pStrItem->GetValue()); + m_xDecimalSeparator->set_entry_text( pDecdelItem->GetValue() ); + m_xThousandsSeparator->set_entry_text( pThodelItem->GetValue() ); + } + + if ( ( m_nAvailableSections & TC_CHARSET ) != 0 ) + { + m_xCharSet->SelectEntryByIanaName( pCharsetItem->GetValue() ); + } + } + + bool OTextConnectionHelper::prepareLeave() + { + OUString sExtension = GetExtension(); + OUString aErrorText; + weld::Widget* pErrorWin = nullptr; + OUString aDelText(m_xFieldSeparator->get_active_text()); + if(aDelText.isEmpty()) + { // No FieldSeparator + aErrorText = DBA_RES(STR_AUTODELIMITER_MISSING); + aErrorText = aErrorText.replaceFirst("#1",m_xFieldSeparatorLabel->get_label()); + pErrorWin = m_xFieldSeparator.get(); + } + else if (m_xDecimalSeparator->get_active_text().isEmpty()) + { // No DecimalSeparator + aErrorText = DBA_RES(STR_AUTODELIMITER_MISSING); + aErrorText = aErrorText.replaceFirst("#1",m_xDecimalSeparatorLabel->get_label()); + pErrorWin = m_xDecimalSeparator.get(); + } + else if (m_xTextSeparator->get_active_text() == m_xFieldSeparator->get_active_text()) + { // Field and TextSeparator must not be the same + aErrorText = DBA_RES(STR_AUTODELIMITER_MUST_DIFFER); + aErrorText = aErrorText.replaceFirst("#1",m_xTextSeparatorLabel->get_label()); + aErrorText = aErrorText.replaceFirst("#2",m_xFieldSeparatorLabel->get_label()); + pErrorWin = m_xTextSeparator.get(); + } + else if (m_xDecimalSeparator->get_active_text() == m_xThousandsSeparator->get_active_text()) + { // Thousands and DecimalSeparator must not be the same + aErrorText = DBA_RES(STR_AUTODELIMITER_MUST_DIFFER); + aErrorText = aErrorText.replaceFirst("#1",m_xDecimalSeparatorLabel->get_label()); + aErrorText = aErrorText.replaceFirst("#2",m_xThousandsSeparatorLabel->get_label()); + pErrorWin = m_xDecimalSeparator.get(); + } + else if (m_xFieldSeparator->get_active_text() == m_xThousandsSeparator->get_active_text()) + { // Thousands and FieldSeparator must not be the same + aErrorText = DBA_RES(STR_AUTODELIMITER_MUST_DIFFER); + aErrorText = aErrorText.replaceFirst("#1",m_xFieldSeparatorLabel->get_label()); + aErrorText = aErrorText.replaceFirst("#2",m_xThousandsSeparatorLabel->get_label()); + pErrorWin = m_xFieldSeparator.get(); + } + else if (m_xFieldSeparator->get_active_text() == m_xDecimalSeparator->get_active_text()) + { // Tenner and FieldSeparator must not be the same + aErrorText = DBA_RES(STR_AUTODELIMITER_MUST_DIFFER); + aErrorText = aErrorText.replaceFirst("#1",m_xFieldSeparatorLabel->get_label()); + aErrorText = aErrorText.replaceFirst("#2",m_xDecimalSeparatorLabel->get_label()); + pErrorWin = m_xFieldSeparator.get(); + } + else if (m_xTextSeparator->get_active_text() == m_xThousandsSeparator->get_active_text()) + { // Thousands and TextSeparator must not be the same + aErrorText = DBA_RES(STR_AUTODELIMITER_MUST_DIFFER); + aErrorText = aErrorText.replaceFirst("#1",m_xTextSeparatorLabel->get_label()); + aErrorText = aErrorText.replaceFirst("#2",m_xThousandsSeparatorLabel->get_label()); + pErrorWin = m_xTextSeparator.get(); + } + else if (m_xTextSeparator->get_active_text() == m_xDecimalSeparator->get_active_text()) + { // Tenner and TextSeparator must not be the same + aErrorText = DBA_RES(STR_AUTODELIMITER_MUST_DIFFER); + aErrorText = aErrorText.replaceFirst("#1",m_xTextSeparatorLabel->get_label()); + aErrorText = aErrorText.replaceFirst("#2",m_xDecimalSeparatorLabel->get_label()); + pErrorWin = m_xTextSeparator.get(); + } + else if ((sExtension.indexOf('*') != -1) || (sExtension.indexOf('?') != -1)) + { + aErrorText = DBA_RES(STR_AUTONO_WILDCARDS); + aErrorText = aErrorText.replaceFirst("#1",sExtension); + pErrorWin = m_xOwnExtension.get(); + } + else + return true; + std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xContainer.get(), + VclMessageType::Warning, VclButtonsType::Ok, + MnemonicGenerator::EraseAllMnemonicChars(aErrorText))); + xBox->run(); + pErrorWin->grab_focus(); + return false; + } + + bool OTextConnectionHelper::FillItemSet( SfxItemSet& rSet, const bool _bChangedSomething ) + { + bool bChangedSomething = _bChangedSomething; + + if ( ( m_nAvailableSections & TC_EXTENSION ) != 0 ) + { + OUString sExtension = GetExtension(); + if( m_aOldExtension != sExtension ) + { + rSet.Put( SfxStringItem( DSID_TEXTFILEEXTENSION, sExtension ) ); + bChangedSomething = true; + } + } + + if ( ( m_nAvailableSections & TC_HEADER ) != 0 ) + { + if (m_xRowHeader->get_state_changed_from_saved()) + { + rSet.Put(SfxBoolItem(DSID_TEXTFILEHEADER, m_xRowHeader->get_active())); + bChangedSomething = true; + } + } + + if ( ( m_nAvailableSections & TC_SEPARATORS ) != 0 ) + { + if (m_xFieldSeparator->get_value_changed_from_saved()) + { + rSet.Put( SfxStringItem(DSID_FIELDDELIMITER, GetSeparator( *m_xFieldSeparator, m_aFieldSeparatorList) ) ); + bChangedSomething = true; + } + if (m_xTextSeparator->get_value_changed_from_saved()) + { + rSet.Put( SfxStringItem(DSID_TEXTDELIMITER, GetSeparator( *m_xTextSeparator, m_aTextSeparatorList) ) ); + bChangedSomething = true; + } + + if (m_xDecimalSeparator->get_value_changed_from_saved()) + { + rSet.Put( SfxStringItem(DSID_DECIMALDELIMITER, m_xDecimalSeparator->get_active_text().copy(0, 1) ) ); + bChangedSomething = true; + } + if (m_xThousandsSeparator->get_value_changed_from_saved()) + { + rSet.Put( SfxStringItem(DSID_THOUSANDSDELIMITER, m_xThousandsSeparator->get_active_text().copy(0,1) ) ); + bChangedSomething = true; + } + } + + if ( ( m_nAvailableSections & TC_CHARSET ) != 0 ) + { + if ( m_xCharSet->StoreSelectedCharSet( rSet, DSID_CHARSET ) ) + bChangedSomething = true; + } + + return bChangedSomething; + } + + void OTextConnectionHelper::SetExtension(const OUString& _rVal) + { + if (_rVal == "txt") + m_xAccessTextFiles->set_active(true); + else if (_rVal == "csv") + m_xAccessCSVFiles->set_active(true); + else + { + m_xAccessOtherFiles->set_active(true); + m_xExtensionExample->set_label(_rVal); + } + } + + OUString OTextConnectionHelper::GetExtension() const + { + OUString sExtension; + if (m_xAccessTextFiles->get_active()) + sExtension = "txt"; + else if (m_xAccessCSVFiles->get_active()) + sExtension = "csv"; + else + { + sExtension = m_xOwnExtension->get_text(); + if ( sExtension.startsWith("*.") ) + sExtension = sExtension.copy(2); + } + return sExtension; + } + + OUString OTextConnectionHelper::GetSeparator(const weld::ComboBox& rBox, const OUString& rList) + { + sal_Unicode const nTok = '\t'; + int nPos(rBox.find_text(rBox.get_active_text())); + + if (nPos == -1) + return rBox.get_active_text().copy(0); + + if ( !( m_xTextSeparator.get() == &rBox && nPos == (rBox.get_count()-1) ) ) + return OUString( + static_cast< sal_Unicode >( rList.getToken((nPos*2)+1, nTok ).toInt32() )); + // somewhat strange ... translates for instance an "32" into " " + return OUString(); + } + + void OTextConnectionHelper::SetSeparator( weld::ComboBox& rBox, const OUString& rList, const OUString& rVal ) + { + if (rVal.getLength()==1) + { + const sal_Unicode nVal {rVal[0]}; + for(sal_Int32 nIdx {0}; nIdx>=0;) + { + sal_Int32 nPrevIdx {nIdx}; + if (static_cast<sal_Unicode>(rList.getToken(1, '\t', nIdx).toInt32()) == nVal) + { + rBox.set_entry_text(rList.getToken(0, '\t', nPrevIdx)); + return; + } + } + rBox.set_entry_text( rVal ); + } + else if ( m_xTextSeparator.get() == &rBox && rVal.isEmpty() ) + rBox.set_entry_text(m_aTextNone); + else + rBox.set_entry_text(rVal.copy(0, 1)); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/TextConnectionHelper.hxx b/dbaccess/source/ui/dlg/TextConnectionHelper.hxx new file mode 100644 index 000000000..e002c77e8 --- /dev/null +++ b/dbaccess/source/ui/dlg/TextConnectionHelper.hxx @@ -0,0 +1,92 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_DBACCESS_SOURCE_UI_DLG_TEXTCONNECTIONHELPER_HXX +#define INCLUDED_DBACCESS_SOURCE_UI_DLG_TEXTCONNECTIONHELPER_HXX + +#include "adminpages.hxx" +#include <charsetlistbox.hxx> +#include <rtl/ustring.hxx> + +namespace dbaui + +{ + + #define TC_EXTENSION (short(0x01)) // a section specifying the extension of the files to connect to + #define TC_SEPARATORS (short(0x02)) // a section specifying the various separators + #define TC_HEADER (short(0x04)) // a section containing the "Text contains header" check box only + #define TC_CHARSET (short(0x08)) // not yet implemented + + class OTextConnectionHelper final + { + public: + OTextConnectionHelper(weld::Widget* pParent , const short _nAvailableSections); + + private: + OUString m_aFieldSeparatorList; + OUString m_aTextSeparatorList; + OUString m_aTextNone; + OUString m_aOldExtension; + Link<OTextConnectionHelper*, void> m_aGetExtensionHandler; /// to be called if a new type is selected + + short m_nAvailableSections; + + std::unique_ptr<weld::Builder> m_xBuilder; + std::unique_ptr<weld::Widget> m_xContainer; + std::unique_ptr<weld::Widget> m_xExtensionHeader; + std::unique_ptr<weld::RadioButton> m_xAccessTextFiles; + std::unique_ptr<weld::RadioButton> m_xAccessCSVFiles; + std::unique_ptr<weld::RadioButton> m_xAccessOtherFiles; + std::unique_ptr<weld::Entry> m_xOwnExtension; + std::unique_ptr<weld::Label> m_xExtensionExample; + std::unique_ptr<weld::Widget> m_xFormatHeader; + std::unique_ptr<weld::Label> m_xFieldSeparatorLabel; + std::unique_ptr<weld::ComboBox> m_xFieldSeparator; + std::unique_ptr<weld::Label> m_xTextSeparatorLabel; + std::unique_ptr<weld::ComboBox> m_xTextSeparator; + std::unique_ptr<weld::Label> m_xDecimalSeparatorLabel; + std::unique_ptr<weld::ComboBox> m_xDecimalSeparator; + std::unique_ptr<weld::Label> m_xThousandsSeparatorLabel; + std::unique_ptr<weld::ComboBox> m_xThousandsSeparator; + std::unique_ptr<weld::CheckButton> m_xRowHeader; + std::unique_ptr<weld::Widget> m_xCharSetHeader; + std::unique_ptr<weld::Label> m_xCharSetLabel; + std::unique_ptr<CharSetListBox> m_xCharSet; + + DECL_LINK(OnSetExtensionHdl, weld::ToggleButton&, void); + DECL_LINK(OnEditModified, weld::Entry&, void); + + OUString GetSeparator(const weld::ComboBox& rBox, const OUString& rList); + void SetSeparator(weld::ComboBox& rBox, const OUString& rList, const OUString& rVal); + void SetExtension(const OUString& _rVal); + + public: + void implInitControls(const SfxItemSet& _rSet, bool _bValid); + void fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList); + void fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList); + void SetClickHandler(const Link<OTextConnectionHelper*, void>& _rHandler) { m_aGetExtensionHandler = _rHandler; } + OUString GetExtension() const; + bool FillItemSet( SfxItemSet& rSet, const bool bChangedSomething ); + bool prepareLeave(); + }; +} // namespace dbaui + +#endif // INCLUDED_DBACCESS_SOURCE_UI_DLG_TEXTCONNECTIONHELPER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/UserAdmin.cxx b/dbaccess/source/ui/dlg/UserAdmin.cxx new file mode 100644 index 000000000..3e63f9424 --- /dev/null +++ b/dbaccess/source/ui/dlg/UserAdmin.cxx @@ -0,0 +1,318 @@ +/* -*- 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 "UserAdmin.hxx" +#include <com/sun/star/sdbc/SQLException.hpp> +#include <com/sun/star/sdbc/XDatabaseMetaData.hpp> +#include <com/sun/star/sdbc/XDriver.hpp> +#include <com/sun/star/sdbcx/XDataDefinitionSupplier.hpp> +#include <com/sun/star/sdbcx/XUsersSupplier.hpp> +#include <com/sun/star/sdbcx/XDrop.hpp> +#include <ucbhelper/interactionrequest.hxx> +#include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/sdbcx/XUser.hpp> +#include <com/sun/star/sdbcx/XAppend.hpp> +#include <IItemSetHelper.hxx> +#include <strings.hrc> +#include <strings.hxx> +#include <core_resource.hxx> +#include <connectivity/dbexception.hxx> +#include <connectivity/dbtools.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> +#include <sfx2/passwd.hxx> + +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::task; +using namespace dbaui; +using namespace ucbhelper; +using namespace comphelper; + +namespace { + +class OPasswordDialog : public weld::GenericDialogController +{ + std::unique_ptr<weld::Frame> m_xUser; + std::unique_ptr<weld::Entry> m_xEDOldPassword; + std::unique_ptr<weld::Entry> m_xEDPassword; + std::unique_ptr<weld::Entry> m_xEDPasswordRepeat; + std::unique_ptr<weld::Button> m_xOKBtn; + + DECL_LINK(OKHdl_Impl, weld::Button&, void); + DECL_LINK(ModifiedHdl, weld::Entry&, void); + +public: + OPasswordDialog(weld::Window* pParent,const OUString& rUserName); + + OUString GetOldPassword() const { return m_xEDOldPassword->get_text(); } + OUString GetNewPassword() const { return m_xEDPassword->get_text(); } +}; + +} + +OPasswordDialog::OPasswordDialog(weld::Window* _pParent,const OUString& rUserName) + : GenericDialogController(_pParent, "dbaccess/ui/password.ui", "PasswordDialog") + , m_xUser(m_xBuilder->weld_frame("userframe")) + , m_xEDOldPassword(m_xBuilder->weld_entry("oldpassword")) + , m_xEDPassword(m_xBuilder->weld_entry("newpassword")) + , m_xEDPasswordRepeat(m_xBuilder->weld_entry("confirmpassword")) + , m_xOKBtn(m_xBuilder->weld_button("ok")) +{ + OUString sUser = m_xUser->get_label(); + sUser = sUser.replaceFirst("$name$: $", rUserName); + m_xUser->set_label(sUser); + m_xOKBtn->set_sensitive(false); + + m_xOKBtn->connect_clicked( LINK( this, OPasswordDialog, OKHdl_Impl ) ); + m_xEDOldPassword->connect_changed( LINK( this, OPasswordDialog, ModifiedHdl ) ); +} + +IMPL_LINK_NOARG(OPasswordDialog, OKHdl_Impl, weld::Button&, void) +{ + if (m_xEDPassword->get_text() == m_xEDPasswordRepeat->get_text()) + m_xDialog->response(RET_OK); + else + { + OUString aErrorMsg( DBA_RES( STR_ERROR_PASSWORDS_NOT_IDENTICAL)); + std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Warning, VclButtonsType::Ok, + aErrorMsg)); + xErrorBox->run(); + m_xEDPassword->set_text(OUString()); + m_xEDPasswordRepeat->set_text(OUString()); + m_xEDPassword->grab_focus(); + } +} + +IMPL_LINK(OPasswordDialog, ModifiedHdl, weld::Entry&, rEdit, void) +{ + m_xOKBtn->set_sensitive(!rEdit.get_text().isEmpty()); +} + +// OUserAdmin +OUserAdmin::OUserAdmin(weld::Container* pPage, weld::DialogController* pController,const SfxItemSet& _rAttrSet) + : OGenericAdministrationPage(pPage, pController, "dbaccess/ui/useradminpage.ui", "UserAdminPage", _rAttrSet) + , m_xUSER(m_xBuilder->weld_combo_box("user")) + , m_xNEWUSER(m_xBuilder->weld_button("add")) + , m_xCHANGEPWD(m_xBuilder->weld_button("changepass")) + , m_xDELETEUSER(m_xBuilder->weld_button("delete")) + , m_xTable(m_xBuilder->weld_container("table")) + , m_xTableCtrlParent(m_xTable->CreateChildFrame()) + , m_xTableCtrl(VclPtr<OTableGrantControl>::Create(m_xTableCtrlParent)) +{ + m_xTableCtrl->Show(); + + m_xUSER->connect_changed(LINK(this, OUserAdmin, ListDblClickHdl)); + m_xNEWUSER->connect_clicked(LINK(this, OUserAdmin, UserHdl)); + m_xCHANGEPWD->connect_clicked(LINK(this, OUserAdmin, UserHdl)); + m_xDELETEUSER->connect_clicked(LINK(this, OUserAdmin, UserHdl)); +} + +OUserAdmin::~OUserAdmin() +{ + m_xConnection = nullptr; + m_xTableCtrl.disposeAndClear(); + m_xTableCtrlParent->dispose(); + m_xTableCtrlParent.clear(); +} + +void OUserAdmin::FillUserNames() +{ + if(m_xConnection.is()) + { + m_xUSER->clear(); + + Reference<XDatabaseMetaData> xMetaData = m_xConnection->getMetaData(); + + if ( xMetaData.is() ) + { + m_UserName = xMetaData->getUserName(); + + // first we need the users + if ( m_xUsers.is() ) + { + m_xUSER->clear(); + + m_aUserNames = m_xUsers->getElementNames(); + const OUString* pBegin = m_aUserNames.getConstArray(); + const OUString* pEnd = pBegin + m_aUserNames.getLength(); + for(;pBegin != pEnd;++pBegin) + m_xUSER->append_text(*pBegin); + + m_xUSER->set_active(0); + if(m_xUsers->hasByName(m_UserName)) + { + Reference<XAuthorizable> xAuth; + m_xUsers->getByName(m_UserName) >>= xAuth; + m_xTableCtrl->setGrantUser(xAuth); + } + + m_xTableCtrl->setUserName(GetUser()); + m_xTableCtrl->Init(); + } + } + } + + Reference<XAppend> xAppend(m_xUsers,UNO_QUERY); + m_xNEWUSER->set_sensitive(xAppend.is()); + Reference<XDrop> xDrop(m_xUsers,UNO_QUERY); + m_xDELETEUSER->set_sensitive(xDrop.is()); + + m_xCHANGEPWD->set_sensitive(m_xUsers.is()); + m_xTableCtrl->Enable(m_xUsers.is()); +} + +std::unique_ptr<SfxTabPage> OUserAdmin::Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet ) +{ + return std::make_unique<OUserAdmin>( pPage, pController, *_rAttrSet ); +} + +IMPL_LINK(OUserAdmin, UserHdl, weld::Button&, rButton, void) +{ + try + { + if (&rButton == m_xNEWUSER.get()) + { + SfxPasswordDialog aPwdDlg(GetFrameWeld()); + aPwdDlg.ShowExtras(SfxShowExtras::ALL); + if (aPwdDlg.run()) + { + Reference<XDataDescriptorFactory> xUserFactory(m_xUsers,UNO_QUERY); + Reference<XPropertySet> xNewUser = xUserFactory->createDataDescriptor(); + if(xNewUser.is()) + { + xNewUser->setPropertyValue(PROPERTY_NAME,makeAny(aPwdDlg.GetUser())); + xNewUser->setPropertyValue(PROPERTY_PASSWORD,makeAny(aPwdDlg.GetPassword())); + Reference<XAppend> xAppend(m_xUsers,UNO_QUERY); + if(xAppend.is()) + xAppend->appendByDescriptor(xNewUser); + } + } + } + else if (&rButton == m_xCHANGEPWD.get()) + { + OUString sName = GetUser(); + + if(m_xUsers->hasByName(sName)) + { + Reference<XUser> xUser; + m_xUsers->getByName(sName) >>= xUser; + if(xUser.is()) + { + OUString sNewPassword,sOldPassword; + OPasswordDialog aDlg(GetFrameWeld(), sName); + if (aDlg.run() == RET_OK) + { + sNewPassword = aDlg.GetNewPassword(); + sOldPassword = aDlg.GetOldPassword(); + + if(!sNewPassword.isEmpty()) + xUser->changePassword(sOldPassword,sNewPassword); + } + } + } + } + else + {// delete user + if(m_xUsers.is() && m_xUsers->hasByName(GetUser())) + { + Reference<XDrop> xDrop(m_xUsers,UNO_QUERY); + if(xDrop.is()) + { + std::unique_ptr<weld::MessageDialog> xQry(Application::CreateMessageDialog(GetFrameWeld(), + VclMessageType::Question, VclButtonsType::YesNo, + DBA_RES(STR_QUERY_USERADMIN_DELETE_USER))); + if (xQry->run() == RET_YES) + xDrop->dropByName(GetUser()); + } + } + } + FillUserNames(); + } + catch(const SQLException& e) + { + ::dbtools::showError(::dbtools::SQLExceptionInfo(e), GetDialogController()->getDialog()->GetXWindow(), m_xORB); + } + catch(Exception& ) + { + } +} + +IMPL_LINK_NOARG(OUserAdmin, ListDblClickHdl, weld::ComboBox&, void) +{ + m_xTableCtrl->setUserName(GetUser()); + m_xTableCtrl->UpdateTables(); + m_xTableCtrl->DeactivateCell(); + m_xTableCtrl->ActivateCell(m_xTableCtrl->GetCurRow(),m_xTableCtrl->GetCurColumnId()); +} + +OUString OUserAdmin::GetUser() const +{ + return m_xUSER->get_active_text(); +} + +void OUserAdmin::fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& /*_rControlList*/) +{ +} + +void OUserAdmin::fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& /*_rControlList*/) +{ +} + +void OUserAdmin::implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) +{ + m_xTableCtrl->setComponentContext(m_xORB); + try + { + if ( !m_xConnection.is() && m_pAdminDialog ) + { + m_xConnection = m_pAdminDialog->createConnection().first; + Reference< XTablesSupplier > xTablesSup(m_xConnection,UNO_QUERY); + Reference<XUsersSupplier> xUsersSup(xTablesSup,UNO_QUERY); + if ( !xUsersSup.is() ) + { + Reference< XDataDefinitionSupplier > xDriver(m_pAdminDialog->getDriver(),UNO_QUERY); + if ( xDriver.is() ) + { + xUsersSup.set(xDriver->getDataDefinitionByConnection(m_xConnection),UNO_QUERY); + xTablesSup.set(xUsersSup,UNO_QUERY); + } + } + if ( xUsersSup.is() ) + { + m_xTableCtrl->setTablesSupplier(xTablesSup); + m_xUsers = xUsersSup->getUsers(); + } + } + FillUserNames(); + } + catch(const SQLException& e) + { + ::dbtools::showError(::dbtools::SQLExceptionInfo(e), GetDialogController()->getDialog()->GetXWindow(), m_xORB); + } + + OGenericAdministrationPage::implInitControls(_rSet, _bSaveValue); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/UserAdmin.hxx b/dbaccess/source/ui/dlg/UserAdmin.hxx new file mode 100644 index 000000000..09098e30a --- /dev/null +++ b/dbaccess/source/ui/dlg/UserAdmin.hxx @@ -0,0 +1,76 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_DBACCESS_SOURCE_UI_DLG_USERADMIN_HXX +#define INCLUDED_DBACCESS_SOURCE_UI_DLG_USERADMIN_HXX + +#include <TableGrantCtrl.hxx> +#include "adminpages.hxx" + +namespace com::sun::star { + namespace sdbc { + class XConnection; + } +} + +namespace dbaui +{ + +class OUserAdmin final : public OGenericAdministrationPage +{ + std::unique_ptr<weld::ComboBox> m_xUSER; + std::unique_ptr<weld::Button> m_xNEWUSER; + std::unique_ptr<weld::Button> m_xCHANGEPWD; + std::unique_ptr<weld::Button> m_xDELETEUSER; + std::unique_ptr<weld::Container> m_xTable; + css::uno::Reference<css::awt::XWindow> m_xTableCtrlParent; + VclPtr<OTableGrantControl> m_xTableCtrl; // show the grant rights of one user + + css::uno::Reference< css::sdbc::XConnection> m_xConnection; + css::uno::Reference< css::container::XNameAccess > m_xUsers; + css::uno::Sequence< OUString> m_aUserNames; + + OUString m_UserName; + + // methods + DECL_LINK(ListDblClickHdl, weld::ComboBox&, void); + DECL_LINK(UserHdl, weld::Button&, void); + + void FillUserNames(); + +public: + OUserAdmin(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rCoreAttrs); + static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet); + virtual ~OUserAdmin() override; + + OUString GetUser() const; + + // subclasses must override this, but it isn't pure virtual + virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override; + + // <method>OGenericAdministrationPage::fillControls</method> + virtual void fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override; + + // <method>OGenericAdministrationPage::fillWindows</method> + virtual void fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override; +}; + +} +#endif // INCLUDED_DBACCESS_SOURCE_UI_DLG_USERADMIN_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/UserAdminDlg.cxx b/dbaccess/source/ui/dlg/UserAdminDlg.cxx new file mode 100644 index 000000000..ec44c3399 --- /dev/null +++ b/dbaccess/source/ui/dlg/UserAdminDlg.cxx @@ -0,0 +1,162 @@ +/* -*- 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 <core_resource.hxx> +#include "adminpages.hxx" +#include "DbAdminImpl.hxx" +#include <strings.hrc> +#include "UserAdmin.hxx" +#include <UserAdminDlg.hxx> + +#include <com/sun/star/sdbc/SQLException.hpp> + +#include <connectivity/dbexception.hxx> +#include <connectivity/dbmetadata.hxx> +#include <connectivity/dbtools.hxx> +#include <comphelper/types.hxx> +#include <cppuhelper/exc_hlp.hxx> +#include <tools/diagnose_ex.h> + +namespace dbaui +{ + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::sdbc; + using namespace ::com::sun::star::sdbcx; + + // OUserAdminDlg + OUserAdminDlg::OUserAdminDlg(weld::Window* pParent, + SfxItemSet* pItems, + const Reference< XComponentContext >& rxORB, + const css::uno::Any& rDataSourceName, + const Reference< XConnection >& xConnection) + : SfxTabDialogController(pParent, "dbaccess/ui/useradmindialog.ui", "UserAdminDialog", pItems) + , m_pParent(pParent) + , m_pItemSet(pItems) + , m_xConnection(xConnection) + , m_bOwnConnection(!xConnection.is()) + { + m_pImpl.reset(new ODbDataSourceAdministrationHelper(rxORB, m_xDialog.get(), pParent, this)); + m_pImpl->setDataSourceOrName(rDataSourceName); + Reference< XPropertySet > xDatasource = m_pImpl->getCurrentDataSource(); + m_pImpl->translateProperties(xDatasource, *pItems); + SetInputSet(pItems); + // propagate this set as our new input set and reset the example set + m_xExampleSet.reset(new SfxItemSet(*GetInputSetImpl())); + + AddTabPage("settings", OUserAdmin::Create, nullptr); + + // remove the reset button - it's meaning is much too ambiguous in this dialog + RemoveResetButton(); + } + + OUserAdminDlg::~OUserAdminDlg() + { + if ( m_bOwnConnection ) + { + try + { + ::comphelper::disposeComponent(m_xConnection); + } + catch(const Exception&) + { + } + } + + SetInputSet(nullptr); + } + + short OUserAdminDlg::run() + { + try + { + ::dbtools::DatabaseMetaData aMetaData( createConnection().first ); + if ( !aMetaData.supportsUserAdministration( getORB() ) ) + { + OUString sError(DBA_RES(STR_USERADMIN_NOT_AVAILABLE)); + throw SQLException(sError, nullptr, "S1000", 0, Any()); + } + } + catch(const SQLException&) + { + ::dbtools::showError(::dbtools::SQLExceptionInfo(::cppu::getCaughtException()), m_pParent->GetXWindow(), getORB()); + return RET_CANCEL; + } + catch(const Exception&) + { + DBG_UNHANDLED_EXCEPTION("dbaccess"); + } + short nRet = SfxTabDialogController::run(); + if ( nRet == RET_OK ) + m_pImpl->saveChanges(*GetOutputItemSet()); + return nRet; + } + void OUserAdminDlg::PageCreated(const OString& rId, SfxTabPage& _rPage) + { + // register ourself as modified listener + static_cast<OGenericAdministrationPage&>(_rPage).SetServiceFactory( m_pImpl->getORB() ); + static_cast<OGenericAdministrationPage&>(_rPage).SetAdminDialog(this,this); + SfxTabDialogController::PageCreated(rId, _rPage); + } + const SfxItemSet* OUserAdminDlg::getOutputSet() const + { + return m_pItemSet; + } + SfxItemSet* OUserAdminDlg::getWriteOutputSet() + { + return m_pItemSet; + } + std::pair< Reference<XConnection>,bool> OUserAdminDlg::createConnection() + { + if ( !m_xConnection.is() ) + { + m_xConnection = m_pImpl->createConnection().first; + m_bOwnConnection = m_xConnection.is(); + } + return std::pair< Reference<XConnection>,bool> (m_xConnection,false); + } + Reference< XComponentContext > OUserAdminDlg::getORB() const + { + return m_pImpl->getORB(); + } + Reference< XDriver > OUserAdminDlg::getDriver() + { + return m_pImpl->getDriver(); + } + OUString OUserAdminDlg::getDatasourceType(const SfxItemSet& _rSet) const + { + return dbaui::ODbDataSourceAdministrationHelper::getDatasourceType(_rSet); + } + void OUserAdminDlg::clearPassword() + { + m_pImpl->clearPassword(); + } + void OUserAdminDlg::setTitle(const OUString& _sTitle) + { + m_xDialog->set_title(_sTitle); + } + void OUserAdminDlg::enableConfirmSettings( bool ) {} + void OUserAdminDlg::saveDatasource() + { + PrepareLeaveCurrentPage(); + } +} // namespace dbaui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/admincontrols.cxx b/dbaccess/source/ui/dlg/admincontrols.cxx new file mode 100644 index 000000000..88a3bdc14 --- /dev/null +++ b/dbaccess/source/ui/dlg/admincontrols.cxx @@ -0,0 +1,201 @@ +/* -*- 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 "admincontrols.hxx" +#include <dsitems.hxx> + +#include <svl/eitem.hxx> +#include <svl/stritem.hxx> +#include <svl/intitem.hxx> +#include <vcl/svapp.hxx> + +namespace dbaui +{ + + // MySQLNativeSettings + MySQLNativeSettings::MySQLNativeSettings(weld::Widget* pParent, const Link<weld::Widget*,void>& rControlModificationLink) + : m_xBuilder(Application::CreateBuilder(pParent, "dbaccess/ui/mysqlnativesettings.ui")) + , m_xContainer(m_xBuilder->weld_widget("MysqlNativeSettings")) + , m_xDatabaseNameLabel(m_xBuilder->weld_label("dbnamelabel")) + , m_xDatabaseName(m_xBuilder->weld_entry("dbname")) + , m_xHostPortRadio(m_xBuilder->weld_radio_button("hostport")) + , m_xSocketRadio(m_xBuilder->weld_radio_button("socketlabel")) + , m_xNamedPipeRadio(m_xBuilder->weld_radio_button("namedpipelabel")) + , m_xHostNameLabel(m_xBuilder->weld_label("serverlabel")) + , m_xHostName(m_xBuilder->weld_entry("server")) + , m_xPortLabel(m_xBuilder->weld_label("portlabel")) + , m_xPort(m_xBuilder->weld_spin_button("port")) + , m_xDefaultPort(m_xBuilder->weld_label("defaultport")) + , m_xSocket(m_xBuilder->weld_entry("socket")) + , m_xNamedPipe(m_xBuilder->weld_entry("namedpipe")) + , m_aControlModificationLink(rControlModificationLink) + { + m_xDatabaseName->connect_changed( LINK(this, MySQLNativeSettings, EditModifyHdl) ); + m_xHostName->connect_changed( LINK(this, MySQLNativeSettings, EditModifyHdl) ); + m_xPort->connect_value_changed( LINK(this, MySQLNativeSettings, SpinModifyHdl) ); + m_xSocket->connect_changed( LINK(this, MySQLNativeSettings, EditModifyHdl) ); + m_xNamedPipe->connect_changed( LINK(this, MySQLNativeSettings, EditModifyHdl) ); + m_xSocketRadio->connect_toggled( LINK(this, MySQLNativeSettings, RadioToggleHdl) ); + m_xNamedPipeRadio->connect_toggled( LINK(this, MySQLNativeSettings, RadioToggleHdl) ); + m_xHostPortRadio->connect_toggled( LINK(this, MySQLNativeSettings, RadioToggleHdl) ); + + // sockets are available on Unix systems only, named pipes only on Windows +#ifdef UNX + m_xNamedPipeRadio->hide(); + m_xNamedPipe->hide(); +#else + m_xSocketRadio->hide(); + m_xSocket->hide(); +#endif + m_xContainer->show(); + } + + IMPL_LINK(MySQLNativeSettings, RadioToggleHdl, weld::ToggleButton&, rRadioButton, void) + { + m_aControlModificationLink.Call(&rRadioButton); + + const bool bHostPortRadio = m_xHostPortRadio->get_active(); + m_xHostNameLabel->set_sensitive(bHostPortRadio); + m_xHostName->set_sensitive(bHostPortRadio); + m_xPortLabel->set_sensitive(bHostPortRadio); + m_xPort->set_sensitive(bHostPortRadio); + m_xDefaultPort->set_sensitive(bHostPortRadio); + + m_xSocket->set_sensitive(m_xSocketRadio->get_active()); + m_xNamedPipe->set_sensitive(m_xNamedPipeRadio->get_active()); + } + + IMPL_LINK(MySQLNativeSettings, EditModifyHdl, weld::Entry&, rEdit, void) + { + m_aControlModificationLink.Call(&rEdit); + } + + IMPL_LINK(MySQLNativeSettings, SpinModifyHdl, weld::SpinButton&, rEdit, void) + { + m_aControlModificationLink.Call(&rEdit); + } + + void MySQLNativeSettings::fillControls( std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList ) + { + _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::Entry>(m_xDatabaseName.get())); + _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::Entry>(m_xHostName.get())); + _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::Entry>(m_xPort.get())); + _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::Entry>(m_xSocket.get())); + _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::Entry>(m_xNamedPipe.get())); + } + + void MySQLNativeSettings::fillWindows( std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList ) + { + _rControlList.emplace_back( new ODisableWidgetWrapper<weld::Label>( m_xDatabaseNameLabel.get() ) ); + _rControlList.emplace_back( new ODisableWidgetWrapper<weld::Label>( m_xHostNameLabel.get() ) ); + _rControlList.emplace_back( new ODisableWidgetWrapper<weld::Label>( m_xPortLabel.get() ) ); + _rControlList.emplace_back( new ODisableWidgetWrapper<weld::Label>( m_xDefaultPort.get() ) ); + _rControlList.emplace_back( new ODisableWidgetWrapper<weld::RadioButton>( m_xSocketRadio.get() ) ); + _rControlList.emplace_back( new ODisableWidgetWrapper<weld::RadioButton>( m_xNamedPipeRadio.get() ) ); + } + + bool MySQLNativeSettings::FillItemSet( SfxItemSet* _rSet ) + { + bool bChangedSomething = false; + + OGenericAdministrationPage::fillString( *_rSet, m_xHostName.get(), DSID_CONN_HOSTNAME, bChangedSomething ); + OGenericAdministrationPage::fillString( *_rSet, m_xDatabaseName.get(), DSID_DATABASENAME, bChangedSomething ); + OGenericAdministrationPage::fillInt32 ( *_rSet, m_xPort.get(), DSID_MYSQL_PORTNUMBER, bChangedSomething ); +#ifdef UNX + OGenericAdministrationPage::fillString( *_rSet, m_xSocket.get(), DSID_CONN_SOCKET, bChangedSomething ); +#else + OGenericAdministrationPage::fillString( *_rSet, m_xNamedPipe.get(), DSID_NAMED_PIPE, bChangedSomething ); +#endif + + return bChangedSomething; + } + + void MySQLNativeSettings::implInitControls(const SfxItemSet& _rSet ) + { + const SfxBoolItem* pInvalid = _rSet.GetItem<SfxBoolItem>(DSID_INVALID_SELECTION); + bool bValid = !pInvalid || !pInvalid->GetValue(); + if ( !bValid ) + return; + + const SfxStringItem* pDatabaseName = _rSet.GetItem<SfxStringItem>(DSID_DATABASENAME); + const SfxStringItem* pHostName = _rSet.GetItem<SfxStringItem>(DSID_CONN_HOSTNAME); + const SfxInt32Item* pPortNumber = _rSet.GetItem<SfxInt32Item>(DSID_MYSQL_PORTNUMBER); + const SfxStringItem* pSocket = _rSet.GetItem<SfxStringItem>(DSID_CONN_SOCKET); + const SfxStringItem* pNamedPipe = _rSet.GetItem<SfxStringItem>(DSID_NAMED_PIPE); + + m_xDatabaseName->set_text( pDatabaseName->GetValue() ); + m_xDatabaseName->save_value(); + + m_xHostName->set_text( pHostName->GetValue() ); + m_xHostName->save_value(); + + m_xPort->set_value( pPortNumber->GetValue() ); + m_xPort->save_value(); + + m_xSocket->set_text( pSocket->GetValue() ); + m_xSocket->save_value(); + + m_xNamedPipe->set_text( pNamedPipe->GetValue() ); + m_xNamedPipe->save_value(); + + // if a socket (on Unix) or a pipe name (on Windows) is given, this is preferred over + // the port +#ifdef UNX + weld::RadioButton& rSocketPipeRadio = *m_xSocketRadio; + const SfxStringItem* pSocketPipeItem = pSocket; +#else + weld::RadioButton& rSocketPipeRadio = *m_xNamedPipeRadio; + const SfxStringItem* pSocketPipeItem = pNamedPipe; +#endif + const OUString& rSocketPipe( pSocketPipeItem->GetValue() ); + if (!rSocketPipe.isEmpty()) + rSocketPipeRadio.set_active(true); + else + m_xHostPortRadio->set_active(true); + } + + bool MySQLNativeSettings::canAdvance() const + { + if (m_xDatabaseName->get_text().isEmpty()) + return false; + + if ( m_xHostPortRadio->get_active() + && ( ( m_xHostName->get_text().isEmpty() ) + || ( m_xPort->get_text().isEmpty() ) + ) + ) + return false; + +#ifdef UNX + if ( ( m_xSocketRadio->get_active() ) + && ( m_xSocket->get_text().isEmpty() ) + ) +#else + if ( ( m_xNamedPipeRadio->get_active() ) + && ( m_xNamedPipe->get_text().isEmpty() ) + ) +#endif + return false; + + return true; + } + +} // namespace dbaui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/admincontrols.hxx b/dbaccess/source/ui/dlg/admincontrols.hxx new file mode 100644 index 000000000..219f93f0e --- /dev/null +++ b/dbaccess/source/ui/dlg/admincontrols.hxx @@ -0,0 +1,68 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_DBACCESS_SOURCE_UI_DLG_ADMINCONTROLS_HXX +#define INCLUDED_DBACCESS_SOURCE_UI_DLG_ADMINCONTROLS_HXX + +#include "adminpages.hxx" + +#include <vcl/weld.hxx> + +namespace dbaui +{ + + // MySQLNativeSettings + class MySQLNativeSettings + { + private: + std::unique_ptr<weld::Builder> m_xBuilder; + std::unique_ptr<weld::Widget> m_xContainer; + std::unique_ptr<weld::Label> m_xDatabaseNameLabel; + std::unique_ptr<weld::Entry> m_xDatabaseName; + std::unique_ptr<weld::RadioButton> m_xHostPortRadio; + std::unique_ptr<weld::RadioButton> m_xSocketRadio; + std::unique_ptr<weld::RadioButton> m_xNamedPipeRadio; + std::unique_ptr<weld::Label> m_xHostNameLabel; + std::unique_ptr<weld::Entry> m_xHostName; + std::unique_ptr<weld::Label> m_xPortLabel; + std::unique_ptr<weld::SpinButton> m_xPort; + std::unique_ptr<weld::Label> m_xDefaultPort; + std::unique_ptr<weld::Entry> m_xSocket; + std::unique_ptr<weld::Entry> m_xNamedPipe; + Link<weld::Widget*,void> m_aControlModificationLink; + DECL_LINK(RadioToggleHdl, weld::ToggleButton&, void); + DECL_LINK(SpinModifyHdl, weld::SpinButton&, void); + DECL_LINK(EditModifyHdl, weld::Entry&, void); + + public: + MySQLNativeSettings(weld::Widget* pParent, const Link<weld::Widget*,void>& rControlModificationLink); + void fillControls( std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList ); + void fillWindows( std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList ); + + bool FillItemSet( SfxItemSet* rCoreAttrs ); + void implInitControls( const SfxItemSet& _rSet ); + + bool canAdvance() const; + }; + +} // namespace dbaui + +#endif // INCLUDED_DBACCESS_SOURCE_UI_DLG_ADMINCONTROLS_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/adminpages.cxx b/dbaccess/source/ui/dlg/adminpages.cxx new file mode 100644 index 000000000..4dbdb3d6a --- /dev/null +++ b/dbaccess/source/ui/dlg/adminpages.cxx @@ -0,0 +1,278 @@ +/* -*- 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 "adminpages.hxx" +#include <core_resource.hxx> +#include <dbu_dlg.hxx> +#include <IItemSetHelper.hxx> +#include <strings.hrc> +#include <svl/stritem.hxx> +#include <svl/eitem.hxx> +#include <svl/intitem.hxx> +#include <dsitems.hxx> +#include "dsselect.hxx" +#include "odbcconfig.hxx" +#include "optionalboolitem.hxx" +#include <sqlmessage.hxx> +#include <com/sun/star/sdbc/XConnection.hpp> +#include <comphelper/types.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> + +namespace dbaui +{ + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::sdbc; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::lang; + using namespace ::dbtools; + + ISaveValueWrapper::~ISaveValueWrapper() + { + } + + OGenericAdministrationPage::OGenericAdministrationPage(weld::Container* pPage, weld::DialogController* pController, const OUString& rUIXMLDescription, const OString& rId, const SfxItemSet& rAttrSet) + : SfxTabPage(pPage, pController, rUIXMLDescription, rId, &rAttrSet) + , m_abEnableRoadmap(false) + , m_pAdminDialog(nullptr) + , m_pItemSetHelper(nullptr) + { + SetExchangeSupport(); + + m_xContainer->set_size_request(m_xContainer->get_approximate_digit_width() * WIZARD_PAGE_X, + m_xContainer->get_text_height() * WIZARD_PAGE_Y); + } + + DeactivateRC OGenericAdministrationPage::DeactivatePage(SfxItemSet* _pSet) + { + if (_pSet) + { + if (!prepareLeave()) + return DeactivateRC::KeepPage; + FillItemSet(_pSet); + } + + return DeactivateRC::LeavePage; + } + + void OGenericAdministrationPage::Reset(const SfxItemSet* _rCoreAttrs) + { + implInitControls(*_rCoreAttrs, false); + } + + void OGenericAdministrationPage::Activate() + { + BuilderPage::Activate(); + OSL_ENSURE(m_pItemSetHelper,"NO ItemSetHelper set!"); + if ( m_pItemSetHelper ) + ActivatePage(*m_pItemSetHelper->getOutputSet()); + } + + void OGenericAdministrationPage::ActivatePage(const SfxItemSet& _rSet) + { + implInitControls(_rSet, true); + } + + void OGenericAdministrationPage::getFlags(const SfxItemSet& _rSet, bool& _rValid, bool& _rReadonly) + { + const SfxBoolItem* pInvalid = _rSet.GetItem<SfxBoolItem>(DSID_INVALID_SELECTION); + _rValid = !pInvalid || !pInvalid->GetValue(); + const SfxBoolItem* pReadonly = _rSet.GetItem<SfxBoolItem>(DSID_READONLY); + _rReadonly = !_rValid || (pReadonly && pReadonly->GetValue()); + } + + IMPL_LINK(OGenericAdministrationPage, OnControlModified, weld::Widget*, pCtrl, void) + { + callModifiedHdl(pCtrl); + } + + IMPL_LINK(OGenericAdministrationPage, OnControlModifiedButtonClick, weld::ToggleButton&, rCtrl, void) + { + callModifiedHdl(&rCtrl); + } + + IMPL_LINK(OGenericAdministrationPage, OnControlEntryModifyHdl, weld::Entry&, rCtrl, void) + { + callModifiedHdl(&rCtrl); + } + + IMPL_LINK(OGenericAdministrationPage, OnControlSpinButtonModifyHdl, weld::SpinButton&, rCtrl, void) + { + callModifiedHdl(&rCtrl); + } + + bool OGenericAdministrationPage::getSelectedDataSource(OUString& _sReturn, OUString const & _sCurr) + { + // collect all ODBC data source names + std::set<OUString> aOdbcDatasources; + OOdbcEnumeration aEnumeration; + if (!aEnumeration.isLoaded()) + { + // show an error message + OUString sError(DBA_RES(STR_COULD_NOT_LOAD_ODBC_LIB)); + sError = sError.replaceFirst("#lib#", aEnumeration.getLibraryName()); + std::unique_ptr<weld::MessageDialog> xDialog(Application::CreateMessageDialog(GetFrameWeld(), + VclMessageType::Warning, VclButtonsType::Ok, + sError)); + xDialog->run(); + return false; + } + else + { + aEnumeration.getDatasourceNames(aOdbcDatasources); + // execute the select dialog + ODatasourceSelectDialog aSelector(GetFrameWeld(), aOdbcDatasources); + if (!_sCurr.isEmpty()) + aSelector.Select(_sCurr); + if (RET_OK == aSelector.run()) + _sReturn = aSelector.GetSelected(); + } + return true; + } + + void OGenericAdministrationPage::implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) + { + // check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa) + bool bValid, bReadonly; + getFlags(_rSet, bValid, bReadonly); + + std::vector< std::unique_ptr<ISaveValueWrapper> > aControlList; + if ( _bSaveValue ) + { + fillControls(aControlList); + for( const auto& pValueWrapper : aControlList ) + { + pValueWrapper->SaveValue(); + } + } + + if ( bReadonly ) + { + fillWindows(aControlList); + for( const auto& pValueWrapper : aControlList ) + { + pValueWrapper->Disable(); + } + } + } + + void OGenericAdministrationPage::initializePage() + { + OSL_ENSURE(m_pItemSetHelper,"NO ItemSetHelper set!"); + if ( m_pItemSetHelper ) + Reset(m_pItemSetHelper->getOutputSet()); + } + bool OGenericAdministrationPage::commitPage( ::vcl::WizardTypes::CommitPageReason ) + { + return true; + } + bool OGenericAdministrationPage::canAdvance() const + { + return true; + } + void OGenericAdministrationPage::fillBool( SfxItemSet& _rSet, const weld::CheckButton* pCheckBox, sal_uInt16 _nID, bool bOptionalBool, bool& _bChangedSomething, bool _bRevertValue ) + { + if (!(pCheckBox && pCheckBox->get_state_changed_from_saved())) + return; + + bool bValue = pCheckBox->get_active(); + if ( _bRevertValue ) + bValue = !bValue; + + if (bOptionalBool) + { + OptionalBoolItem aValue( _nID ); + if ( pCheckBox->get_state() != TRISTATE_INDET ) + aValue.SetValue( bValue ); + _rSet.Put( aValue ); + } + else + _rSet.Put( SfxBoolItem( _nID, bValue ) ); + + _bChangedSomething = true; + } + void OGenericAdministrationPage::fillInt32(SfxItemSet& _rSet, const weld::SpinButton* pEdit, sal_uInt16 _nID, bool& _bChangedSomething) + { + if (pEdit && pEdit->get_value_changed_from_saved()) + { + _rSet.Put(SfxInt32Item(_nID, pEdit->get_value())); + _bChangedSomething = true; + } + } + void OGenericAdministrationPage::fillString(SfxItemSet& _rSet, const weld::Entry* pEdit, sal_uInt16 _nID, bool& _bChangedSomething) + { + if (pEdit && pEdit->get_value_changed_from_saved()) + { + _rSet.Put(SfxStringItem(_nID, pEdit->get_text())); + _bChangedSomething = true; + } + } + void OGenericAdministrationPage::fillString(SfxItemSet& _rSet, const dbaui::OConnectionURLEdit* pEdit, sal_uInt16 _nID, bool& _bChangedSomething) + { + if (pEdit && pEdit->get_value_changed_from_saved()) + { + _rSet.Put(SfxStringItem(_nID, pEdit->GetText())); + _bChangedSomething = true; + } + } + + IMPL_LINK_NOARG(OGenericAdministrationPage, OnTestConnectionButtonClickHdl, weld::Button&, void) + { + OSL_ENSURE(m_pAdminDialog,"No Admin dialog set! ->GPF"); + bool bSuccess = false; + if ( !m_pAdminDialog ) + return; + + m_pAdminDialog->saveDatasource(); + OGenericAdministrationPage::implInitControls(*m_pItemSetHelper->getOutputSet(), true); + bool bShowMessage = true; + try + { + std::pair< Reference<XConnection>,bool> aConnectionPair = m_pAdminDialog->createConnection(); + bShowMessage = aConnectionPair.second; + bSuccess = aConnectionPair.first.is(); + ::comphelper::disposeComponent(aConnectionPair.first); + } + catch(Exception&) + { + } + if ( bShowMessage ) + { + MessageType eImage = MessageType::Info; + OUString aMessage,sTitle; + sTitle = DBA_RES(STR_CONNECTION_TEST); + if ( bSuccess ) + { + aMessage = DBA_RES(STR_CONNECTION_SUCCESS); + } + else + { + eImage = MessageType::Error; + aMessage = DBA_RES(STR_CONNECTION_NO_SUCCESS); + } + OSQLMessageBox aMsg(GetFrameWeld(), sTitle, aMessage, MessBoxStyle::Ok, eImage); + aMsg.run(); + } + if ( !bSuccess ) + m_pAdminDialog->clearPassword(); + } +} // namespace dbaui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/adminpages.hxx b/dbaccess/source/ui/dlg/adminpages.hxx new file mode 100644 index 000000000..cbdec09d0 --- /dev/null +++ b/dbaccess/source/ui/dlg/adminpages.hxx @@ -0,0 +1,238 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_DBACCESS_SOURCE_UI_DLG_ADMINPAGES_HXX +#define INCLUDED_DBACCESS_SOURCE_UI_DLG_ADMINPAGES_HXX + +#include <sfx2/tabdlg.hxx> +#include <vcl/wizardmachine.hxx> +#include <curledit.hxx> + +class NumericField; +class Edit; +namespace dbaui +{ + /// helper class to wrap the savevalue and disable call + class SAL_NO_VTABLE ISaveValueWrapper + { + public: + virtual ~ISaveValueWrapper() = 0; + virtual void SaveValue() = 0; + virtual void Disable() = 0; + }; + + template < class T > class OSaveValueWidgetWrapper : public ISaveValueWrapper + { + T* m_pSaveValue; + public: + explicit OSaveValueWidgetWrapper(T* _pSaveValue) : m_pSaveValue(_pSaveValue) + { OSL_ENSURE(m_pSaveValue,"Illegal argument!"); } + + virtual void SaveValue() override { m_pSaveValue->save_value(); } + virtual void Disable() override { m_pSaveValue->set_sensitive(false); } + }; + + template <> class OSaveValueWidgetWrapper<weld::ToggleButton> : public ISaveValueWrapper + { + weld::ToggleButton* m_pSaveValue; + public: + explicit OSaveValueWidgetWrapper(weld::ToggleButton* _pSaveValue) : m_pSaveValue(_pSaveValue) + { OSL_ENSURE(m_pSaveValue,"Illegal argument!"); } + + virtual void SaveValue() override { m_pSaveValue->save_state(); } + virtual void Disable() override { m_pSaveValue->set_sensitive(false); } + }; + + template <> class OSaveValueWidgetWrapper<dbaui::OConnectionURLEdit> : public ISaveValueWrapper + { + dbaui::OConnectionURLEdit* m_pSaveValue; + public: + explicit OSaveValueWidgetWrapper(dbaui::OConnectionURLEdit* _pSaveValue) : m_pSaveValue(_pSaveValue) + { OSL_ENSURE(m_pSaveValue,"Illegal argument!"); } + + virtual void SaveValue() override { m_pSaveValue->save_value(); } + virtual void Disable() override { m_pSaveValue->set_sensitive(false); } + }; + + template <class T> class ODisableWidgetWrapper : public ISaveValueWrapper + { + T* m_pSaveValue; + public: + explicit ODisableWidgetWrapper(T* _pSaveValue) : m_pSaveValue(_pSaveValue) + { OSL_ENSURE(m_pSaveValue,"Illegal argument!"); } + + virtual void SaveValue() override {} + virtual void Disable() override { m_pSaveValue->set_sensitive(false); } + }; + + // OGenericAdministrationPage + class IDatabaseSettingsDialog; + class IItemSetHelper; + class OGenericAdministrationPage :public SfxTabPage + ,public ::vcl::IWizardPageController + { + private: + Link<OGenericAdministrationPage const *, void> m_aModifiedHandler; /// to be called if something on the page has been modified + bool m_abEnableRoadmap; + protected: + IDatabaseSettingsDialog* m_pAdminDialog; + IItemSetHelper* m_pItemSetHelper; + + css::uno::Reference< css::uno::XComponentContext > + m_xORB; + public: + OGenericAdministrationPage(weld::Container* pPage, weld::DialogController* pController, const OUString& rUIXMLDescription, const OString& rId, const SfxItemSet& rAttrSet); + /// set a handler which gets called every time something on the page has been modified + void SetModifiedHandler(const Link<OGenericAdministrationPage const *, void>& _rHandler) { m_aModifiedHandler = _rHandler; } + + /** Sets the ParentDialog + @param _pAdminDialog + the ParentDialog + @param _pItemSetHelper + the itemset helper + */ + void SetAdminDialog(IDatabaseSettingsDialog* _pDialog,IItemSetHelper* _pItemSetHelper) + { + OSL_ENSURE(_pDialog && _pItemSetHelper,"Values are NULL!"); + m_pAdminDialog = _pDialog; + m_pItemSetHelper = _pItemSetHelper; + } + + /** Sets the ServiceFactory + @param _rxORB + The service factory. + */ + void SetServiceFactory(const css::uno::Reference< css::uno::XComponentContext >& rxORB) + { + m_xORB = rxORB; + } + + /** opens a dialog filled with all data sources available for this type and + returns the selected on. + @param _eType + The type for which the data source dialog should be opened. + @param _sReturn + <OUT/> contains the selected name. + @return + <FALSE/> if an error occurred, otherwise <TRUE/> + */ + bool getSelectedDataSource(OUString& _sReturn, OUString const & _sCurr); + + // svt::IWizardPageController + virtual void initializePage() override; + virtual bool commitPage( ::vcl::WizardTypes::CommitPageReason _eReason ) override; + virtual bool canAdvance() const override; + + void SetRoadmapStateValue( bool _bDoEnable ) { m_abEnableRoadmap = _bDoEnable; } + bool GetRoadmapStateValue() const { return m_abEnableRoadmap; } + + protected: + /// default implementation: call FillItemSet, call prepareLeave, + virtual DeactivateRC DeactivatePage(SfxItemSet* pSet) override; + /// default implementation: call implInitControls with the given item set and _bSaveValue = sal_False + virtual void Reset(const SfxItemSet* _rCoreAttrs) override; + /// default implementation: call implInitControls with the given item set and _bSaveValue = sal_True + virtual void ActivatePage(const SfxItemSet& _rSet) override; + + // BuilderPage overridables + virtual void Activate() override; + + protected: + virtual void callModifiedHdl(weld::Widget* /*pControl*/ = nullptr) { m_aModifiedHandler.Call(this); } + + /// called from within DeactivatePage. The page is allowed to be deactivated if this method returns sal_True + virtual bool prepareLeave() { return true; } + + /** called from within Reset and ActivatePage, use to initialize the controls with the items from the given set + @param _bSaveValue if set to sal_True, the implementation should call SaveValue on all relevant controls + */ + virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue); + + /// analyze the invalid and the readonly flag which may be present in the set + static void getFlags(const SfxItemSet& _rSet, bool& _rValid, bool& _rReadonly); + + /** will be called inside <method>implInitControls</method> to save the value if necessary + @param _rControlList + The list must be filled with the controls. + It is not allowed to clear the list before pushing data into it. + */ + virtual void fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) = 0; + + /** will be called inside <method>implInitControls</method> to disable if necessary + @param _rControlList + The list must be filled with the controls. + It is not allowed to clear the list before pushing data into it. + */ + virtual void fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) = 0; + + public: + /** fills the Boolean value into the item set when the value changed. + @param _rSet + The item set where to put the new value into. + @param _pCheckBox + The check box which is checked. + @param _nID + The id in the itemset to set with the new value. + @param _bChangedSomething + <TRUE/> if something changed otherwise <FALSE/> + @param _bRevertValue + set to <TRUE/> if the display value should be reverted before putting it into the set + */ + static void fillBool(SfxItemSet& _rSet, const weld::CheckButton* pCheckBox, sal_uInt16 _nID, bool bOptionalBool, bool& _bChangedSomething, bool _bRevertValue = false); + + /** fills the int value into the item set when the value changed. + @param _rSet + The item set where to put the new value into. + @param _pEdit + The check box which is checked. + @param _nID + The id in the itemset to set with the new value. + @param _bChangedSomething + <TRUE/> if something changed otherwise <FALSE/> + */ + static void fillInt32(SfxItemSet& _rSet,const weld::SpinButton* pEdit,sal_uInt16 _nID, bool& _bChangedSomething); + + /** fills the String value into the item set when the value changed. + @param _rSet + The item set where to put the new value into. + @param _pEdit + The check box which is checked. + @param _nID + The id in the itemset to set with the new value. + @param _bChangedSomething + <TRUE/> if something changed otherwise <FALSE/> + */ + static void fillString(SfxItemSet& _rSet,const weld::Entry* pEdit,sal_uInt16 _nID, bool& _bChangedSomething); + static void fillString(SfxItemSet& _rSet,const dbaui::OConnectionURLEdit* pEdit,sal_uInt16 _nID, bool& _bChangedSomething); + + protected: + /** This link be used for controls where the tabpage does not need to take any special action when the control + is modified. The implementation just calls callModifiedHdl. + */ + DECL_LINK(OnControlModified, weld::Widget*, void); + DECL_LINK(OnControlEntryModifyHdl, weld::Entry&, void); + DECL_LINK(OnControlSpinButtonModifyHdl, weld::SpinButton&, void); + DECL_LINK(OnControlModifiedButtonClick, weld::ToggleButton&, void); + DECL_LINK(OnTestConnectionButtonClickHdl, weld::Button&, void); + }; +} // namespace dbaui + +#endif // INCLUDED_DBACCESS_SOURCE_UI_DLG_ADMINPAGES_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/adodatalinks.cxx b/dbaccess/source/ui/dlg/adodatalinks.cxx new file mode 100644 index 000000000..fc129b2de --- /dev/null +++ b/dbaccess/source/ui/dlg/adodatalinks.cxx @@ -0,0 +1,199 @@ +/* -*- 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 . + */ + + +#if defined(_WIN32) +// LO/windows.h conflict +#undef WB_LEFT +#undef WB_RIGHT +#include <msdasc.h> + +#include <o3tl/char16_t2wchar_t.hxx> + +#include <initguid.h> +#include <adoid.h> +#include <adoint.h> + +#include "adodatalinks.hxx" + +namespace { + +OUString PromptNew(long hWnd) +{ + HRESULT hr; + IDataSourceLocator* dlPrompt = nullptr; + ADOConnection* piTmpConnection = nullptr; + BSTR _result=nullptr; + + // Initialize COM + ::CoInitializeEx( nullptr, COINIT_APARTMENTTHREADED ); + + // Instantiate DataLinks object. + hr = CoCreateInstance( + CLSID_DataLinks, //clsid -- Data Links UI + nullptr, //pUnkOuter + CLSCTX_INPROC_SERVER, //dwClsContext + IID_IDataSourceLocator, //riid + reinterpret_cast<void**>(&dlPrompt) //ppvObj + ); + if( FAILED( hr ) ) + { + return OUString(); + } + + dlPrompt->put_hWnd(hWnd); + if( FAILED( hr ) ) + { + dlPrompt->Release( ); + return OUString(); + } + + // Prompt for connection information. + hr = dlPrompt->PromptNew(reinterpret_cast<IDispatch **>(&piTmpConnection)); + + if( FAILED( hr ) || !piTmpConnection ) + { + dlPrompt->Release( ); + return OUString(); + } + + hr = piTmpConnection->get_ConnectionString(&_result); + if( FAILED( hr ) ) + { + piTmpConnection->Release( ); + dlPrompt->Release( ); + return OUString(); + } + + piTmpConnection->Release( ); + dlPrompt->Release( ); + CoUninitialize(); + // Don't we need SysFreeString(_result)? + return o3tl::toU(_result); +} + +OUString PromptEdit(long hWnd, OUString const & connstr) +{ + HRESULT hr; + IDataSourceLocator* dlPrompt = nullptr; + ADOConnection* piTmpConnection = nullptr; + BSTR _result=nullptr; + + // Initialize COM + ::CoInitializeEx( nullptr, COINIT_APARTMENTTHREADED ); + + hr = CoCreateInstance(CLSID_CADOConnection, + nullptr, + CLSCTX_INPROC_SERVER, + IID_IADOConnection, + reinterpret_cast<LPVOID *>(&piTmpConnection)); + if( FAILED( hr ) ) + { + piTmpConnection->Release( ); + return connstr; + } + + + hr = piTmpConnection->put_ConnectionString( + const_cast<BSTR>(o3tl::toW(connstr.getStr()))); + if( FAILED( hr ) ) + { + piTmpConnection->Release( ); + return connstr; + } + + // Instantiate DataLinks object. + hr = CoCreateInstance( + CLSID_DataLinks, //clsid -- Data Links UI + nullptr, //pUnkOuter + CLSCTX_INPROC_SERVER, //dwClsContext + IID_IDataSourceLocator, //riid + reinterpret_cast<void**>(&dlPrompt) //ppvObj + ); + if( FAILED( hr ) ) + { + piTmpConnection->Release( ); + dlPrompt->Release( ); + return connstr; + } + + dlPrompt->put_hWnd(hWnd); + if( FAILED( hr ) ) + { + piTmpConnection->Release( ); + dlPrompt->Release( ); + return connstr; + } + + VARIANT_BOOL pbSuccess; + + // Prompt for connection information. + hr = dlPrompt->PromptEdit(reinterpret_cast<IDispatch **>(&piTmpConnection),&pbSuccess); + if( SUCCEEDED( hr ) && !pbSuccess ) //if user press cancel then sal_False == pbSuccess + { + piTmpConnection->Release( ); + dlPrompt->Release( ); + return connstr; + } + + if( FAILED( hr ) ) + { + // Prompt for new connection information. + piTmpConnection->Release( ); + piTmpConnection = nullptr; + hr = dlPrompt->PromptNew(reinterpret_cast<IDispatch **>(&piTmpConnection)); + if( FAILED( hr ) || !piTmpConnection ) + { + dlPrompt->Release( ); + return connstr; + } + } + + hr = piTmpConnection->get_ConnectionString(&_result); + if( FAILED( hr ) ) + { + piTmpConnection->Release( ); + dlPrompt->Release( ); + return connstr; + } + + piTmpConnection->Release( ); + dlPrompt->Release( ); + CoUninitialize(); + // Don't we need SysFreeString(_result)? + return o3tl::toU(_result); +} + +} + +OUString getAdoDatalink(long hWnd,OUString const & oldLink) +{ + OUString dataLink; + if (!oldLink.isEmpty()) + { + dataLink=PromptEdit(hWnd,oldLink); + } + else + dataLink=PromptNew(hWnd); + return dataLink; +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/adodatalinks.hxx b/dbaccess/source/ui/dlg/adodatalinks.hxx new file mode 100644 index 000000000..d13203ad8 --- /dev/null +++ b/dbaccess/source/ui/dlg/adodatalinks.hxx @@ -0,0 +1,27 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_DBACCESS_SOURCE_UI_DLG_ADODATALINKS_HXX +#define INCLUDED_DBACCESS_SOURCE_UI_DLG_ADODATALINKS_HXX + +#include <rtl/ustring.hxx> + +OUString getAdoDatalink(long hWnd, OUString const& oldLink); +#endif +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/adtabdlg.cxx b/dbaccess/source/ui/dlg/adtabdlg.cxx new file mode 100644 index 000000000..35e29ed17 --- /dev/null +++ b/dbaccess/source/ui/dlg/adtabdlg.cxx @@ -0,0 +1,468 @@ +/* -*- 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 <adtabdlg.hxx> +#include <tools/diagnose_ex.h> +#include <core_resource.hxx> +#include <strings.hrc> +#include <connectivity/dbtools.hxx> +#include <com/sun/star/container/XContainer.hpp> +#include <com/sun/star/sdb/application/DatabaseObject.hpp> +#include <com/sun/star/sdb/XQueriesSupplier.hpp> +#include <com/sun/star/sdbcx/XViewsSupplier.hpp> +#include <com/sun/star/sdbcx/XTablesSupplier.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <imageprovider.hxx> +#include <comphelper/containermultiplexer.hxx> +#include <cppuhelper/basemutex.hxx> +#include <algorithm> + +// slot ids +using namespace dbaui; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace dbtools; + +TableObjectListFacade::~TableObjectListFacade() +{ +} + +namespace { + +class TableListFacade : public ::cppu::BaseMutex + , public TableObjectListFacade + , public ::comphelper::OContainerListener +{ + TableTreeListBox& m_rTableList; + Reference< XConnection > m_xConnection; + ::rtl::Reference< comphelper::OContainerListenerAdapter> + m_pContainerListener; + bool m_bAllowViews; + +public: + TableListFacade( TableTreeListBox& _rTableList, const Reference< XConnection >& _rxConnection ) + : ::comphelper::OContainerListener(m_aMutex) + ,m_rTableList( _rTableList ) + ,m_xConnection( _rxConnection ) + ,m_bAllowViews(true) + { + } + virtual ~TableListFacade() override; + +private: + virtual void updateTableObjectList( bool _bAllowViews ) override; + virtual OUString getSelectedName( OUString& _out_rAliasName ) const override; + virtual bool isLeafSelected() const override; + // OContainerListener + virtual void _elementInserted( const css::container::ContainerEvent& _rEvent ) override; + virtual void _elementRemoved( const css::container::ContainerEvent& _rEvent ) override; + virtual void _elementReplaced( const css::container::ContainerEvent& _rEvent ) override; +}; + +} + +TableListFacade::~TableListFacade() +{ + if ( m_pContainerListener.is() ) + m_pContainerListener->dispose(); +} + +OUString TableListFacade::getSelectedName( OUString& _out_rAliasName ) const +{ + weld::TreeView& rTableList = m_rTableList.GetWidget(); + std::unique_ptr<weld::TreeIter> xEntry(rTableList.make_iterator()); + + if (!rTableList.get_selected(xEntry.get())) + return OUString(); + + OUString aCatalog, aSchema, aTableName; + std::unique_ptr<weld::TreeIter> xSchema(rTableList.make_iterator(xEntry.get())); + if (rTableList.iter_parent(*xSchema)) + { + auto xAll = m_rTableList.getAllObjectsEntry(); + if (!xAll || !xSchema->equal(*xAll)) + { + std::unique_ptr<weld::TreeIter> xCatalog(rTableList.make_iterator(xSchema.get())); + if (rTableList.iter_parent(*xCatalog)) + { + if (!xAll || !xCatalog->equal(*xAll)) + aCatalog = rTableList.get_text(*xCatalog, 0); + } + aSchema = rTableList.get_text(*xSchema, 0); + } + } + aTableName = rTableList.get_text(*xEntry, 0); + + OUString aComposedName; + try + { + Reference< XDatabaseMetaData > xMeta( m_xConnection->getMetaData(), UNO_SET_THROW ); + if ( aCatalog.isEmpty() + && !aSchema.isEmpty() + && xMeta->supportsCatalogsInDataManipulation() + && !xMeta->supportsSchemasInDataManipulation() ) + { + aCatalog = aSchema; + aSchema.clear(); + } + + aComposedName = ::dbtools::composeTableName( + xMeta, aCatalog, aSchema, aTableName, false, ::dbtools::EComposeRule::InDataManipulation ); + } + catch ( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("dbaccess"); + } + + _out_rAliasName = aTableName; + return aComposedName; +} + +void TableListFacade::_elementInserted( const container::ContainerEvent& /*_rEvent*/ ) +{ + updateTableObjectList(m_bAllowViews); +} + +void TableListFacade::_elementRemoved( const container::ContainerEvent& /*_rEvent*/ ) +{ + updateTableObjectList(m_bAllowViews); +} + +void TableListFacade::_elementReplaced( const container::ContainerEvent& /*_rEvent*/ ) +{ +} + +void TableListFacade::updateTableObjectList( bool _bAllowViews ) +{ + m_bAllowViews = _bAllowViews; + weld::TreeView& rTableList = m_rTableList.GetWidget(); + rTableList.clear(); + try + { + Reference< XTablesSupplier > xTableSupp( m_xConnection, UNO_QUERY_THROW ); + + Reference< XViewsSupplier > xViewSupp; + Reference< XNameAccess > xTables, xViews; + Sequence< OUString > sTables, sViews; + + xTables = xTableSupp->getTables(); + if ( xTables.is() ) + { + if ( !m_pContainerListener.is() ) + { + Reference< XContainer> xContainer(xTables,uno::UNO_QUERY); + if ( xContainer.is() ) + m_pContainerListener = new ::comphelper::OContainerListenerAdapter(this,xContainer); + } + sTables = xTables->getElementNames(); + } + + xViewSupp.set( xTableSupp, UNO_QUERY ); + if ( xViewSupp.is() ) + { + xViews = xViewSupp->getViews(); + if ( xViews.is() ) + sViews = xViews->getElementNames(); + } + + // if no views are allowed remove the views also out the table name filter + if ( !_bAllowViews ) + { + const OUString* pTableBegin = sTables.getConstArray(); + const OUString* pTableEnd = pTableBegin + sTables.getLength(); + std::vector< OUString > aTables(pTableBegin,pTableEnd); + + const OUString* pViewBegin = sViews.getConstArray(); + const OUString* pViewEnd = pViewBegin + sViews.getLength(); + ::comphelper::UStringMixEqual aEqualFunctor; + for(;pViewBegin != pViewEnd;++pViewBegin) + aTables.erase(std::remove_if(aTables.begin(),aTables.end(), + [&aEqualFunctor, pViewBegin](const OUString& lhs) + { return aEqualFunctor(lhs, *pViewBegin); } ) + , aTables.end()); + sTables = Sequence< OUString>(aTables.data(), aTables.size()); + sViews = Sequence< OUString>(); + } + + m_rTableList.UpdateTableList( m_xConnection, sTables, sViews ); + + std::unique_ptr<weld::TreeIter> xEntry(rTableList.make_iterator()); + bool bEntry = rTableList.get_iter_first(*xEntry); + while (bEntry && rTableList.iter_has_child(*xEntry)) + { + rTableList.expand_row(*xEntry); + bEntry = rTableList.iter_next(*xEntry); + } + if (bEntry) + rTableList.select(*xEntry); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("dbaccess"); + } +} + +bool TableListFacade::isLeafSelected() const +{ + weld::TreeView& rTableList = m_rTableList.GetWidget(); + std::unique_ptr<weld::TreeIter> xEntry(rTableList.make_iterator()); + const bool bEntry = rTableList.get_selected(xEntry.get()); + return bEntry && !rTableList.iter_has_child(*xEntry); +} + +namespace { + +class QueryListFacade : public ::cppu::BaseMutex + , public TableObjectListFacade + , public ::comphelper::OContainerListener +{ + weld::TreeView& m_rQueryList; + Reference< XConnection > m_xConnection; + ::rtl::Reference< comphelper::OContainerListenerAdapter> + m_pContainerListener; + +public: + QueryListFacade( weld::TreeView& _rQueryList, const Reference< XConnection >& _rxConnection ) + : ::comphelper::OContainerListener(m_aMutex) + ,m_rQueryList( _rQueryList ) + ,m_xConnection( _rxConnection ) + { + } + virtual ~QueryListFacade() override; + +private: + virtual void updateTableObjectList( bool _bAllowViews ) override; + virtual OUString getSelectedName( OUString& _out_rAliasName ) const override; + virtual bool isLeafSelected() const override; + // OContainerListener + virtual void _elementInserted( const css::container::ContainerEvent& _rEvent ) override; + virtual void _elementRemoved( const css::container::ContainerEvent& _rEvent ) override; + virtual void _elementReplaced( const css::container::ContainerEvent& _rEvent ) override; +}; + +} + +QueryListFacade::~QueryListFacade() +{ + if ( m_pContainerListener.is() ) + m_pContainerListener->dispose(); +} + +void QueryListFacade::_elementInserted( const container::ContainerEvent& _rEvent ) +{ + OUString sName; + if ( _rEvent.Accessor >>= sName ) + { + OUString aQueryImage(ImageProvider::getDefaultImageResourceID(css::sdb::application::DatabaseObject::QUERY)); + m_rQueryList.append("", sName, aQueryImage); + } +} + +void QueryListFacade::_elementRemoved( const container::ContainerEvent& /*_rEvent*/ ) +{ + updateTableObjectList(true); +} + +void QueryListFacade::_elementReplaced( const container::ContainerEvent& /*_rEvent*/ ) +{ +} + +void QueryListFacade::updateTableObjectList( bool /*_bAllowViews*/ ) +{ + m_rQueryList.clear(); + try + { + OUString aQueryImage(ImageProvider::getDefaultImageResourceID(css::sdb::application::DatabaseObject::QUERY)); + + Reference< XQueriesSupplier > xSuppQueries( m_xConnection, UNO_QUERY_THROW ); + Reference< XNameAccess > xQueries( xSuppQueries->getQueries(), UNO_SET_THROW ); + if ( !m_pContainerListener.is() ) + { + Reference< XContainer> xContainer(xQueries,UNO_QUERY_THROW); + m_pContainerListener = new ::comphelper::OContainerListenerAdapter(this,xContainer); + } + const Sequence< OUString > aQueryNames = xQueries->getElementNames(); + + for ( auto const & name : aQueryNames ) + m_rQueryList.append("", name, aQueryImage); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("dbaccess"); + } +} + +OUString QueryListFacade::getSelectedName( OUString& _out_rAliasName ) const +{ + OUString sSelected; + std::unique_ptr<weld::TreeIter> xEntry(m_rQueryList.make_iterator()); + const bool bEntry = m_rQueryList.get_selected(xEntry.get()); + if (bEntry) + sSelected = _out_rAliasName = m_rQueryList.get_text(*xEntry, 0); + return sSelected; +} + +bool QueryListFacade::isLeafSelected() const +{ + std::unique_ptr<weld::TreeIter> xEntry(m_rQueryList.make_iterator()); + const bool bEntry = m_rQueryList.get_selected(xEntry.get()); + return bEntry && !m_rQueryList.iter_has_child(*xEntry); + +} + +OAddTableDlg::OAddTableDlg(weld::Window* pParent, IAddTableDialogContext& _rContext) + : GenericDialogController(pParent, "dbaccess/ui/tablesjoindialog.ui", "TablesJoinDialog") + , m_rContext(_rContext) + , m_xCaseTables(m_xBuilder->weld_radio_button("tables")) + , m_xCaseQueries(m_xBuilder->weld_radio_button("queries")) + , m_xTableList(new TableTreeListBox(m_xBuilder->weld_tree_view("tablelist"))) + , m_xQueryList(m_xBuilder->weld_tree_view("querylist")) + , m_xAddButton(m_xBuilder->weld_button("add")) + , m_xCloseButton(m_xBuilder->weld_button("close")) +{ + weld::TreeView& rTableList = m_xTableList->GetWidget(); + Size aSize(rTableList.get_approximate_digit_width() * 23, + rTableList.get_height_rows(15)); + rTableList.set_size_request(aSize.Width(), aSize.Height()); + m_xQueryList->set_size_request(aSize.Width(), aSize.Height()); + + m_xCaseTables->connect_clicked( LINK( this, OAddTableDlg, OnTypeSelected ) ); + m_xCaseQueries->connect_clicked( LINK( this, OAddTableDlg, OnTypeSelected ) ); + m_xAddButton->connect_clicked( LINK( this, OAddTableDlg, AddClickHdl ) ); + m_xCloseButton->connect_clicked( LINK( this, OAddTableDlg, CloseClickHdl ) ); + rTableList.connect_row_activated( LINK( this, OAddTableDlg, TableListDoubleClickHdl ) ); + rTableList.connect_changed( LINK( this, OAddTableDlg, TableListSelectHdl ) ); + m_xQueryList->connect_row_activated( LINK( this, OAddTableDlg, TableListDoubleClickHdl ) ); + m_xQueryList->connect_changed( LINK( this, OAddTableDlg, TableListSelectHdl ) ); + + rTableList.set_selection_mode(SelectionMode::Single); + m_xTableList->DisableCheckButtons(); // do not show any buttons + m_xTableList->SuppressEmptyFolders(); + + m_xQueryList->set_selection_mode(SelectionMode::Single); + + if ( !m_rContext.allowQueries() ) + { + m_xCaseTables->hide(); + m_xCaseQueries->hide(); + } + + m_xDialog->set_title(getDialogTitleForContext(m_rContext)); +} + +OAddTableDlg::~OAddTableDlg() +{ +} + +void OAddTableDlg::impl_switchTo( ObjectList _eList ) +{ + switch ( _eList ) + { + case Tables: + m_xTableList->GetWidget().show(); m_xCaseTables->set_active(true); + m_xQueryList->hide(); m_xCaseQueries->set_active(false); + m_xCurrentList.reset( new TableListFacade( *m_xTableList, m_rContext.getConnection() ) ); + m_xTableList->GetWidget().grab_focus(); + break; + + case Queries: + m_xTableList->GetWidget().hide(); m_xCaseTables->set_active(false); + m_xQueryList->show(); m_xCaseQueries->set_active(true); + m_xCurrentList.reset( new QueryListFacade( *m_xQueryList, m_rContext.getConnection() ) ); + m_xQueryList->grab_focus(); + break; + } + m_xCurrentList->updateTableObjectList( m_rContext.allowViews() ); +} + +void OAddTableDlg::Update() +{ + if (!m_xCurrentList) + impl_switchTo( Tables ); + else + m_xCurrentList->updateTableObjectList( m_rContext.allowViews() ); +} + +IMPL_LINK_NOARG( OAddTableDlg, AddClickHdl, weld::Button&, void ) +{ + TableListDoubleClickHdl(m_xTableList->GetWidget()); +} + +IMPL_LINK_NOARG(OAddTableDlg, TableListDoubleClickHdl, weld::TreeView&, bool) +{ + if ( impl_isAddAllowed() ) + { + if ( m_xCurrentList->isLeafSelected() ) + { + OUString sSelectedName, sAliasName; + sSelectedName = m_xCurrentList->getSelectedName( sAliasName ); + + m_rContext.addTableWindow( sSelectedName, sAliasName ); + } + if ( !impl_isAddAllowed() ) + m_xDialog->response(RET_CLOSE); + } + return true; +} + +IMPL_LINK_NOARG( OAddTableDlg, TableListSelectHdl, weld::TreeView&, void ) +{ + m_xAddButton->set_sensitive( m_xCurrentList->isLeafSelected() ); +} + +IMPL_LINK_NOARG( OAddTableDlg, CloseClickHdl, weld::Button&, void ) +{ + m_xDialog->response(RET_CLOSE); +} + +IMPL_LINK_NOARG( OAddTableDlg, OnTypeSelected, weld::Button&, void ) +{ + if ( m_xCaseTables->get_active() ) + impl_switchTo( Tables ); + else + impl_switchTo( Queries ); +} + +void OAddTableDlg::OnClose() +{ + m_rContext.onWindowClosing(); +} + +bool OAddTableDlg::impl_isAddAllowed() +{ + return m_rContext.allowAddition(); +} + +OUString OAddTableDlg::getDialogTitleForContext( IAddTableDialogContext const & _rContext ) +{ + OUString sTitle; + + if ( _rContext.allowQueries() ) + sTitle = DBA_RES( STR_ADD_TABLE_OR_QUERY ); + else + sTitle = DBA_RES( STR_ADD_TABLES ); + + return sTitle; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/advancedsettings.cxx b/dbaccess/source/ui/dlg/advancedsettings.cxx new file mode 100644 index 000000000..6ec06a9db --- /dev/null +++ b/dbaccess/source/ui/dlg/advancedsettings.cxx @@ -0,0 +1,472 @@ +/* -*- 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 <sal/config.h> + +#include <memory> + +#include "advancedsettings.hxx" +#include <advancedsettingsdlg.hxx> +#include <dsitems.hxx> +#include "DbAdminImpl.hxx" +#include "DriverSettings.hxx" +#include "optionalboolitem.hxx" + +#include <svl/eitem.hxx> +#include <svl/intitem.hxx> +#include <svl/stritem.hxx> + +namespace dbaui +{ + + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::Any; + using ::com::sun::star::uno::XComponentContext; + using ::com::sun::star::beans::XPropertySet; + using ::com::sun::star::sdbc::XConnection; + using ::com::sun::star::sdbc::XDriver; + + // SpecialSettingsPage + struct BooleanSettingDesc + { + std::unique_ptr<weld::CheckButton>& xControl; // the dialog's control which displays this setting + OString sControlId; // the widget name of the control in the .ui + sal_uInt16 nItemId; // the ID of the item (in an SfxItemSet) which corresponds to this setting + bool bInvertedDisplay; // true if and only if the checkbox is checked when the item is sal_False, and vice versa + bool bOptionalBool; // type is OptionalBool + }; + + // SpecialSettingsPage + SpecialSettingsPage::SpecialSettingsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rCoreAttrs, const DataSourceMetaData& _rDSMeta) + : OGenericAdministrationPage(pPage, pController, "dbaccess/ui/specialsettingspage.ui", "SpecialSettingsPage", _rCoreAttrs) + , m_aBooleanSettings { + { m_xIsSQL92Check, "usesql92", DSID_SQL92CHECK, false, false }, + { m_xAppendTableAlias, "append", DSID_APPEND_TABLE_ALIAS, false, false }, + { m_xAsBeforeCorrelationName, "useas", DSID_AS_BEFORE_CORRNAME, false, false }, + { m_xEnableOuterJoin, "useoj", DSID_ENABLEOUTERJOIN, false, false }, + { m_xIgnoreDriverPrivileges, "ignoreprivs", DSID_IGNOREDRIVER_PRIV, false, false }, + { m_xParameterSubstitution, "replaceparams", DSID_PARAMETERNAMESUBST, false, false }, + { m_xSuppressVersionColumn, "displayver", DSID_SUPPRESSVERSIONCL, true, false }, + { m_xCatalog, "usecatalogname", DSID_CATALOG, false, false }, + { m_xSchema, "useschemaname", DSID_SCHEMA, false, false }, + { m_xIndexAppendix, "createindex", DSID_INDEXAPPENDIX, false, false }, + { m_xDosLineEnds, "eol", DSID_DOSLINEENDS, false, false }, + { m_xCheckRequiredFields, "inputchecks", DSID_CHECK_REQUIRED_FIELDS, false, false }, + { m_xIgnoreCurrency, "ignorecurrency", DSID_IGNORECURRENCY, false, false }, + { m_xEscapeDateTime, "useodbcliterals", DSID_ESCAPE_DATETIME, false, false }, + { m_xPrimaryKeySupport, "primarykeys", DSID_PRIMARY_KEY_SUPPORT, false, false }, + { m_xRespectDriverResultSetType, "resulttype", DSID_RESPECTRESULTSETTYPE, false, false } } + , m_bHasBooleanComparisonMode( _rDSMeta.getFeatureSet().has( DSID_BOOLEANCOMPARISON ) ) + , m_bHasMaxRowScan( _rDSMeta.getFeatureSet().has( DSID_MAX_ROW_SCAN ) ) + { + const FeatureSet& rFeatures( _rDSMeta.getFeatureSet() ); + // create all the check boxes for the boolean settings + for (auto & booleanSetting : m_aBooleanSettings) + { + sal_uInt16 nItemId = booleanSetting.nItemId; + if ( rFeatures.has( nItemId ) ) + { + // check whether this must be a tristate check box + const SfxPoolItem& rItem = _rCoreAttrs.Get(nItemId); + booleanSetting.bOptionalBool = dynamic_cast<const OptionalBoolItem*>(&rItem) != nullptr; + booleanSetting.xControl = m_xBuilder->weld_check_button(booleanSetting.sControlId); + if (booleanSetting.bOptionalBool) + booleanSetting.xControl->connect_toggled(LINK(this, SpecialSettingsPage, OnTriStateToggleHdl)); + else + booleanSetting.xControl->connect_toggled(LINK(this, SpecialSettingsPage, OnToggleHdl)); + booleanSetting.xControl->show(); + } + } + + // create the controls for the boolean comparison mode + if ( m_bHasBooleanComparisonMode ) + { + m_xBooleanComparisonModeLabel = m_xBuilder->weld_label("comparisonft"); + m_xBooleanComparisonMode = m_xBuilder->weld_combo_box("comparison"); + m_xBooleanComparisonMode->connect_changed(LINK(this, SpecialSettingsPage, BooleanComparisonSelectHdl)); + m_xBooleanComparisonModeLabel->show(); + m_xBooleanComparisonMode->show(); + } + // create the controls for the max row scan + if ( m_bHasMaxRowScan ) + { + m_xMaxRowScanLabel = m_xBuilder->weld_label("rowsft"); + m_xMaxRowScan = m_xBuilder->weld_spin_button("rows"); + m_xMaxRowScan->connect_value_changed(LINK(this, OGenericAdministrationPage, OnControlSpinButtonModifyHdl)); + m_xMaxRowScanLabel->show(); + m_xMaxRowScan->show(); + } + } + + IMPL_LINK(SpecialSettingsPage, OnTriStateToggleHdl, weld::ToggleButton&, rToggle, void) + { + auto eOldState = m_aTriStates[&rToggle]; + switch (eOldState) + { + case TRISTATE_INDET: + rToggle.set_state(TRISTATE_FALSE); + break; + case TRISTATE_TRUE: + rToggle.set_state(TRISTATE_INDET); + break; + case TRISTATE_FALSE: + rToggle.set_state(TRISTATE_TRUE); + break; + } + m_aTriStates[&rToggle] = rToggle.get_state(); + OnToggleHdl(rToggle); + } + + IMPL_LINK(SpecialSettingsPage, OnToggleHdl, weld::ToggleButton&, rBtn, void) + { + if (&rBtn == m_xAppendTableAlias.get() && m_xAsBeforeCorrelationName) + { + // make m_xAsBeforeCorrelationName depend on m_xAppendTableAlias + m_xAsBeforeCorrelationName->set_sensitive(m_xAppendTableAlias->get_active()); + } + OnControlModifiedButtonClick(rBtn); + } + + IMPL_LINK(SpecialSettingsPage, BooleanComparisonSelectHdl, weld::ComboBox&, rControl, void) + { + callModifiedHdl(&rControl); + } + + SpecialSettingsPage::~SpecialSettingsPage() + { + } + + void SpecialSettingsPage::fillWindows( std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList ) + { + if ( m_bHasBooleanComparisonMode ) + { + _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xBooleanComparisonModeLabel.get())); + } + if ( m_bHasMaxRowScan ) + { + _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xMaxRowScanLabel.get())); + } + } + + void SpecialSettingsPage::fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) + { + for (auto const& booleanSetting : m_aBooleanSettings) + { + if (booleanSetting.xControl) + { + _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::ToggleButton>(booleanSetting.xControl.get())); + } + } + + if ( m_bHasBooleanComparisonMode ) + _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::ComboBox>(m_xBooleanComparisonMode.get())); + if ( m_bHasMaxRowScan ) + _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::SpinButton>(m_xMaxRowScan.get())); + } + + void SpecialSettingsPage::implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) + { + // check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa) + bool bValid, bReadonly; + getFlags( _rSet, bValid, bReadonly ); + + if ( !bValid ) + { + OGenericAdministrationPage::implInitControls(_rSet, _bSaveValue); + return; + } + + m_aTriStates.clear(); + + // the boolean items + for (auto const& booleanSetting : m_aBooleanSettings) + { + if (!booleanSetting.xControl) + continue; + + bool bTriState = false; + + std::optional<bool> aValue; + + const SfxPoolItem* pItem = _rSet.GetItem<SfxPoolItem>(booleanSetting.nItemId); + if (const SfxBoolItem *pBoolItem = dynamic_cast<const SfxBoolItem*>( pItem) ) + { + aValue = pBoolItem->GetValue(); + } + else if (const OptionalBoolItem *pOptionalItem = dynamic_cast<const OptionalBoolItem*>( pItem) ) + { + aValue = pOptionalItem->GetFullValue(); + bTriState = true; + } + else + OSL_FAIL( "SpecialSettingsPage::implInitControls: unknown boolean item type!" ); + + if ( !aValue ) + { + booleanSetting.xControl->set_state(TRISTATE_INDET); + } + else + { + bool bValue = *aValue; + if ( booleanSetting.bInvertedDisplay ) + bValue = !bValue; + booleanSetting.xControl->set_active(bValue); + } + if (bTriState) + m_aTriStates[booleanSetting.xControl.get()] = booleanSetting.xControl->get_state(); + } + + if (m_xAppendTableAlias && m_xAsBeforeCorrelationName) + { + // make m_xAsBeforeCorrelationName depend on m_xAppendTableAlias + m_xAsBeforeCorrelationName->set_sensitive(m_xAppendTableAlias->get_active()); + } + + // the non-boolean items + if ( m_bHasBooleanComparisonMode ) + { + const SfxInt32Item* pBooleanComparison = _rSet.GetItem<SfxInt32Item>(DSID_BOOLEANCOMPARISON); + m_xBooleanComparisonMode->set_active(static_cast<sal_uInt16>(pBooleanComparison->GetValue())); + } + + if ( m_bHasMaxRowScan ) + { + const SfxInt32Item* pMaxRowScan = _rSet.GetItem<SfxInt32Item>(DSID_MAX_ROW_SCAN); + m_xMaxRowScan->set_value(pMaxRowScan->GetValue()); + } + + OGenericAdministrationPage::implInitControls(_rSet, _bSaveValue); + } + + bool SpecialSettingsPage::FillItemSet( SfxItemSet* _rSet ) + { + bool bChangedSomething = false; + + // the boolean items + for (auto const& booleanSetting : m_aBooleanSettings) + { + if (!booleanSetting.xControl) + continue; + fillBool(*_rSet, booleanSetting.xControl.get(), booleanSetting.nItemId, booleanSetting.bOptionalBool, bChangedSomething, booleanSetting.bInvertedDisplay); + } + + // the non-boolean items + if ( m_bHasBooleanComparisonMode ) + { + if (m_xBooleanComparisonMode->get_value_changed_from_saved()) + { + _rSet->Put(SfxInt32Item(DSID_BOOLEANCOMPARISON, m_xBooleanComparisonMode->get_active())); + bChangedSomething = true; + } + } + if ( m_bHasMaxRowScan ) + { + fillInt32(*_rSet,m_xMaxRowScan.get(),DSID_MAX_ROW_SCAN,bChangedSomething); + } + return bChangedSomething; + } + + // GeneratedValuesPage + GeneratedValuesPage::GeneratedValuesPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rCoreAttrs) + : OGenericAdministrationPage(pPage, pController, "dbaccess/ui/generatedvaluespage.ui", "GeneratedValuesPage", _rCoreAttrs) + , m_xAutoRetrievingEnabled(m_xBuilder->weld_check_button("autoretrieve")) + , m_xGrid(m_xBuilder->weld_widget("grid")) + , m_xAutoIncrementLabel(m_xBuilder->weld_label("statementft")) + , m_xAutoIncrement(m_xBuilder->weld_entry("statement")) + , m_xAutoRetrievingLabel(m_xBuilder->weld_label("queryft")) + , m_xAutoRetrieving(m_xBuilder->weld_entry("query")) + { + m_xAutoRetrievingEnabled->connect_toggled(LINK(this, GeneratedValuesPage, OnAutoToggleHdl)); + m_xAutoIncrement->connect_changed(LINK(this, OGenericAdministrationPage, OnControlEntryModifyHdl)); + m_xAutoRetrieving->connect_changed(LINK(this, OGenericAdministrationPage, OnControlEntryModifyHdl)); + } + + IMPL_LINK(GeneratedValuesPage, OnAutoToggleHdl, weld::ToggleButton&, rBtn, void) + { + m_xGrid->set_sensitive(rBtn.get_active()); + OnControlModifiedButtonClick(rBtn); + } + + GeneratedValuesPage::~GeneratedValuesPage() + { + } + + void GeneratedValuesPage::fillWindows( std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList ) + { + _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Widget>(m_xContainer.get())); + } + + void GeneratedValuesPage::fillControls( std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList ) + { + _rControlList.emplace_back( new OSaveValueWidgetWrapper<weld::ToggleButton>( m_xAutoRetrievingEnabled.get() ) ); + _rControlList.emplace_back( new OSaveValueWidgetWrapper<weld::Entry>( m_xAutoIncrement.get() ) ); + _rControlList.emplace_back( new OSaveValueWidgetWrapper<weld::Entry>( m_xAutoRetrieving.get() ) ); + } + + void GeneratedValuesPage::implInitControls( const SfxItemSet& _rSet, bool _bSaveValue ) + { + // check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa) + bool bValid, bReadonly; + getFlags(_rSet, bValid, bReadonly); + + // collect the items + const SfxStringItem* pAutoIncrementItem = _rSet.GetItem<SfxStringItem>(DSID_AUTOINCREMENTVALUE); + const SfxStringItem* pAutoRetrieveValueItem = _rSet.GetItem<SfxStringItem>(DSID_AUTORETRIEVEVALUE); + const SfxBoolItem* pAutoRetrieveEnabledItem = _rSet.GetItem<SfxBoolItem>(DSID_AUTORETRIEVEENABLED); + + // forward the values to the controls + if (bValid) + { + bool bEnabled = pAutoRetrieveEnabledItem->GetValue(); + m_xAutoRetrievingEnabled->set_active(bEnabled); + + m_xAutoIncrement->set_text(pAutoIncrementItem->GetValue()); + m_xAutoIncrement->save_value(); + m_xAutoRetrieving->set_text(pAutoRetrieveValueItem->GetValue()); + m_xAutoRetrieving->save_value(); + } + OGenericAdministrationPage::implInitControls( _rSet, _bSaveValue ); + } + + bool GeneratedValuesPage::FillItemSet(SfxItemSet* _rSet) + { + bool bChangedSomething = false; + + fillString( *_rSet, m_xAutoIncrement.get(), DSID_AUTOINCREMENTVALUE, bChangedSomething ); + fillBool( *_rSet, m_xAutoRetrievingEnabled.get(), DSID_AUTORETRIEVEENABLED, false, bChangedSomething ); + fillString( *_rSet, m_xAutoRetrieving.get(), DSID_AUTORETRIEVEVALUE, bChangedSomething ); + + return bChangedSomething; + } + + // AdvancedSettingsDialog + AdvancedSettingsDialog::AdvancedSettingsDialog(weld::Window* pParent, SfxItemSet* _pItems, + const Reference< XComponentContext >& _rxContext, const Any& _aDataSourceName ) + : SfxTabDialogController(pParent, "dbaccess/ui/advancedsettingsdialog.ui", "AdvancedSettingsDialog", _pItems) + { + m_pImpl.reset(new ODbDataSourceAdministrationHelper(_rxContext, m_xDialog.get(), pParent, this)); + m_pImpl->setDataSourceOrName(_aDataSourceName); + Reference< XPropertySet > xDatasource = m_pImpl->getCurrentDataSource(); + m_pImpl->translateProperties(xDatasource, *_pItems); + SetInputSet(_pItems); + // propagate this set as our new input set and reset the example set + m_xExampleSet.reset(new SfxItemSet(*GetInputSetImpl())); + + const OUString eType = dbaui::ODbDataSourceAdministrationHelper::getDatasourceType(*_pItems); + + DataSourceMetaData aMeta( eType ); + const FeatureSet& rFeatures( aMeta.getFeatureSet() ); + + // auto-generated values? + if (rFeatures.supportsGeneratedValues()) + AddTabPage("generated", ODriversSettings::CreateGeneratedValuesPage, nullptr); + else + RemoveTabPage("generated"); + + // any "special settings"? + if (rFeatures.supportsAnySpecialSetting()) + AddTabPage("special", ODriversSettings::CreateSpecialSettingsPage, nullptr); + else + RemoveTabPage("special"); + + // remove the reset button - it's meaning is much too ambiguous in this dialog + RemoveResetButton(); + } + + AdvancedSettingsDialog::~AdvancedSettingsDialog() + { + SetInputSet(nullptr); + } + + bool AdvancedSettingsDialog::doesHaveAnyAdvancedSettings( const OUString& _sURL ) + { + DataSourceMetaData aMeta( _sURL ); + const FeatureSet& rFeatures( aMeta.getFeatureSet() ); + return rFeatures.supportsGeneratedValues() || rFeatures.supportsAnySpecialSetting(); + } + + short AdvancedSettingsDialog::Ok() + { + short nRet = SfxTabDialogController::Ok(); + if ( nRet == RET_OK ) + { + m_xExampleSet->Put(*GetOutputItemSet()); + m_pImpl->saveChanges(*m_xExampleSet); + } + return nRet; + } + + void AdvancedSettingsDialog::PageCreated(const OString& rId, SfxTabPage& _rPage) + { + // register ourself as modified listener + static_cast<OGenericAdministrationPage&>(_rPage).SetServiceFactory( getORB() ); + static_cast<OGenericAdministrationPage&>(_rPage).SetAdminDialog(this,this); + SfxTabDialogController::PageCreated(rId, _rPage); + } + + const SfxItemSet* AdvancedSettingsDialog::getOutputSet() const + { + return m_xExampleSet.get(); + } + + SfxItemSet* AdvancedSettingsDialog::getWriteOutputSet() + { + return m_xExampleSet.get(); + } + + std::pair< Reference< XConnection >, bool > AdvancedSettingsDialog::createConnection() + { + return m_pImpl->createConnection(); + } + + Reference< XComponentContext > AdvancedSettingsDialog::getORB() const + { + return m_pImpl->getORB(); + } + + Reference< XDriver > AdvancedSettingsDialog::getDriver() + { + return m_pImpl->getDriver(); + } + + OUString AdvancedSettingsDialog::getDatasourceType(const SfxItemSet& _rSet) const + { + return dbaui::ODbDataSourceAdministrationHelper::getDatasourceType(_rSet); + } + + void AdvancedSettingsDialog::clearPassword() + { + m_pImpl->clearPassword(); + } + + void AdvancedSettingsDialog::setTitle(const OUString& _sTitle) + { + m_xDialog->set_title(_sTitle); + } + + void AdvancedSettingsDialog::enableConfirmSettings( bool ) {} + + void AdvancedSettingsDialog::saveDatasource() + { + PrepareLeaveCurrentPage(); + } + +} // namespace dbaui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/advancedsettings.hxx b/dbaccess/source/ui/dlg/advancedsettings.hxx new file mode 100644 index 000000000..8efc86428 --- /dev/null +++ b/dbaccess/source/ui/dlg/advancedsettings.hxx @@ -0,0 +1,120 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_DBACCESS_SOURCE_UI_DLG_ADVANCEDSETTINGS_HXX +#define INCLUDED_DBACCESS_SOURCE_UI_DLG_ADVANCEDSETTINGS_HXX + +#include "adminpages.hxx" +#include <dsmeta.hxx> +#include <vector> + +namespace dbaui +{ + struct BooleanSettingDesc; + typedef std::vector< BooleanSettingDesc > BooleanSettingDescs; + + // SpecialSettingsPage + // implements the "Special Settings" page of the advanced database settings + class SpecialSettingsPage final : public OGenericAdministrationPage + { + std::unique_ptr<weld::CheckButton> m_xIsSQL92Check; + std::unique_ptr<weld::CheckButton> m_xAppendTableAlias; + std::unique_ptr<weld::CheckButton> m_xAsBeforeCorrelationName; + std::unique_ptr<weld::CheckButton> m_xEnableOuterJoin; + std::unique_ptr<weld::CheckButton> m_xIgnoreDriverPrivileges; + std::unique_ptr<weld::CheckButton> m_xParameterSubstitution; + std::unique_ptr<weld::CheckButton> m_xSuppressVersionColumn; + std::unique_ptr<weld::CheckButton> m_xCatalog; + std::unique_ptr<weld::CheckButton> m_xSchema; + std::unique_ptr<weld::CheckButton> m_xIndexAppendix; + std::unique_ptr<weld::CheckButton> m_xDosLineEnds; + std::unique_ptr<weld::CheckButton> m_xCheckRequiredFields; + std::unique_ptr<weld::CheckButton> m_xIgnoreCurrency; + std::unique_ptr<weld::CheckButton> m_xEscapeDateTime; + std::unique_ptr<weld::CheckButton> m_xPrimaryKeySupport; + std::unique_ptr<weld::CheckButton> m_xRespectDriverResultSetType; + + std::unique_ptr<weld::Label> m_xBooleanComparisonModeLabel; + std::unique_ptr<weld::ComboBox> m_xBooleanComparisonMode; + + std::unique_ptr<weld::Label> m_xMaxRowScanLabel; + std::unique_ptr<weld::SpinButton> m_xMaxRowScan; + + std::map<weld::ToggleButton*, TriState> m_aTriStates; + + BooleanSettingDescs m_aBooleanSettings; + + bool m_bHasBooleanComparisonMode; + bool m_bHasMaxRowScan; + + public: + DECL_LINK(OnToggleHdl, weld::ToggleButton&, void); + DECL_LINK(OnTriStateToggleHdl, weld::ToggleButton&, void); + + virtual bool FillItemSet ( SfxItemSet* _rCoreAttrs ) override; + + SpecialSettingsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rCoreAttrs, const DataSourceMetaData& _rDSMeta); + virtual ~SpecialSettingsPage() override; + + private: + // OGenericAdministrationPage overridables + virtual void implInitControls (const SfxItemSet& _rSet, bool _bSaveValue ) override; + + // <method>OGenericAdministrationPage::fillControls</method> + virtual void fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override; + + // <method>OGenericAdministrationPage::fillWindows</method> + virtual void fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override; + + DECL_LINK(BooleanComparisonSelectHdl, weld::ComboBox&, void); + }; + + // GeneratedValuesPage + class GeneratedValuesPage final : public OGenericAdministrationPage + { + std::unique_ptr<weld::CheckButton> m_xAutoRetrievingEnabled; + std::unique_ptr<weld::Widget> m_xGrid; + std::unique_ptr<weld::Label> m_xAutoIncrementLabel; + std::unique_ptr<weld::Entry> m_xAutoIncrement; + std::unique_ptr<weld::Label> m_xAutoRetrievingLabel; + std::unique_ptr<weld::Entry> m_xAutoRetrieving; + + public: + virtual bool FillItemSet (SfxItemSet* _rCoreAttrs) override; + + GeneratedValuesPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rCoreAttrs); + virtual ~GeneratedValuesPage() override; + + private: + DECL_LINK(OnAutoToggleHdl, weld::ToggleButton&, void); + + // subclasses must override this, but it isn't pure virtual + virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override; + + // <method>OGenericAdministrationPage::fillControls</method> + virtual void fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override; + + // <method>OGenericAdministrationPage::fillWindows</method> + virtual void fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override; + }; +} + +#endif // INCLUDED_DBACCESS_SOURCE_UI_DLG_ADVANCEDSETTINGS_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/dbadmin.cxx b/dbaccess/source/ui/dlg/dbadmin.cxx new file mode 100644 index 000000000..e37541bfd --- /dev/null +++ b/dbaccess/source/ui/dlg/dbadmin.cxx @@ -0,0 +1,432 @@ +/* -*- 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 "ConnectionPage.hxx" +#include "DbAdminImpl.hxx" +#include "DriverSettings.hxx" +#include "adminpages.hxx" +#include <dbadmin.hxx> +#include <svl/stritem.hxx> +#include <svl/eitem.hxx> +#include <svl/intitem.hxx> +#include <core_resource.hxx> +#include <strings.hrc> +#include <dsitems.hxx> +#include "dsnItem.hxx" +#include "optionalboolitem.hxx" +#include <stringlistitem.hxx> + +#include <unotools/confignode.hxx> + +namespace dbaui +{ +using namespace com::sun::star::uno; +using namespace com::sun::star::sdbc; +using namespace com::sun::star::lang; +using namespace com::sun::star::util; +using namespace com::sun::star::beans; +using namespace com::sun::star::container; + +// ODbAdminDialog +ODbAdminDialog::ODbAdminDialog(weld::Window* pParent, + SfxItemSet const * _pItems, + const Reference< XComponentContext >& _rxContext) + : SfxTabDialogController(pParent, "dbaccess/ui/admindialog.ui", "AdminDialog", _pItems) + , m_sMainPageID("advanced") +{ + m_pImpl.reset(new ODbDataSourceAdministrationHelper(_rxContext, m_xDialog.get(), pParent, this)); + + // add the initial tab page + AddTabPage(m_sMainPageID, OConnectionTabPage::Create, nullptr); + + // remove the reset button - it's meaning is much too ambiguous in this dialog + RemoveResetButton(); +} + +ODbAdminDialog::~ODbAdminDialog() +{ + SetInputSet(nullptr); +} + +short ODbAdminDialog::Ok() +{ + SfxTabDialogController::Ok(); + return ( AR_LEAVE_MODIFIED == implApplyChanges() ) ? RET_OK : RET_CANCEL; + // TODO : AR_ERROR is not handled correctly, we always close the dialog here +} + +void ODbAdminDialog::PageCreated(const OString& rId, SfxTabPage& _rPage) +{ + // register ourself as modified listener + static_cast<OGenericAdministrationPage&>(_rPage).SetServiceFactory( getORB() ); + static_cast<OGenericAdministrationPage&>(_rPage).SetAdminDialog(this,this); + + SfxTabDialogController::PageCreated(rId, _rPage); +} + +void ODbAdminDialog::addDetailPage(const OString& rPageId, const char* pTextId, CreateTabPage pCreateFunc) +{ + AddTabPage(rPageId, DBA_RES(pTextId), pCreateFunc); +} + +void ODbAdminDialog::impl_selectDataSource(const css::uno::Any& _aDataSourceName) +{ + m_pImpl->setDataSourceOrName(_aDataSourceName); + Reference< XPropertySet > xDatasource = m_pImpl->getCurrentDataSource(); + impl_resetPages( xDatasource ); + + const DbuTypeCollectionItem& rCollectionItem = dynamic_cast<const DbuTypeCollectionItem&>(*getOutputSet()->GetItem(DSID_TYPECOLLECTION)); + ::dbaccess::ODsnTypeCollection* pCollection = rCollectionItem.getCollection(); + ::dbaccess::DATASOURCE_TYPE eType = pCollection->determineType(getDatasourceType(*getOutputSet())); + + // and insert the new ones + switch ( eType ) + { + case ::dbaccess::DST_DBASE: + addDetailPage("dbase", STR_PAGETITLE_ADVANCED, ODriversSettings::CreateDbase); + break; + + case ::dbaccess::DST_ADO: + addDetailPage("ado", STR_PAGETITLE_ADVANCED, ODriversSettings::CreateAdo); + break; + + case ::dbaccess::DST_FLAT: + addDetailPage("text", STR_PAGETITLE_ADVANCED, ODriversSettings::CreateText); + break; + + case ::dbaccess::DST_ODBC: + addDetailPage("odbc", STR_PAGETITLE_ADVANCED, ODriversSettings::CreateODBC); + break; + + case ::dbaccess::DST_MYSQL_ODBC: + addDetailPage("mysqlodbc", STR_PAGETITLE_ADVANCED, ODriversSettings::CreateMySQLODBC); + break; + + case ::dbaccess::DST_MYSQL_JDBC: + addDetailPage("mysqljdbc", STR_PAGETITLE_ADVANCED, ODriversSettings::CreateMySQLJDBC); + break; + + case ::dbaccess::DST_ORACLE_JDBC: + addDetailPage("oraclejdbc", STR_PAGETITLE_ADVANCED, ODriversSettings::CreateOracleJDBC); + break; + + case ::dbaccess::DST_LDAP: + addDetailPage("ldap",STR_PAGETITLE_ADVANCED,ODriversSettings::CreateLDAP); + break; + case ::dbaccess::DST_USERDEFINE1: /// first user defined driver + case ::dbaccess::DST_USERDEFINE2: + case ::dbaccess::DST_USERDEFINE3: + case ::dbaccess::DST_USERDEFINE4: + case ::dbaccess::DST_USERDEFINE5: + case ::dbaccess::DST_USERDEFINE6: + case ::dbaccess::DST_USERDEFINE7: + case ::dbaccess::DST_USERDEFINE8: + case ::dbaccess::DST_USERDEFINE9: + case ::dbaccess::DST_USERDEFINE10: + { + OUString aTitle(DBA_RES(STR_PAGETITLE_ADVANCED)); + AddTabPage("user" + OString::number(eType - dbaccess::DST_USERDEFINE1 + 1), aTitle, ODriversSettings::CreateUser); + } + break; + default: + break; + } +} + +void ODbAdminDialog::impl_resetPages(const Reference< XPropertySet >& _rxDatasource) +{ + // the selection is valid if and only if we have a datasource now + GetInputSetImpl()->Put(SfxBoolItem(DSID_INVALID_SELECTION, !_rxDatasource.is())); + // (sal_False tells the tab pages to disable and reset all their controls, which is different + // from "just set them to readonly") + + // reset the pages + + // prevent flicker + m_xDialog->freeze(); + + // remove all items which relate to indirect properties from the input set + // (without this, the following may happen: select an arbitrary data source where some indirect properties + // are set. Select another data source of the same type, where the indirect props are not set (yet). Then, + // the indirect property values of the first ds are shown in the second ds ...) + const ODbDataSourceAdministrationHelper::MapInt2String& rMap = m_pImpl->getIndirectProperties(); + for (auto const& elem : rMap) + GetInputSetImpl()->ClearItem( static_cast<sal_uInt16>(elem.first) ); + + // extract all relevant data from the property set of the data source + m_pImpl->translateProperties(_rxDatasource, *GetInputSetImpl()); + + // reset the example set + m_xExampleSet.reset(new SfxItemSet(*GetInputSetImpl())); + + // special case: MySQL Native does not have the generic "advanced" page + + const DbuTypeCollectionItem& rCollectionItem = dynamic_cast<const DbuTypeCollectionItem&>(*getOutputSet()->GetItem(DSID_TYPECOLLECTION)); + ::dbaccess::ODsnTypeCollection* pCollection = rCollectionItem.getCollection(); + if ( pCollection->determineType(getDatasourceType( *m_xExampleSet )) == ::dbaccess::DST_MYSQL_NATIVE ) + { + OString sMySqlNative("mysqlnative"); + AddTabPage(sMySqlNative, DBA_RES(STR_PAGETITLE_CONNECTION), ODriversSettings::CreateMySQLNATIVE); + RemoveTabPage("advanced"); + m_sMainPageID = sMySqlNative; + } + + SetCurPageId(m_sMainPageID); + SfxTabPage* pConnectionPage = GetTabPage(m_sMainPageID); + if ( pConnectionPage ) + pConnectionPage->Reset(GetInputSetImpl()); + // if this is NULL, the page has not been created yet, which means we're called before the + // dialog was displayed (probably from inside the ctor) + + m_xDialog->thaw(); +} + +void ODbAdminDialog::setTitle(const OUString& rTitle) +{ + m_xDialog->set_title(rTitle); +} + +void ODbAdminDialog::enableConfirmSettings( bool ) {} + +void ODbAdminDialog::saveDatasource() +{ + PrepareLeaveCurrentPage(); +} + +ODbAdminDialog::ApplyResult ODbAdminDialog::implApplyChanges() +{ + if (!PrepareLeaveCurrentPage()) + { // the page did not allow us to leave + return AR_KEEP; + } + + if ( !m_pImpl->saveChanges(*m_xExampleSet) ) + return AR_KEEP; + + return AR_LEAVE_MODIFIED; +} + +void ODbAdminDialog::selectDataSource(const css::uno::Any& _aDataSourceName) +{ + impl_selectDataSource(_aDataSourceName); +} + +const SfxItemSet* ODbAdminDialog::getOutputSet() const +{ + return GetExampleSet(); +} + +SfxItemSet* ODbAdminDialog::getWriteOutputSet() +{ + return m_xExampleSet.get(); +} + +std::pair< Reference<XConnection>,bool> ODbAdminDialog::createConnection() +{ + return m_pImpl->createConnection(); +} + +Reference< XComponentContext > ODbAdminDialog::getORB() const +{ + return m_pImpl->getORB(); +} + +Reference< XDriver > ODbAdminDialog::getDriver() +{ + return m_pImpl->getDriver(); +} + +OUString ODbAdminDialog::getDatasourceType(const SfxItemSet& _rSet) const +{ + return dbaui::ODbDataSourceAdministrationHelper::getDatasourceType(_rSet); +} + +void ODbAdminDialog::clearPassword() +{ + m_pImpl->clearPassword(); +} + +void ODbAdminDialog::createItemSet(std::unique_ptr<SfxItemSet>& _rpSet, SfxItemPool*& _rpPool, std::vector<SfxPoolItem*>*& _rpDefaults, ::dbaccess::ODsnTypeCollection* _pTypeCollection) +{ + // just to be sure... + _rpSet = nullptr; + _rpPool = nullptr; + _rpDefaults = nullptr; + + const OUString sFilterAll( "%" ); + // create and initialize the defaults + _rpDefaults = new std::vector<SfxPoolItem*>(DSID_LAST_ITEM_ID - DSID_FIRST_ITEM_ID + 1); + SfxPoolItem** pCounter = _rpDefaults->data(); // want to modify this without affecting the out param _rppDefaults + *pCounter++ = new SfxStringItem(DSID_NAME, OUString()); + *pCounter++ = new SfxStringItem(DSID_ORIGINALNAME, OUString()); + *pCounter++ = new SfxStringItem(DSID_CONNECTURL, OUString()); + *pCounter++ = new OStringListItem(DSID_TABLEFILTER, Sequence< OUString >(&sFilterAll, 1)); + *pCounter++ = new DbuTypeCollectionItem(DSID_TYPECOLLECTION, _pTypeCollection); + *pCounter++ = new SfxBoolItem(DSID_INVALID_SELECTION, false); + *pCounter++ = new SfxBoolItem(DSID_READONLY, false); + *pCounter++ = new SfxStringItem(DSID_USER, OUString()); + *pCounter++ = new SfxStringItem(DSID_PASSWORD, OUString()); + *pCounter++ = new SfxStringItem(DSID_ADDITIONALOPTIONS, OUString()); + *pCounter++ = new SfxStringItem(DSID_CHARSET, OUString()); + *pCounter++ = new SfxBoolItem(DSID_PASSWORDREQUIRED, false); + *pCounter++ = new SfxBoolItem(DSID_SHOWDELETEDROWS, false); + *pCounter++ = new SfxBoolItem(DSID_ALLOWLONGTABLENAMES, false); + *pCounter++ = new SfxStringItem(DSID_JDBCDRIVERCLASS, OUString()); + *pCounter++ = new SfxStringItem(DSID_FIELDDELIMITER, OUString(',')); + *pCounter++ = new SfxStringItem(DSID_TEXTDELIMITER, OUString('"')); + *pCounter++ = new SfxStringItem(DSID_DECIMALDELIMITER, OUString('.')); + *pCounter++ = new SfxStringItem(DSID_THOUSANDSDELIMITER, OUString()); + *pCounter++ = new SfxStringItem(DSID_TEXTFILEEXTENSION, "txt"); + *pCounter++ = new SfxBoolItem(DSID_TEXTFILEHEADER, true); + *pCounter++ = new SfxBoolItem(DSID_PARAMETERNAMESUBST, false); + *pCounter++ = new SfxInt32Item(DSID_CONN_PORTNUMBER, 8100); + *pCounter++ = new SfxBoolItem(DSID_SUPPRESSVERSIONCL, false); + *pCounter++ = new SfxBoolItem(DSID_CONN_SHUTSERVICE, false); + *pCounter++ = new SfxInt32Item(DSID_CONN_DATAINC, 20); + *pCounter++ = new SfxInt32Item(DSID_CONN_CACHESIZE, 20); + *pCounter++ = new SfxStringItem(DSID_CONN_CTRLUSER, OUString()); + *pCounter++ = new SfxStringItem(DSID_CONN_CTRLPWD, OUString()); + *pCounter++ = new SfxBoolItem(DSID_USECATALOG, false); + *pCounter++ = new SfxStringItem(DSID_CONN_HOSTNAME, OUString()); + *pCounter++ = new SfxStringItem(DSID_CONN_LDAP_BASEDN, OUString()); + *pCounter++ = new SfxInt32Item(DSID_CONN_LDAP_PORTNUMBER, 389); + *pCounter++ = new SfxInt32Item(DSID_CONN_LDAP_ROWCOUNT, 100); + *pCounter++ = new SfxBoolItem(DSID_SQL92CHECK, false); + *pCounter++ = new SfxStringItem(DSID_AUTOINCREMENTVALUE, OUString()); + *pCounter++ = new SfxStringItem(DSID_AUTORETRIEVEVALUE, OUString()); + *pCounter++ = new SfxBoolItem(DSID_AUTORETRIEVEENABLED, false); + *pCounter++ = new SfxBoolItem(DSID_APPEND_TABLE_ALIAS, false); + *pCounter++ = new SfxInt32Item(DSID_MYSQL_PORTNUMBER, 3306); + *pCounter++ = new SfxBoolItem(DSID_IGNOREDRIVER_PRIV, true); + *pCounter++ = new SfxInt32Item(DSID_BOOLEANCOMPARISON, 0); + *pCounter++ = new SfxInt32Item(DSID_ORACLE_PORTNUMBER, 1521); + *pCounter++ = new SfxBoolItem(DSID_ENABLEOUTERJOIN, true); + *pCounter++ = new SfxBoolItem(DSID_CATALOG, true); + *pCounter++ = new SfxBoolItem(DSID_SCHEMA, true); + *pCounter++ = new SfxBoolItem(DSID_INDEXAPPENDIX, true); + *pCounter++ = new SfxBoolItem(DSID_CONN_LDAP_USESSL, false); + *pCounter++ = new SfxStringItem(DSID_DOCUMENT_URL, OUString()); + *pCounter++ = new SfxBoolItem(DSID_DOSLINEENDS, false); + *pCounter++ = new SfxStringItem(DSID_DATABASENAME, OUString()); + *pCounter++ = new SfxBoolItem(DSID_AS_BEFORE_CORRNAME, false); + *pCounter++ = new SfxBoolItem(DSID_CHECK_REQUIRED_FIELDS, true); + *pCounter++ = new SfxBoolItem(DSID_IGNORECURRENCY, false); + *pCounter++ = new SfxStringItem(DSID_CONN_SOCKET, OUString()); + *pCounter++ = new SfxBoolItem(DSID_ESCAPE_DATETIME, true); + *pCounter++ = new SfxStringItem(DSID_NAMED_PIPE, OUString()); + *pCounter++ = new OptionalBoolItem( DSID_PRIMARY_KEY_SUPPORT ); + *pCounter++ = new SfxInt32Item(DSID_MAX_ROW_SCAN, 100); + *pCounter++ = new SfxBoolItem( DSID_RESPECTRESULTSETTYPE,false ); + + // create the pool + static SfxItemInfo const aItemInfos[DSID_LAST_ITEM_ID - DSID_FIRST_ITEM_ID + 1] = + { + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + {0,false}, + }; + + OSL_ENSURE(SAL_N_ELEMENTS(aItemInfos) == DSID_LAST_ITEM_ID,"Invalid Ids!"); + _rpPool = new SfxItemPool("DSAItemPool", DSID_FIRST_ITEM_ID, DSID_LAST_ITEM_ID, + aItemInfos, _rpDefaults); + _rpPool->FreezeIdRanges(); + + // and, finally, the set + _rpSet.reset(new SfxItemSet(*_rpPool)); +} + +void ODbAdminDialog::destroyItemSet(std::unique_ptr<SfxItemSet>& _rpSet, SfxItemPool*& _rpPool, std::vector<SfxPoolItem*>*& _rpDefaults) +{ + // _first_ delete the set (referring the pool) + _rpSet.reset(); + + // delete the pool + if (_rpPool) + { + _rpPool->ReleaseDefaults(true); + // the "true" means delete the items, too + SfxItemPool::Free(_rpPool); + _rpPool = nullptr; + } + + // reset the defaults ptr + _rpDefaults = nullptr; + // no need to explicitly delete the defaults, this has been done by the ReleaseDefaults +} + +} // namespace dbaui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/dbfindex.cxx b/dbaccess/source/ui/dlg/dbfindex.cxx new file mode 100644 index 000000000..84635980b --- /dev/null +++ b/dbaccess/source/ui/dlg/dbfindex.cxx @@ -0,0 +1,430 @@ +/* -*- 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 "dbfindex.hxx" +#include <comphelper/processfactory.hxx> +#include <osl/file.hxx> +#include <osl/thread.hxx> +#include <tools/config.hxx> +#include <osl/diagnose.h> +#include <unotools/localfilehelper.hxx> +#include <tools/urlobj.hxx> +#include <unotools/pathoptions.hxx> +#include <ucbhelper/content.hxx> +#include <svl/filenotation.hxx> +#include <rtl/strbuf.hxx> + +namespace dbaui +{ +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ucb; +using namespace ::svt; + +const OString aGroupIdent("dBase III"); + + +ODbaseIndexDialog::ODbaseIndexDialog(weld::Window * pParent, const OUString& aDataSrcName) + : GenericDialogController(pParent, "dbaccess/ui/dbaseindexdialog.ui", "DBaseIndexDialog") + , m_aDSN(aDataSrcName) + , m_xPB_OK(m_xBuilder->weld_button("ok")) + , m_xCB_Tables(m_xBuilder->weld_combo_box("table")) + , m_xIndexes(m_xBuilder->weld_widget("frame")) + , m_xLB_TableIndexes(m_xBuilder->weld_tree_view("tableindex")) + , m_xLB_FreeIndexes(m_xBuilder->weld_tree_view("freeindex")) + , m_xAdd(m_xBuilder->weld_button("add")) + , m_xRemove(m_xBuilder->weld_button("remove")) + , m_xAddAll(m_xBuilder->weld_button("addall")) + , m_xRemoveAll(m_xBuilder->weld_button("removeall")) +{ + int nWidth = m_xLB_TableIndexes->get_approximate_digit_width() * 18; + int nHeight = m_xLB_TableIndexes->get_height_rows(10); + m_xLB_TableIndexes->set_size_request(nWidth, nHeight); + m_xLB_FreeIndexes->set_size_request(nWidth, nHeight); + + m_xCB_Tables->connect_changed( LINK(this, ODbaseIndexDialog, TableSelectHdl) ); + m_xAdd->connect_clicked( LINK(this, ODbaseIndexDialog, AddClickHdl) ); + m_xRemove->connect_clicked( LINK(this, ODbaseIndexDialog, RemoveClickHdl) ); + m_xAddAll->connect_clicked( LINK(this, ODbaseIndexDialog, AddAllClickHdl) ); + m_xRemoveAll->connect_clicked( LINK(this, ODbaseIndexDialog, RemoveAllClickHdl) ); + m_xPB_OK->connect_clicked( LINK(this, ODbaseIndexDialog, OKClickHdl) ); + + m_xLB_FreeIndexes->connect_changed( LINK(this, ODbaseIndexDialog, OnListEntrySelected) ); + m_xLB_TableIndexes->connect_changed( LINK(this, ODbaseIndexDialog, OnListEntrySelected) ); + + Init(); + SetCtrls(); +} + +ODbaseIndexDialog::~ODbaseIndexDialog() +{ +} + +void ODbaseIndexDialog::checkButtons() +{ + m_xAdd->set_sensitive(0 != m_xLB_FreeIndexes->count_selected_rows()); + m_xAddAll->set_sensitive(0 != m_xLB_FreeIndexes->n_children()); + + m_xRemove->set_sensitive(0 != m_xLB_TableIndexes->count_selected_rows()); + m_xRemoveAll->set_sensitive(0 != m_xLB_TableIndexes->n_children()); +} + +OTableIndex ODbaseIndexDialog::implRemoveIndex(const OUString& _rName, TableIndexList& _rList, weld::TreeView& _rDisplay, bool _bMustExist) +{ + OTableIndex aReturn; + + TableIndexList::iterator aSearch = std::find_if(_rList.begin(), _rList.end(), + [&_rName](const OTableIndex& rIndex) { return rIndex.GetIndexFileName() == _rName; }); + if (aSearch != _rList.end()) + { + sal_Int32 nPos = static_cast<sal_Int32>(std::distance(_rList.begin(), aSearch)); + + aReturn = *aSearch; + + _rList.erase(aSearch); + _rDisplay.remove_text(_rName); + + // adjust selection if necessary + if (static_cast<sal_uInt32>(nPos) == _rList.size()) + _rDisplay.select(static_cast<sal_uInt16>(nPos)-1); + else + _rDisplay.select(static_cast<sal_uInt16>(nPos)); + } + OSL_ENSURE(!_bMustExist || !aReturn.GetIndexFileName().isEmpty(), "ODbaseIndexDialog::implRemoveIndex : did not find the index!"); + return aReturn; +} + +void ODbaseIndexDialog::implInsertIndex(const OTableIndex& _rIndex, TableIndexList& _rList, weld::TreeView& _rDisplay) +{ + _rList.push_front(_rIndex); + _rDisplay.append_text(_rIndex.GetIndexFileName()); + _rDisplay.select(0); +} + +OTableIndex ODbaseIndexDialog::RemoveTableIndex( const OUString& _rTableName, const OUString& _rIndexName ) +{ + OTableIndex aReturn; + + // does the table exist ? + TableInfoList::iterator aTablePos = std::find_if(m_aTableInfoList.begin(), m_aTableInfoList.end(), + [&] (const OTableInfo& arg) { return arg.aTableName == _rTableName; }); + + if (aTablePos == m_aTableInfoList.end()) + return aReturn; + + return implRemoveIndex(_rIndexName, aTablePos->aIndexList, *m_xLB_TableIndexes, true/*_bMustExist*/); +} + +void ODbaseIndexDialog::InsertTableIndex( const OUString& _rTableName, const OTableIndex& _rIndex) +{ + TableInfoList::iterator aTablePos = std::find_if(m_aTableInfoList.begin(), m_aTableInfoList.end(), + [&] (const OTableInfo& arg) { return arg.aTableName == _rTableName; }); + + if (aTablePos == m_aTableInfoList.end()) + return; + + implInsertIndex(_rIndex, aTablePos->aIndexList, *m_xLB_TableIndexes); +} + +IMPL_LINK_NOARG(ODbaseIndexDialog, OKClickHdl, weld::Button&, void) +{ + // let all tables write their INF file + + for (auto const& tableInfo : m_aTableInfoList) + tableInfo.WriteInfFile(m_aDSN); + + m_xDialog->response(RET_OK); +} + +IMPL_LINK_NOARG(ODbaseIndexDialog, AddClickHdl, weld::Button&, void) +{ + OUString aSelection = m_xLB_FreeIndexes->get_selected_text(); + OUString aTableName = m_xCB_Tables->get_active_text(); + OTableIndex aIndex = RemoveFreeIndex( aSelection, true ); + InsertTableIndex( aTableName, aIndex ); + + checkButtons(); +} + +IMPL_LINK_NOARG(ODbaseIndexDialog, RemoveClickHdl, weld::Button&, void) +{ + OUString aSelection = m_xLB_TableIndexes->get_selected_text(); + OUString aTableName = m_xCB_Tables->get_active_text(); + OTableIndex aIndex = RemoveTableIndex( aTableName, aSelection ); + InsertFreeIndex( aIndex ); + + checkButtons(); +} + +IMPL_LINK_NOARG(ODbaseIndexDialog, AddAllClickHdl, weld::Button&, void) +{ + const sal_Int32 nCnt = m_xLB_FreeIndexes->n_children(); + OUString aTableName = m_xCB_Tables->get_active_text(); + + for (sal_Int32 nPos = 0; nPos < nCnt; ++nPos) + InsertTableIndex(aTableName, RemoveFreeIndex(m_xLB_FreeIndexes->get_text(0), true)); + + checkButtons(); +} + +IMPL_LINK_NOARG(ODbaseIndexDialog, RemoveAllClickHdl, weld::Button&, void) +{ + const sal_Int32 nCnt = m_xLB_TableIndexes->n_children(); + OUString aTableName = m_xCB_Tables->get_active_text(); + + for (sal_Int32 nPos = 0; nPos < nCnt; ++nPos) + InsertFreeIndex(RemoveTableIndex(aTableName, m_xLB_TableIndexes->get_text(0))); + + checkButtons(); +} + +IMPL_LINK_NOARG(ODbaseIndexDialog, OnListEntrySelected, weld::TreeView&, void) +{ + checkButtons(); +} + +IMPL_LINK(ODbaseIndexDialog, TableSelectHdl, weld::ComboBox&, rComboBox, void) +{ + // search the table + TableInfoList::iterator aTablePos = std::find_if(m_aTableInfoList.begin(), m_aTableInfoList.end(), + [&] (const OTableInfo& arg) { return arg.aTableName == rComboBox.get_active_text() ; }); + + if (aTablePos == m_aTableInfoList.end()) + return; + + // fill the listbox for the indexes + m_xLB_TableIndexes->clear(); + for (auto const& index : aTablePos->aIndexList) + m_xLB_TableIndexes->append_text(index.GetIndexFileName()); + + if (!aTablePos->aIndexList.empty()) + m_xLB_TableIndexes->select(0); + + checkButtons(); +} + +void ODbaseIndexDialog::Init() +{ + m_xPB_OK->set_sensitive(false); + m_xIndexes->set_sensitive(false); + + // All indices are first added to a list of free indices. + // Afterwards, check the index of each table in the Inf-file. + // These indices are removed from the list of free indices and + // entered in the indexlist of the table. + + // if the string does not contain a path, cut the string + INetURLObject aURL; + aURL.SetSmartProtocol(INetProtocol::File); + { + SvtPathOptions aPathOptions; + m_aDSN = aPathOptions.SubstituteVariable(m_aDSN); + } + aURL.SetSmartURL(m_aDSN); + + // String aFileName = aURL.PathToFileName(); + m_aDSN = aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE); + ::ucbhelper::Content aFile; + bool bFolder=true; + try + { + aFile = ::ucbhelper::Content(m_aDSN,Reference< css::ucb::XCommandEnvironment >(), comphelper::getProcessComponentContext()); + bFolder = aFile.isFolder(); + } + catch(Exception&) + { + return; + } + + // first assume for all indexes they're free + + OUString const aIndexExt("ndx"); + OUString const aTableExt("dbf"); + + std::vector< OUString > aUsedIndexes; + + aURL.SetSmartProtocol(INetProtocol::File); + const Sequence<OUString> aFolderUrls = ::utl::LocalFileHelper::GetFolderContents(m_aDSN, bFolder); + for(const OUString& rURL : aFolderUrls) + { + OUString aName; + osl::FileBase::getSystemPathFromFileURL(rURL,aName); + aURL.SetSmartURL(aName); + OUString aExt = aURL.getExtension(); + if (aExt == aIndexExt) + { + m_aFreeIndexList.emplace_back(aURL.getName() ); + } + else if (aExt == aTableExt) + { + m_aTableInfoList.emplace_back(aURL.getName() ); + OTableInfo& rTabInfo = m_aTableInfoList.back(); + + // open the INF file + aURL.setExtension("inf"); + OFileNotation aTransformer(aURL.GetURLNoPass(), OFileNotation::N_URL); + Config aInfFile( aTransformer.get(OFileNotation::N_SYSTEM) ); + aInfFile.SetGroup( aGroupIdent ); + + // fill the indexes list + OString aNDX; + sal_uInt16 nKeyCnt = aInfFile.GetKeyCount(); + OString aKeyName; + OUString aEntry; + + for( sal_uInt16 nKey = 0; nKey < nKeyCnt; nKey++ ) + { + // does the key point to an index file ? + aKeyName = aInfFile.GetKeyName( nKey ); + aNDX = aKeyName.copy(0,3); + + // yes -> add to the tables index list + if (aNDX == "NDX") + { + aEntry = OStringToOUString(aInfFile.ReadKey(aKeyName), osl_getThreadTextEncoding()); + rTabInfo.aIndexList.emplace_back( aEntry ); + + // and remove it from the free index list + aUsedIndexes.push_back(aEntry); + // do this later below. We may not have encountered the index file, yet, thus we may not + // know the index as being free, yet + } + } + } + } + + for (auto const& usedIndex : aUsedIndexes) + RemoveFreeIndex( usedIndex, false ); + + if (!m_aTableInfoList.empty()) + { + m_xPB_OK->set_sensitive(true); + m_xIndexes->set_sensitive(true); + } + + checkButtons(); +} + +void ODbaseIndexDialog::SetCtrls() +{ + // ComboBox tables + for (auto const& tableInfo : m_aTableInfoList) + m_xCB_Tables->append_text(tableInfo.aTableName); + + // put the first dataset into Edit + if (!m_aTableInfoList.empty()) + { + const OTableInfo& rTabInfo = m_aTableInfoList.front(); + m_xCB_Tables->set_entry_text(rTabInfo.aTableName); + + // build ListBox of the table indices + for (auto const& index : rTabInfo.aIndexList) + m_xLB_TableIndexes->append_text(index.GetIndexFileName()); + + if (!rTabInfo.aIndexList.empty()) + m_xLB_TableIndexes->select(0); + } + + // ListBox of the free indices + for (auto const& freeIndex : m_aFreeIndexList) + m_xLB_FreeIndexes->append_text(freeIndex.GetIndexFileName()); + + if (!m_aFreeIndexList.empty()) + m_xLB_FreeIndexes->select(0); + + TableSelectHdl(*m_xCB_Tables); + checkButtons(); +} + +void OTableInfo::WriteInfFile( const OUString& rDSN ) const +{ + // open INF file + INetURLObject aURL; + aURL.SetSmartProtocol(INetProtocol::File); + OUString aDsn = rDSN; + { + SvtPathOptions aPathOptions; + aDsn = aPathOptions.SubstituteVariable(aDsn); + } + aURL.SetSmartURL(aDsn); + aURL.Append(aTableName); + aURL.setExtension("inf"); + + OFileNotation aTransformer(aURL.GetURLNoPass(), OFileNotation::N_URL); + Config aInfFile( aTransformer.get(OFileNotation::N_SYSTEM) ); + aInfFile.SetGroup( aGroupIdent ); + + // first, delete all table indices + OString aNDX; + sal_uInt16 nKeyCnt = aInfFile.GetKeyCount(); + sal_uInt16 nKey = 0; + + while( nKey < nKeyCnt ) + { + // Does the key point to an index file?... + OString aKeyName = aInfFile.GetKeyName( nKey ); + aNDX = aKeyName.copy(0,3); + + //...if yes, delete index file, nKey is at subsequent key + if (aNDX == "NDX") + { + aInfFile.DeleteKey(aKeyName); + nKeyCnt--; + } + else + nKey++; + + } + + // now add all saved indices + sal_uInt16 nPos = 0; + for (auto const& index : aIndexList) + { + OStringBuffer aKeyName("NDX"); + if( nPos > 0 ) // first index contains no number + aKeyName.append(static_cast<sal_Int32>(nPos)); + aInfFile.WriteKey( + aKeyName.makeStringAndClear(), + OUStringToOString(index.GetIndexFileName(), + osl_getThreadTextEncoding())); + ++nPos; + } + + aInfFile.Flush(); + + // if only [dbase] is left in INF-file, delete file + if(nPos) + return; + + try + { + ::ucbhelper::Content aContent(aURL.GetURLNoPass(),Reference<XCommandEnvironment>(), comphelper::getProcessComponentContext()); + aContent.executeCommand( "delete", makeAny( true ) ); + } + catch (const Exception& ) + { + // simply silent this. The strange algorithm here does a lot of + // things even if no files at all were created or accessed, so it's + // possible that the file we're trying to delete does not even + // exist, and this is a valid condition. + } +} + +} // namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/dbfindex.hxx b/dbaccess/source/ui/dlg/dbfindex.hxx new file mode 100644 index 000000000..d0c23a416 --- /dev/null +++ b/dbaccess/source/ui/dlg/dbfindex.hxx @@ -0,0 +1,113 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_DBACCESS_SOURCE_UI_DLG_DBFINDEX_HXX +#define INCLUDED_DBACCESS_SOURCE_UI_DLG_DBFINDEX_HXX + +#include <vcl/weld.hxx> +#include <deque> + +namespace dbaui +{ + +// OTableIndex +/// represents a single dbf index +class OTableIndex +{ +private: + OUString aIndexFileName; + +public: + OTableIndex() { } + explicit OTableIndex( const OUString& rFileName ) : aIndexFileName( rFileName ) { } + + const OUString& GetIndexFileName() const { return aIndexFileName; } +}; + +typedef std::deque< OTableIndex > TableIndexList; + +// OTableInfo +class ODbaseIndexDialog; +/** holds the INF file of a table +*/ +class OTableInfo +{ + friend class ODbaseIndexDialog; +private: + OUString aTableName; + TableIndexList aIndexList; + +public: + explicit OTableInfo( const OUString& rName ) : aTableName(rName) { } + + void WriteInfFile( const OUString& rDSN ) const; +}; + +typedef std::deque< OTableInfo > TableInfoList; + +// IndexDialog +class ODbaseIndexDialog : public weld::GenericDialogController +{ +protected: + OUString m_aDSN; + TableInfoList m_aTableInfoList; + TableIndexList m_aFreeIndexList; + + std::unique_ptr<weld::Button> m_xPB_OK; + std::unique_ptr<weld::ComboBox> m_xCB_Tables; + std::unique_ptr<weld::Widget> m_xIndexes; + std::unique_ptr<weld::TreeView> m_xLB_TableIndexes; + std::unique_ptr<weld::TreeView> m_xLB_FreeIndexes; + + std::unique_ptr<weld::Button> m_xAdd; + std::unique_ptr<weld::Button> m_xRemove; + std::unique_ptr<weld::Button> m_xAddAll; + std::unique_ptr<weld::Button> m_xRemoveAll; + + DECL_LINK( TableSelectHdl, weld::ComboBox&, void ); + DECL_LINK( AddClickHdl, weld::Button&, void ); + DECL_LINK( RemoveClickHdl, weld::Button&, void ); + DECL_LINK( AddAllClickHdl, weld::Button&, void ); + DECL_LINK( RemoveAllClickHdl, weld::Button&, void ); + DECL_LINK( OKClickHdl, weld::Button&, void ); + DECL_LINK( OnListEntrySelected, weld::TreeView&, void ); + + void Init(); + void SetCtrls(); + + static OTableIndex implRemoveIndex(const OUString& _rName, TableIndexList& _rList, weld::TreeView& _rDisplay, bool _bMustExist); + static void implInsertIndex(const OTableIndex& _rIndex, TableIndexList& _rList, weld::TreeView& _rDisplay); + + OTableIndex RemoveFreeIndex( const OUString& _rName, bool _bMustExist ) { return implRemoveIndex(_rName, m_aFreeIndexList, *m_xLB_FreeIndexes, _bMustExist); } + void InsertFreeIndex( const OTableIndex& _rIndex ) { implInsertIndex(_rIndex, m_aFreeIndexList, *m_xLB_FreeIndexes); } + OTableIndex RemoveTableIndex( const OUString& _rTableName, const OUString& _rIndexName ); + void InsertTableIndex( const OUString& _rTableName, const OTableIndex& _rIndex ); + + void checkButtons(); + +public: + ODbaseIndexDialog(weld::Window * pParent, const OUString& rDataSrcName); + virtual ~ODbaseIndexDialog() override; +}; + +} // namespace dbaui + +#endif // INCLUDED_DBACCESS_SOURCE_UI_DLG_DBFINDEX_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/dbwiz.cxx b/dbaccess/source/ui/dlg/dbwiz.cxx new file mode 100644 index 000000000..d39fd3c79 --- /dev/null +++ b/dbaccess/source/ui/dlg/dbwiz.cxx @@ -0,0 +1,335 @@ +/* -*- 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 <core_resource.hxx> +#include <dbwiz.hxx> +#include <strings.hrc> +#include <strings.hxx> +#include <dsitems.hxx> +#include "dsnItem.hxx" +#include "adminpages.hxx" +#include "generalpage.hxx" +#include <unotools/confignode.hxx> +#include "ConnectionPage.hxx" +#include "DriverSettings.hxx" +#include "DbAdminImpl.hxx" +#include <helpids.h> + +namespace dbaui +{ +using namespace com::sun::star::uno; +using namespace com::sun::star::sdbc; +using namespace com::sun::star::lang; +using namespace com::sun::star::util; +using namespace com::sun::star::beans; +using namespace com::sun::star::container; + +#define START_PAGE 0 +#define CONNECTION_PAGE 1 +#define ADDITIONAL_PAGE_DBASE 2 +#define ADDITIONAL_PAGE_FLAT 3 +#define ADDITIONAL_PAGE_LDAP 4 +//5 was ADDITIONAL_PAGE_ADABAS +#define ADDITIONAL_PAGE_MYSQL_JDBC 6 +#define ADDITIONAL_PAGE_MYSQL_ODBC 7 +#define ADDITIONAL_PAGE_ORACLE_JDBC 8 +#define ADDITIONAL_PAGE_ADO 9 +#define ADDITIONAL_PAGE_ODBC 10 +#define ADDITIONAL_USERDEFINED 11 +#define ADDITIONAL_PAGE_MYSQL_NATIVE 12 + +// ODbTypeWizDialog +ODbTypeWizDialog::ODbTypeWizDialog(weld::Window* _pParent, SfxItemSet const * _pItems, + const Reference< XComponentContext >& _rxORB, const css::uno::Any& _aDataSourceName) + : WizardMachine(_pParent, WizardButtonFlags::NEXT | WizardButtonFlags::PREVIOUS | WizardButtonFlags::FINISH | WizardButtonFlags::CANCEL | WizardButtonFlags::HELP ) +{ + m_pImpl.reset(new ODbDataSourceAdministrationHelper(_rxORB, m_xAssistant.get(), _pParent, this)); + m_pImpl->setDataSourceOrName(_aDataSourceName); + Reference< XPropertySet > xDatasource = m_pImpl->getCurrentDataSource(); + m_pOutSet.reset(new SfxItemSet( *_pItems->GetPool(), _pItems->GetRanges() )); + + m_pImpl->translateProperties(xDatasource, *m_pOutSet); + m_eType = dbaui::ODbDataSourceAdministrationHelper::getDatasourceType(*m_pOutSet); + + defaultButton(WizardButtonFlags::NEXT); + enableButtons(WizardButtonFlags::FINISH, false); + enableAutomaticNextButtonState(); + + m_xPrevPage->set_help_id(HID_DBWIZ_PREVIOUS); + m_xNextPage->set_help_id(HID_DBWIZ_NEXT); + m_xCancel->set_help_id(HID_DBWIZ_CANCEL); + m_xFinish->set_help_id(HID_DBWIZ_FINISH); + // no local resources needed anymore + + const DbuTypeCollectionItem& rCollectionItem = dynamic_cast<const DbuTypeCollectionItem&>(*_pItems->GetItem(DSID_TYPECOLLECTION)); + m_pCollection = rCollectionItem.getCollection(); + + ActivatePage(); + setTitleBase(DBA_RES(STR_DATABASE_TYPE_CHANGE)); + + m_xAssistant->set_current_page(0); +} + +ODbTypeWizDialog::~ODbTypeWizDialog() +{ +} + +IMPL_LINK(ODbTypeWizDialog, OnTypeSelected, OGeneralPage&, _rTabPage, void) +{ + m_eType = _rTabPage.GetSelectedType(); + const bool bURLRequired = m_pCollection->isConnectionUrlRequired(m_eType); + enableButtons(WizardButtonFlags::NEXT,bURLRequired); + enableButtons(WizardButtonFlags::FINISH,!bURLRequired); +} + +WizardState ODbTypeWizDialog::determineNextState( WizardState _nCurrentState ) const +{ + WizardState nNextState = WZS_INVALID_STATE; + switch(_nCurrentState) + { + case START_PAGE: + switch(m_pCollection->determineType(m_eType)) + { + case ::dbaccess::DST_MOZILLA: + case ::dbaccess::DST_OUTLOOK: + case ::dbaccess::DST_OUTLOOKEXP: + case ::dbaccess::DST_EVOLUTION: + case ::dbaccess::DST_EVOLUTION_GROUPWISE: + case ::dbaccess::DST_EVOLUTION_LDAP: + case ::dbaccess::DST_KAB: + case ::dbaccess::DST_MACAB: + nNextState = WZS_INVALID_STATE; + break; + case ::dbaccess::DST_MYSQL_NATIVE: + nNextState = ADDITIONAL_PAGE_MYSQL_NATIVE; + break; + default: + nNextState = CONNECTION_PAGE; + break; + } + break; + case CONNECTION_PAGE: + switch(m_pCollection->determineType(m_eType)) + { + case ::dbaccess::DST_MOZILLA: + case ::dbaccess::DST_THUNDERBIRD: + case ::dbaccess::DST_OUTLOOK: + case ::dbaccess::DST_OUTLOOKEXP: + case ::dbaccess::DST_EVOLUTION: + case ::dbaccess::DST_EVOLUTION_GROUPWISE: + case ::dbaccess::DST_EVOLUTION_LDAP: + case ::dbaccess::DST_KAB: + case ::dbaccess::DST_MACAB: + case ::dbaccess::DST_MSACCESS: + case ::dbaccess::DST_MSACCESS_2007: + case ::dbaccess::DST_JDBC: + case ::dbaccess::DST_CALC: + case ::dbaccess::DST_WRITER: + nNextState = WZS_INVALID_STATE; + break; + case ::dbaccess::DST_DBASE: + nNextState = ADDITIONAL_PAGE_DBASE; + break; + case ::dbaccess::DST_FLAT: + nNextState = ADDITIONAL_PAGE_FLAT; + break; + case ::dbaccess::DST_LDAP: + nNextState = ADDITIONAL_PAGE_LDAP; + break; + case ::dbaccess::DST_MYSQL_JDBC: + nNextState = ADDITIONAL_PAGE_MYSQL_JDBC; + break; + case ::dbaccess::DST_MYSQL_ODBC: + nNextState = ADDITIONAL_PAGE_MYSQL_ODBC; + break; + case ::dbaccess::DST_ORACLE_JDBC: + nNextState = ADDITIONAL_PAGE_ORACLE_JDBC; + break; + case ::dbaccess::DST_ADO: + nNextState = ADDITIONAL_PAGE_ADO; + break; + case ::dbaccess::DST_ODBC: + nNextState = ADDITIONAL_PAGE_ODBC; + break; + default: + nNextState = WZS_INVALID_STATE; + break; + } + break; + } + + return nNextState; +} + +const SfxItemSet* ODbTypeWizDialog::getOutputSet() const +{ + return m_pOutSet.get(); +} + +SfxItemSet* ODbTypeWizDialog::getWriteOutputSet() +{ + return m_pOutSet.get(); +} + +std::pair< Reference<XConnection>,bool> ODbTypeWizDialog::createConnection() +{ + return m_pImpl->createConnection(); +} + +Reference< XComponentContext > ODbTypeWizDialog::getORB() const +{ + return m_pImpl->getORB(); +} + +Reference< XDriver > ODbTypeWizDialog::getDriver() +{ + return m_pImpl->getDriver(); +} + +OUString ODbTypeWizDialog::getDatasourceType(const SfxItemSet& _rSet) const +{ + return dbaui::ODbDataSourceAdministrationHelper::getDatasourceType(_rSet); +} + +void ODbTypeWizDialog::clearPassword() +{ + m_pImpl->clearPassword(); +} + +std::unique_ptr<BuilderPage> ODbTypeWizDialog::createPage(WizardState _nState) +{ + const char* pStringId = STR_PAGETITLE_ADVANCED; + std::unique_ptr<BuilderPage> xPage; + + OString sIdent(OString::number(_nState)); + weld::Container* pPageContainer = m_xAssistant->append_page(sIdent); + + switch(_nState) + { + case START_PAGE: // start state + { + xPage = std::make_unique<OGeneralPageDialog>(pPageContainer, this, *m_pOutSet); + OGeneralPage* pGeneralPage = static_cast<OGeneralPage*>(xPage.get()); + pGeneralPage->SetTypeSelectHandler( LINK( this, ODbTypeWizDialog, OnTypeSelected)); + pStringId = STR_PAGETITLE_GENERAL; + } + break; + case CONNECTION_PAGE: + xPage = OConnectionTabPage::Create(pPageContainer, this, m_pOutSet.get()); + pStringId = STR_PAGETITLE_CONNECTION; + break; + + case ADDITIONAL_PAGE_DBASE: + xPage = ODriversSettings::CreateDbase(pPageContainer, this, m_pOutSet.get()); + break; + case ADDITIONAL_PAGE_FLAT: + xPage = ODriversSettings::CreateText(pPageContainer, this, m_pOutSet.get()); + break; + case ADDITIONAL_PAGE_LDAP: + xPage = ODriversSettings::CreateLDAP(pPageContainer, this, m_pOutSet.get()); + break; + case ADDITIONAL_PAGE_MYSQL_JDBC: + xPage = ODriversSettings::CreateMySQLJDBC(pPageContainer, this, m_pOutSet.get()); + break; + case ADDITIONAL_PAGE_MYSQL_NATIVE: + xPage = ODriversSettings::CreateMySQLNATIVE(pPageContainer, this, m_pOutSet.get()); + break; + case ADDITIONAL_PAGE_MYSQL_ODBC: + xPage = ODriversSettings::CreateMySQLODBC(pPageContainer, this, m_pOutSet.get()); + break; + case ADDITIONAL_PAGE_ORACLE_JDBC: + xPage = ODriversSettings::CreateOracleJDBC(pPageContainer, this, m_pOutSet.get()); + break; + case ADDITIONAL_PAGE_ADO: + xPage = ODriversSettings::CreateAdo(pPageContainer, this, m_pOutSet.get()); + break; + case ADDITIONAL_PAGE_ODBC: + xPage = ODriversSettings::CreateODBC(pPageContainer, this, m_pOutSet.get()); + break; + case ADDITIONAL_USERDEFINED: + xPage = ODriversSettings::CreateUser(pPageContainer, this, m_pOutSet.get()); + break; + default: + OSL_FAIL("Wrong state!"); + break; + } + + // register ourself as modified listener + if ( xPage ) + { + static_cast<OGenericAdministrationPage*>(xPage.get())->SetServiceFactory( m_pImpl->getORB() ); + static_cast<OGenericAdministrationPage*>(xPage.get())->SetAdminDialog(this,this); + m_xAssistant->set_page_title(sIdent, DBA_RES(pStringId)); + defaultButton( _nState == START_PAGE ? WizardButtonFlags::NEXT : WizardButtonFlags::FINISH ); + enableButtons( WizardButtonFlags::FINISH, _nState != START_PAGE); + } + return xPage; +} + +bool ODbTypeWizDialog::leaveState(WizardState _nState) +{ + SfxTabPage* pPage = static_cast<SfxTabPage*>(WizardMachine::GetPage(_nState)); + if ( pPage ) + pPage->FillItemSet(m_pOutSet.get()); + return true; +} + +void ODbTypeWizDialog::setTitle(const OUString& _sTitle) +{ + m_xAssistant->set_title(_sTitle); +} + +void ODbTypeWizDialog::enableConfirmSettings( bool _bEnable ) +{ + enableButtons( WizardButtonFlags::FINISH, _bEnable ); + // TODO: + // this is hacky. At the moment, this method is used in only one case. + // As soon as it is to be used more wide-spread, we should find a proper concept + // for enabling both the Next and Finish buttons, depending on the current page state. + // Plus, the concept must also care for the case where those pages are embedded into + // anormal tab dialog. +} + +void ODbTypeWizDialog::saveDatasource() +{ + SfxTabPage* pPage = static_cast<SfxTabPage*>(WizardMachine::GetPage(getCurrentState())); + if ( pPage ) + pPage->FillItemSet(m_pOutSet.get()); + + OUString sOldURL; + if ( m_pImpl->getCurrentDataSource().is() ) + m_pImpl->getCurrentDataSource()->getPropertyValue(PROPERTY_URL) >>= sOldURL; + DataSourceInfoConverter::convert( getORB(), m_pCollection,sOldURL,m_eType,m_pImpl->getCurrentDataSource()); +} + +vcl::IWizardPageController* ODbTypeWizDialog::getPageController(BuilderPage* pCurrentPage) const +{ + OGenericAdministrationPage* pPage = static_cast<OGenericAdministrationPage*>(pCurrentPage); + return pPage; +} + +bool ODbTypeWizDialog::onFinish() +{ + saveDatasource(); + return m_pImpl->saveChanges(*m_pOutSet) && WizardMachine::onFinish(); +} + +} // namespace dbaui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/dbwizsetup.cxx b/dbaccess/source/ui/dlg/dbwizsetup.cxx new file mode 100644 index 000000000..1dd342c12 --- /dev/null +++ b/dbaccess/source/ui/dlg/dbwizsetup.cxx @@ -0,0 +1,999 @@ +/* -*- 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 <core_resource.hxx> +#include <dbwizsetup.hxx> +#include <dsmeta.hxx> +#include "DBSetupConnectionPages.hxx" +#include <strings.hrc> +#include <strings.hxx> +#include <dsitems.hxx> +#include "dsnItem.hxx" + +#include <unotools/pathoptions.hxx> +#include <svl/stritem.hxx> +#include "adminpages.hxx" +#include <sfx2/docfilt.hxx> +#include <unotools/ucbhelper.hxx> +#include "generalpage.hxx" +#include <unotools/confignode.hxx> +#include "DbAdminImpl.hxx" +#include <helpids.h> +#include "ConnectionPageSetup.hxx" +#include <UITools.hxx> +#include <dbaccess/AsynchronousLink.hxx> +#include <sfx2/filedlghelper.hxx> +#include <cppuhelper/exc_hlp.hxx> +#include <cppuhelper/implbase.hxx> +#include <com/sun/star/frame/TerminationVetoException.hpp> +#include <com/sun/star/frame/XStorable.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/sdb/DatabaseContext.hpp> +#include <com/sun/star/frame/Desktop.hpp> +#include <com/sun/star/frame/FrameSearchFlag.hpp> +#include <com/sun/star/frame/XComponentLoader.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/ucb/SimpleFileAccess.hpp> +#include <com/sun/star/ucb/InteractiveIOException.hpp> +#include <com/sun/star/io/IOException.hpp> +#include <com/sun/star/frame/XTerminateListener.hpp> +#include <com/sun/star/document/MacroExecMode.hpp> +#include <com/sun/star/ucb/IOErrorCode.hpp> +#include <com/sun/star/task/InteractionHandler.hpp> +#include <com/sun/star/task/XInteractionHandler2.hpp> +#include <com/sun/star/ui/dialogs/TemplateDescription.hpp> + +#include <comphelper/interaction.hxx> +#include <comphelper/namedvaluecollection.hxx> +#include <tools/diagnose_ex.h> +#include <osl/diagnose.h> +#include <connectivity/DriversConfig.hxx> + +namespace dbaui +{ +using namespace dbtools; +using namespace vcl; +using namespace com::sun::star; +using namespace com::sun::star::uno; +using namespace com::sun::star::sdbc; +using namespace com::sun::star::sdbcx; +using namespace com::sun::star::task; +using namespace com::sun::star::lang; +using namespace com::sun::star::io; +using namespace com::sun::star::util; +using namespace com::sun::star::beans; +using namespace com::sun::star::container; +using namespace com::sun::star::frame; +using namespace com::sun::star::ucb; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::document; +using namespace ::comphelper; +using namespace ::cppu; + +using vcl::RoadmapWizardTypes::WizardPath; + +// ODbTypeWizDialogSetup +ODbTypeWizDialogSetup::ODbTypeWizDialogSetup(weld::Window* _pParent + ,SfxItemSet const * _pItems + ,const Reference< XComponentContext >& _rxORB + ,const css::uno::Any& _aDataSourceName + ) + : vcl::RoadmapWizardMachine( _pParent ) + + , m_bIsConnectable( false) + , m_sRM_IntroText( DBA_RES( STR_PAGETITLE_INTROPAGE ) ) + , m_sRM_dBaseText( DBA_RES( STR_PAGETITLE_DBASE ) ) + , m_sRM_TextText( DBA_RES( STR_PAGETITLE_TEXT ) ) + , m_sRM_MSAccessText( DBA_RES( STR_PAGETITLE_MSACCESS ) ) + , m_sRM_LDAPText( DBA_RES( STR_PAGETITLE_LDAP ) ) + , m_sRM_ADOText( DBA_RES( STR_PAGETITLE_ADO ) ) + , m_sRM_JDBCText( DBA_RES( STR_PAGETITLE_JDBC ) ) + , m_sRM_MySQLNativePageTitle( DBA_RES( STR_PAGETITLE_MYSQL_NATIVE ) ) + , m_sRM_OracleText( DBA_RES( STR_PAGETITLE_ORACLE ) ) + , m_sRM_MySQLText( DBA_RES( STR_PAGETITLE_MYSQL ) ) + , m_sRM_ODBCText( DBA_RES( STR_PAGETITLE_ODBC ) ) + , m_sRM_DocumentOrSpreadSheetText( DBA_RES( STR_PAGETITLE_DOCUMENT_OR_SPREADSHEET ) ) + , m_sRM_AuthentificationText( DBA_RES( STR_PAGETITLE_AUTHENTIFICATION ) ) + , m_sRM_FinalText( DBA_RES( STR_PAGETITLE_FINAL ) ) + , m_sWorkPath( SvtPathOptions().GetWorkPath() ) + , m_pGeneralPage( nullptr ) + , m_pMySQLIntroPage( nullptr ) + , m_pFinalPage( nullptr ) + , m_pCollection( nullptr ) +{ + // no local resources needed anymore + // extract the datasource type collection from the item set + const DbuTypeCollectionItem* pCollectionItem = dynamic_cast<const DbuTypeCollectionItem*>( _pItems->GetItem(DSID_TYPECOLLECTION) ); + if (pCollectionItem) + m_pCollection = pCollectionItem->getCollection(); + + OSL_ENSURE(m_pCollection, "ODbTypeWizDialogSetup::ODbTypeWizDialogSetup : really need a DSN type collection !"); + + m_pImpl.reset(new ODbDataSourceAdministrationHelper(_rxORB, m_xAssistant.get(), _pParent, this)); + m_pImpl->setDataSourceOrName(_aDataSourceName); + Reference< XPropertySet > xDatasource = m_pImpl->getCurrentDataSource(); + m_pOutSet.reset( new SfxItemSet( *_pItems->GetPool(), _pItems->GetRanges() ) ); + + m_pImpl->translateProperties(xDatasource, *m_pOutSet); + + defaultButton(WizardButtonFlags::NEXT); + enableButtons(WizardButtonFlags::FINISH, true); + enableAutomaticNextButtonState(); + + ::dbaccess::ODsnTypeCollection::TypeIterator aIter = m_pCollection->begin(); + ::dbaccess::ODsnTypeCollection::TypeIterator aEnd = m_pCollection->end(); + for(PathId i = 1;aIter != aEnd;++aIter,++i) + { + const OUString& sURLPrefix = aIter.getURLPrefix(); + WizardPath aPath; + aPath.push_back(PAGE_DBSETUPWIZARD_INTRO); + m_pCollection->fillPageIds(sURLPrefix,aPath); + aPath.push_back(PAGE_DBSETUPWIZARD_AUTHENTIFICATION); + aPath.push_back(PAGE_DBSETUPWIZARD_FINAL); + + declareAuthDepPath(sURLPrefix,i,aPath); + } + + WizardPath aPath; + aPath.push_back(PAGE_DBSETUPWIZARD_INTRO); + declarePath( static_cast<PathId>(m_pCollection->size()+1), aPath); + + m_xPrevPage->set_help_id(HID_DBWIZ_PREVIOUS); + m_xNextPage->set_help_id(HID_DBWIZ_NEXT); + m_xCancel->set_help_id(HID_DBWIZ_CANCEL); + m_xFinish->set_help_id(HID_DBWIZ_FINISH); + ActivatePage(); + setTitleBase(DBA_RES(STR_DBWIZARDTITLE)); + m_xAssistant->set_current_page(0); +} + +void ODbTypeWizDialogSetup::declareAuthDepPath( const OUString& _sURL, PathId _nPathId, const WizardPath& _rPaths) +{ + bool bHasAuthentication = DataSourceMetaData::getAuthentication( _sURL ) != AuthNone; + + // collect the elements of the path + WizardPath aPath; + + for (auto const& path : _rPaths) + { + if ( bHasAuthentication || ( path != PAGE_DBSETUPWIZARD_AUTHENTIFICATION ) ) + aPath.push_back(path); + } + + // call base method + ::vcl::RoadmapWizardMachine::declarePath( _nPathId, aPath ); +} + +OUString ODbTypeWizDialogSetup::getStateDisplayName(WizardState _nState) const +{ + OUString sRoadmapItem; + switch( _nState ) + { + case PAGE_DBSETUPWIZARD_INTRO: + sRoadmapItem = m_sRM_IntroText; + break; + + case PAGE_DBSETUPWIZARD_DBASE: + sRoadmapItem = m_sRM_dBaseText; + break; + case PAGE_DBSETUPWIZARD_ADO: + sRoadmapItem = m_sRM_ADOText; + break; + case PAGE_DBSETUPWIZARD_TEXT: + sRoadmapItem = m_sRM_TextText; + break; + case PAGE_DBSETUPWIZARD_MSACCESS: + sRoadmapItem = m_sRM_MSAccessText; + break; + case PAGE_DBSETUPWIZARD_LDAP: + sRoadmapItem = m_sRM_LDAPText; + break; + case PAGE_DBSETUPWIZARD_JDBC: + sRoadmapItem = m_sRM_JDBCText; + break; + case PAGE_DBSETUPWIZARD_ORACLE: + sRoadmapItem = m_sRM_OracleText; + break; + case PAGE_DBSETUPWIZARD_MYSQL_INTRO: + sRoadmapItem = m_sRM_MySQLText; + break; + case PAGE_DBSETUPWIZARD_MYSQL_JDBC: + sRoadmapItem = m_sRM_JDBCText; + break; + case PAGE_DBSETUPWIZARD_MYSQL_NATIVE: + sRoadmapItem = m_sRM_MySQLNativePageTitle; + break; + case PAGE_DBSETUPWIZARD_MYSQL_ODBC: + sRoadmapItem = m_sRM_ODBCText; + break; + case PAGE_DBSETUPWIZARD_ODBC: + sRoadmapItem = m_sRM_ODBCText; + break; + case PAGE_DBSETUPWIZARD_DOCUMENT_OR_SPREADSHEET: + sRoadmapItem = m_sRM_DocumentOrSpreadSheetText; + break; + case PAGE_DBSETUPWIZARD_AUTHENTIFICATION: + sRoadmapItem = m_sRM_AuthentificationText; + break; + case PAGE_DBSETUPWIZARD_USERDEFINED: + sRoadmapItem = DBA_RES(STR_PAGETITLE_CONNECTION); + break; + case PAGE_DBSETUPWIZARD_FINAL: + sRoadmapItem = m_sRM_FinalText; + break; + default: + break; + } + return sRoadmapItem; +} + +ODbTypeWizDialogSetup::~ODbTypeWizDialogSetup() +{ +} + +IMPL_LINK_NOARG(ODbTypeWizDialogSetup, OnTypeSelected, OGeneralPage&, void) +{ + activateDatabasePath(); +} + +static void lcl_removeUnused(const ::comphelper::NamedValueCollection& _aOld,const ::comphelper::NamedValueCollection& _aNew,::comphelper::NamedValueCollection& _rDSInfo) +{ + _rDSInfo.merge(_aNew,true); + uno::Sequence< beans::NamedValue > aOldValues = _aOld.getNamedValues(); + const beans::NamedValue* pIter = aOldValues.getConstArray(); + const beans::NamedValue* pEnd = pIter + aOldValues.getLength(); + for(;pIter != pEnd;++pIter) + { + if ( !_aNew.has(pIter->Name) ) + { + _rDSInfo.remove(pIter->Name); + } + } +} + +void DataSourceInfoConverter::convert(const Reference<XComponentContext> & xContext, const ::dbaccess::ODsnTypeCollection* _pCollection,const OUString& _sOldURLPrefix,const OUString& _sNewURLPrefix,const css::uno::Reference< css::beans::XPropertySet >& _xDatasource) +{ + if ( _pCollection->getPrefix(_sOldURLPrefix) == _pCollection->getPrefix(_sNewURLPrefix) ) + return ; + uno::Sequence< beans::PropertyValue> aInfo; + _xDatasource->getPropertyValue(PROPERTY_INFO) >>= aInfo; + ::comphelper::NamedValueCollection aDS(aInfo); + + ::connectivity::DriversConfig aDriverConfig(xContext); + + const ::comphelper::NamedValueCollection& aOldProperties = aDriverConfig.getProperties(_sOldURLPrefix); + const ::comphelper::NamedValueCollection& aNewProperties = aDriverConfig.getProperties(_sNewURLPrefix); + lcl_removeUnused(aOldProperties,aNewProperties,aDS); + + aDS >>= aInfo; + _xDatasource->setPropertyValue(PROPERTY_INFO,uno::makeAny(aInfo)); +} + +void ODbTypeWizDialogSetup::activateDatabasePath() +{ + switch ( m_pGeneralPage->GetDatabaseCreationMode() ) + { + case OGeneralPageWizard::eCreateNew: + { + sal_Int32 nCreateNewDBIndex = m_pCollection->getIndexOf( m_pGeneralPage->GetSelectedType() ); + if ( nCreateNewDBIndex == -1 ) + nCreateNewDBIndex = m_pCollection->getIndexOf( "sdbc:dbase:" ); + OSL_ENSURE( nCreateNewDBIndex != -1, "ODbTypeWizDialogSetup::activateDatabasePath: the GeneralPage should have prevented this!" ); + activatePath( static_cast< PathId >( nCreateNewDBIndex + 1 ), true ); + + enableState(PAGE_DBSETUPWIZARD_FINAL ); + enableButtons( WizardButtonFlags::FINISH, true); + } + break; + case OGeneralPageWizard::eConnectExternal: + { + OUString sOld = m_sURL; + m_sURL = m_pGeneralPage->GetSelectedType(); + DataSourceInfoConverter::convert(getORB(), m_pCollection,sOld,m_sURL,m_pImpl->getCurrentDataSource()); + ::dbaccess::DATASOURCE_TYPE eType = VerifyDataSourceType(m_pCollection->determineType(m_sURL)); + if (eType == ::dbaccess::DST_UNKNOWN) + m_pCollection->determineType(m_sOldURL); + + activatePath( static_cast<PathId>(m_pCollection->getIndexOf(m_sURL) + 1), true); + updateTypeDependentStates(); + } + break; + case OGeneralPageWizard::eOpenExisting: + { + activatePath( static_cast<PathId>(m_pCollection->size() + 1), true ); + enableButtons( WizardButtonFlags::FINISH, !m_pGeneralPage->GetSelectedDocumentURL().isEmpty() ); + } + break; + default: + OSL_FAIL( "ODbTypeWizDialogSetup::activateDatabasePath: unknown creation mode!" ); + } + + enableButtons( WizardButtonFlags::NEXT, m_pGeneralPage->GetDatabaseCreationMode() != OGeneralPageWizard::eOpenExisting ); + // TODO: this should go into the base class. Point is, we activate a path whose *last* + // step is also the current one. The base class should automatically disable + // the Next button in such a case. However, not for this patch ... +} + +void ODbTypeWizDialogSetup::updateTypeDependentStates() +{ + bool bDoEnable = false; + bool bIsConnectionRequired = m_pCollection->isConnectionUrlRequired(m_sURL); + if (!bIsConnectionRequired) + { + bDoEnable = true; + } + else if ( m_sURL == m_sOldURL ) + { + bDoEnable = m_bIsConnectable; + } + enableState(PAGE_DBSETUPWIZARD_AUTHENTIFICATION, bDoEnable); + enableState(PAGE_DBSETUPWIZARD_FINAL, bDoEnable ); + enableButtons( WizardButtonFlags::FINISH, bDoEnable); +} + +void ODbTypeWizDialogSetup::resetPages(const Reference< XPropertySet >& _rxDatasource) +{ + // remove all items which relate to indirect properties from the input set + // (without this, the following may happen: select an arbitrary data source where some indirect properties + // are set. Select another data source of the same type, where the indirect props are not set (yet). Then, + // the indirect property values of the first ds are shown in the second ds ...) + const ODbDataSourceAdministrationHelper::MapInt2String& rMap = m_pImpl->getIndirectProperties(); + for (auto const& elem : rMap) + getWriteOutputSet()->ClearItem( static_cast<sal_uInt16>(elem.first) ); + + // extract all relevant data from the property set of the data source + m_pImpl->translateProperties(_rxDatasource, *getWriteOutputSet()); +} + +const SfxItemSet* ODbTypeWizDialogSetup::getOutputSet() const +{ + return m_pOutSet.get(); +} + +SfxItemSet* ODbTypeWizDialogSetup::getWriteOutputSet() +{ + return m_pOutSet.get(); +} + +std::pair< Reference<XConnection>,bool> ODbTypeWizDialogSetup::createConnection() +{ + return m_pImpl->createConnection(); +} + +Reference< XComponentContext > ODbTypeWizDialogSetup::getORB() const +{ + return m_pImpl->getORB(); +} + +Reference< XDriver > ODbTypeWizDialogSetup::getDriver() +{ + return m_pImpl->getDriver(); +} + +::dbaccess::DATASOURCE_TYPE ODbTypeWizDialogSetup::VerifyDataSourceType(const ::dbaccess::DATASOURCE_TYPE DatabaseType) const +{ + ::dbaccess::DATASOURCE_TYPE LocDatabaseType = DatabaseType; + if ((LocDatabaseType == ::dbaccess::DST_MYSQL_JDBC) || (LocDatabaseType == ::dbaccess::DST_MYSQL_ODBC) || (LocDatabaseType == ::dbaccess::DST_MYSQL_NATIVE)) + { + if (m_pMySQLIntroPage != nullptr) + { + switch( m_pMySQLIntroPage->getMySQLMode() ) + { + case OMySQLIntroPageSetup::VIA_JDBC: + return ::dbaccess::DST_MYSQL_JDBC; + case OMySQLIntroPageSetup::VIA_NATIVE: + return ::dbaccess::DST_MYSQL_NATIVE; + case OMySQLIntroPageSetup::VIA_ODBC: + return ::dbaccess::DST_MYSQL_ODBC; + } + } + } + return LocDatabaseType; +} + +OUString ODbTypeWizDialogSetup::getDatasourceType(const SfxItemSet& _rSet) const +{ + OUString sRet = dbaui::ODbDataSourceAdministrationHelper::getDatasourceType(_rSet); + if (m_pMySQLIntroPage && m_pMySQLIntroPage->IsVisible()) + { + switch( m_pMySQLIntroPage->getMySQLMode() ) + { + case OMySQLIntroPageSetup::VIA_JDBC: + sRet = "sdbc:mysql:jdbc:"; + break; + case OMySQLIntroPageSetup::VIA_NATIVE: + sRet = "sdbc:mysql:mysqlc:"; + break; + case OMySQLIntroPageSetup::VIA_ODBC: + sRet = "sdbc:mysql:odbc:"; + break; + } + } + return sRet; +} + +void ODbTypeWizDialogSetup::clearPassword() +{ + m_pImpl->clearPassword(); +} + +void ODbTypeWizDialogSetup::SetIntroPage(OMySQLIntroPageSetup* pPage) +{ + m_pMySQLIntroPage = pPage; + m_pMySQLIntroPage->SetClickHdl(LINK( this, ODbTypeWizDialogSetup, ImplClickHdl ) ); +} + +void ODbTypeWizDialogSetup::SetGeneralPage(OGeneralPageWizard* pPage) +{ + m_pGeneralPage = pPage; + m_pGeneralPage->SetTypeSelectHandler(LINK(this, ODbTypeWizDialogSetup, OnTypeSelected)); + m_pGeneralPage->SetCreationModeHandler(LINK( this, ODbTypeWizDialogSetup, OnChangeCreationMode ) ); + m_pGeneralPage->SetDocumentSelectionHandler(LINK( this, ODbTypeWizDialogSetup, OnRecentDocumentSelected ) ); + m_pGeneralPage->SetChooseDocumentHandler(LINK( this, ODbTypeWizDialogSetup, OnSingleDocumentChosen ) ); +} + +void ODbTypeWizDialogSetup::SetFinalPage(OFinalDBPageSetup* pPage) +{ + m_pFinalPage = pPage; +} + +std::unique_ptr<BuilderPage> ODbTypeWizDialogSetup::createPage(WizardState _nState) +{ + std::unique_ptr<OGenericAdministrationPage> xPage; + + OString sIdent(OString::number(_nState)); + weld::Container* pPageContainer = m_xAssistant->append_page(sIdent); + + switch(_nState) + { + case PAGE_DBSETUPWIZARD_INTRO: + xPage = std::make_unique<OGeneralPageWizard>(pPageContainer,this,*m_pOutSet); + break; + + case PAGE_DBSETUPWIZARD_DBASE: + xPage = OConnectionTabPageSetup::CreateDbaseTabPage(pPageContainer, this, *m_pOutSet); + break; + + case PAGE_DBSETUPWIZARD_ADO: + xPage = OConnectionTabPageSetup::CreateADOTabPage(pPageContainer, this, *m_pOutSet); + break; + + case PAGE_DBSETUPWIZARD_TEXT: + xPage = OTextConnectionPageSetup::CreateTextTabPage(pPageContainer, this, *m_pOutSet); + break; + + case PAGE_DBSETUPWIZARD_ODBC: + xPage = OConnectionTabPageSetup::CreateODBCTabPage(pPageContainer, this, *m_pOutSet); + break; + + case PAGE_DBSETUPWIZARD_JDBC: + xPage = OJDBCConnectionPageSetup::CreateJDBCTabPage(pPageContainer, this, *m_pOutSet); + break; + + case PAGE_DBSETUPWIZARD_MYSQL_ODBC: + m_pOutSet->Put(SfxStringItem(DSID_CONNECTURL, m_pCollection->getPrefix("sdbc:mysql:odbc:"))); + xPage = OConnectionTabPageSetup::CreateODBCTabPage(pPageContainer, this, *m_pOutSet); + break; + + case PAGE_DBSETUPWIZARD_MYSQL_JDBC: + m_pOutSet->Put(SfxStringItem(DSID_CONNECTURL, m_pCollection->getPrefix("sdbc:mysql:jdbc:"))); + xPage = OGeneralSpecialJDBCConnectionPageSetup::CreateMySQLJDBCTabPage(pPageContainer, this, *m_pOutSet); + break; + case PAGE_DBSETUPWIZARD_MYSQL_NATIVE: + m_pOutSet->Put(SfxStringItem(DSID_CONNECTURL, m_pCollection->getPrefix("sdbc:mysql:mysqlc:"))); + xPage = MySQLNativeSetupPage::Create(pPageContainer, this, *m_pOutSet); + break; + + case PAGE_DBSETUPWIZARD_ORACLE: + xPage = OGeneralSpecialJDBCConnectionPageSetup::CreateOracleJDBCTabPage(pPageContainer, this, *m_pOutSet); + break; + + case PAGE_DBSETUPWIZARD_LDAP: + xPage = OLDAPConnectionPageSetup::CreateLDAPTabPage(pPageContainer, this, *m_pOutSet); + break; + + case PAGE_DBSETUPWIZARD_DOCUMENT_OR_SPREADSHEET: + xPage = OSpreadSheetConnectionPageSetup::CreateDocumentOrSpreadSheetTabPage(pPageContainer, this, *m_pOutSet); + break; + + case PAGE_DBSETUPWIZARD_MSACCESS: + xPage = OConnectionTabPageSetup::CreateMSAccessTabPage(pPageContainer, this, *m_pOutSet); + break; + case PAGE_DBSETUPWIZARD_MYSQL_INTRO: + xPage = OMySQLIntroPageSetup::CreateMySQLIntroTabPage(pPageContainer, this, *m_pOutSet); + break; + + case PAGE_DBSETUPWIZARD_AUTHENTIFICATION: + xPage = OAuthentificationPageSetup::CreateAuthentificationTabPage(pPageContainer, this, *m_pOutSet); + break; + + case PAGE_DBSETUPWIZARD_USERDEFINED: + xPage = OConnectionTabPageSetup::CreateUserDefinedTabPage(pPageContainer, this, *m_pOutSet); + break; + + case PAGE_DBSETUPWIZARD_FINAL: + xPage = OFinalDBPageSetup::CreateFinalDBTabPageSetup(pPageContainer, this, *m_pOutSet); + break; + } + + if ( xPage ) + { + if ((_nState != PAGE_DBSETUPWIZARD_INTRO) && (_nState != PAGE_DBSETUPWIZARD_AUTHENTIFICATION)) + { + xPage->SetModifiedHandler(LINK( this, ODbTypeWizDialogSetup, ImplModifiedHdl ) ); + } + + xPage->SetServiceFactory( m_pImpl->getORB() ); + xPage->SetAdminDialog(this, this); + + defaultButton( _nState == PAGE_DBSETUPWIZARD_FINAL ? WizardButtonFlags::FINISH : WizardButtonFlags::NEXT ); + enableButtons( WizardButtonFlags::FINISH, _nState == PAGE_DBSETUPWIZARD_FINAL ); + enableButtons( WizardButtonFlags::NEXT, _nState != PAGE_DBSETUPWIZARD_FINAL ); + + m_xAssistant->set_page_title(sIdent, getStateDisplayName(_nState)); + } + return xPage; +} + +IMPL_LINK(ODbTypeWizDialogSetup, ImplModifiedHdl, OGenericAdministrationPage const *, _pConnectionPageSetup, void) +{ + m_bIsConnectable = _pConnectionPageSetup->GetRoadmapStateValue( ); + enableState(PAGE_DBSETUPWIZARD_FINAL, m_bIsConnectable); + enableState(PAGE_DBSETUPWIZARD_AUTHENTIFICATION, m_bIsConnectable); + if (getCurrentState() == PAGE_DBSETUPWIZARD_FINAL) + enableButtons( WizardButtonFlags::FINISH, true); + else + enableButtons( WizardButtonFlags::FINISH, m_bIsConnectable); + enableButtons( WizardButtonFlags::NEXT, m_bIsConnectable && (getCurrentState() != PAGE_DBSETUPWIZARD_FINAL)); +} + +IMPL_LINK(ODbTypeWizDialogSetup, ImplClickHdl, OMySQLIntroPageSetup*, _pMySQLIntroPageSetup, void) +{ + OUString sURLPrefix; + switch( _pMySQLIntroPageSetup->getMySQLMode() ) + { + case OMySQLIntroPageSetup::VIA_ODBC: + sURLPrefix = "sdbc:mysql:odbc:"; + break; + case OMySQLIntroPageSetup::VIA_JDBC: + sURLPrefix = "sdbc:mysql:jdbc:"; + break; + case OMySQLIntroPageSetup::VIA_NATIVE: + sURLPrefix = "sdbc:mysql:mysqlc:"; + break; + } + activatePath( static_cast<PathId>(m_pCollection->getIndexOf(sURLPrefix) + 1), true); +} + +IMPL_LINK_NOARG(ODbTypeWizDialogSetup, OnChangeCreationMode, OGeneralPageWizard&, void) +{ + activateDatabasePath(); +} + +IMPL_LINK_NOARG(ODbTypeWizDialogSetup, OnRecentDocumentSelected, OGeneralPageWizard&, void) +{ + enableButtons( WizardButtonFlags::FINISH, !m_pGeneralPage->GetSelectedDocumentURL().isEmpty() ); +} + +IMPL_LINK_NOARG(ODbTypeWizDialogSetup, OnSingleDocumentChosen, OGeneralPageWizard&, void) +{ + if (prepareLeaveCurrentState(WizardTypes::eFinish)) + onFinish(); +} + +void ODbTypeWizDialogSetup::enterState(WizardState _nState) +{ + m_sURL = dbaui::ODbDataSourceAdministrationHelper::getDatasourceType(*m_pOutSet); + RoadmapWizardMachine::enterState(_nState); + switch(_nState) + { + case PAGE_DBSETUPWIZARD_INTRO: + m_sOldURL = m_sURL; + break; + case PAGE_DBSETUPWIZARD_FINAL: + enableButtons( WizardButtonFlags::FINISH, true); + if ( m_pFinalPage ) + m_pFinalPage->enableTableWizardCheckBox(m_pCollection->supportsTableCreation(m_sURL)); + break; + } +} + +void ODbTypeWizDialogSetup::saveDatasource() +{ + SfxTabPage* pPage = static_cast<SfxTabPage*>(GetPage(getCurrentState())); + if ( pPage ) + pPage->FillItemSet(m_pOutSet.get()); +} + +bool ODbTypeWizDialogSetup::leaveState(WizardState _nState) +{ + if (_nState == PAGE_DBSETUPWIZARD_MYSQL_INTRO) + return true; + if ( _nState == PAGE_DBSETUPWIZARD_INTRO && m_sURL != m_sOldURL ) + { + resetPages(m_pImpl->getCurrentDataSource()); + } + SfxTabPage* pPage = static_cast<SfxTabPage*>(GetPage(_nState)); + return pPage && pPage->DeactivatePage(m_pOutSet.get()) != DeactivateRC::KeepPage; +} + +void ODbTypeWizDialogSetup::setTitle(const OUString& _sTitle) +{ + m_xAssistant->set_title(_sTitle); +} + +void ODbTypeWizDialogSetup::enableConfirmSettings( bool /*_bEnable*/ ) +{ +} + +namespace +{ + bool lcl_handle( const Reference< XInteractionHandler2 >& _rxHandler, const Any& _rRequest ) + { + OInteractionRequest* pRequest = new OInteractionRequest( _rRequest ); + Reference < XInteractionRequest > xRequest( pRequest ); + OInteractionAbort* pAbort = new OInteractionAbort; + pRequest->addContinuation( pAbort ); + + return _rxHandler->handleInteractionRequest( xRequest ); + } +} + +bool ODbTypeWizDialogSetup::SaveDatabaseDocument() +{ + Reference< XInteractionHandler2 > xHandler( InteractionHandler::createWithParent(getORB(), nullptr) ); + try + { + if (callSaveAsDialog()) + { + m_pImpl->saveChanges(*m_pOutSet); + Reference< XPropertySet > xDatasource = m_pImpl->getCurrentDataSource(); + Reference< XModel > xModel( getDataSourceOrModel( xDatasource ), UNO_QUERY_THROW ); + Reference< XStorable > xStore( xModel, UNO_QUERY_THROW ); + + if ( m_pGeneralPage->GetDatabaseCreationMode() == OGeneralPageWizard::eCreateNew ) + CreateDatabase(); + + ::comphelper::NamedValueCollection aArgs( xModel->getArgs() ); + aArgs.put( "Overwrite", true ); + aArgs.put( "InteractionHandler", xHandler ); + aArgs.put( "MacroExecutionMode", MacroExecMode::USE_CONFIG ); + aArgs.put( "IgnoreFirebirdMigration", true ); + + OUString sPath = ODbDataSourceAdministrationHelper::getDocumentUrl( *m_pOutSet ); + xStore->storeAsURL( sPath, aArgs.getPropertyValues() ); + + if ( !m_pFinalPage || m_pFinalPage->IsDatabaseDocumentToBeRegistered() ) + RegisterDataSourceByLocation( sPath ); + + return true; + } + } + catch ( const Exception& e ) + { + Any aError = ::cppu::getCaughtException(); + if ( xHandler.is() ) + { + if ( !lcl_handle( xHandler, aError ) ) + { + InteractiveIOException aRequest; + aRequest.Classification = InteractionClassification_ERROR; + if ( aError.isExtractableTo( ::cppu::UnoType< IOException >::get() ) ) + // assume saving the document failed + aRequest.Code = IOErrorCode_CANT_WRITE; + else + aRequest.Code = IOErrorCode_GENERAL; + aRequest.Message = e.Message; + aRequest.Context = e.Context; + lcl_handle( xHandler, makeAny( aRequest ) ); + } + } + } + return false; +} + + bool ODbTypeWizDialogSetup::IsDatabaseDocumentToBeOpened() const + { + if ( m_pGeneralPage->GetDatabaseCreationMode() == OGeneralPageWizard::eOpenExisting ) + return true; + + if ( m_pFinalPage != nullptr ) + return m_pFinalPage->IsDatabaseDocumentToBeOpened(); + + return true; + } + + bool ODbTypeWizDialogSetup::IsTableWizardToBeStarted() const + { + if ( m_pGeneralPage->GetDatabaseCreationMode() == OGeneralPageWizard::eOpenExisting ) + return false; + + if ( m_pFinalPage != nullptr ) + return m_pFinalPage->IsTableWizardToBeStarted(); + + return false; + } + + void ODbTypeWizDialogSetup::CreateDatabase() + { + OUString sUrl; + const OUString eType = m_pGeneralPage->GetSelectedType(); + if ( dbaccess::ODsnTypeCollection::isEmbeddedDatabase(eType) ) + { + sUrl = eType; + Reference< XPropertySet > xDatasource = m_pImpl->getCurrentDataSource(); + OSL_ENSURE(xDatasource.is(),"DataSource is null!"); + if ( xDatasource.is() ) + xDatasource->setPropertyValue( PROPERTY_INFO, makeAny( m_pCollection->getDefaultDBSettings( eType ) ) ); + m_pImpl->translateProperties(xDatasource,*m_pOutSet); + } + else if ( m_pCollection->isFileSystemBased(eType) ) + { + Reference< XSimpleFileAccess3 > xSimpleFileAccess(ucb::SimpleFileAccess::create(getORB())); + INetURLObject aDBPathURL(m_sWorkPath); + aDBPathURL.Append(m_aDocURL.getBase()); + createUniqueFolderName(&aDBPathURL); + sUrl = aDBPathURL.GetMainURL( INetURLObject::DecodeMechanism::NONE); + xSimpleFileAccess->createFolder(sUrl); + sUrl = eType.concat(sUrl); + } + m_pOutSet->Put(SfxStringItem(DSID_CONNECTURL, sUrl)); + m_pImpl->saveChanges(*m_pOutSet); + } + + void ODbTypeWizDialogSetup::RegisterDataSourceByLocation(const OUString& _sPath) + { + Reference< XPropertySet > xDatasource = m_pImpl->getCurrentDataSource(); + Reference< XDatabaseContext > xDatabaseContext( DatabaseContext::create(getORB()) ); + INetURLObject aURL( _sPath ); + OUString sFilename = aURL.getBase( INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::WithCharset ); + OUString sDatabaseName = ::dbtools::createUniqueName(xDatabaseContext, sFilename, false); + xDatabaseContext->registerObject(sDatabaseName, xDatasource); + } + + bool ODbTypeWizDialogSetup::callSaveAsDialog() + { + bool bRet = false; + ::sfx2::FileDialogHelper aFileDlg( + ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION, + FileDialogFlags::NONE, m_xAssistant.get()); + std::shared_ptr<const SfxFilter> pFilter = getStandardDatabaseFilter(); + if ( pFilter ) + { + INetURLObject aWorkURL( m_sWorkPath ); + aFileDlg.SetDisplayFolder( aWorkURL.GetMainURL( INetURLObject::DecodeMechanism::NONE )); + + OUString sDefaultName = DBA_RES( STR_DATABASEDEFAULTNAME ); + OUString sExtension = pFilter->GetDefaultExtension(); + sDefaultName += sExtension.replaceAt( 0, 1, OUString() ); + aWorkURL.Append( sDefaultName ); + sDefaultName = createUniqueFileName( aWorkURL ); + aFileDlg.SetFileName( sDefaultName ); + + aFileDlg.AddFilter(pFilter->GetUIName(),pFilter->GetDefaultExtension()); + aFileDlg.SetCurrentFilter(pFilter->GetUIName()); + } + if ( aFileDlg.Execute() == ERRCODE_NONE ) + { + m_aDocURL = INetURLObject(aFileDlg.GetPath()); + + if( m_aDocURL.GetProtocol() != INetProtocol::NotValid ) + { + OUString sFileName = m_aDocURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ); + if ( ::utl::UCBContentHelper::IsDocument(sFileName) ) + ::utl::UCBContentHelper::Kill(sFileName); + m_pOutSet->Put(SfxStringItem(DSID_DOCUMENT_URL, sFileName)); + bRet = true; + } + } + return bRet; + } + + void ODbTypeWizDialogSetup::createUniqueFolderName(INetURLObject* pURL) + { + Reference< XSimpleFileAccess3 > xSimpleFileAccess(ucb::SimpleFileAccess::create(getORB())); + OUString sLastSegmentName = pURL->getName(); + bool bFolderExists = true; + sal_Int32 i = 1; + while (bFolderExists) + { + bFolderExists = xSimpleFileAccess->isFolder(pURL->GetMainURL( INetURLObject::DecodeMechanism::NONE )); + if (bFolderExists) + { + i++; + pURL->setName(sLastSegmentName.concat(OUString::number(i))); + } + } + } + + OUString ODbTypeWizDialogSetup::createUniqueFileName(const INetURLObject& _rURL) + { + Reference< XSimpleFileAccess3 > xSimpleFileAccess(ucb::SimpleFileAccess::create(getORB())); + OUString BaseName = _rURL.getBase(); + + bool bElementExists = true; + + INetURLObject aExistenceCheck( _rURL ); + for ( sal_Int32 i = 1; bElementExists; ) + { + bElementExists = xSimpleFileAccess->exists( aExistenceCheck.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); + if ( bElementExists ) + { + aExistenceCheck.setBase( BaseName.concat( OUString::number( i ) ) ); + ++i; + } + } + return aExistenceCheck.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::WithCharset ); + } + + vcl::IWizardPageController* ODbTypeWizDialogSetup::getPageController(BuilderPage* pCurrentPage) const + { + OGenericAdministrationPage* pPage = static_cast<OGenericAdministrationPage*>(pCurrentPage); + return pPage; + } + + namespace + { + typedef ::cppu::WeakImplHelper< XTerminateListener + > AsyncLoader_Base; + class AsyncLoader : public AsyncLoader_Base + { + private: + Reference< XComponentLoader > m_xFrameLoader; + Reference< XDesktop2 > m_xDesktop; + Reference< XInteractionHandler2 > m_xInteractionHandler; + OUString m_sURL; + OAsynchronousLink m_aAsyncCaller; + + public: + AsyncLoader( const Reference< XComponentContext >& _rxORB, const OUString& _rURL ); + + void doLoadAsync(); + + // XTerminateListener + virtual void SAL_CALL queryTermination( const css::lang::EventObject& Event ) override; + virtual void SAL_CALL notifyTermination( const css::lang::EventObject& Event ) override; + // XEventListener + virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override; + + private: + DECL_LINK( OnOpenDocument, void*, void ); + }; + + AsyncLoader::AsyncLoader( const Reference< XComponentContext >& _rxORB, const OUString& _rURL ) + :m_sURL( _rURL ) + ,m_aAsyncCaller( LINK( this, AsyncLoader, OnOpenDocument ) ) + { + try + { + m_xDesktop.set( Desktop::create(_rxORB) ); + m_xFrameLoader.set( m_xDesktop, UNO_QUERY_THROW ); + m_xInteractionHandler = InteractionHandler::createWithParent(_rxORB, nullptr); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("dbaccess"); + } + } + + void AsyncLoader::doLoadAsync() + { + OSL_ENSURE( !m_aAsyncCaller.IsRunning(), "AsyncLoader:doLoadAsync: already running!" ); + + acquire(); + try + { + if ( m_xDesktop.is() ) + m_xDesktop->addTerminateListener( this ); + } + catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION("dbaccess"); } + + m_aAsyncCaller.Call(); + } + + IMPL_LINK_NOARG( AsyncLoader, OnOpenDocument, void*, void ) + { + try + { + if ( m_xFrameLoader.is() ) + { + ::comphelper::NamedValueCollection aLoadArgs; + aLoadArgs.put( "InteractionHandler", m_xInteractionHandler ); + aLoadArgs.put( "MacroExecutionMode", MacroExecMode::USE_CONFIG ); + + Sequence< PropertyValue > aLoadArgPV; + aLoadArgs >>= aLoadArgPV; + + m_xFrameLoader->loadComponentFromURL( m_sURL, + "_default", + FrameSearchFlag::ALL, + aLoadArgPV + ); + } + } + catch( const Exception& ) + { + // do not assert. + // Such an exception happens for instance of the to-be-loaded document does not exist anymore. + } + + try + { + if ( m_xDesktop.is() ) + m_xDesktop->removeTerminateListener( this ); + } + catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION("dbaccess"); } + + release(); + } + + void SAL_CALL AsyncLoader::queryTermination( const css::lang::EventObject& /*Event*/ ) + { + throw TerminationVetoException(); + } + + void SAL_CALL AsyncLoader::notifyTermination( const css::lang::EventObject& /*Event*/ ) + { + } + void SAL_CALL AsyncLoader::disposing( const css::lang::EventObject& /*Source*/ ) + { + } + } + + bool ODbTypeWizDialogSetup::onFinish() + { + if ( m_pGeneralPage->GetDatabaseCreationMode() == OGeneralPageWizard::eOpenExisting ) + { + // we're not going to re-use the XModel we have - since the document the user + // wants us to load could be a non-database document. Instead, we asynchronously + // open the selected document. Thus, the wizard's return value is RET_CANCEL, + // which means to not continue loading the database document + if ( !WizardMachine::Finish() ) + return false; + + try + { + AsyncLoader* pAsyncLoader = new AsyncLoader( getORB(), m_pGeneralPage->GetSelectedDocumentURL() ); + ::rtl::Reference< AsyncLoader > xKeepAlive( pAsyncLoader ); + pAsyncLoader->doLoadAsync(); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("dbaccess"); + } + + return true; + } + + if (getCurrentState() != PAGE_DBSETUPWIZARD_FINAL) + { + skipUntil(PAGE_DBSETUPWIZARD_FINAL); + } + if (getCurrentState() == PAGE_DBSETUPWIZARD_FINAL) + return SaveDatabaseDocument() && WizardMachine::onFinish(); + else + { + enableButtons( WizardButtonFlags::FINISH, false ); + return false; + } + } + +} // namespace dbaui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/detailpages.cxx b/dbaccess/source/ui/dlg/detailpages.cxx new file mode 100644 index 000000000..1ce6475b6 --- /dev/null +++ b/dbaccess/source/ui/dlg/detailpages.cxx @@ -0,0 +1,718 @@ +/* -*- 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 <config_java.h> +#include <core_resource.hxx> +#include "detailpages.hxx" +#include <sqlmessage.hxx> +#include <dsmeta.hxx> +#include "advancedsettings.hxx" +#include "DbAdminImpl.hxx" +#include <dsitems.hxx> +#include "dbfindex.hxx" +#include "dsnItem.hxx" + +#include <IItemSetHelper.hxx> +#include <strings.hrc> + +#include <svl/itemset.hxx> +#include <svl/stritem.hxx> +#include <svl/eitem.hxx> +#include <svl/intitem.hxx> +#if HAVE_FEATURE_JAVA +#include <jvmaccess/virtualmachine.hxx> +#endif +#include <connectivity/CommonTools.hxx> +#include "DriverSettings.hxx" + +namespace dbaui +{ + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::sdbc; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::container; + using namespace ::dbtools; + + OCommonBehaviourTabPage::OCommonBehaviourTabPage(weld::Container* pPage, weld::DialogController* pController, + const OUString& rUIXMLDescription, const OString& rId, const SfxItemSet& rCoreAttrs, + OCommonBehaviourTabPageFlags nControlFlags) + : OGenericAdministrationPage(pPage, pController, rUIXMLDescription, rId, rCoreAttrs) + , m_nControlFlags(nControlFlags) + { + if (m_nControlFlags & OCommonBehaviourTabPageFlags::UseOptions) + { + m_xOptionsLabel = m_xBuilder->weld_label("optionslabel"); + m_xOptionsLabel->show(); + m_xOptions = m_xBuilder->weld_entry("options"); + m_xOptions->show(); + m_xOptions->connect_changed(LINK(this,OGenericAdministrationPage,OnControlEntryModifyHdl)); + } + + if (m_nControlFlags & OCommonBehaviourTabPageFlags::UseCharset) + { + m_xDataConvertLabel = m_xBuilder->weld_label("charsetheader"); + m_xDataConvertLabel->show(); + m_xCharsetLabel = m_xBuilder->weld_label("charsetlabel"); + m_xCharsetLabel->show(); + m_xCharset.reset(new CharSetListBox(m_xBuilder->weld_combo_box("charset"))); + m_xCharset->show(); + m_xCharset->connect_changed(LINK(this, OCommonBehaviourTabPage, CharsetSelectHdl)); + } + } + + IMPL_LINK_NOARG(OCommonBehaviourTabPage, CharsetSelectHdl, weld::ComboBox&, void) + { + callModifiedHdl(); + } + + OCommonBehaviourTabPage::~OCommonBehaviourTabPage() + { + m_xCharset.reset(); + } + + void OCommonBehaviourTabPage::fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) + { + if (m_nControlFlags & OCommonBehaviourTabPageFlags::UseOptions) + { + _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xOptionsLabel.get())); + } + + if (m_nControlFlags & OCommonBehaviourTabPageFlags::UseCharset) + { + _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xCharsetLabel.get())); + } + } + + void OCommonBehaviourTabPage::fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) + { + if (m_nControlFlags & OCommonBehaviourTabPageFlags::UseOptions) + _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::Entry>(m_xOptions.get())); + + if (m_nControlFlags & OCommonBehaviourTabPageFlags::UseCharset) + _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::ComboBox>(m_xCharset->get_widget())); + } + + void OCommonBehaviourTabPage::implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) + { + // check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa) + bool bValid, bReadonly; + getFlags(_rSet, bValid, bReadonly); + + // collect the items + const SfxStringItem* pOptionsItem = _rSet.GetItem<SfxStringItem>(DSID_ADDITIONALOPTIONS); + const SfxStringItem* pCharsetItem = _rSet.GetItem<SfxStringItem>(DSID_CHARSET); + + // forward the values to the controls + if (bValid) + { + if (m_nControlFlags & OCommonBehaviourTabPageFlags::UseOptions) + { + m_xOptions->set_text(pOptionsItem->GetValue()); + m_xOptions->save_value(); + } + + if (m_nControlFlags & OCommonBehaviourTabPageFlags::UseCharset) + { + m_xCharset->SelectEntryByIanaName( pCharsetItem->GetValue() ); + } + } + OGenericAdministrationPage::implInitControls(_rSet, _bSaveValue); + } + + bool OCommonBehaviourTabPage::FillItemSet(SfxItemSet* _rSet) + { + bool bChangedSomething = false; + + if (m_nControlFlags & OCommonBehaviourTabPageFlags::UseOptions) + { + fillString(*_rSet,m_xOptions.get(),DSID_ADDITIONALOPTIONS,bChangedSomething); + } + + if (m_nControlFlags & OCommonBehaviourTabPageFlags::UseCharset) + { + if ( m_xCharset->StoreSelectedCharSet( *_rSet, DSID_CHARSET ) ) + bChangedSomething = true; + } + + return bChangedSomething; + } + + // ODbaseDetailsPage + ODbaseDetailsPage::ODbaseDetailsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rCoreAttrs) + : OCommonBehaviourTabPage(pPage, pController, "dbaccess/ui/dbasepage.ui", "DbasePage", + _rCoreAttrs, OCommonBehaviourTabPageFlags::UseCharset) + , m_xShowDeleted(m_xBuilder->weld_check_button("showDelRowsCheckbutton")) + , m_xFT_Message(m_xBuilder->weld_label("specMessageLabel")) + , m_xIndexes(m_xBuilder->weld_button("indiciesButton")) + { + m_xIndexes->connect_clicked(LINK(this, ODbaseDetailsPage, OnButtonClicked)); + m_xShowDeleted->connect_clicked(LINK(this, ODbaseDetailsPage, OnButtonClicked)); + } + + ODbaseDetailsPage::~ODbaseDetailsPage() + { + } + + std::unique_ptr<SfxTabPage> ODriversSettings::CreateDbase(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet) + { + return std::make_unique<ODbaseDetailsPage>(pPage, pController, *_rAttrSet); + } + + void ODbaseDetailsPage::implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) + { + // check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa) + bool bValid, bReadonly; + getFlags(_rSet, bValid, bReadonly); + + // get the DSN string (needed for the index dialog) + const SfxStringItem* pUrlItem = _rSet.GetItem<SfxStringItem>(DSID_CONNECTURL); + const DbuTypeCollectionItem* pTypesItem = _rSet.GetItem<DbuTypeCollectionItem>(DSID_TYPECOLLECTION); + ::dbaccess::ODsnTypeCollection* pTypeCollection = pTypesItem ? pTypesItem->getCollection() : nullptr; + if (pTypeCollection && pUrlItem && pUrlItem->GetValue().getLength()) + m_sDsn = pTypeCollection->cutPrefix(pUrlItem->GetValue()); + + // get the other relevant items + const SfxBoolItem* pDeletedItem = _rSet.GetItem<SfxBoolItem>(DSID_SHOWDELETEDROWS); + + if ( bValid ) + { + m_xShowDeleted->set_active(pDeletedItem->GetValue()); + m_xFT_Message->set_visible(m_xShowDeleted->get_active()); + } + + OCommonBehaviourTabPage::implInitControls(_rSet, _bSaveValue); + } + + bool ODbaseDetailsPage::FillItemSet( SfxItemSet* _rSet ) + { + bool bChangedSomething = OCommonBehaviourTabPage::FillItemSet(_rSet); + + fillBool(*_rSet, m_xShowDeleted.get(), DSID_SHOWDELETEDROWS, false, bChangedSomething); + return bChangedSomething; + } + + IMPL_LINK(ODbaseDetailsPage, OnButtonClicked, weld::Button&, rButton, void) + { + if (m_xIndexes.get() == &rButton) + { + ODbaseIndexDialog aIndexDialog(GetFrameWeld(), m_sDsn); + aIndexDialog.run(); + } + else + { + m_xFT_Message->set_visible(m_xShowDeleted->get_active()); + // it was one of the checkboxes -> we count as modified from now on + callModifiedHdl(); + } + } + + // OAdoDetailsPage + OAdoDetailsPage::OAdoDetailsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs) + : OCommonBehaviourTabPage(pPage, pController, "dbaccess/ui/autocharsetpage.ui", "AutoCharset", + rCoreAttrs, OCommonBehaviourTabPageFlags::UseCharset ) + { + + } + + std::unique_ptr<SfxTabPage> ODriversSettings::CreateAdo(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet) + { + return std::make_unique<OAdoDetailsPage>(pPage, pController, *rAttrSet); + } + + // OOdbcDetailsPage + OOdbcDetailsPage::OOdbcDetailsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs) + : OCommonBehaviourTabPage(pPage, pController, "dbaccess/ui/odbcpage.ui", "ODBC", rCoreAttrs, + OCommonBehaviourTabPageFlags::UseCharset | OCommonBehaviourTabPageFlags::UseOptions) + , m_xUseCatalog(m_xBuilder->weld_check_button("useCatalogCheckbutton")) + { + m_xUseCatalog->connect_toggled(LINK(this, OGenericAdministrationPage, OnControlModifiedButtonClick)); + } + + OOdbcDetailsPage::~OOdbcDetailsPage() + { + } + + std::unique_ptr<SfxTabPage> ODriversSettings::CreateODBC(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* pAttrSet) + { + return std::make_unique<OOdbcDetailsPage>(pPage, pController, *pAttrSet); + } + + bool OOdbcDetailsPage::FillItemSet( SfxItemSet* _rSet ) + { + bool bChangedSomething = OCommonBehaviourTabPage::FillItemSet(_rSet); + fillBool(*_rSet,m_xUseCatalog.get(),DSID_USECATALOG,false,bChangedSomething); + return bChangedSomething; + } + void OOdbcDetailsPage::implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) + { + // check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa) + bool bValid, bReadonly; + getFlags(_rSet, bValid, bReadonly); + + const SfxBoolItem* pUseCatalogItem = _rSet.GetItem<SfxBoolItem>(DSID_USECATALOG); + + if ( bValid ) + m_xUseCatalog->set_active(pUseCatalogItem->GetValue()); + + OCommonBehaviourTabPage::implInitControls(_rSet, _bSaveValue); + } + // OOdbcDetailsPage + OUserDriverDetailsPage::OUserDriverDetailsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs) + : OCommonBehaviourTabPage(pPage, pController, "dbaccess/ui/userdetailspage.ui", "UserDetailsPage", + rCoreAttrs, OCommonBehaviourTabPageFlags::UseCharset | OCommonBehaviourTabPageFlags::UseOptions) + , m_xFTHostname(m_xBuilder->weld_label("hostnameft")) + , m_xEDHostname(m_xBuilder->weld_entry("hostname")) + , m_xPortNumber(m_xBuilder->weld_label("portnumberft")) + , m_xNFPortNumber(m_xBuilder->weld_spin_button("portnumber")) + , m_xUseCatalog(m_xBuilder->weld_check_button("usecatalog")) + { + m_xUseCatalog->connect_toggled(LINK(this, OGenericAdministrationPage, OnControlModifiedButtonClick)); + } + + OUserDriverDetailsPage::~OUserDriverDetailsPage() + { + } + + std::unique_ptr<SfxTabPage> ODriversSettings::CreateUser(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* pAttrSet) + { + return std::make_unique<OUserDriverDetailsPage>(pPage, pController, *pAttrSet); + } + + bool OUserDriverDetailsPage::FillItemSet( SfxItemSet* _rSet ) + { + bool bChangedSomething = OCommonBehaviourTabPage::FillItemSet(_rSet); + + fillInt32(*_rSet,m_xNFPortNumber.get(),DSID_CONN_PORTNUMBER,bChangedSomething); + fillString(*_rSet,m_xEDHostname.get(),DSID_CONN_HOSTNAME,bChangedSomething); + fillBool(*_rSet,m_xUseCatalog.get(),DSID_USECATALOG,false,bChangedSomething); + + return bChangedSomething; + } + void OUserDriverDetailsPage::fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) + { + OCommonBehaviourTabPage::fillControls(_rControlList); + _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::Entry>(m_xEDHostname.get())); + _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::ToggleButton>(m_xUseCatalog.get())); + _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::SpinButton>(m_xNFPortNumber.get())); + } + void OUserDriverDetailsPage::fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) + { + OCommonBehaviourTabPage::fillWindows(_rControlList); + _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xFTHostname.get())); + _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xPortNumber.get())); + } + void OUserDriverDetailsPage::implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) + { + // check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa) + bool bValid, bReadonly; + getFlags(_rSet, bValid, bReadonly); + + const SfxBoolItem* pUseCatalogItem = _rSet.GetItem<SfxBoolItem>(DSID_USECATALOG); + const SfxStringItem* pHostName = _rSet.GetItem<SfxStringItem>(DSID_CONN_HOSTNAME); + const SfxInt32Item* pPortNumber = _rSet.GetItem<SfxInt32Item>(DSID_CONN_PORTNUMBER); + + if ( bValid ) + { + m_xEDHostname->set_text(pHostName->GetValue()); + m_xEDHostname->save_value(); + + m_xNFPortNumber->set_value(pPortNumber->GetValue()); + m_xNFPortNumber->save_value(); + + m_xUseCatalog->set_active(pUseCatalogItem->GetValue()); + } + + OCommonBehaviourTabPage::implInitControls(_rSet, _bSaveValue); + } + // OMySQLODBCDetailsPage + OMySQLODBCDetailsPage::OMySQLODBCDetailsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs) + : OCommonBehaviourTabPage(pPage, pController, "dbaccess/ui/autocharsetpage.ui", "AutoCharset", + rCoreAttrs, OCommonBehaviourTabPageFlags::UseCharset ) + { + } + + std::unique_ptr<SfxTabPage> ODriversSettings::CreateMySQLODBC(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* pAttrSet) + { + return std::make_unique<OMySQLODBCDetailsPage>(pPage, pController, *pAttrSet); + } + + // OMySQLJDBCDetailsPage + OGeneralSpecialJDBCDetailsPage::OGeneralSpecialJDBCDetailsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs ,sal_uInt16 _nPortId, bool bShowSocket) + : OCommonBehaviourTabPage(pPage, pController, "dbaccess/ui/generalspecialjdbcdetailspage.ui", "GeneralSpecialJDBCDetails", + rCoreAttrs, OCommonBehaviourTabPageFlags::UseCharset) + , m_nPortId(_nPortId) + , m_bUseClass(true) + , m_xEDHostname(m_xBuilder->weld_entry("hostNameEntry")) + , m_xNFPortNumber(m_xBuilder->weld_spin_button("portNumberSpinbutton")) + , m_xFTSocket(m_xBuilder->weld_label("socketLabel")) + , m_xEDSocket(m_xBuilder->weld_entry("socketEntry")) + , m_xFTDriverClass(m_xBuilder->weld_label("driverClassLabel")) + , m_xEDDriverClass(m_xBuilder->weld_entry("jdbcDriverClassEntry")) + , m_xTestJavaDriver(m_xBuilder->weld_button("testDriverClassButton")) + { + const SfxStringItem* pUrlItem = rCoreAttrs.GetItem<SfxStringItem>(DSID_CONNECTURL); + const DbuTypeCollectionItem* pTypesItem = rCoreAttrs.GetItem<DbuTypeCollectionItem>(DSID_TYPECOLLECTION); + ::dbaccess::ODsnTypeCollection* pTypeCollection = pTypesItem ? pTypesItem->getCollection() : nullptr; + if (pTypeCollection && pUrlItem && pUrlItem->GetValue().getLength() ) + { + m_sDefaultJdbcDriverName = pTypeCollection->getJavaDriverClass(pUrlItem->GetValue()); + } + if ( m_sDefaultJdbcDriverName.getLength() ) + { + m_xEDDriverClass->connect_changed(LINK(this,OGenericAdministrationPage,OnControlEntryModifyHdl)); + m_xTestJavaDriver->connect_clicked(LINK(this,OGeneralSpecialJDBCDetailsPage,OnTestJavaClickHdl)); + } + else + { + m_bUseClass = false; + m_xFTDriverClass->hide(); + m_xEDDriverClass->hide(); + m_xTestJavaDriver->hide(); + } + + m_xFTSocket->set_visible(bShowSocket && !m_bUseClass); + m_xEDSocket->set_visible(bShowSocket && !m_bUseClass); + + m_xEDHostname->connect_changed(LINK(this,OGenericAdministrationPage,OnControlEntryModifyHdl)); + m_xNFPortNumber->connect_value_changed(LINK(this,OGenericAdministrationPage,OnControlSpinButtonModifyHdl)); + m_xEDSocket->connect_changed(LINK(this,OGenericAdministrationPage,OnControlEntryModifyHdl)); + } + + OGeneralSpecialJDBCDetailsPage::~OGeneralSpecialJDBCDetailsPage() + { + } + + bool OGeneralSpecialJDBCDetailsPage::FillItemSet( SfxItemSet* _rSet ) + { + bool bChangedSomething = OCommonBehaviourTabPage::FillItemSet(_rSet); + if ( m_bUseClass ) + fillString(*_rSet,m_xEDDriverClass.get(),DSID_JDBCDRIVERCLASS,bChangedSomething); + fillString(*_rSet,m_xEDHostname.get(),DSID_CONN_HOSTNAME,bChangedSomething); + fillString(*_rSet,m_xEDSocket.get(),DSID_CONN_SOCKET,bChangedSomething); + fillInt32(*_rSet,m_xNFPortNumber.get(),m_nPortId,bChangedSomething ); + + return bChangedSomething; + } + void OGeneralSpecialJDBCDetailsPage::implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) + { + // check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa) + bool bValid, bReadonly; + getFlags(_rSet, bValid, bReadonly); + + const SfxStringItem* pDrvItem = _rSet.GetItem<SfxStringItem>(DSID_JDBCDRIVERCLASS); + const SfxStringItem* pHostName = _rSet.GetItem<SfxStringItem>(DSID_CONN_HOSTNAME); + const SfxInt32Item* pPortNumber = _rSet.GetItem<SfxInt32Item>(m_nPortId); + const SfxStringItem* pSocket = _rSet.GetItem<SfxStringItem>(DSID_CONN_SOCKET); + + if ( bValid ) + { + if ( m_bUseClass ) + { + m_xEDDriverClass->set_text(pDrvItem->GetValue()); + m_xEDDriverClass->save_value(); + } + + m_xEDHostname->set_text(pHostName->GetValue()); + m_xEDHostname->save_value(); + + m_xNFPortNumber->set_value(pPortNumber->GetValue()); + m_xNFPortNumber->save_value(); + + m_xEDSocket->set_text(pSocket->GetValue()); + m_xEDSocket->save_value(); + } + + OCommonBehaviourTabPage::implInitControls(_rSet, _bSaveValue); + + // to get the correct value when saveValue was called by base class + if ( m_bUseClass && m_xEDDriverClass->get_text().trim().isEmpty() ) + { + m_xEDDriverClass->set_text(m_sDefaultJdbcDriverName); + m_xEDDriverClass->save_value(); + } + } + IMPL_LINK_NOARG(OGeneralSpecialJDBCDetailsPage, OnTestJavaClickHdl, weld::Button&, void) + { + OSL_ENSURE(m_pAdminDialog,"No Admin dialog set! ->GPF"); + OSL_ENSURE(m_bUseClass,"Who called me?"); + + bool bSuccess = false; +#if HAVE_FEATURE_JAVA + try + { + if (!m_xEDDriverClass->get_text().trim().isEmpty()) + { +// TODO change jvmaccess + ::rtl::Reference< jvmaccess::VirtualMachine > xJVM = ::connectivity::getJavaVM( m_pAdminDialog->getORB() ); + m_xEDDriverClass->set_text(m_xEDDriverClass->get_text().trim()); // fdo#68341 + bSuccess = ::connectivity::existsJavaClassByName(xJVM,m_xEDDriverClass->get_text()); + } + } + catch(Exception&) + { + } +#endif + const char* pMessage = bSuccess ? STR_JDBCDRIVER_SUCCESS : STR_JDBCDRIVER_NO_SUCCESS; + const MessageType mt = bSuccess ? MessageType::Info : MessageType::Error; + OSQLMessageBox aMsg(GetFrameWeld(), DBA_RES(pMessage), OUString(), MessBoxStyle::Ok | MessBoxStyle::DefaultOk, mt); + aMsg.run(); + } + + void OGeneralSpecialJDBCDetailsPage::callModifiedHdl(weld::Widget* pControl) + { + if (m_bUseClass && pControl == m_xEDDriverClass.get()) + m_xTestJavaDriver->set_sensitive(!m_xEDDriverClass->get_text().trim().isEmpty()); + + // tell the listener we were modified + OGenericAdministrationPage::callModifiedHdl(); + } + + // MySQLNativePage + MySQLNativePage::MySQLNativePage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs) + : OCommonBehaviourTabPage(pPage, pController, "dbaccess/ui/mysqlnativepage.ui", "MysqlNativePage", rCoreAttrs, OCommonBehaviourTabPageFlags::UseCharset) + , m_xMySQLSettingsContainer(m_xBuilder->weld_widget("MySQLSettingsContainer")) + , m_xMySQLSettings(new MySQLNativeSettings(m_xMySQLSettingsContainer.get(), LINK(this,OGenericAdministrationPage,OnControlModified))) + , m_xSeparator1(m_xBuilder->weld_label("connectionheader")) + , m_xSeparator2(m_xBuilder->weld_label("userheader")) + , m_xUserNameLabel(m_xBuilder->weld_label("usernamelabel")) + , m_xUserName(m_xBuilder->weld_entry("username")) + , m_xPasswordRequired(m_xBuilder->weld_check_button("passwordrequired")) + { + m_xUserName->connect_changed(LINK(this,OGenericAdministrationPage,OnControlEntryModifyHdl)); + } + + MySQLNativePage::~MySQLNativePage() + { + m_xMySQLSettings.reset(); + } + + void MySQLNativePage::fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) + { + OCommonBehaviourTabPage::fillControls( _rControlList ); + m_xMySQLSettings->fillControls( _rControlList ); + + _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::Entry>(m_xUserName.get())); + _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::ToggleButton>(m_xPasswordRequired.get())); + } + + void MySQLNativePage::fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) + { + OCommonBehaviourTabPage::fillWindows( _rControlList ); + m_xMySQLSettings->fillWindows( _rControlList); + + _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xSeparator1.get())); + _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xSeparator2.get())); + _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xUserNameLabel.get())); + } + + bool MySQLNativePage::FillItemSet( SfxItemSet* _rSet ) + { + bool bChangedSomething = OCommonBehaviourTabPage::FillItemSet( _rSet ); + + bChangedSomething |= m_xMySQLSettings->FillItemSet( _rSet ); + + if (m_xUserName->get_value_changed_from_saved()) + { + _rSet->Put( SfxStringItem( DSID_USER, m_xUserName->get_text() ) ); + _rSet->Put( SfxStringItem( DSID_PASSWORD, OUString())); + bChangedSomething = true; + } + fillBool(*_rSet,m_xPasswordRequired.get(),DSID_PASSWORDREQUIRED,false,bChangedSomething); + + return bChangedSomething; + } + void MySQLNativePage::implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) + { + // check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa) + bool bValid, bReadonly; + getFlags(_rSet, bValid, bReadonly); + + m_xMySQLSettings->implInitControls( _rSet ); + + const SfxStringItem* pUidItem = _rSet.GetItem<SfxStringItem>(DSID_USER); + const SfxBoolItem* pAllowEmptyPwd = _rSet.GetItem<SfxBoolItem>(DSID_PASSWORDREQUIRED); + + if ( bValid ) + { + m_xUserName->set_text(pUidItem->GetValue()); + m_xUserName->save_value(); + m_xPasswordRequired->set_active(pAllowEmptyPwd->GetValue()); + } + + OCommonBehaviourTabPage::implInitControls(_rSet, _bSaveValue); + } + + std::unique_ptr<SfxTabPage> ODriversSettings::CreateMySQLJDBC( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet ) + { + return std::make_unique<OGeneralSpecialJDBCDetailsPage>(pPage, pController, *_rAttrSet,DSID_MYSQL_PORTNUMBER); + } + + std::unique_ptr<SfxTabPage> ODriversSettings::CreateMySQLNATIVE(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* pAttrSet) + { + return std::make_unique<MySQLNativePage>(pPage, pController, *pAttrSet); + } + + std::unique_ptr<SfxTabPage> ODriversSettings::CreateOracleJDBC(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet) + { + return std::make_unique<OGeneralSpecialJDBCDetailsPage>(pPage, pController, *_rAttrSet,DSID_ORACLE_PORTNUMBER, false); + } + + // OLDAPDetailsPage + OLDAPDetailsPage::OLDAPDetailsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs) + : OCommonBehaviourTabPage(pPage, pController, "dbaccess/ui/ldappage.ui", "LDAP", + rCoreAttrs, OCommonBehaviourTabPageFlags::NONE) + , m_xETBaseDN(m_xBuilder->weld_entry("baseDNEntry")) + , m_xCBUseSSL(m_xBuilder->weld_check_button("useSSLCheckbutton")) + , m_xNFPortNumber(m_xBuilder->weld_spin_button("portNumberSpinbutton")) + , m_xNFRowCount(m_xBuilder->weld_spin_button("LDAPRowCountspinbutton")) + { + m_xETBaseDN->connect_changed(LINK(this,OGenericAdministrationPage,OnControlEntryModifyHdl)); + m_xNFPortNumber->connect_value_changed(LINK(this,OGenericAdministrationPage,OnControlSpinButtonModifyHdl)); + m_xNFRowCount->connect_value_changed(LINK(this,OGenericAdministrationPage,OnControlSpinButtonModifyHdl)); + + m_iNormalPort = 389; + m_iSSLPort = 636; + m_xCBUseSSL->connect_toggled(LINK(this, OLDAPDetailsPage, OnCheckBoxClick)); + } + + OLDAPDetailsPage::~OLDAPDetailsPage() + { + } + + std::unique_ptr<SfxTabPage> ODriversSettings::CreateLDAP(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet) + { + return std::make_unique<OLDAPDetailsPage>(pPage, pController, *_rAttrSet); + } + + bool OLDAPDetailsPage::FillItemSet( SfxItemSet* _rSet ) + { + bool bChangedSomething = OCommonBehaviourTabPage::FillItemSet(_rSet); + + fillString(*_rSet,m_xETBaseDN.get(),DSID_CONN_LDAP_BASEDN,bChangedSomething); + fillInt32(*_rSet,m_xNFPortNumber.get(),DSID_CONN_LDAP_PORTNUMBER,bChangedSomething); + fillInt32(*_rSet,m_xNFRowCount.get(),DSID_CONN_LDAP_ROWCOUNT,bChangedSomething); + fillBool(*_rSet,m_xCBUseSSL.get(),DSID_CONN_LDAP_USESSL,false,bChangedSomething); + return bChangedSomething; + } + + IMPL_LINK(OLDAPDetailsPage, OnCheckBoxClick, weld::ToggleButton&, rCheckBox, void) + { + OnControlModifiedButtonClick(rCheckBox); + callModifiedHdl(); + if (m_xCBUseSSL->get_active()) + { + m_iNormalPort = m_xNFPortNumber->get_value(); + m_xNFPortNumber->set_value(m_iSSLPort); + } + else + { + m_iSSLPort = m_xNFPortNumber->get_value(); + m_xNFPortNumber->set_value(m_iNormalPort); + } + } + + void OLDAPDetailsPage::implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) + { + // check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa) + bool bValid, bReadonly; + getFlags(_rSet, bValid, bReadonly); + + const SfxStringItem* pBaseDN = _rSet.GetItem<SfxStringItem>(DSID_CONN_LDAP_BASEDN); + const SfxBoolItem* pUseSSL = _rSet.GetItem<SfxBoolItem>(DSID_CONN_LDAP_USESSL); + const SfxInt32Item* pPortNumber = _rSet.GetItem<SfxInt32Item>(DSID_CONN_LDAP_PORTNUMBER); + const SfxInt32Item* pRowCount = _rSet.GetItem<SfxInt32Item>(DSID_CONN_LDAP_ROWCOUNT); + + if ( bValid ) + { + m_xETBaseDN->set_text(pBaseDN->GetValue()); + m_xNFPortNumber->set_value(pPortNumber->GetValue()); + m_xNFRowCount->set_value(pRowCount->GetValue()); + m_xCBUseSSL->set_active(pUseSSL->GetValue()); + } + + OCommonBehaviourTabPage::implInitControls(_rSet, _bSaveValue); + } + + // OTextDetailsPage + OTextDetailsPage::OTextDetailsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs) + : OCommonBehaviourTabPage(pPage, pController, "dbaccess/ui/emptypage.ui", "EmptyPage", rCoreAttrs, OCommonBehaviourTabPageFlags::NONE) + , m_xTextConnectionHelper(new OTextConnectionHelper(m_xContainer.get(), TC_EXTENSION | TC_HEADER | TC_SEPARATORS | TC_CHARSET)) + { + } + + OTextDetailsPage::~OTextDetailsPage() + { + m_xTextConnectionHelper.reset(); + } + + std::unique_ptr<SfxTabPage> ODriversSettings::CreateText(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* pAttrSet) + { + return std::make_unique<OTextDetailsPage>(pPage, pController, *pAttrSet); + } + + void OTextDetailsPage::fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) + { + OCommonBehaviourTabPage::fillControls(_rControlList); + m_xTextConnectionHelper->fillControls(_rControlList); + + } + void OTextDetailsPage::fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) + { + OCommonBehaviourTabPage::fillWindows(_rControlList); + m_xTextConnectionHelper->fillWindows(_rControlList); + + } + void OTextDetailsPage::implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) + { + // first check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa) + bool bValid, bReadonly; + getFlags(_rSet, bValid, bReadonly); + + m_xTextConnectionHelper->implInitControls(_rSet, bValid); + OCommonBehaviourTabPage::implInitControls(_rSet, _bSaveValue); + } + + bool OTextDetailsPage::FillItemSet( SfxItemSet* rSet ) + { + bool bChangedSomething = OCommonBehaviourTabPage::FillItemSet(rSet); + bChangedSomething = m_xTextConnectionHelper->FillItemSet(*rSet, bChangedSomething); + return bChangedSomething; + } + + bool OTextDetailsPage::prepareLeave() + { + return m_xTextConnectionHelper->prepareLeave(); + } + + std::unique_ptr<SfxTabPage> ODriversSettings::CreateGeneratedValuesPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet) + { + return std::make_unique<GeneratedValuesPage>(pPage, pController, *_rAttrSet); + } + + std::unique_ptr<SfxTabPage> ODriversSettings::CreateSpecialSettingsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet) + { + OUString eType = ODbDataSourceAdministrationHelper::getDatasourceType( *_rAttrSet ); + DataSourceMetaData aMetaData( eType ); + return std::make_unique<SpecialSettingsPage>(pPage, pController, *_rAttrSet, aMetaData); + } +} // namespace dbaui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/detailpages.hxx b/dbaccess/source/ui/dlg/detailpages.hxx new file mode 100644 index 000000000..ff82ce06d --- /dev/null +++ b/dbaccess/source/ui/dlg/detailpages.hxx @@ -0,0 +1,255 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_DBACCESS_SOURCE_UI_DLG_DETAILPAGES_HXX +#define INCLUDED_DBACCESS_SOURCE_UI_DLG_DETAILPAGES_HXX + +#include "adminpages.hxx" +#include <charsetlistbox.hxx> +#include "TextConnectionHelper.hxx" +#include "admincontrols.hxx" + +#include <o3tl/typed_flags_set.hxx> + +enum class OCommonBehaviourTabPageFlags { + NONE = 0x0000, + UseCharset = 0x0002, + UseOptions = 0x0004, +}; +namespace o3tl { + template<> struct typed_flags<OCommonBehaviourTabPageFlags> : is_typed_flags<OCommonBehaviourTabPageFlags, 0x0006> {}; +} + +namespace dbaui +{ + /** eases the implementation of tab pages handling user/password and/or character + set and/or generic options input + <BR> + The controls to be used have to be defined within the resource, as usual, but + this class does all the handling necessary. + */ + class OCommonBehaviourTabPage : public OGenericAdministrationPage + { + OCommonBehaviourTabPageFlags m_nControlFlags; + + std::unique_ptr<weld::Label> m_xOptionsLabel; + std::unique_ptr<weld::Entry> m_xOptions; + + std::unique_ptr<weld::Label> m_xDataConvertLabel; + std::unique_ptr<weld::Label> m_xCharsetLabel; + std::unique_ptr<CharSetListBox> m_xCharset; + + std::unique_ptr<weld::CheckButton> m_xAutoRetrievingEnabled; + std::unique_ptr<weld::Label> m_xAutoIncrementLabel; + std::unique_ptr<weld::Entry> m_xAutoIncrement; + std::unique_ptr<weld::Label> m_xAutoRetrievingLabel; + std::unique_ptr<weld::Entry> m_xAutoRetrieving; + + public: + virtual bool FillItemSet (SfxItemSet* _rCoreAttrs) override; + + OCommonBehaviourTabPage(weld::Container* pPage, weld::DialogController* pController, const OUString& rUIXMLDescription, const OString& rId, const SfxItemSet& _rCoreAttrs, OCommonBehaviourTabPageFlags nControlFlags); + protected: + + virtual ~OCommonBehaviourTabPage() override; + + // subclasses must override this, but it isn't pure virtual + virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override; + + // <method>OGenericAdministrationPage::fillControls</method> + virtual void fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override; + + // <method>OGenericAdministrationPage::fillWindows</method> + virtual void fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override; + private: + DECL_LINK(CharsetSelectHdl, weld::ComboBox&, void); + }; + + + // ODbaseDetailsPage + class ODbaseDetailsPage : public OCommonBehaviourTabPage + { + public: + virtual bool FillItemSet ( SfxItemSet* _rCoreAttrs ) override; + + ODbaseDetailsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rCoreAttrs); + virtual ~ODbaseDetailsPage() override; + private: + OUString m_sDsn; + + std::unique_ptr<weld::CheckButton> m_xShowDeleted; + std::unique_ptr<weld::Label> m_xFT_Message; + std::unique_ptr<weld::Button> m_xIndexes; + + protected: + virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override; + + private: + DECL_LINK(OnButtonClicked, weld::Button&, void); + }; + + // OAdoDetailsPage + class OAdoDetailsPage : public OCommonBehaviourTabPage + { + public: + OAdoDetailsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs); + }; + + // OOdbcDetailsPage + class OOdbcDetailsPage : public OCommonBehaviourTabPage + { + public: + virtual bool FillItemSet ( SfxItemSet* _rCoreAttrs ) override; + + OOdbcDetailsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs); + virtual ~OOdbcDetailsPage() override; + protected: + virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override; + private: + std::unique_ptr<weld::CheckButton> m_xUseCatalog; + }; + + // OUserDriverDetailsPage + class OUserDriverDetailsPage : public OCommonBehaviourTabPage + { + public: + virtual bool FillItemSet ( SfxItemSet* _rCoreAttrs ) override; + + OUserDriverDetailsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rCoreAttrs); + virtual ~OUserDriverDetailsPage() override; + protected: + virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override; + virtual void fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override; + virtual void fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override; + private: + std::unique_ptr<weld::Label> m_xFTHostname; + std::unique_ptr<weld::Entry> m_xEDHostname; + std::unique_ptr<weld::Label> m_xPortNumber; + std::unique_ptr<weld::SpinButton> m_xNFPortNumber; + std::unique_ptr<weld::CheckButton> m_xUseCatalog; + }; + + // OMySQLODBCDetailsPage + class OMySQLODBCDetailsPage : public OCommonBehaviourTabPage + { + public: + OMySQLODBCDetailsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs); + }; + + // OGeneralSpecialJDBCDetailsPage + class OGeneralSpecialJDBCDetailsPage final : public OCommonBehaviourTabPage + { + public: + OGeneralSpecialJDBCDetailsPage(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet& _rCoreAttrs, + sal_uInt16 _nPortId, + bool bShowSocket = true); + virtual ~OGeneralSpecialJDBCDetailsPage() override; + + private: + + virtual bool FillItemSet( SfxItemSet* _rCoreAttrs ) override; + virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override; + virtual void callModifiedHdl(weld::Widget* pControl = nullptr) override; + + DECL_LINK(OnTestJavaClickHdl, weld::Button&, void); + + OUString m_sDefaultJdbcDriverName; + sal_uInt16 m_nPortId; + bool m_bUseClass; + + std::unique_ptr<weld::Entry> m_xEDHostname; + std::unique_ptr<weld::SpinButton> m_xNFPortNumber; + std::unique_ptr<weld::Label> m_xFTSocket; + std::unique_ptr<weld::Entry> m_xEDSocket; + std::unique_ptr<weld::Label> m_xFTDriverClass; + std::unique_ptr<weld::Entry> m_xEDDriverClass; + std::unique_ptr<weld::Button> m_xTestJavaDriver; + }; + + // MySQLNativePage + class MySQLNativePage : public OCommonBehaviourTabPage + { + public: + MySQLNativePage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs); + virtual ~MySQLNativePage() override; + + private: + std::unique_ptr<weld::Widget> m_xMySQLSettingsContainer; + std::unique_ptr<MySQLNativeSettings> m_xMySQLSettings; + std::unique_ptr<weld::Label> m_xSeparator1; + std::unique_ptr<weld::Label> m_xSeparator2; + std::unique_ptr<weld::Label> m_xUserNameLabel; + std::unique_ptr<weld::Entry> m_xUserName; + std::unique_ptr<weld::CheckButton> m_xPasswordRequired; + + protected: + virtual bool FillItemSet( SfxItemSet* _rCoreAttrs ) override; + virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override; + virtual void fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override; + virtual void fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override; + }; + + // OOdbcDetailsPage + class OLDAPDetailsPage : public OCommonBehaviourTabPage + { + public: + virtual bool FillItemSet ( SfxItemSet* _rCoreAttrs ) override; + + OLDAPDetailsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs); + virtual ~OLDAPDetailsPage() override; + protected: + virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override; + private: + sal_Int32 m_iSSLPort; + sal_Int32 m_iNormalPort; + + std::unique_ptr<weld::Entry> m_xETBaseDN; + std::unique_ptr<weld::CheckButton> m_xCBUseSSL; + std::unique_ptr<weld::SpinButton> m_xNFPortNumber; + std::unique_ptr<weld::SpinButton> m_xNFRowCount; + + DECL_LINK(OnCheckBoxClick, weld::ToggleButton&, void); + }; + + // OTextDetailsPage + class OTextDetailsPage : public OCommonBehaviourTabPage + { + public: + virtual bool FillItemSet ( SfxItemSet* _rCoreAttrs ) override; + + OTextDetailsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs); + virtual ~OTextDetailsPage() override; + + protected: + virtual bool prepareLeave() override; + + virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override; + virtual void fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override; + virtual void fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override; + + private: + std::unique_ptr<OTextConnectionHelper> m_xTextConnectionHelper; + }; + +} // namespace dbaui + +#endif // INCLUDED_DBACCESS_SOURCE_UI_DLG_DETAILPAGES_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/directsql.cxx b/dbaccess/source/ui/dlg/directsql.cxx new file mode 100644 index 000000000..8cb2a2e2a --- /dev/null +++ b/dbaccess/source/ui/dlg/directsql.cxx @@ -0,0 +1,504 @@ +/* -*- 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 <core_resource.hxx> +#include <directsql.hxx> +#include <strings.hrc> +#include <comphelper/types.hxx> +#include <editeng/colritem.hxx> +#include <editeng/wghtitem.hxx> +#include <editeng/eeitem.hxx> +#include <osl/mutex.hxx> +#include <svl/itemset.hxx> +#include <svtools/editsyntaxhighlighter.hxx> +#include <tools/diagnose_ex.h> +#include <vcl/event.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> +#include <com/sun/star/sdbc/SQLException.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/sdbc/XMultipleResults.hpp> + +namespace dbaui +{ + SQLEditView::SQLEditView() + { + } + + void SQLEditView::DoBracketHilight(sal_uInt16 nKey) + { + ESelection aCurrentPos = m_xEditView->GetSelection(); + sal_Int32 nStartPos = aCurrentPos.nStartPos; + const sal_uInt32 nStartPara = aCurrentPos.nStartPara; + sal_uInt16 nCount = 0; + int nChar = -1; + + switch (nKey) + { + case '\'': // no break + case '"': + { + nChar = nKey; + break; + } + case '}' : + { + nChar = '{'; + break; + } + case ')': + { + nChar = '('; + break; + } + case ']': + { + nChar = '['; + break; + } + } + + if (nChar == -1) + return; + + bool bUndoEnabled = m_xEditEngine->IsUndoEnabled(); + m_xEditEngine->EnableUndo(false); + + sal_uInt32 nPara = nStartPara; + do + { + if (nPara == nStartPara && nStartPos == 0) + continue; + + OUString aLine( m_xEditEngine->GetText( nPara ) ); + + if (aLine.isEmpty()) + continue; + + for (sal_Int32 i = (nPara==nStartPara) ? nStartPos-1 : aLine.getLength()-1; i>0; --i) + { + if (aLine[i] == nChar) + { + if (!nCount) + { + SfxItemSet aSet(m_xEditEngine->GetEmptyItemSet()); + aSet.Put(SvxColorItem(Color(0,0,0), EE_CHAR_COLOR)); + aSet.Put(SvxWeightItem(WEIGHT_ULTRABOLD, EE_CHAR_WEIGHT)); + aSet.Put(SvxWeightItem(WEIGHT_ULTRABOLD, EE_CHAR_WEIGHT_CJK)); + aSet.Put(SvxWeightItem(WEIGHT_ULTRABOLD, EE_CHAR_WEIGHT_CTL)); + + m_xEditEngine->QuickSetAttribs(aSet, ESelection(nPara, i, nPara, i + 1)); + m_xEditEngine->QuickSetAttribs(aSet, ESelection(nStartPara, nStartPos, nStartPara, nStartPos)); + return; + } + else + --nCount; + } + if (aLine[i] == nKey) + ++nCount; + } + } while (nPara--); + + m_xEditEngine->EnableUndo(bUndoEnabled); + } + + bool SQLEditView::KeyInput(const KeyEvent& rKEvt) + { + DoBracketHilight(rKEvt.GetCharCode()); + return WeldEditView::KeyInput(rKEvt); + } + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::sdbc; + using namespace ::com::sun::star::lang; + + constexpr sal_Int32 g_nHistoryLimit = 20; + + // DirectSQLDialog + DirectSQLDialog::DirectSQLDialog(weld::Window* _pParent, const Reference< XConnection >& _rxConn) + : GenericDialogController(_pParent, "dbaccess/ui/directsqldialog.ui", "DirectSQLDialog") + , m_xExecute(m_xBuilder->weld_button("execute")) + , m_xSQLHistory(m_xBuilder->weld_combo_box("sqlhistory")) + , m_xStatus(m_xBuilder->weld_text_view("status")) + , m_xShowOutput(m_xBuilder->weld_check_button("showoutput")) + , m_xOutput(m_xBuilder->weld_text_view("output")) + , m_xClose(m_xBuilder->weld_button("close")) + , m_xSQL(new SQLEditView) + , m_xSQLEd(new weld::CustomWeld(*m_xBuilder, "sql", *m_xSQL)) + , m_aHighlighter(HighlighterLanguage::SQL) + , m_nStatusCount(1) + , m_bInUpdate(false) + , m_xConnection(_rxConn) + , m_pClosingEvent(nullptr) + { + int nWidth = m_xStatus->get_approximate_digit_width() * 60; + int nHeight = m_xStatus->get_height_rows(7); + + m_xSQLEd->set_size_request(nWidth, nHeight); + m_xStatus->set_size_request(-1, nHeight); + m_xOutput->set_size_request(-1, nHeight); + + m_xSQL->GrabFocus(); + + m_xExecute->connect_clicked(LINK(this, DirectSQLDialog, OnExecute)); + m_xClose->connect_clicked(LINK(this, DirectSQLDialog, OnCloseClick)); + m_xSQLHistory->connect_changed(LINK(this, DirectSQLDialog, OnListEntrySelected)); + + // add a dispose listener to the connection + Reference< XComponent > xConnComp(m_xConnection, UNO_QUERY); + OSL_ENSURE(xConnComp.is(), "DirectSQLDialog::DirectSQLDialog: invalid connection!"); + if (xConnComp.is()) + startComponentListening(xConnComp); + + m_xSQL->SetModifyHdl(LINK(this, DirectSQLDialog, OnStatementModified)); + OnStatementModified(nullptr); + + m_aUpdateDataTimer.SetTimeout(300); + m_aUpdateDataTimer.SetInvokeHandler(LINK(this, DirectSQLDialog, ImplUpdateDataHdl)); + } + + DirectSQLDialog::~DirectSQLDialog() + { + ::osl::MutexGuard aGuard(m_aMutex); + if (m_pClosingEvent) + Application::RemoveUserEvent(m_pClosingEvent); + stopAllComponentListening(); + } + + void DirectSQLDialog::_disposing( const EventObject& _rSource ) + { + SolarMutexGuard aSolarGuard; + ::osl::MutexGuard aGuard(m_aMutex); + + assert(!m_pClosingEvent); + + OSL_ENSURE(Reference< XConnection >(_rSource.Source, UNO_QUERY).get() == m_xConnection.get(), + "DirectSQLDialog::_disposing: where does this come from?"); + + { + OUString sMessage(DBA_RES(STR_DIRECTSQL_CONNECTIONLOST)); + std::unique_ptr<weld::MessageDialog> xError(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Warning, VclButtonsType::Ok, + sMessage)); + xError->run(); + } + + m_pClosingEvent = Application::PostUserEvent(LINK(this, DirectSQLDialog, OnClose)); + } + + sal_Int32 DirectSQLDialog::getHistorySize() const + { + CHECK_INVARIANTS("DirectSQLDialog::getHistorySize"); + return m_aStatementHistory.size(); + } + + void DirectSQLDialog::implEnsureHistoryLimit() + { + CHECK_INVARIANTS("DirectSQLDialog::implEnsureHistoryLimit"); + + if (getHistorySize() <= g_nHistoryLimit) + // nothing to do + return; + + sal_Int32 nRemoveEntries = getHistorySize() - g_nHistoryLimit; + while (nRemoveEntries--) + { + m_aStatementHistory.pop_front(); + m_aNormalizedHistory.pop_front(); + m_xSQLHistory->remove(0); + } + } + + void DirectSQLDialog::implAddToStatementHistory(const OUString& _rStatement) + { + CHECK_INVARIANTS("DirectSQLDialog::implAddToStatementHistory"); + + // add the statement to the history + m_aStatementHistory.push_back(_rStatement); + + // normalize the statement, and remember the normalized form, too + OUString sNormalized = _rStatement.replaceAll("\n", " "); + m_aNormalizedHistory.push_back(sNormalized); + + // add the normalized version to the list box + m_xSQLHistory->append_text(sNormalized); + + // ensure that we don't exceed the history limit + implEnsureHistoryLimit(); + } + +#ifdef DBG_UTIL + const char* DirectSQLDialog::impl_CheckInvariants() const + { + if (m_aStatementHistory.size() != m_aNormalizedHistory.size()) + return "statement history is inconsistent!"; + + if (!m_xSQLHistory) + return "invalid listbox!"; + + if (m_aStatementHistory.size() != static_cast<size_t>(m_xSQLHistory->get_count())) + return "invalid listbox entry count!"; + + if (!m_xConnection.is()) + return "have no connection!"; + + return nullptr; + } +#endif + + void DirectSQLDialog::implExecuteStatement(const OUString& _rStatement) + { + CHECK_INVARIANTS("DirectSQLDialog::implExecuteStatement"); + + ::osl::MutexGuard aGuard(m_aMutex); + + OUString sStatus; + + // clear the output box + m_xOutput->set_text(OUString()); + try + { + // create a statement + Reference< XStatement > xStatement = m_xConnection->createStatement(); + + Reference<XDatabaseMetaData> xMeta = m_xConnection->getMetaData(); + css::uno::Reference< css::sdbc::XMultipleResults > xMR ( xStatement, UNO_QUERY ); + + if (xMeta.is() && xMeta->supportsMultipleResultSets() && xMR.is()) + { + bool hasRS = xStatement->execute(_rStatement); + if(hasRS) + { + css::uno::Reference< css::sdbc::XResultSet > xRS (xMR->getResultSet()); + if (m_xShowOutput->get_active()) + display(xRS); + } + else + addOutputText(OUString::number(xMR->getUpdateCount()) + " rows updated\n"); + for (;;) + { + hasRS = xMR->getMoreResults(); + if (!hasRS && xMR->getUpdateCount() == -1) + break; + if(hasRS) + { + css::uno::Reference< css::sdbc::XResultSet > xRS (xMR->getResultSet()); + if (m_xShowOutput->get_active()) + display(xRS); + } + } + } + else + { + if (_rStatement.toAsciiUpperCase().startsWith("SELECT")) + { + css::uno::Reference< css::sdbc::XResultSet > xRS = xStatement->executeQuery(_rStatement); + if (m_xShowOutput->get_active()) + display(xRS); + } + else + { + sal_Int32 resultCount = xStatement->executeUpdate(_rStatement); + addOutputText(OUString::number(resultCount) + " rows updated\n"); + } + } + // successful + sStatus = DBA_RES(STR_COMMAND_EXECUTED_SUCCESSFULLY); + + // dispose the statement + ::comphelper::disposeComponent(xStatement); + } + catch(const SQLException& e) + { + sStatus = e.Message; + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("dbaccess"); + } + + // add the status text + addStatusText(sStatus); + } + + void DirectSQLDialog::display(const css::uno::Reference< css::sdbc::XResultSet >& xRS) + { + // get a handle for the rows + css::uno::Reference< css::sdbc::XRow > xRow( xRS, css::uno::UNO_QUERY ); + // work through each of the rows + while (xRS->next()) + { + // initialise the output line for each row + OUStringBuffer out; + // work along the columns until that are none left + try + { + int i = 1; + for (;;) + { + // be dumb, treat everything as a string + out.append(xRow->getString(i)).append(","); + i++; + } + } + // trap for when we fall off the end of the row + catch (const SQLException&) + { + } + // report the output + addOutputText(out.makeStringAndClear()); + } + } + + void DirectSQLDialog::addStatusText(const OUString& _rMessage) + { + OUString sAppendMessage = OUString::number(m_nStatusCount++) + ": " + _rMessage + "\n\n"; + + OUString sCompleteMessage = m_xStatus->get_text() + sAppendMessage; + m_xStatus->set_text(sCompleteMessage); + + m_xStatus->select_region(sCompleteMessage.getLength(), sCompleteMessage.getLength()); + } + + void DirectSQLDialog::addOutputText(const OUString& _rMessage) + { + OUString sAppendMessage = _rMessage + "\n"; + + OUString sCompleteMessage = m_xOutput->get_text() + sAppendMessage; + m_xOutput->set_text(sCompleteMessage); + } + + void DirectSQLDialog::executeCurrent() + { + CHECK_INVARIANTS("DirectSQLDialog::executeCurrent"); + + OUString sStatement = m_xSQL->GetText(); + + // execute + implExecuteStatement(sStatement); + + // add the statement to the history + implAddToStatementHistory(sStatement); + + m_xSQL->GrabFocus(); + } + + void DirectSQLDialog::switchToHistory(sal_Int32 _nHistoryPos) + { + CHECK_INVARIANTS("DirectSQLDialog::switchToHistory"); + + if ((_nHistoryPos >= 0) && (_nHistoryPos < getHistorySize())) + { + // set the text in the statement editor + OUString sStatement = m_aStatementHistory[_nHistoryPos]; + m_xSQL->SetText(sStatement); + UpdateData(); + OnStatementModified(nullptr); + + m_xSQL->GrabFocus(); + } + else + OSL_FAIL("DirectSQLDialog::switchToHistory: invalid position!"); + } + + IMPL_LINK_NOARG( DirectSQLDialog, OnStatementModified, LinkParamNone*, void ) + { + if (m_bInUpdate) + return; + + m_xExecute->set_sensitive(!m_xSQL->GetText().isEmpty()); + m_aUpdateDataTimer.Start(); + } + + IMPL_LINK_NOARG( DirectSQLDialog, OnCloseClick, weld::Button&, void ) + { + m_xDialog->response(RET_OK); + } + + IMPL_LINK_NOARG( DirectSQLDialog, OnClose, void*, void ) + { + assert(m_pClosingEvent); + Application::RemoveUserEvent(m_pClosingEvent); + m_pClosingEvent = nullptr; + + m_xDialog->response(RET_OK); + } + + IMPL_LINK_NOARG( DirectSQLDialog, OnExecute, weld::Button&, void ) + { + executeCurrent(); + } + + IMPL_LINK_NOARG( DirectSQLDialog, OnListEntrySelected, weld::ComboBox&, void ) + { + const sal_Int32 nSelected = m_xSQLHistory->get_active(); + if (nSelected != -1) + switchToHistory(nSelected); + } + + Color DirectSQLDialog::GetColorValue(TokenType aToken) + { + return MultiLineEditSyntaxHighlight::GetSyntaxHighlightColor(m_aColorConfig, m_aHighlighter.GetLanguage(), aToken); + } + + IMPL_LINK_NOARG(DirectSQLDialog, ImplUpdateDataHdl, Timer*, void) + { + UpdateData(); + } + + void DirectSQLDialog::UpdateData() + { + m_bInUpdate = true; + EditEngine& rEditEngine = m_xSQL->GetEditEngine(); + + bool bUndoEnabled = rEditEngine.IsUndoEnabled(); + rEditEngine.EnableUndo(false); + + // syntax highlighting + bool bOrigModified = rEditEngine.IsModified(); + for (sal_Int32 nLine=0; nLine < rEditEngine.GetParagraphCount(); ++nLine) + { + OUString aLine( rEditEngine.GetText( nLine ) ); + + ESelection aAllLine(nLine, 0, nLine, EE_TEXTPOS_ALL); + rEditEngine.RemoveAttribs(aAllLine, false, EE_CHAR_COLOR); + rEditEngine.RemoveAttribs(aAllLine, false, EE_CHAR_WEIGHT); + rEditEngine.RemoveAttribs(aAllLine, false, EE_CHAR_WEIGHT_CJK); + rEditEngine.RemoveAttribs(aAllLine, false, EE_CHAR_WEIGHT_CTL); + + std::vector<HighlightPortion> aPortions; + m_aHighlighter.getHighlightPortions( aLine, aPortions ); + for (auto const& portion : aPortions) + { + SfxItemSet aSet(rEditEngine.GetEmptyItemSet()); + aSet.Put(SvxColorItem(GetColorValue(portion.tokenType), EE_CHAR_COLOR)); + rEditEngine.QuickSetAttribs(aSet, ESelection(nLine, portion.nBegin, nLine, portion.nEnd)); + } + } + if (!bOrigModified) + rEditEngine.ClearModifyFlag(); + + rEditEngine.EnableUndo(bUndoEnabled); + + m_bInUpdate = false; + } + +} // namespace dbaui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/dlgattr.cxx b/dbaccess/source/ui/dlg/dlgattr.cxx new file mode 100644 index 000000000..a69f29fe7 --- /dev/null +++ b/dbaccess/source/ui/dlg/dlgattr.cxx @@ -0,0 +1,61 @@ +/* -*- 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 <dlgattr.hxx> + +#include <sfx2/tabdlg.hxx> + +#include <svx/numinf.hxx> + +#include <svx/dialogs.hrc> +#include <svl/itemset.hxx> +#include <svl/zforlist.hxx> +#include <svx/svxids.hrc> + +using namespace dbaui; + + +SbaSbAttrDlg::SbaSbAttrDlg(weld::Window* pParent, const SfxItemSet* pCellAttrs, + SvNumberFormatter* pFormatter, bool bHasFormat) + : SfxTabDialogController(pParent, "dbaccess/ui/fielddialog.ui", "FieldDialog", pCellAttrs) +{ + pNumberInfoItem.reset( new SvxNumberInfoItem( pFormatter, 0 ) ); + + if (bHasFormat) + AddTabPage("format", RID_SVXPAGE_NUMBERFORMAT); + else + RemoveTabPage("format"); + AddTabPage("alignment", RID_SVXPAGE_ALIGNMENT); +} + +SbaSbAttrDlg::~SbaSbAttrDlg() +{ +} + +void SbaSbAttrDlg::PageCreated(const OString& rPageId, SfxTabPage& rTabPage) +{ + SfxAllItemSet aSet(*(GetInputSetImpl()->GetPool())); + if (rPageId == "format") + { + aSet.Put (SvxNumberInfoItem( pNumberInfoItem->GetNumberFormatter(), static_cast<sal_uInt16>(SID_ATTR_NUMBERFORMAT_INFO))); + rTabPage.PageCreated(aSet); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/dlgsave.cxx b/dbaccess/source/ui/dlg/dlgsave.cxx new file mode 100644 index 000000000..ce5d16881 --- /dev/null +++ b/dbaccess/source/ui/dlg/dlgsave.cxx @@ -0,0 +1,351 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <dlgsave.hxx> +#include <core_resource.hxx> +#include <strings.hrc> +#include <com/sun/star/sdb/CommandType.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +#include <connectivity/dbtools.hxx> +#include <UITools.hxx> +#include <SqlNameEdit.hxx> +#include <com/sun/star/sdbc/XDatabaseMetaData.hpp> +#include <objectnamecheck.hxx> +#include <tools/diagnose_ex.h> + +using namespace dbaui; +using namespace dbtools; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +namespace dbaui +{ + +class OSaveAsDlgImpl +{ +public: + OUString m_aQryLabel; + OUString m_sTblLabel; + OUString m_aName; + const IObjectNameCheck& m_rObjectNameCheck; + css::uno::Reference< css::sdbc::XDatabaseMetaData> m_xMetaData; + sal_Int32 m_nType; + SADFlags m_nFlags; + + OSQLNameChecker m_aChecker; + + std::unique_ptr<weld::Label> m_xDescription; + std::unique_ptr<weld::Label> m_xCatalogLbl; + std::unique_ptr<weld::ComboBox> m_xCatalog; + std::unique_ptr<weld::Label> m_xSchemaLbl; + std::unique_ptr<weld::ComboBox> m_xSchema; + std::unique_ptr<weld::Label> m_xLabel; + std::unique_ptr<weld::Entry> m_xTitle; + std::unique_ptr<weld::Button> m_xPB_OK; + + DECL_LINK(TextFilterHdl, OUString&, bool); + + OSaveAsDlgImpl( weld::Builder* pParent, sal_Int32 _rType, + const css::uno::Reference< css::sdbc::XConnection>& _xConnection, + const OUString& rDefault, + const IObjectNameCheck& _rObjectNameCheck, + SADFlags _nFlags); + OSaveAsDlgImpl( weld::Builder* pParent, + const OUString& rDefault, + const IObjectNameCheck& _rObjectNameCheck, + SADFlags _nFlags); +}; + +} // dbaui + +IMPL_LINK(OSaveAsDlgImpl, TextFilterHdl, OUString&, rTest, bool) +{ + OUString sCorrected; + if (m_aChecker.checkString(rTest, sCorrected)) + rTest = sCorrected; + return true; +} + +OSaveAsDlgImpl::OSaveAsDlgImpl(weld::Builder* pBuilder, + sal_Int32 _rType, + const Reference< XConnection>& _xConnection, + const OUString& rDefault, + const IObjectNameCheck& _rObjectNameCheck, + SADFlags _nFlags) + : m_aQryLabel(DBA_RES(STR_QRY_LABEL)) + , m_sTblLabel(DBA_RES(STR_TBL_LABEL)) + , m_aName(rDefault) + , m_rObjectNameCheck( _rObjectNameCheck ) + , m_nType(_rType) + , m_nFlags(_nFlags) + , m_aChecker(OUString()) + , m_xDescription(pBuilder->weld_label("descriptionft")) + , m_xCatalogLbl(pBuilder->weld_label("catalogft")) + , m_xCatalog(pBuilder->weld_combo_box("catalog")) + , m_xSchemaLbl(pBuilder->weld_label("schemaft")) + , m_xSchema(pBuilder->weld_combo_box("schema")) + , m_xLabel(pBuilder->weld_label("titleft")) + , m_xTitle(pBuilder->weld_entry("title")) + , m_xPB_OK(pBuilder->weld_button("ok")) +{ + if ( _xConnection.is() ) + m_xMetaData = _xConnection->getMetaData(); + + if (m_xMetaData.is()) + { + OUString sExtraNameChars(m_xMetaData->getExtraNameCharacters()); + m_aChecker.setAllowedChars(sExtraNameChars); + } + + m_xTitle->connect_insert_text(LINK(this, OSaveAsDlgImpl, TextFilterHdl)); + m_xSchema->connect_entry_insert_text(LINK(this, OSaveAsDlgImpl, TextFilterHdl)); + m_xCatalog->connect_entry_insert_text(LINK(this, OSaveAsDlgImpl, TextFilterHdl)); +} + +OSaveAsDlgImpl::OSaveAsDlgImpl(weld::Builder* pBuilder, + const OUString& rDefault, + const IObjectNameCheck& _rObjectNameCheck, + SADFlags _nFlags) + : m_aQryLabel(DBA_RES(STR_QRY_LABEL)) + , m_sTblLabel(DBA_RES(STR_TBL_LABEL)) + , m_aName(rDefault) + , m_rObjectNameCheck( _rObjectNameCheck ) + , m_nType(CommandType::COMMAND) + , m_nFlags(_nFlags) + , m_aChecker(OUString()) + , m_xDescription(pBuilder->weld_label("descriptionft")) + , m_xCatalogLbl(pBuilder->weld_label("catalogft")) + , m_xCatalog(pBuilder->weld_combo_box("catalog")) + , m_xSchemaLbl(pBuilder->weld_label("schemaft")) + , m_xSchema(pBuilder->weld_combo_box("schema")) + , m_xLabel(pBuilder->weld_label("titleft")) + , m_xTitle(pBuilder->weld_entry("title")) + , m_xPB_OK(pBuilder->weld_button("ok")) +{ + m_xTitle->connect_insert_text(LINK(this, OSaveAsDlgImpl, TextFilterHdl)); + m_xSchema->connect_entry_insert_text(LINK(this, OSaveAsDlgImpl, TextFilterHdl)); + m_xCatalog->connect_entry_insert_text(LINK(this, OSaveAsDlgImpl, TextFilterHdl)); +} + +using namespace ::com::sun::star::lang; + +namespace +{ +typedef Reference< XResultSet > (SAL_CALL XDatabaseMetaData::*FGetMetaStrings)(); + +void lcl_fillComboList( weld::ComboBox& _rList, const Reference< XConnection >& _rxConnection, + FGetMetaStrings GetAll, const OUString& _rCurrent ) +{ + try { + Reference< XDatabaseMetaData > xMetaData( _rxConnection->getMetaData(), UNO_SET_THROW ); + + Reference< XResultSet > xRes = (xMetaData.get()->*GetAll)(); + Reference< XRow > xRow( xRes, UNO_QUERY_THROW ); + OUString sValue; + while ( xRes->next() ) { + sValue = xRow->getString( 1 ); + if ( !xRow->wasNull() ) + _rList.append_text( sValue ); + } + + int nPos = _rList.find_text( _rCurrent ); + if (nPos != -1) + _rList.set_active( nPos ); + else + _rList.set_active( 0 ); + } catch( const Exception& ) { + DBG_UNHANDLED_EXCEPTION("dbaccess"); + } +} +} + +OSaveAsDlg::OSaveAsDlg( weld::Window * pParent, + sal_Int32 _rType, + const Reference< XComponentContext >& _rxContext, + const Reference< XConnection>& _xConnection, + const OUString& rDefault, + const IObjectNameCheck& _rObjectNameCheck, + SADFlags _nFlags) + : GenericDialogController(pParent, "dbaccess/ui/savedialog.ui", "SaveDialog") + , m_xContext( _rxContext ) +{ + m_pImpl.reset( new OSaveAsDlgImpl(m_xBuilder.get(),_rType,_xConnection,rDefault,_rObjectNameCheck,_nFlags) ); + + switch (_rType) { + case CommandType::QUERY: + implInitOnlyTitle(m_pImpl->m_aQryLabel); + break; + + case CommandType::TABLE: + OSL_ENSURE( m_pImpl->m_xMetaData.is(), "OSaveAsDlg::OSaveAsDlg: no meta data for entering table names: this will crash!" ); + { + m_pImpl->m_xLabel->set_label(m_pImpl->m_sTblLabel); + if(m_pImpl->m_xMetaData.is() && !m_pImpl->m_xMetaData->supportsCatalogsInTableDefinitions()) { + m_pImpl->m_xCatalogLbl->hide(); + m_pImpl->m_xCatalog->hide(); + } else { + // now fill the catalogs + lcl_fillComboList( *m_pImpl->m_xCatalog, _xConnection, + &XDatabaseMetaData::getCatalogs, _xConnection->getCatalog() ); + } + + if ( !m_pImpl->m_xMetaData->supportsSchemasInTableDefinitions()) { + m_pImpl->m_xSchemaLbl->hide(); + m_pImpl->m_xSchema->hide(); + } else { + lcl_fillComboList( *m_pImpl->m_xSchema, _xConnection, + &XDatabaseMetaData::getSchemas, m_pImpl->m_xMetaData->getUserName() ); + } + + OSL_ENSURE(m_pImpl->m_xMetaData.is(),"The metadata can not be null!"); + if(m_pImpl->m_aName.indexOf('.') != -1) { + OUString sCatalog,sSchema,sTable; + ::dbtools::qualifiedNameComponents(m_pImpl->m_xMetaData, + m_pImpl->m_aName, + sCatalog, + sSchema, + sTable, + ::dbtools::EComposeRule::InDataManipulation); + + int nPos = m_pImpl->m_xCatalog->find_text(sCatalog); + if (nPos != -1) + m_pImpl->m_xCatalog->set_active(nPos); + + if ( !sSchema.isEmpty() ) { + nPos = m_pImpl->m_xSchema->find_text(sSchema); + if (nPos != -1) + m_pImpl->m_xSchema->set_active(nPos); + } + m_pImpl->m_xTitle->set_text(sTable); + } else + m_pImpl->m_xTitle->set_text(m_pImpl->m_aName); + m_pImpl->m_xTitle->select_region(0, -1); + + sal_Int32 nLength = m_pImpl->m_xMetaData.is() ? m_pImpl->m_xMetaData->getMaxTableNameLength() : 0; + if (nLength) + { + m_pImpl->m_xTitle->set_max_length(nLength); + m_pImpl->m_xSchema->set_entry_max_length(nLength); + m_pImpl->m_xCatalog->set_entry_max_length(nLength); + } + + bool bCheck = _xConnection.is() && isSQL92CheckEnabled(_xConnection); + m_pImpl->m_aChecker.setCheck(bCheck); // enable non valid sql chars as well + } + break; + + default: + OSL_FAIL( "OSaveAsDlg::OSaveAsDlg: Type not supported yet!" ); + } + + implInit(); +} + +OSaveAsDlg::OSaveAsDlg(weld::Window * pParent, + const Reference< XComponentContext >& _rxContext, + const OUString& rDefault, + const OUString& _sLabel, + const IObjectNameCheck& _rObjectNameCheck, + SADFlags _nFlags) + : GenericDialogController(pParent, "dbaccess/ui/savedialog.ui", "SaveDialog") + , m_xContext( _rxContext ) +{ + m_pImpl.reset( new OSaveAsDlgImpl(m_xBuilder.get(),rDefault,_rObjectNameCheck,_nFlags) ); + implInitOnlyTitle(_sLabel); + implInit(); +} + +OSaveAsDlg::~OSaveAsDlg() +{ +} + +IMPL_LINK_NOARG(OSaveAsDlg, ButtonClickHdl, weld::Button&, void) +{ + m_pImpl->m_aName = m_pImpl->m_xTitle->get_text(); + + OUString sNameToCheck( m_pImpl->m_aName ); + + if ( m_pImpl->m_nType == CommandType::TABLE ) { + sNameToCheck = ::dbtools::composeTableName( + m_pImpl->m_xMetaData, + getCatalog(), + getSchema(), + sNameToCheck, + false, // no quoting + ::dbtools::EComposeRule::InDataManipulation + ); + } + + SQLExceptionInfo aNameError; + if ( m_pImpl->m_rObjectNameCheck.isNameValid( sNameToCheck, aNameError ) ) + m_xDialog->response(RET_OK); + + showError(aNameError, m_xDialog->GetXWindow(), m_xContext); + m_pImpl->m_xTitle->grab_focus(); +} + +IMPL_LINK_NOARG(OSaveAsDlg, EditModifyHdl, weld::Entry&, void) +{ + m_pImpl->m_xPB_OK->set_sensitive(!m_pImpl->m_xTitle->get_text().isEmpty()); +} + +void OSaveAsDlg::implInitOnlyTitle(const OUString& _rLabel) +{ + m_pImpl->m_xLabel->set_label(_rLabel); + m_pImpl->m_xCatalogLbl->hide(); + m_pImpl->m_xCatalog->hide(); + m_pImpl->m_xSchemaLbl->hide(); + m_pImpl->m_xSchema->hide(); + + m_pImpl->m_xTitle->set_text(m_pImpl->m_aName); + m_pImpl->m_aChecker.setCheck(false); // enable non valid sql chars as well +} + +void OSaveAsDlg::implInit() +{ + if ( !( m_pImpl->m_nFlags & SADFlags::AdditionalDescription ) ) { + // hide the description window + m_pImpl->m_xDescription->hide(); + } + + if ( SADFlags::TitlePasteAs == ( m_pImpl->m_nFlags & SADFlags::TitlePasteAs ) ) + m_xDialog->set_title( DBA_RES( STR_TITLE_PASTE_AS ) ); + else if ( SADFlags::TitleRename == ( m_pImpl->m_nFlags & SADFlags::TitleRename ) ) + m_xDialog->set_title( DBA_RES( STR_TITLE_RENAME ) ); + + m_pImpl->m_xPB_OK->connect_clicked(LINK(this,OSaveAsDlg,ButtonClickHdl)); + m_pImpl->m_xTitle->connect_changed(LINK(this,OSaveAsDlg,EditModifyHdl)); + m_pImpl->m_xTitle->grab_focus(); +} + +const OUString& OSaveAsDlg::getName() const +{ + return m_pImpl->m_aName; +} +OUString OSaveAsDlg::getCatalog() const +{ + return m_pImpl->m_xCatalog->get_visible() ? m_pImpl->m_xCatalog->get_active_text() : OUString(); +} +OUString OSaveAsDlg::getSchema() const +{ + return m_pImpl->m_xSchema->get_visible() ? m_pImpl->m_xSchema->get_active_text() : OUString(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/dlgsize.cxx b/dbaccess/source/ui/dlg/dlgsize.cxx new file mode 100644 index 000000000..5b9f3a1ae --- /dev/null +++ b/dbaccess/source/ui/dlg/dlgsize.cxx @@ -0,0 +1,83 @@ +/* -*- 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 <dlgsize.hxx> + +namespace dbaui +{ + +#define DEF_ROW_HEIGHT 45 +#define DEF_COL_WIDTH 227 + +DlgSize::DlgSize(weld::Window* pParent, sal_Int32 nVal, bool bRow, sal_Int32 _nAlternativeStandard ) + : GenericDialogController(pParent, bRow ? OUString("dbaccess/ui/rowheightdialog.ui") : OUString("dbaccess/ui/colwidthdialog.ui"), + bRow ? OString("RowHeightDialog") : OString("ColWidthDialog")) + , m_nPrevValue(nVal) + , m_xMF_VALUE(m_xBuilder->weld_metric_spin_button("value", FieldUnit::CM)) + , m_xCB_STANDARD(m_xBuilder->weld_check_button("automatic")) +{ + sal_Int32 nStandard(bRow ? DEF_ROW_HEIGHT : DEF_COL_WIDTH); + if ( _nAlternativeStandard > 0 ) + nStandard = _nAlternativeStandard; + m_xCB_STANDARD->connect_toggled(LINK(this,DlgSize,CbClickHdl)); + + bool bDefault = -1 == nVal; + m_xCB_STANDARD->set_active(bDefault); + if (bDefault) + { + SetValue(nStandard); + m_nPrevValue = nStandard; + } + CbClickHdl(*m_xCB_STANDARD); +} + +DlgSize::~DlgSize() +{ +} + +void DlgSize::SetValue( sal_Int32 nVal ) +{ + m_xMF_VALUE->set_value(nVal, FieldUnit::CM ); +} + +sal_Int32 DlgSize::GetValue() const +{ + if (m_xCB_STANDARD->get_active()) + return -1; + return static_cast<sal_Int32>(m_xMF_VALUE->get_value( FieldUnit::CM )); +} + +IMPL_LINK_NOARG(DlgSize, CbClickHdl, weld::ToggleButton&, void) +{ + m_xMF_VALUE->set_sensitive(!m_xCB_STANDARD->get_active()); + if (m_xCB_STANDARD->get_active()) + { + // don't use getValue as this will use m_xCB_STANDARD->to determine if we're standard + m_nPrevValue = static_cast<sal_Int32>(m_xMF_VALUE->get_value(FieldUnit::CM)); + m_xMF_VALUE->set_text(""); + } + else + { + SetValue(m_nPrevValue); + } +} + +} // namespace dbaui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/dsnItem.hxx b/dbaccess/source/ui/dlg/dsnItem.hxx new file mode 100644 index 000000000..41103f8de --- /dev/null +++ b/dbaccess/source/ui/dlg/dsnItem.hxx @@ -0,0 +1,51 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_DBACCESS_SOURCE_UI_DLG_DSNITEM_HXX +#define INCLUDED_DBACCESS_SOURCE_UI_DLG_DSNITEM_HXX + +#include <svl/poolitem.hxx> + +namespace dbaccess +{ + class ODsnTypeCollection; +} +namespace dbaui +{ + // DbuTypeCollectionItem + /** allows an ODsnTypeCollection to be transported in an SfxItemSet + */ + class DbuTypeCollectionItem : public SfxPoolItem + { + ::dbaccess::ODsnTypeCollection* m_pCollection; + + public: + DbuTypeCollectionItem(sal_Int16 nWhich, ::dbaccess::ODsnTypeCollection* _pCollection); + DbuTypeCollectionItem(const DbuTypeCollectionItem& _rSource); + + virtual bool operator==(const SfxPoolItem& _rItem) const override; + virtual DbuTypeCollectionItem* Clone(SfxItemPool* _pPool = nullptr) const override; + + ::dbaccess::ODsnTypeCollection* getCollection() const { return m_pCollection; } + }; +} // namespace dbaui + +#endif // INCLUDED_DBACCESS_SOURCE_UI_DLG_DSNITEM_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/dsselect.cxx b/dbaccess/source/ui/dlg/dsselect.cxx new file mode 100644 index 000000000..4c0b9a836 --- /dev/null +++ b/dbaccess/source/ui/dlg/dsselect.cxx @@ -0,0 +1,133 @@ +/* -*- 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 "dsselect.hxx" + +#include <com/sun/star/sdbcx/XCreateCatalog.hpp> +#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp> + +namespace dbaui +{ +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::ui::dialogs; + +ODatasourceSelectDialog::ODatasourceSelectDialog(weld::Window* _pParent, const std::set<OUString>& _rDatasources) + : GenericDialogController(_pParent, "dbaccess/ui/choosedatasourcedialog.ui", "ChooseDataSourceDialog") + , m_xDatasource(m_xBuilder->weld_tree_view("treeview")) + , m_xOk(m_xBuilder->weld_button("ok")) + , m_xCancel(m_xBuilder->weld_button("cancel")) + , m_xManageDatasources(m_xBuilder->weld_button("organize")) +{ + m_xDatasource->set_size_request(-1, m_xDatasource->get_height_rows(6)); + + fillListBox(_rDatasources); +#ifdef HAVE_ODBC_ADMINISTRATION + // allow ODBC datasource management + m_xManageDatasources->show(); + m_xManageDatasources->set_sensitive(true); + m_xManageDatasources->connect_clicked(LINK(this,ODatasourceSelectDialog,ManageClickHdl)); +#endif + m_xDatasource->connect_row_activated(LINK(this,ODatasourceSelectDialog,ListDblClickHdl)); +} + +ODatasourceSelectDialog::~ODatasourceSelectDialog() +{ +} + +IMPL_LINK(ODatasourceSelectDialog, ListDblClickHdl, weld::TreeView&, rListBox, bool) +{ + if (rListBox.n_children()) + m_xDialog->response(RET_OK); + return true; +} + +short ODatasourceSelectDialog::run() +{ + short nRet = GenericDialogController::run(); +#ifdef HAVE_ODBC_ADMINISTRATION + if (m_xODBCManagement.get()) + m_xODBCManagement->disableCallback(); +#endif + return nRet; +} + +#ifdef HAVE_ODBC_ADMINISTRATION +IMPL_LINK_NOARG(ODatasourceSelectDialog, ManageClickHdl, weld::Button&, void) +{ + if ( !m_xODBCManagement.get() ) + m_xODBCManagement.reset( new OOdbcManagement( LINK( this, ODatasourceSelectDialog, ManageProcessFinished ) ) ); + + if ( !m_xODBCManagement->manageDataSources_async() ) + { + // TODO: error message + m_xDatasource->grab_focus(); + m_xManageDatasources->set_sensitive(false); + return; + } + + m_xDatasource->set_sensitive(false); + m_xOk->set_sensitive(false); + m_xCancel->set_sensitive(false); + m_xManageDatasources->set_sensitive(false); + + SAL_WARN_IF( !m_xODBCManagement->isRunning(), "dbaccess.ui", "ODatasourceSelectDialog::ManageClickHdl: success, but not running - you were *fast*!" ); +} + +IMPL_LINK_NOARG( ODatasourceSelectDialog, ManageProcessFinished, void*, void ) +{ + m_xODBCManagement->receivedCallback(); + + std::set<OUString> aOdbcDatasources; + OOdbcEnumeration aEnumeration; + aEnumeration.getDatasourceNames( aOdbcDatasources ); + fillListBox( aOdbcDatasources ); + + m_xDatasource->set_sensitive(true); + m_xOk->set_sensitive(true); + m_xCancel->set_sensitive(true); + m_xManageDatasources->set_sensitive(true); +} + +#endif +void ODatasourceSelectDialog::fillListBox(const std::set<OUString>& _rDatasources) +{ + OUString sSelected; + if (m_xDatasource->n_children()) + sSelected = m_xDatasource->get_selected_text(); + m_xDatasource->clear(); + // fill the list + for (auto const& datasource : _rDatasources) + { + m_xDatasource->append_text(datasource); + } + + if (m_xDatasource->n_children()) + { + if (!sSelected.isEmpty()) + m_xDatasource->select_text(sSelected); + else // select the first entry + m_xDatasource->select(0); + } +} + +} // namespace dbaui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/dsselect.hxx b/dbaccess/source/ui/dlg/dsselect.hxx new file mode 100644 index 000000000..f365eaf00 --- /dev/null +++ b/dbaccess/source/ui/dlg/dsselect.hxx @@ -0,0 +1,69 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_DBACCESS_SOURCE_UI_DLG_DSSELECT_HXX +#define INCLUDED_DBACCESS_SOURCE_UI_DLG_DSSELECT_HXX + +#include <rtl/ustring.hxx> +#include <vcl/weld.hxx> + +#include <memory> +#include <set> + +class SfxItemSet; +namespace dbaui +{ + +// ODatasourceSelector +class ODatasourceSelectDialog final : public weld::GenericDialogController +{ + std::unique_ptr<weld::TreeView> m_xDatasource; + std::unique_ptr<weld::Button> m_xOk; + std::unique_ptr<weld::Button> m_xCancel; + std::unique_ptr<weld::Button> m_xManageDatasources; +#ifdef HAVE_ODBC_ADMINISTRATION + std::unique_ptr<OOdbcManagement> m_xODBCManagement; +#endif + +public: + ODatasourceSelectDialog(weld::Window* pParent, const std::set<OUString>& rDatasources); + virtual ~ODatasourceSelectDialog() override; + OUString GetSelected() const { + return m_xDatasource->get_selected_text(); + } + void Select( const OUString& _rEntry ) { + m_xDatasource->select_text(_rEntry); + } + + virtual short run() override; + +private: + DECL_LINK( ListDblClickHdl, weld::TreeView&, bool ); +#ifdef HAVE_ODBC_ADMINISTRATION + DECL_LINK(ManageClickHdl, weld::Button&, void); + DECL_LINK(ManageProcessFinished, void*, void); +#endif + void fillListBox(const std::set<OUString>& _rDatasources); +}; + +} // namespace dbaui + +#endif // INCLUDED_DBACCESS_SOURCE_UI_DLG_DSSELECT_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/finteraction.cxx b/dbaccess/source/ui/dlg/finteraction.cxx new file mode 100644 index 000000000..611119a0c --- /dev/null +++ b/dbaccess/source/ui/dlg/finteraction.cxx @@ -0,0 +1,59 @@ +/* -*- 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 "finteraction.hxx" +#include <com/sun/star/ucb/InteractiveIOException.hpp> + +namespace dbaui +{ + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::task; + using namespace ::com::sun::star::ucb; + + // OFilePickerInteractionHandler + OFilePickerInteractionHandler::OFilePickerInteractionHandler( const Reference< XInteractionHandler >& _rxMaster ) + :m_xMaster( _rxMaster ) + ,m_bDoesNotExist(false) + { + assert(m_xMaster.is()); + } + + OFilePickerInteractionHandler::~OFilePickerInteractionHandler( ) + { + } + + void SAL_CALL OFilePickerInteractionHandler::handle( const Reference< XInteractionRequest >& _rxRequest ) + { + InteractiveIOException aIoException; + if ( _rxRequest->getRequest() >>= aIoException ) + { + if ( IOErrorCode_NOT_EXISTING == aIoException.Code ) + { + m_bDoesNotExist = true; + return; + } + } + + if ( m_xMaster.is() ) + m_xMaster->handle( _rxRequest ); + } + +} // namespace svt + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/finteraction.hxx b/dbaccess/source/ui/dlg/finteraction.hxx new file mode 100644 index 000000000..fdc70b7fc --- /dev/null +++ b/dbaccess/source/ui/dlg/finteraction.hxx @@ -0,0 +1,57 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_DBACCESS_SOURCE_UI_DLG_FINTERACTION_HXX +#define INCLUDED_DBACCESS_SOURCE_UI_DLG_FINTERACTION_HXX + +#include <cppuhelper/implbase.hxx> +#include <com/sun/star/task/XInteractionHandler.hpp> + +namespace dbaui +{ + + // OFilePickerInteractionHandler + typedef ::cppu::WeakImplHelper< css::task::XInteractionHandler + > OFilePickerInteractionHandler_Base; + + /** an InteractionHandler implementation which extends another handler with some customizability + */ + class OFilePickerInteractionHandler final : public OFilePickerInteractionHandler_Base + { + css::uno::Reference< css::task::XInteractionHandler > + m_xMaster; // our master handler + bool m_bDoesNotExist; + + public: + explicit OFilePickerInteractionHandler( const css::uno::Reference< css::task::XInteractionHandler >& _rxMaster ); + + bool isDoesNotExist() const { return m_bDoesNotExist; } + + private: + // XInteractionHandler + virtual void SAL_CALL handle( const css::uno::Reference< css::task::XInteractionRequest >& _rxRequest ) override; + + virtual ~OFilePickerInteractionHandler() override; + }; + +} // namespace dbaui + +#endif // INCLUDED_DBACCESS_SOURCE_UI_DLG_FINTERACTION_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/generalpage.cxx b/dbaccess/source/ui/dlg/generalpage.cxx new file mode 100644 index 000000000..5361fc2d0 --- /dev/null +++ b/dbaccess/source/ui/dlg/generalpage.cxx @@ -0,0 +1,683 @@ +/* -*- 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 <core_resource.hxx> +#include "dsnItem.hxx" +#include "generalpage.hxx" +#include <connectivity/dbexception.hxx> +#include <strings.hrc> +#include <dsitems.hxx> +#include <sfx2/filedlghelper.hxx> +#include <sfx2/docfilt.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> +#include <svl/stritem.hxx> +#include <com/sun/star/ui/dialogs/TemplateDescription.hpp> +#include <UITools.hxx> +#include <comphelper/processfactory.hxx> +#include <unotools/confignode.hxx> +#include <o3tl/safeint.hxx> +#include <osl/diagnose.h> +#include <svtools/miscopt.hxx> +#include <sal/log.hxx> +#include <dbwizsetup.hxx> + +namespace dbaui +{ + using namespace ::com::sun::star; + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::sdbc; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::container; + + // OGeneralPage + OGeneralPage::OGeneralPage(weld::Container* pPage, weld::DialogController* pController, const OUString& _rUIXMLDescription, const SfxItemSet& _rItems) + : OGenericAdministrationPage(pPage, pController, _rUIXMLDescription, "PageGeneral", _rItems) + , m_xSpecialMessage(m_xBuilder->weld_label("specialMessage")) + , m_eLastMessage(smNone) + , m_bInitTypeList(true) + , m_xDatasourceType(m_xBuilder->weld_combo_box("datasourceType")) + , m_pCollection(nullptr) + { + // extract the datasource type collection from the item set + const DbuTypeCollectionItem* pCollectionItem = dynamic_cast<const DbuTypeCollectionItem*>( _rItems.GetItem(DSID_TYPECOLLECTION) ); + if (pCollectionItem) + m_pCollection = pCollectionItem->getCollection(); + SAL_WARN_IF(!m_pCollection, "dbaccess.ui.generalpage", "OGeneralPage::OGeneralPage : really need a DSN type collection !"); + + // do some knittings + m_xDatasourceType->connect_changed(LINK(this, OGeneralPage, OnDatasourceTypeSelected)); + } + + OGeneralPage::~OGeneralPage() + { + } + + namespace + { + struct DisplayedType + { + OUString eType; + OUString sDisplayName; + + DisplayedType( const OUString& _eType, const OUString& _rDisplayName ) : eType( _eType ), sDisplayName( _rDisplayName ) { } + }; + typedef std::vector< DisplayedType > DisplayedTypes; + + struct DisplayedTypeLess + { + bool operator() ( const DisplayedType& _rLHS, const DisplayedType& _rRHS ) + { + return _rLHS.eType < _rRHS.eType; + } + }; + } + + void OGeneralPage::initializeTypeList() + { + if ( !m_bInitTypeList ) + return; + + m_bInitTypeList = false; + m_xDatasourceType->clear(); + + if ( !m_pCollection ) + return; + + DisplayedTypes aDisplayedTypes; + + ::dbaccess::ODsnTypeCollection::TypeIterator aEnd = m_pCollection->end(); + for ( ::dbaccess::ODsnTypeCollection::TypeIterator aTypeLoop = m_pCollection->begin(); + aTypeLoop != aEnd; + ++aTypeLoop + ) + { + const OUString& sURLPrefix = aTypeLoop.getURLPrefix(); + if ( !sURLPrefix.isEmpty() ) + { + // skip mysql connection variations. It is handled in another window. + if(sURLPrefix.startsWith("sdbc:mysql:") && !sURLPrefix.startsWith("sdbc:mysql:jdbc:")) + continue; + + OUString sDisplayName = aTypeLoop.getDisplayName(); + if (m_xDatasourceType->find_text(sDisplayName) == -1 && + approveDatasourceType(sURLPrefix, sDisplayName)) + { + aDisplayedTypes.emplace_back( sURLPrefix, sDisplayName ); + } + } + } + std::sort( aDisplayedTypes.begin(), aDisplayedTypes.end(), DisplayedTypeLess() ); + for ( const auto& rDisplayedType : aDisplayedTypes ) + insertDatasourceTypeEntryData( rDisplayedType.eType, rDisplayedType.sDisplayName ); + } + + void OGeneralPageWizard::initializeEmbeddedDBList() + { + if ( !m_bInitEmbeddedDBList ) + return; + + m_bInitEmbeddedDBList = false; + m_xEmbeddedDBType->clear(); + + if ( !m_pCollection ) + return; + + DisplayedTypes aDisplayedTypes; + + ::dbaccess::ODsnTypeCollection::TypeIterator aEnd = m_pCollection->end(); + + SvtMiscOptions aMiscOptions; + + for ( ::dbaccess::ODsnTypeCollection::TypeIterator aTypeLoop = m_pCollection->begin(); + aTypeLoop != aEnd; + ++aTypeLoop + ) + { + const OUString& sURLPrefix = aTypeLoop.getURLPrefix(); + if ( !sURLPrefix.isEmpty() ) + { + OUString sDisplayName = aTypeLoop.getDisplayName(); + if (m_xEmbeddedDBType->find_text(sDisplayName) == -1 && + dbaccess::ODsnTypeCollection::isEmbeddedDatabase(sURLPrefix)) + { + if( !aMiscOptions.IsExperimentalMode() && sURLPrefix.startsWith("sdbc:embedded:firebird") ) + continue; + aDisplayedTypes.emplace_back( sURLPrefix, sDisplayName ); + } + } + } + std::sort( aDisplayedTypes.begin(), aDisplayedTypes.end(), DisplayedTypeLess() ); + for (auto const& displayedType : aDisplayedTypes) + insertEmbeddedDBTypeEntryData( displayedType.eType, displayedType.sDisplayName ); + } + + void OGeneralPage::setParentTitle(const OUString&) + { + } + + void OGeneralPage::switchMessage(const OUString& _sURLPrefix) + { + SPECIAL_MESSAGE eMessage = smNone; + if ( _sURLPrefix.isEmpty()/*_eType == m_eNotSupportedKnownType*/ ) + { + eMessage = smUnsupportedType; + } + + if ( eMessage != m_eLastMessage ) + { + const char* pResId = nullptr; + if ( smUnsupportedType == eMessage ) + pResId = STR_UNSUPPORTED_DATASOURCE_TYPE; + OUString sMessage; + if ( pResId ) + sMessage = DBA_RES(pResId); + + m_xSpecialMessage->set_label( sMessage ); + m_eLastMessage = eMessage; + } + } + + void OGeneralPage::onTypeSelected(const OUString& _sURLPrefix) + { + // the new URL text as indicated by the selection history + implSetCurrentType( _sURLPrefix ); + + switchMessage(_sURLPrefix); + + m_aTypeSelectHandler.Call(*this); + } + + void OGeneralPage::implInitControls( const SfxItemSet& _rSet, bool _bSaveValue ) + { + initializeTypeList(); + + m_xDatasourceType->set_active_text(getDatasourceName(_rSet)); + + // notify our listener that our type selection has changed (if so) + // FIXME: how to detect that it did not changed? (fdo#62937) + setParentTitle( m_eCurrentSelection ); + onTypeSelected( m_eCurrentSelection ); + + // a special message for the current page state + switchMessage( m_eCurrentSelection ); + + OGenericAdministrationPage::implInitControls( _rSet, _bSaveValue ); + } + + OUString OGeneralPageWizard::getEmbeddedDBName( const SfxItemSet& _rSet ) + { + // first check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa) + bool bValid, bReadonly; + getFlags( _rSet, bValid, bReadonly ); + + // if the selection is invalid, disable everything + + implSetCurrentType( OUString() ); + + // compare the DSN prefix with the registered ones + OUString sDisplayName; + + if (m_pCollection && bValid) + { + implSetCurrentType( dbaccess::ODsnTypeCollection::getEmbeddedDatabase() ); + sDisplayName = m_pCollection->getTypeDisplayName( m_eCurrentSelection ); + onTypeSelected(m_eCurrentSelection); + } + + // select the correct datasource type + if ( dbaccess::ODsnTypeCollection::isEmbeddedDatabase( m_eCurrentSelection ) + && m_xEmbeddedDBType->find_text(sDisplayName) == -1 ) + { // this indicates it's really a type which is known in general, but not supported on the current platform + // show a message saying so + // eSpecialMessage = smUnsupportedType; + insertEmbeddedDBTypeEntryData( m_eCurrentSelection, sDisplayName ); + } + + return sDisplayName; + } + + OUString OGeneralPage::getDatasourceName( const SfxItemSet& _rSet ) + { + // first check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa) + bool bValid, bReadonly; + getFlags( _rSet, bValid, bReadonly ); + + // if the selection is invalid, disable everything + OUString sConnectURL; + if ( bValid ) + { + // collect some items and some values + const SfxStringItem* pUrlItem = _rSet.GetItem<SfxStringItem>(DSID_CONNECTURL); + assert( pUrlItem ); + sConnectURL = pUrlItem->GetValue(); + } + + implSetCurrentType( OUString() ); + + // compare the DSN prefix with the registered ones + OUString sDisplayName; + + if (m_pCollection && bValid) + { + implSetCurrentType( m_pCollection->getPrefix( sConnectURL ) ); + sDisplayName = m_pCollection->getTypeDisplayName( m_eCurrentSelection ); + } + + // select the correct datasource type + if ( approveDatasourceType( m_eCurrentSelection, sDisplayName ) + && m_xDatasourceType->find_text(sDisplayName) == -1 ) + { // this indicates it's really a type which is known in general, but not supported on the current platform + // show a message saying so + // eSpecialMessage = smUnsupportedType; + insertDatasourceTypeEntryData( m_eCurrentSelection, sDisplayName ); + } + + return sDisplayName; + } + + // For the databaseWizard we only have one entry for the MySQL Database, + // because we have a separate tabpage to retrieve the respective datasource type + // ( ::dbaccess::DST_MYSQL_ODBC || ::dbaccess::DST_MYSQL_JDBC). Therefore we use ::dbaccess::DST_MYSQL_JDBC as a temporary + // representative for all MySQl databases) + // Also, embedded databases (embedded HSQL, at the moment), are not to appear in the list of + // databases to connect to. + bool OGeneralPage::approveDatasourceType( const OUString& _sURLPrefix, OUString& _inout_rDisplayName ) + { + return approveDatasourceType( m_pCollection->determineType(_sURLPrefix), _inout_rDisplayName ); + } + + bool OGeneralPage::approveDatasourceType( ::dbaccess::DATASOURCE_TYPE eType, OUString& _inout_rDisplayName ) + { + if ( eType == ::dbaccess::DST_MYSQL_NATIVE_DIRECT ) + { + // do not display the Connector/OOo driver itself, it is always wrapped via the MySQL-Driver, if + // this driver is installed + if ( m_pCollection->hasDriver( "sdbc:mysql:mysqlc:" ) ) + _inout_rDisplayName.clear(); + } + + if ( eType == ::dbaccess::DST_EMBEDDED_HSQLDB + || eType == ::dbaccess::DST_EMBEDDED_FIREBIRD ) + _inout_rDisplayName.clear(); + + return _inout_rDisplayName.getLength() > 0; + } + + void OGeneralPage::insertDatasourceTypeEntryData(const OUString& _sType, const OUString& sDisplayName) + { + // insert a (temporary) entry + m_xDatasourceType->append_text(sDisplayName); + m_aURLPrefixes.push_back(_sType); + } + + void OGeneralPageWizard::insertEmbeddedDBTypeEntryData(const OUString& _sType, const OUString& sDisplayName) + { + // insert a (temporary) entry + m_xEmbeddedDBType->append_text(sDisplayName); + m_aEmbeddedURLPrefixes.push_back(_sType); + } + + void OGeneralPage::fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) + { + _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Label>(m_xSpecialMessage.get())); + } + + void OGeneralPage::fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) + { + _rControlList.emplace_back(new OSaveValueWidgetWrapper<weld::ComboBox>(m_xDatasourceType.get())); + } + + void OGeneralPage::implSetCurrentType( const OUString& _eType ) + { + if ( _eType == m_eCurrentSelection ) + return; + + m_eCurrentSelection = _eType; + } + + void OGeneralPage::Reset(const SfxItemSet* _rCoreAttrs) + { + // reset all locale data + implSetCurrentType( OUString() ); + // this ensures that our type selection link will be called, even if the new one is the same as the + // current one + OGenericAdministrationPage::Reset(_rCoreAttrs); + } + + IMPL_LINK( OGeneralPageWizard, OnEmbeddedDBTypeSelected, weld::ComboBox&, _rBox, void ) + { + // get the type from the entry data + const sal_Int32 nSelected = _rBox.get_active(); + if (o3tl::make_unsigned(nSelected) >= m_aEmbeddedURLPrefixes.size() ) + { + SAL_WARN("dbaccess.ui.generalpage", "Got out-of-range value '" << nSelected << "' from the DatasourceType selection ListBox's GetSelectedEntryPos(): no corresponding URL prefix"); + return; + } + const OUString sURLPrefix = m_aEmbeddedURLPrefixes[ nSelected ]; + + setParentTitle( sURLPrefix ); + // let the impl method do all the stuff + onTypeSelected( sURLPrefix ); + // tell the listener we were modified + callModifiedHdl(); + } + + IMPL_LINK( OGeneralPage, OnDatasourceTypeSelected, weld::ComboBox&, _rBox, void ) + { + // get the type from the entry data + const sal_Int32 nSelected = _rBox.get_active(); + if (nSelected == -1) + return; + if (o3tl::make_unsigned(nSelected) >= m_aURLPrefixes.size() ) + { + SAL_WARN("dbaccess.ui.generalpage", "Got out-of-range value '" << nSelected << "' from the DatasourceType selection ListBox's GetSelectedEntryPos(): no corresponding URL prefix"); + return; + } + const OUString sURLPrefix = m_aURLPrefixes[ nSelected ]; + + setParentTitle( sURLPrefix ); + // let the impl method do all the stuff + onTypeSelected( sURLPrefix ); + // tell the listener we were modified + callModifiedHdl(); + } + + // OGeneralPageDialog + OGeneralPageDialog::OGeneralPageDialog(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rItems) + : OGeneralPage(pPage, pController, "dbaccess/ui/generalpagedialog.ui", _rItems) + { + } + + void OGeneralPageDialog::setParentTitle( const OUString& _sURLPrefix ) + { + const OUString sName = m_pCollection->getTypeDisplayName( _sURLPrefix ); + if ( m_pAdminDialog ) + { + OUString sMessage = DBA_RES(STR_PARENTTITLE_GENERAL); + m_pAdminDialog->setTitle( sMessage.replaceAll( "#", sName ) ); + } + } + + void OGeneralPageDialog::implInitControls( const SfxItemSet& _rSet, bool _bSaveValue ) + { + OGeneralPage::implInitControls( _rSet, _bSaveValue ); + + // first check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa) + bool bValid, bReadonly; + getFlags(_rSet, bValid, bReadonly ); + + m_xDatasourceType->set_sensitive( bValid ); + } + + bool OGeneralPageDialog::FillItemSet( SfxItemSet* _rCoreAttrs ) + { + bool bChangedSomething = false; + + const sal_Int32 nEntry = m_xDatasourceType->get_active(); + OUString sURLPrefix = m_aURLPrefixes[ nEntry ]; + + if (m_xDatasourceType->get_value_changed_from_saved()) + { + _rCoreAttrs->Put( SfxStringItem( DSID_CONNECTURL, sURLPrefix ) ); + bChangedSomething = true; + } + + return bChangedSomething; + } + + // OGeneralPageWizard + OGeneralPageWizard::OGeneralPageWizard(weld::Container* pPage, ODbTypeWizDialogSetup* pController, const SfxItemSet& _rItems) + : OGeneralPage( pPage, pController, "dbaccess/ui/generalpagewizard.ui", _rItems ) + , m_xRB_CreateDatabase(m_xBuilder->weld_radio_button("createDatabase")) + , m_xRB_OpenExistingDatabase(m_xBuilder->weld_radio_button("openExistingDatabase")) + , m_xRB_ConnectDatabase(m_xBuilder->weld_radio_button("connectDatabase")) + , m_xFT_EmbeddedDBLabel(m_xBuilder->weld_label("embeddeddbLabel")) + , m_xEmbeddedDBType(m_xBuilder->weld_combo_box("embeddeddbList")) + , m_xFT_DocListLabel(m_xBuilder->weld_label("docListLabel")) + , m_xFT_HelpText(m_xBuilder->weld_label("helpText")) + , m_xLB_DocumentList(new OpenDocumentListBox(m_xBuilder->weld_combo_box("documentList"), "com.sun.star.sdb.OfficeDatabaseDocument")) + , m_xPB_OpenDatabase(new OpenDocumentButton(m_xBuilder->weld_button("openDatabase"), "com.sun.star.sdb.OfficeDatabaseDocument")) + , m_eOriginalCreationMode(eCreateNew) + , m_bInitEmbeddedDBList(true) + { + // If no driver for embedded DBs is installed, and no dBase driver, then hide the "Create new database" option + sal_Int32 nCreateNewDBIndex = m_pCollection->getIndexOf( dbaccess::ODsnTypeCollection::getEmbeddedDatabase() ); + if ( nCreateNewDBIndex == -1 ) + nCreateNewDBIndex = m_pCollection->getIndexOf( "sdbc:dbase:" ); + bool bHideCreateNew = ( nCreateNewDBIndex == -1 ); + + // also, if our application policies tell us to hide the option, do it + ::utl::OConfigurationTreeRoot aConfig( ::utl::OConfigurationTreeRoot::createWithComponentContext( + ::comphelper::getProcessComponentContext(), + "/org.openoffice.Office.DataAccess/Policies/Features/Base" + ) ); + bool bAllowCreateLocalDatabase( true ); + OSL_VERIFY( aConfig.getNodeValue( "CreateLocalDatabase" ) >>= bAllowCreateLocalDatabase ); + if ( !bAllowCreateLocalDatabase ) + bHideCreateNew = true; + + if ( bHideCreateNew ) + { + m_xRB_CreateDatabase->hide(); + m_xRB_ConnectDatabase->set_active(true); + } + else + m_xRB_CreateDatabase->set_active(true); + + // do some knittings + m_xEmbeddedDBType->connect_changed(LINK(this, OGeneralPageWizard, OnEmbeddedDBTypeSelected)); + m_xRB_CreateDatabase->connect_clicked( LINK( this, OGeneralPageWizard, OnSetupModeSelected ) ); + m_xRB_ConnectDatabase->connect_clicked( LINK( this, OGeneralPageWizard, OnSetupModeSelected ) ); + m_xRB_OpenExistingDatabase->connect_clicked( LINK( this, OGeneralPageWizard, OnSetupModeSelected ) ); + m_xLB_DocumentList->connect_changed( LINK( this, OGeneralPageWizard, OnDocumentSelected ) ); + m_xPB_OpenDatabase->connect_clicked( LINK( this, OGeneralPageWizard, OnOpenDocument ) ); + + pController->SetGeneralPage(this); + } + + OGeneralPageWizard::~OGeneralPageWizard() + { + } + + OGeneralPageWizard::CreationMode OGeneralPageWizard::GetDatabaseCreationMode() const + { + if ( m_xRB_CreateDatabase->get_active() ) + return eCreateNew; + if ( m_xRB_ConnectDatabase->get_active() ) + return eConnectExternal; + return eOpenExisting; + } + + void OGeneralPageWizard::implInitControls( const SfxItemSet& _rSet, bool _bSaveValue ) + { + OGeneralPage::implInitControls( _rSet, _bSaveValue ); + + initializeEmbeddedDBList(); + m_xEmbeddedDBType->set_active_text(getEmbeddedDBName(_rSet)); + + // first check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa) + bool bValid, bReadonly; + getFlags( _rSet, bValid, bReadonly ); + + SetPageTitle(OUString()); + + if ( !bValid || bReadonly ) + { + m_xFT_EmbeddedDBLabel->set_sensitive( false ); + m_xDatasourceType->set_sensitive( false ); + m_xPB_OpenDatabase->set_sensitive( false ); + m_xFT_DocListLabel->set_sensitive( false ); + m_xLB_DocumentList->set_sensitive( false ); + } + + if (m_xLB_DocumentList->get_count()) + m_xLB_DocumentList->set_active(0); + + m_eOriginalCreationMode = GetDatabaseCreationMode(); + + SetupModeSelected(); + } + + OUString OGeneralPageWizard::getDatasourceName(const SfxItemSet& _rSet) + { + // Sets the default selected database on startup. + if (m_xRB_CreateDatabase->get_active() ) + { + return m_pCollection->getTypeDisplayName( "sdbc:firebird:" ); + } + + return OGeneralPage::getDatasourceName( _rSet ); + } + + bool OGeneralPageWizard::approveDatasourceType( ::dbaccess::DATASOURCE_TYPE eType, OUString& _inout_rDisplayName ) + { + switch ( eType ) + { + case ::dbaccess::DST_MYSQL_JDBC: + case ::dbaccess::DST_MYSQL_ODBC: + case ::dbaccess::DST_MYSQL_NATIVE: + _inout_rDisplayName = "MySQL"; + break; + default: + break; + } + + return OGeneralPage::approveDatasourceType( eType, _inout_rDisplayName ); + } + + bool OGeneralPageWizard::FillItemSet(SfxItemSet* _rCoreAttrs) + { + bool bChangedSomething = false; + + bool bCommitTypeSelection = true; + + if ( m_xRB_CreateDatabase->get_active() ) + { + _rCoreAttrs->Put( SfxStringItem( DSID_CONNECTURL, "sdbc:dbase:" ) ); + bChangedSomething = true; + bCommitTypeSelection = false; + } + else if ( m_xRB_OpenExistingDatabase->get_active() ) + { + if ( m_xRB_OpenExistingDatabase->get_state_changed_from_saved() ) + bChangedSomething = true; + + // TODO + bCommitTypeSelection = false; + } + + if ( bCommitTypeSelection ) + { + const sal_Int32 nEntry = m_xDatasourceType->get_active(); + OUString sURLPrefix = m_aURLPrefixes[nEntry]; + + if ( m_xDatasourceType->get_value_changed_from_saved() + || ( GetDatabaseCreationMode() != m_eOriginalCreationMode ) + ) + { + _rCoreAttrs->Put( SfxStringItem( DSID_CONNECTURL,sURLPrefix ) ); + bChangedSomething = true; + } + else + implSetCurrentType( sURLPrefix ); + } + return bChangedSomething; + } + + OUString OGeneralPageWizard::GetSelectedDocumentURL() const + { + if ( !m_aBrowsedDocumentURL.isEmpty() ) + return m_aBrowsedDocumentURL; + else + return m_xLB_DocumentList->GetSelectedDocumentURL(); + } + + void OGeneralPageWizard::EnableControls() + { + bool bValid, bReadonly; + getFlags( GetItemSet(), bValid, bReadonly ); + if ( bValid && !bReadonly ) + { + m_xEmbeddedDBType->set_sensitive(m_xRB_CreateDatabase->get_active()); + m_xFT_EmbeddedDBLabel->set_sensitive(m_xRB_CreateDatabase->get_active()); + m_xDatasourceType->set_sensitive(m_xRB_ConnectDatabase->get_active()); + m_xPB_OpenDatabase->set_sensitive(m_xRB_OpenExistingDatabase->get_active()); + m_xFT_DocListLabel->set_sensitive(m_xRB_OpenExistingDatabase->get_active()); + m_xLB_DocumentList->set_sensitive(m_xRB_OpenExistingDatabase->get_active()); + } + } + + void OGeneralPageWizard::SetupModeSelected() + { + m_aCreationModeHandler.Call( *this ); + + if (m_xRB_CreateDatabase->get_active()) + OnEmbeddedDBTypeSelected(*m_xEmbeddedDBType); + else + OnDatasourceTypeSelected(*m_xDatasourceType); + + EnableControls(); + } + + IMPL_LINK_NOARG( OGeneralPageWizard, OnSetupModeSelected, weld::Button&, void ) + { + SetupModeSelected(); + } + + IMPL_LINK_NOARG( OGeneralPageWizard, OnDocumentSelected, weld::ComboBox&, void ) + { + m_aDocumentSelectionHandler.Call( *this ); + } + + IMPL_LINK_NOARG( OGeneralPageWizard, OnOpenDocument, weld::Button&, void ) + { + ::sfx2::FileDialogHelper aFileDlg( + ui::dialogs::TemplateDescription::FILEOPEN_READONLY_VERSION, + FileDialogFlags::NONE, "sdatabase", SfxFilterFlags::NONE, SfxFilterFlags::NONE, GetFrameWeld()); + std::shared_ptr<const SfxFilter> pFilter = getStandardDatabaseFilter(); + if ( pFilter ) + { + aFileDlg.SetCurrentFilter(pFilter->GetUIName()); + } + if ( aFileDlg.Execute() != ERRCODE_NONE ) + return; + + OUString sPath = aFileDlg.GetPath(); + // check for aFileDlg.GetCurrentFilter used to be here but current fpicker filter + // can be set to anything, see tdf#125267 how this breaks if other value + // than 'ODF Database' is selected. Let's therefore check only if wildcard matches + if ( !pFilter->GetWildcard().Matches(sPath) ) + { + OUString sMessage(DBA_RES(STR_ERR_USE_CONNECT_TO)); + std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(GetFrameWeld(), + VclMessageType::Info, VclButtonsType::Ok, + sMessage)); + xInfoBox->run(); + m_xRB_ConnectDatabase->set_active(true); + OnSetupModeSelected( *m_xRB_ConnectDatabase ); + return; + } + m_aBrowsedDocumentURL = sPath; + m_aChooseDocumentHandler.Call( *this ); + } + +} // namespace dbaui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/generalpage.hxx b/dbaccess/source/ui/dlg/generalpage.hxx new file mode 100644 index 000000000..e8af35387 --- /dev/null +++ b/dbaccess/source/ui/dlg/generalpage.hxx @@ -0,0 +1,188 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_DBACCESS_SOURCE_UI_DLG_GENERALPAGE_HXX +#define INCLUDED_DBACCESS_SOURCE_UI_DLG_GENERALPAGE_HXX + +#include "adminpages.hxx" +#include <opendoccontrols.hxx> + +namespace dbaui +{ + class ODbTypeWizDialogSetup; + + // OGeneralPage + class OGeneralPage : public OGenericAdministrationPage + { + protected: + OGeneralPage(weld::Container* pPage, weld::DialogController* pController, const OUString& _rUIXMLDescription, const SfxItemSet& _rItems); + + OUString m_eCurrentSelection; /// currently selected type + + private: + std::unique_ptr<weld::Label> m_xSpecialMessage; + + enum SPECIAL_MESSAGE + { + smNone, + smUnsupportedType + }; + SPECIAL_MESSAGE m_eLastMessage; + + Link<OGeneralPage&,void> m_aTypeSelectHandler; /// to be called if a new type is selected + bool m_bInitTypeList : 1; + bool approveDatasourceType( const OUString& _sURLPrefix, OUString& _inout_rDisplayName ); + void insertDatasourceTypeEntryData( const OUString& _sType, const OUString& sDisplayName ); + + protected: + std::unique_ptr<weld::ComboBox> m_xDatasourceType; + + ::dbaccess::ODsnTypeCollection* + m_pCollection; /// the DSN type collection instance + + std::vector< OUString> + m_aURLPrefixes; + + public: + virtual ~OGeneralPage() override; + + /// set a handler which gets called every time the user selects a new type + void SetTypeSelectHandler( const Link<OGeneralPage&,void>& _rHandler ) { m_aTypeSelectHandler = _rHandler; } + + /// get the currently selected datasource type + const OUString& GetSelectedType() const { return m_eCurrentSelection; } + + protected: + // SfxTabPage overridables + virtual void Reset( const SfxItemSet* _rCoreAttrs ) override; + + virtual void implInitControls( const SfxItemSet& _rSet, bool _bSaveValue ) override; + virtual OUString getDatasourceName( const SfxItemSet& _rSet ); + virtual bool approveDatasourceType( ::dbaccess::DATASOURCE_TYPE eType, OUString& _inout_rDisplayName ); + + // <method>OGenericAdministrationPage::fillControls</method> + virtual void fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override; + // <method>OGenericAdministrationPage::fillWindows</method> + virtual void fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override; + + void onTypeSelected(const OUString& _sURLPrefix); + + /** + * Initializes the listbox, which contains entries each representing a + * connection to an existing database. + */ + void initializeTypeList(); + + void implSetCurrentType( const OUString& _eType ); + + void switchMessage(const OUString& _sURLPrefix); + + /// sets the title of the parent dialog + virtual void setParentTitle( const OUString& _sURLPrefix ); + + DECL_LINK(OnDatasourceTypeSelected, weld::ComboBox&, void); + }; + + // OGeneralPageDialog + class OGeneralPageDialog : public OGeneralPage + { + public: + OGeneralPageDialog(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rItems); + + protected: + virtual bool FillItemSet( SfxItemSet* _rCoreAttrs ) override; + + virtual void implInitControls( const SfxItemSet& _rSet, bool _bSaveValue ) override; + virtual void setParentTitle( const OUString& _sURLPrefix ) override; + }; + + // OGeneralPageWizard + class OGeneralPageWizard final : public OGeneralPage + { + public: + OGeneralPageWizard( weld::Container* pPage, ODbTypeWizDialogSetup* pController, const SfxItemSet& _rItems ); + virtual ~OGeneralPageWizard() override; + + enum CreationMode + { + eCreateNew, + eConnectExternal, + eOpenExisting + }; + + private: + // dialog controls + std::unique_ptr<weld::RadioButton> m_xRB_CreateDatabase; + std::unique_ptr<weld::RadioButton> m_xRB_OpenExistingDatabase; + std::unique_ptr<weld::RadioButton> m_xRB_ConnectDatabase; + + std::unique_ptr<weld::Label> m_xFT_EmbeddedDBLabel; + std::unique_ptr<weld::ComboBox> m_xEmbeddedDBType; + + std::unique_ptr<weld::Label> m_xFT_DocListLabel; + std::unique_ptr<weld::Label> m_xFT_HelpText; + std::unique_ptr<OpenDocumentListBox> m_xLB_DocumentList; + std::unique_ptr<OpenDocumentButton> m_xPB_OpenDatabase; + + // state + OUString m_aBrowsedDocumentURL; + CreationMode m_eOriginalCreationMode; + + Link<OGeneralPageWizard&,void> m_aCreationModeHandler; /// to be called if a new type is selected + Link<OGeneralPageWizard&,void> m_aDocumentSelectionHandler; /// to be called when a document in the RecentDoc list is selected + Link<OGeneralPageWizard&,void> m_aChooseDocumentHandler; /// to be called when a recent document has been definitely chosen + + bool m_bInitEmbeddedDBList : 1; + void insertEmbeddedDBTypeEntryData( const OUString& _sType, const OUString& sDisplayName ); + + void EnableControls(); + + public: + void SetCreationModeHandler( const Link<OGeneralPageWizard&,void>& _rHandler ) { m_aCreationModeHandler = _rHandler; } + CreationMode GetDatabaseCreationMode() const; + + void SetDocumentSelectionHandler( const Link<OGeneralPageWizard&,void>& _rHandler) { m_aDocumentSelectionHandler = _rHandler; } + void SetChooseDocumentHandler( const Link<OGeneralPageWizard&,void>& _rHandler) { m_aChooseDocumentHandler = _rHandler; } + OUString GetSelectedDocumentURL() const; + + private: + virtual bool FillItemSet( SfxItemSet* _rCoreAttrs ) override; + + virtual void implInitControls( const SfxItemSet& _rSet, bool _bSaveValue ) override; + virtual OUString getDatasourceName( const SfxItemSet& _rSet ) override; + virtual bool approveDatasourceType( ::dbaccess::DATASOURCE_TYPE eType, OUString& _inout_rDisplayName ) override; + + std::vector< OUString> + m_aEmbeddedURLPrefixes; + + OUString getEmbeddedDBName( const SfxItemSet& _rSet ); + void initializeEmbeddedDBList(); + + void SetupModeSelected(); + + DECL_LINK( OnEmbeddedDBTypeSelected, weld::ComboBox&, void ); + DECL_LINK( OnSetupModeSelected, weld::Button&, void ); + DECL_LINK( OnDocumentSelected, weld::ComboBox&, void ); + DECL_LINK( OnOpenDocument, weld::Button&, void ); + }; + +} // namespace dbaui +#endif // INCLUDED_DBACCESS_SOURCE_UI_DLG_GENERALPAGE_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/indexdialog.cxx b/dbaccess/source/ui/dlg/indexdialog.cxx new file mode 100644 index 000000000..978fa9f36 --- /dev/null +++ b/dbaccess/source/ui/dlg/indexdialog.cxx @@ -0,0 +1,707 @@ +/* -*- 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 <sal/config.h> + +#include <set> + +#include <core_resource.hxx> +#include <indexdialog.hxx> +#include <strings.hrc> +#include <bitmaps.hlst> +#include <indexfieldscontrol.hxx> +#include <indexcollection.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> +#include <com/sun/star/sdb/SQLContext.hpp> +#include <connectivity/dbtools.hxx> +#include <osl/diagnose.h> + +namespace dbaui +{ + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::container; + using namespace ::com::sun::star::sdbc; + using namespace ::com::sun::star::sdb; + using namespace ::com::sun::star::lang; + using namespace ::dbtools; + + // helper + static bool operator ==(const OIndexField& _rLHS, const OIndexField& _rRHS) + { + return (_rLHS.sFieldName == _rRHS.sFieldName) + && (_rLHS.bSortAscending == _rRHS.bSortAscending); + } + + static bool operator ==(const IndexFields& _rLHS, const IndexFields& _rRHS) + { + return std::equal(_rLHS.begin(), _rLHS.end(), _rRHS.begin(), _rRHS.end()); + } + + static bool operator !=(const IndexFields& _rLHS, const IndexFields& _rRHS) + { + return !(_rLHS == _rRHS); + } + + // DbaIndexDialog + DbaIndexDialog::DbaIndexDialog(weld::Window* pParent, const Sequence< OUString >& _rFieldNames, + const Reference< XNameAccess >& _rxIndexes, + const Reference< XConnection >& _rxConnection, + const Reference< XComponentContext >& _rxContext) + : GenericDialogController(pParent, "dbaccess/ui/indexdesigndialog.ui", "IndexDesignDialog") + , m_xConnection(_rxConnection) + , m_bEditingActive(false) + , m_bEditAgain(false) + , m_bNoHandlerCall(false) + , m_xContext(_rxContext) + , m_xActions(m_xBuilder->weld_toolbar("ACTIONS")) + , m_xIndexList(m_xBuilder->weld_tree_view("INDEX_LIST")) + , m_xIndexDetails(m_xBuilder->weld_label("INDEX_DETAILS")) + , m_xDescriptionLabel(m_xBuilder->weld_label("DESC_LABEL")) + , m_xDescription(m_xBuilder->weld_label("DESCRIPTION")) + , m_xUnique(m_xBuilder->weld_check_button("UNIQUE")) + , m_xFieldsLabel(m_xBuilder->weld_label("FIELDS_LABEL")) + , m_xClose(m_xBuilder->weld_button("close")) + , m_xTable(m_xBuilder->weld_container("FIELDS")) + , m_xTableCtrlParent(m_xTable->CreateChildFrame()) + , m_xFields(VclPtr<IndexFieldsControl>::Create(m_xTableCtrlParent)) + { + m_xIndexList->set_size_request(m_xIndexList->get_approximate_digit_width() * 17, + m_xIndexList->get_height_rows(12)); + + int nWidth = m_xIndexList->get_approximate_digit_width() * 60; + int nHeight = m_xIndexList->get_height_rows(8); + m_xTable->set_size_request(nWidth, nHeight); + + m_xActions->connect_clicked(LINK(this, DbaIndexDialog, OnIndexAction)); + + m_xIndexList->connect_changed(LINK(this, DbaIndexDialog, OnIndexSelected)); + m_xIndexList->connect_editing(LINK(this, DbaIndexDialog, OnEntryEditing), + LINK(this, DbaIndexDialog, OnEntryEdited)); + + m_xFields->SetSizePixel(Size(nWidth, 100)); + m_xFields->Init(_rFieldNames, ::dbtools::getBooleanDataSourceSetting( m_xConnection, "AddIndexAppendix" )); + m_xFields->Show(); + + m_xIndexes.reset(new OIndexCollection()); + try + { + m_xIndexes->attach(_rxIndexes); + } + catch(SQLException& e) + { + ::dbtools::showError(SQLExceptionInfo(e), pParent->GetXWindow(), _rxContext); + } + catch(Exception&) + { + OSL_FAIL("DbaIndexDialog::DbaIndexDialog: could not retrieve basic information from the UNO collection!"); + } + + fillIndexList(); + + m_xUnique->connect_clicked(LINK(this, DbaIndexDialog, OnModifiedClick)); + m_xFields->SetModifyHdl(LINK(this, DbaIndexDialog, OnModified)); + + m_xClose->connect_clicked(LINK(this, DbaIndexDialog, OnCloseDialog)); + + // if all of the indexes have an empty description, we're not interested in displaying it + bool bFound = false; + for (auto const& check : *m_xIndexes) + { + if (!check.sDescription.isEmpty()) + { + bFound = true; + break; + } + } + if (!bFound) + { + // hide the controls which are necessary for the description + m_xDescription->hide(); + m_xDescriptionLabel->hide(); + } + } + + void DbaIndexDialog::updateToolbox() + { + m_xActions->set_item_sensitive("ID_INDEX_NEW", !m_bEditingActive); + + int nSelected = m_xIndexList->get_selected_index(); + bool bSelectedAnything = nSelected != -1; + if (bSelectedAnything) + { + // is the current entry modified? + Indexes::const_iterator aSelectedPos = m_xIndexes->begin() + m_xIndexList->get_id(nSelected).toUInt32(); + m_xActions->set_item_sensitive("ID_INDEX_SAVE", aSelectedPos->isModified() || aSelectedPos->isNew()); + m_xActions->set_item_sensitive("ID_INDEX_RESET", aSelectedPos->isModified() || aSelectedPos->isNew()); + bSelectedAnything = !aSelectedPos->bPrimaryKey; + } + else + { + m_xActions->set_item_sensitive("ID_INDEX_SAVE", false); + m_xActions->set_item_sensitive("ID_INDEX_RESET", false); + } + m_xActions->set_item_sensitive("ID_INDEX_DROP", bSelectedAnything); + m_xActions->set_item_sensitive("ID_INDEX_RENAME", bSelectedAnything); + } + + void DbaIndexDialog::fillIndexList() + { + OUString aPKeyIcon(BMP_PKEYICON); + // fill the list with the index names + m_xIndexList->clear(); + sal_uInt32 nPos = 0; + for (auto const& indexLoop : *m_xIndexes) + { + m_xIndexList->append(OUString::number(nPos), indexLoop.sName); + if (indexLoop.bPrimaryKey) + m_xIndexList->set_image(nPos, aPKeyIcon); + ++nPos; + } + + if (nPos) + m_xIndexList->select(0); + + IndexSelected(); + } + + DbaIndexDialog::~DbaIndexDialog( ) + { + m_xIndexes.reset(); + m_xFields.disposeAndClear(); + m_xTableCtrlParent->dispose(); + m_xTableCtrlParent.clear(); + } + + bool DbaIndexDialog::implCommit(const weld::TreeIter* pEntry) + { + assert(pEntry && "DbaIndexDialog::implCommit: invalid entry!"); + + Indexes::iterator aCommitPos = m_xIndexes->begin() + m_xIndexList->get_id(*pEntry).toUInt32(); + + // if it's not a new index, remove it + // (we can't modify indexes, only drop'n'insert) + if (!aCommitPos->isNew()) + if (!implDropIndex(pEntry, false)) + return false; + + // create the new index + SQLExceptionInfo aExceptionInfo; + try + { + m_xIndexes->commitNewIndex(aCommitPos); + } + catch(SQLContext& e) { aExceptionInfo = SQLExceptionInfo(e); } + catch(SQLWarning& e) { aExceptionInfo = SQLExceptionInfo(e); } + catch(SQLException& e) { aExceptionInfo = SQLExceptionInfo(e); } + + // reflect the new selection in the toolbox + updateToolbox(); + + if (aExceptionInfo.isValid()) + showError(aExceptionInfo, m_xDialog->GetXWindow(), m_xContext); + else + { + m_xUnique->save_state(); + m_xFields->SaveValue(); + } + + return !aExceptionInfo.isValid(); + } + + void DbaIndexDialog::OnNewIndex() + { + // commit the current entry, if necessary + if (!implCommitPreviouslySelected()) + return; + + // get a new unique name for the new index + OUString sNewIndexName; + const OUString sNewIndexNameBase(DBA_RES(STR_LOGICAL_INDEX_NAME)); + sal_Int32 i; + + for ( i = 1; i < 0x7FFFFFFF; ++i ) + { + sNewIndexName = sNewIndexNameBase + OUString::number(i); + if (m_xIndexes->end() == m_xIndexes->find(sNewIndexName)) + break; + } + if (i == 0x7FFFFFFF) + { + OSL_FAIL("DbaIndexDialog::OnNewIndex: no free index name found!"); + // can't do anything ... of course we try another base, but this could end with the same result ... + return; + } + + std::unique_ptr<weld::TreeIter> xNewEntry(m_xIndexList->make_iterator()); + m_xIndexList->insert(nullptr, -1, &sNewIndexName, nullptr, nullptr, nullptr, nullptr, false, xNewEntry.get()); + m_xIndexes->insert(sNewIndexName); + + // update the user data on the entries in the list box: + // they're iterators of the index collection, and thus they have changed when removing the index + m_xIndexList->all_foreach([this](weld::TreeIter& rEntry){ + Indexes::const_iterator aAfterInsertPos = m_xIndexes->find(m_xIndexList->get_text(rEntry)); + OSL_ENSURE(aAfterInsertPos != m_xIndexes->end(), "DbaIndexDialog::OnNewIndex: problems with one of the entries!"); + m_xIndexList->set_id(rEntry, OUString::number(aAfterInsertPos - m_xIndexes->begin())); + return false; + }); + + // select the entry and start in-place editing + m_bNoHandlerCall = true; + m_xIndexList->select(*xNewEntry); + m_bNoHandlerCall = false; + IndexSelected(); + m_xIndexList->grab_focus(); + m_xIndexList->start_editing(*xNewEntry); + updateToolbox(); + } + + void DbaIndexDialog::OnDropIndex(bool _bConfirm) + { + std::unique_ptr<weld::TreeIter> xSelected(m_xIndexList->make_iterator()); + // the selected index + if (!m_xIndexList->get_selected(xSelected.get())) + return; + + // let the user confirm the drop + if (_bConfirm) + { + OUString sConfirm(DBA_RES(STR_CONFIRM_DROP_INDEX)); + sConfirm = sConfirm.replaceFirst("$name$", m_xIndexList->get_text(*xSelected)); + std::unique_ptr<weld::MessageDialog> xConfirm(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Question, VclButtonsType::YesNo, + sConfirm)); + if (RET_YES != xConfirm->run()) + return; + } + + // do the drop + implDropIndex(xSelected.get(), true); + + // reflect the new selection in the toolbox + updateToolbox(); + } + + bool DbaIndexDialog::implDropIndex(const weld::TreeIter* pEntry, bool _bRemoveFromCollection) + { + // do the drop + Indexes::iterator aDropPos = m_xIndexes->begin() + m_xIndexList->get_id(*pEntry).toUInt32(); + OSL_ENSURE(aDropPos != m_xIndexes->end(), "DbaIndexDialog::OnDropIndex: did not find the index in my collection!"); + + SQLExceptionInfo aExceptionInfo; + bool bSuccess = false; + try + { + if (_bRemoveFromCollection) + bSuccess = m_xIndexes->drop(aDropPos); + else + bSuccess = m_xIndexes->dropNoRemove(aDropPos); + } + catch(SQLContext& e) { aExceptionInfo = SQLExceptionInfo(e); } + catch(SQLWarning& e) { aExceptionInfo = SQLExceptionInfo(e); } + catch(SQLException& e) { aExceptionInfo = SQLExceptionInfo(e); } + + if (aExceptionInfo.isValid()) + showError(aExceptionInfo, m_xDialog->GetXWindow(), m_xContext); + else if (bSuccess && _bRemoveFromCollection) + { + m_bNoHandlerCall = true; + + // if the entry to remove is the selected on... + if (m_xPreviousSelection && m_xPreviousSelection->equal(*pEntry)) + m_xPreviousSelection.reset(); + m_xIndexList->remove(*pEntry); + + m_bNoHandlerCall = false; + + // update the user data on the entries in the list box: + // they're iterators of the index collection, and thus they have changed when removing the index + m_xIndexList->all_foreach([this](weld::TreeIter& rEntry){ + Indexes::const_iterator aAfterDropPos = m_xIndexes->find(m_xIndexList->get_text(rEntry)); + OSL_ENSURE(aAfterDropPos != m_xIndexes->end(), "DbaIndexDialog::OnDropIndex: problems with one of the remaining entries!"); + m_xIndexList->set_id(rEntry, OUString::number(aAfterDropPos - m_xIndexes->begin())); + return false; + }); + + // the Remove automatically selected another entry (if possible), but we disabled the calling of the handler + // to prevent that we missed something... call the handler directly + IndexSelected(); + } + + return !aExceptionInfo.isValid(); + } + + void DbaIndexDialog::OnRenameIndex() + { + // the selected iterator + std::unique_ptr<weld::TreeIter> xSelected(m_xIndexList->make_iterator()); + if (!m_xIndexList->get_selected(xSelected.get())) + return; + + // save the changes made 'til here + // Upon leaving the edit mode, the control will be re-initialized with the + // settings from the current entry + implSaveModified(false); + + m_xIndexList->grab_focus(); + m_xIndexList->start_editing(*xSelected); + updateToolbox(); + } + + void DbaIndexDialog::OnSaveIndex() + { + // the selected index + implCommitPreviouslySelected(); + updateToolbox(); + } + + void DbaIndexDialog::OnResetIndex() + { + // the selected index + std::unique_ptr<weld::TreeIter> xSelected(m_xIndexList->make_iterator()); + // the selected index + if (!m_xIndexList->get_selected(xSelected.get())) + xSelected.reset(); + OSL_ENSURE(xSelected, "DbaIndexDialog::OnResetIndex: invalid call!"); + if (!xSelected) + return; + + Indexes::iterator aResetPos = m_xIndexes->begin() + m_xIndexList->get_id(*xSelected).toUInt32(); + + if (aResetPos->isNew()) + { + OnDropIndex(false); + return; + } + + SQLExceptionInfo aExceptionInfo; + try + { + m_xIndexes->resetIndex(aResetPos); + } + catch(SQLContext& e) { aExceptionInfo = SQLExceptionInfo(e); } + catch(SQLWarning& e) { aExceptionInfo = SQLExceptionInfo(e); } + catch(SQLException& e) { aExceptionInfo = SQLExceptionInfo(e); } + + if (aExceptionInfo.isValid()) + showError(aExceptionInfo, m_xDialog->GetXWindow(), m_xContext); + else + m_xIndexList->set_text(*xSelected, aResetPos->sName); + + updateControls(xSelected.get()); + updateToolbox(); + } + + IMPL_LINK(DbaIndexDialog, OnIndexAction, const OString&, rClicked, void) + { + if (rClicked == "ID_INDEX_NEW") + OnNewIndex(); + else if (rClicked == "ID_INDEX_DROP") + OnDropIndex(); + else if (rClicked == "ID_INDEX_RENAME") + OnRenameIndex(); + else if (rClicked == "ID_INDEX_SAVE") + OnSaveIndex(); + else if (rClicked == "ID_INDEX_RESET") + OnResetIndex(); + } + + IMPL_LINK_NOARG(DbaIndexDialog, OnCloseDialog, weld::Button&, void) + { + if (m_bEditingActive) + { + OSL_ENSURE(!m_bEditAgain, "DbaIndexDialog::OnCloseDialog: somebody was faster than hell!"); + // this means somebody entered a new name, which was invalid, which cause us to posted us an event, + // and before the event arrived the user clicked onto "close". VERY fast, this user... + m_xIndexList->end_editing(); + if (m_bEditAgain) + // could not commit the new name (started a new - asynchronous - edit trial) + return; + } + + // the currently selected entry + std::unique_ptr<weld::TreeIter> xSelected(m_xIndexList->make_iterator()); + // the selected index + if (!m_xIndexList->get_selected(xSelected.get())) + xSelected.reset(); + + OSL_ENSURE(xSelected && m_xPreviousSelection && xSelected->equal(*m_xPreviousSelection), "DbaIndexDialog::OnCloseDialog: inconsistence!"); + + sal_Int32 nResponse = RET_NO; + if (xSelected) + { + // the descriptor + Indexes::const_iterator aSelected = m_xIndexes->begin() + m_xIndexList->get_id(*xSelected).toUInt32(); + if (aSelected->isModified() || aSelected->isNew()) + { + std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(m_xDialog.get(), "dbaccess/ui/saveindexdialog.ui")); + std::unique_ptr<weld::MessageDialog> xQuery(xBuilder->weld_message_dialog("SaveIndexDialog")); + nResponse = xQuery->run(); + } + } + + switch (nResponse) + { + case RET_YES: + if (!implCommitPreviouslySelected()) + return; + break; + case RET_NO: + break; + default: + return; + } + + m_xDialog->response(RET_OK); + } + + IMPL_LINK(DbaIndexDialog, OnEditIndexAgain, void*, p, void) + { + weld::TreeIter* pEntry = static_cast<weld::TreeIter*>(p); + m_bEditAgain = false; + m_xIndexList->grab_focus(); + m_xIndexList->start_editing(*pEntry); + delete pEntry; + } + + IMPL_LINK_NOARG(DbaIndexDialog, OnEntryEditing, const weld::TreeIter&, bool) + { + m_bEditingActive = true; + return true; + } + + IMPL_LINK(DbaIndexDialog, OnEntryEdited, const IterString&, rIterString, bool) + { + m_bEditingActive = false; + + const weld::TreeIter& rEntry = rIterString.first; + OUString sNewName = rIterString.second; + + Indexes::iterator aPosition = m_xIndexes->begin() + m_xIndexList->get_id(rEntry).toUInt32(); + + OSL_ENSURE(aPosition >= m_xIndexes->begin() && aPosition < m_xIndexes->end(), + "DbaIndexDialog::OnEntryEdited: invalid entry!"); + + Indexes::const_iterator aSameName = m_xIndexes->find(sNewName); + if (aSameName != aPosition && m_xIndexes->end() != aSameName) + { + OUString sError(DBA_RES(STR_INDEX_NAME_ALREADY_USED)); + sError = sError.replaceFirst("$name$", sNewName); + std::unique_ptr<weld::MessageDialog> xError(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Warning, VclButtonsType::Ok, + sError)); + xError->run(); + + updateToolbox(); + m_bEditAgain = true; + std::unique_ptr<weld::TreeIter> xEntry(m_xIndexList->make_iterator(&rEntry)); + Application::PostUserEvent(LINK(this, DbaIndexDialog, OnEditIndexAgain), xEntry.release()); + return false; + } + + aPosition->sName = sNewName; + + // rename can be done by a drop/insert combination only + if (aPosition->isNew()) + { + updateToolbox(); + // no commitment needed here... + return true; + } + + if (aPosition->sName != aPosition->getOriginalName()) + { + aPosition->setModified(true); + updateToolbox(); + } + + return true; + } + + bool DbaIndexDialog::implSaveModified(bool _bPlausibility) + { + if (m_xPreviousSelection) + { + // try to commit the previously selected index + if (m_xFields->IsModified() && !m_xFields->SaveModified()) + return false; + + Indexes::iterator aPreviouslySelected = m_xIndexes->begin() + m_xIndexList->get_id(*m_xPreviousSelection).toUInt32(); + + // the unique flag + aPreviouslySelected->bUnique = m_xUnique->get_active(); + if (m_xUnique->get_state_changed_from_saved()) + aPreviouslySelected->setModified(true); + + // the fields + m_xFields->commitTo(aPreviouslySelected->aFields); + if (m_xFields->GetSavedValue() != aPreviouslySelected->aFields) + aPreviouslySelected->setModified(true); + + // plausibility checks + if (_bPlausibility && !implCheckPlausibility(aPreviouslySelected)) + return false; + } + + return true; + } + + bool DbaIndexDialog::implCheckPlausibility(const Indexes::const_iterator& _rPos) + { + // need at least one field + if (_rPos->aFields.empty()) + { + std::unique_ptr<weld::MessageDialog> xError(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Warning, VclButtonsType::Ok, + DBA_RES(STR_NEED_INDEX_FIELDS))); + xError->run(); + m_xFields->GrabFocus(); + return false; + } + + // no double fields + std::set< OUString > aExistentFields; + for (auto const& fieldCheck : _rPos->aFields) + { + if (aExistentFields.end() != aExistentFields.find(fieldCheck.sFieldName)) + { + // a column is specified twice ... won't work anyway, so prevent this here and now + OUString sMessage(DBA_RES(STR_INDEXDESIGN_DOUBLE_COLUMN_NAME)); + sMessage = sMessage.replaceFirst("$name$", fieldCheck.sFieldName); + std::unique_ptr<weld::MessageDialog> xError(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Warning, VclButtonsType::Ok, + sMessage)); + xError->run(); + m_xFields->GrabFocus(); + return false; + } + aExistentFields.insert(fieldCheck.sFieldName); + } + + return true; + } + + bool DbaIndexDialog::implCommitPreviouslySelected() + { + if (m_xPreviousSelection) + { + Indexes::const_iterator aPreviouslySelected = m_xIndexes->begin() + m_xIndexList->get_id(*m_xPreviousSelection).toUInt32(); + + if (!implSaveModified()) + return false; + + // commit the index (if necessary) + if (aPreviouslySelected->isModified() && !implCommit(m_xPreviousSelection.get())) + return false; + } + + return true; + } + + IMPL_LINK_NOARG(DbaIndexDialog, OnModifiedClick, weld::Button&, void) + { + OnModified(*m_xFields); + } + + IMPL_LINK_NOARG( DbaIndexDialog, OnModified, IndexFieldsControl&, void ) + { + assert(m_xPreviousSelection && "DbaIndexDialog, OnModified: invalid call!"); + Indexes::iterator aPosition = m_xIndexes->begin() + m_xIndexList->get_id(*m_xPreviousSelection).toUInt32(); + + aPosition->setModified(true); + updateToolbox(); + } + + void DbaIndexDialog::updateControls(const weld::TreeIter* pEntry) + { + if (pEntry) + { + // the descriptor of the selected index + Indexes::const_iterator aSelectedIndex = m_xIndexes->begin() + m_xIndexList->get_id(*pEntry).toUInt32(); + + // fill the controls + m_xUnique->set_active(aSelectedIndex->bUnique); + m_xUnique->set_sensitive(!aSelectedIndex->bPrimaryKey); + m_xUnique->save_state(); + + m_xFields->initializeFrom(aSelectedIndex->aFields); + m_xFields->Enable(!aSelectedIndex->bPrimaryKey); + m_xFields->SaveValue(); + + m_xDescription->set_label(aSelectedIndex->sDescription); + m_xDescription->set_sensitive(!aSelectedIndex->bPrimaryKey); + + m_xDescriptionLabel->set_sensitive(!aSelectedIndex->bPrimaryKey); + } + else + { + m_xUnique->set_active(false); + m_xFields->initializeFrom(IndexFields()); + m_xDescription->set_label(OUString()); + } + } + + void DbaIndexDialog::IndexSelected() + { + if (m_bEditingActive) + m_xIndexList->end_editing(); + + std::unique_ptr<weld::TreeIter> xSelected(m_xIndexList->make_iterator()); + if (!m_xIndexList->get_selected(xSelected.get())) + xSelected.reset(); + + // commit the old data + if (m_xPreviousSelection && (!xSelected || !m_xPreviousSelection->equal(*xSelected))) + { + // (this call may happen in case somebody ended an in-place edit with 'return', so we need to check this before committing) + if (!implCommitPreviouslySelected()) + { + m_bNoHandlerCall = true; + m_xIndexList->select(*m_xPreviousSelection); + m_bNoHandlerCall = false; + return; + } + } + + // disable/enable the detail controls + m_xIndexDetails->set_sensitive(xSelected != nullptr); + m_xUnique->set_sensitive(xSelected != nullptr); + m_xDescriptionLabel->set_sensitive(xSelected != nullptr); + m_xFieldsLabel->set_sensitive(xSelected != nullptr); + m_xFields->Enable(xSelected != nullptr); + + updateControls(xSelected.get()); + if (xSelected) + m_xIndexList->grab_focus(); + + m_xPreviousSelection = std::move(xSelected); + + updateToolbox(); + } + + IMPL_LINK_NOARG(DbaIndexDialog, OnIndexSelected, weld::TreeView&, void) + { + if (m_bNoHandlerCall) + return; + IndexSelected(); + } +} // namespace dbaui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/indexfieldscontrol.cxx b/dbaccess/source/ui/dlg/indexfieldscontrol.cxx new file mode 100644 index 000000000..8676ff24d --- /dev/null +++ b/dbaccess/source/ui/dlg/indexfieldscontrol.cxx @@ -0,0 +1,447 @@ +/* -*- 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 <core_resource.hxx> +#include <indexfieldscontrol.hxx> +#include <strings.hrc> +#include <osl/diagnose.h> +#include <helpids.h> +#include <toolkit/helper/vclunohelper.hxx> +#include <vcl/settings.hxx> +#include <vcl/svapp.hxx> + +namespace dbaui +{ + +static constexpr auto BROWSER_STANDARD_FLAGS = BrowserMode::COLUMNSELECTION | BrowserMode::HLINES | BrowserMode::VLINES | + BrowserMode::HIDECURSOR | BrowserMode::HIDESELECT | BrowserMode::AUTO_HSCROLL | BrowserMode::AUTO_VSCROLL; + +#define COLUMN_ID_FIELDNAME 1 +#define COLUMN_ID_ORDER 2 + + using namespace ::com::sun::star::uno; + using namespace ::svt; + + // DbaMouseDownListBoxController + class DbaMouseDownListBoxController : public ListBoxCellController + { + protected: + Link<DbaMouseDownListBoxController&,void> m_aAdditionalModifyHdl; + + public: + explicit DbaMouseDownListBoxController(ListBoxControl* _pParent) + :ListBoxCellController(_pParent) + { + } + + void SetAdditionalModifyHdl(const Link<DbaMouseDownListBoxController&,void>& _rHdl); + + protected: + virtual bool WantMouseEvent() const override { return true; } + virtual void callModifyHdl() override; + }; + + void DbaMouseDownListBoxController::SetAdditionalModifyHdl(const Link<DbaMouseDownListBoxController&,void>& _rHdl) + { + m_aAdditionalModifyHdl = _rHdl; + } + + void DbaMouseDownListBoxController::callModifyHdl() + { + m_aAdditionalModifyHdl.Call(*this); + ListBoxCellController::callModifyHdl(); + } + + // IndexFieldsControl + IndexFieldsControl::IndexFieldsControl(const css::uno::Reference<css::awt::XWindow> &rParent) + : EditBrowseBox(VCLUnoHelper::GetWindow(rParent), EditBrowseBoxFlags::SMART_TAB_TRAVEL | EditBrowseBoxFlags::ACTIVATE_ON_BUTTONDOWN, WB_TABSTOP | WB_BORDER, BROWSER_STANDARD_FLAGS) + , m_aSeekRow(m_aFields.end()) + , m_pSortingCell(nullptr) + , m_pFieldNameCell(nullptr) + , m_bAddIndexAppendix(false) + { + } + + IndexFieldsControl::~IndexFieldsControl() + { + disposeOnce(); + } + + void IndexFieldsControl::dispose() + { + m_pSortingCell.disposeAndClear(); + m_pFieldNameCell.disposeAndClear(); + ::svt::EditBrowseBox::dispose(); + } + + bool IndexFieldsControl::SeekRow(long nRow) + { + if (!EditBrowseBox::SeekRow(nRow)) + return false; + + if (nRow < 0) + { + m_aSeekRow = m_aFields.end(); + } + else + { + m_aSeekRow = m_aFields.begin() + nRow; + OSL_ENSURE(m_aSeekRow <= m_aFields.end(), "IndexFieldsControl::SeekRow: invalid row!"); + } + + return true; + } + + void IndexFieldsControl::PaintCell( OutputDevice& _rDev, const tools::Rectangle& _rRect, sal_uInt16 _nColumnId ) const + { + Point aPos(_rRect.TopLeft()); + aPos.AdjustX(1 ); + + OUString aText = GetRowCellText(m_aSeekRow,_nColumnId); + Size TxtSize(GetDataWindow().GetTextWidth(aText), GetDataWindow().GetTextHeight()); + + // clipping + if (aPos.X() < _rRect.Right() || aPos.X() + TxtSize.Width() > _rRect.Right() || + aPos.Y() < _rRect.Top() || aPos.Y() + TxtSize.Height() > _rRect.Bottom()) + _rDev.SetClipRegion(vcl::Region(_rRect)); + + // allow for a disabled control ... + bool bEnabled = IsEnabled(); + Color aOriginalColor = _rDev.GetTextColor(); + if (!bEnabled) + _rDev.SetTextColor(GetSettings().GetStyleSettings().GetDisableColor()); + + // draw the text + _rDev.DrawText(aPos, aText); + + // reset the color (if necessary) + if (!bEnabled) + _rDev.SetTextColor(aOriginalColor); + + if (_rDev.IsClipRegion()) + _rDev.SetClipRegion(); + } + + void IndexFieldsControl::initializeFrom(const IndexFields& _rFields) + { + // copy the field descriptions + m_aFields = _rFields; + m_aSeekRow = m_aFields.end(); + + SetUpdateMode(false); + // remove all rows + RowRemoved(1, GetRowCount()); + // insert rows for the fields + RowInserted(GetRowCount(), m_aFields.size(), false); + // insert an additional row for a new field for that index + RowInserted(GetRowCount(), 1, false); + SetUpdateMode(true); + + GoToRowColumnId(0, COLUMN_ID_FIELDNAME); + } + + void IndexFieldsControl::commitTo(IndexFields& _rFields) + { + // do not just copy the array, we may have empty field names (which should not be copied) + _rFields.resize(m_aFields.size()); + IndexFields::iterator aDest = std::copy_if(m_aFields.begin(), m_aFields.end(), _rFields.begin(), + [](const OIndexField& source) { return !source.sFieldName.isEmpty(); }); + + _rFields.resize(aDest - _rFields.begin()); + } + + sal_uInt32 IndexFieldsControl::GetTotalCellWidth(long _nRow, sal_uInt16 _nColId) + { + if (COLUMN_ID_ORDER == _nColId) + { + sal_Int32 nWidthAsc = GetTextWidth(m_sAscendingText) + GetSettings().GetStyleSettings().GetScrollBarSize(); + sal_Int32 nWidthDesc = GetTextWidth(m_sDescendingText) + GetSettings().GetStyleSettings().GetScrollBarSize(); + // maximum plus some additional space + return std::max(nWidthAsc, nWidthDesc) + GetTextWidth(OUString('0')) * 2; + } + return EditBrowseBox::GetTotalCellWidth(_nRow, _nColId); + } + + void IndexFieldsControl::Init(const Sequence< OUString >& _rAvailableFields, bool _bAddIndexAppendix) + { + m_bAddIndexAppendix = _bAddIndexAppendix; + + RemoveColumns(); + + // for the width: both columns together should be somewhat smaller than the whole window (without the scrollbar) + sal_Int32 nFieldNameWidth = GetSizePixel().Width(); + + if ( m_bAddIndexAppendix ) + { + m_sAscendingText = DBA_RES(STR_ORDER_ASCENDING); + m_sDescendingText = DBA_RES(STR_ORDER_DESCENDING); + + // the "sort order" column + OUString sColumnName = DBA_RES(STR_TAB_INDEX_SORTORDER); + // the width of the order column is the maximum widths of the texts used + // (the title of the column) + sal_Int32 nSortOrderColumnWidth = GetTextWidth(sColumnName); + // ("ascending" + scrollbar width) + sal_Int32 nOther = GetTextWidth(m_sAscendingText) + GetSettings().GetStyleSettings().GetScrollBarSize(); + nSortOrderColumnWidth = std::max(nSortOrderColumnWidth, nOther); + // ("descending" + scrollbar width) + nOther = GetTextWidth(m_sDescendingText) + GetSettings().GetStyleSettings().GetScrollBarSize(); + nSortOrderColumnWidth = std::max(nSortOrderColumnWidth, nOther); + // (plus some additional space) + nSortOrderColumnWidth += GetTextWidth(OUString('0')) * 2; + InsertDataColumn(COLUMN_ID_ORDER, sColumnName, nSortOrderColumnWidth, HeaderBarItemBits::STDSTYLE, 1); + + m_pSortingCell = VclPtr<ListBoxControl>::Create(&GetDataWindow()); + weld::ComboBox& rSortingListBox = m_pSortingCell->get_widget(); + rSortingListBox.append_text(m_sAscendingText); + rSortingListBox.append_text(m_sDescendingText); + rSortingListBox.set_help_id(HID_DLGINDEX_INDEXDETAILS_SORTORDER); + + nFieldNameWidth -= nSortOrderColumnWidth; + } + StyleSettings aSystemStyle = Application::GetSettings().GetStyleSettings(); + nFieldNameWidth -= aSystemStyle.GetScrollBarSize(); + nFieldNameWidth -= 8; + // the "field name" column + OUString sColumnName = DBA_RES(STR_TAB_INDEX_FIELD); + InsertDataColumn(COLUMN_ID_FIELDNAME, sColumnName, nFieldNameWidth, HeaderBarItemBits::STDSTYLE, 0); + + // create the cell controllers + // for the field name cell + m_pFieldNameCell = VclPtr<ListBoxControl>::Create(&GetDataWindow()); + weld::ComboBox& rNameListBox = m_pFieldNameCell->get_widget(); + rNameListBox.append_text(OUString()); + rNameListBox.set_help_id(HID_DLGINDEX_INDEXDETAILS_FIELD); + const OUString* pFields = _rAvailableFields.getConstArray(); + const OUString* pFieldsEnd = pFields + _rAvailableFields.getLength(); + for (;pFields < pFieldsEnd; ++pFields) + rNameListBox.append_text(*pFields); + } + + CellController* IndexFieldsControl::GetController(long _nRow, sal_uInt16 _nColumnId) + { + if (!IsEnabled()) + return nullptr; + + IndexFields::const_iterator aRow; + bool bNewField = !implGetFieldDesc(_nRow, aRow); + + DbaMouseDownListBoxController* pReturn = nullptr; + switch (_nColumnId) + { + case COLUMN_ID_ORDER: + if (!bNewField && m_pSortingCell && !aRow->sFieldName.isEmpty()) + pReturn = new DbaMouseDownListBoxController(m_pSortingCell); + break; + + case COLUMN_ID_FIELDNAME: + pReturn = new DbaMouseDownListBoxController(m_pFieldNameCell); + break; + + default: + OSL_FAIL("IndexFieldsControl::GetController: invalid column id!"); + } + + if (pReturn) + pReturn->SetAdditionalModifyHdl(LINK(this, IndexFieldsControl, OnListEntrySelected)); + + return pReturn; + } + + bool IndexFieldsControl::implGetFieldDesc(long _nRow, IndexFields::const_iterator& _rPos) + { + _rPos = m_aFields.end(); + if ((_nRow < 0) || (_nRow >= static_cast<sal_Int32>(m_aFields.size()))) + return false; + _rPos = m_aFields.begin() + _nRow; + return true; + } + + bool IndexFieldsControl::SaveModified() + { + if (!IsModified()) + return true; + + switch (GetCurColumnId()) + { + case COLUMN_ID_FIELDNAME: + { + weld::ComboBox& rNameListBox = m_pFieldNameCell->get_widget(); + OUString sFieldSelected = rNameListBox.get_active_text(); + bool bEmptySelected = sFieldSelected.isEmpty(); + if (isNewField()) + { + if (!bEmptySelected) + { + // add a new field to the collection + OIndexField aNewField; + aNewField.sFieldName = sFieldSelected; + m_aFields.push_back(aNewField); + RowInserted(GetRowCount()); + } + } + else + { + sal_Int32 nRow = GetCurRow(); + OSL_ENSURE(nRow < static_cast<sal_Int32>(m_aFields.size()), "IndexFieldsControl::SaveModified: invalid current row!"); + if (nRow >= 0) // may be -1 in case the control was empty + { + // remove the field from the selection + IndexFields::iterator aPos = m_aFields.begin() + nRow; + + if (bEmptySelected) + { + aPos->sFieldName.clear(); + + // invalidate the row to force repaint + Invalidate(GetRowRectPixel(nRow)); + return true; + } + + if (sFieldSelected == aPos->sFieldName) + // nothing changed + return true; + + aPos->sFieldName = sFieldSelected; + } + } + + Invalidate(GetRowRectPixel(GetCurRow())); + } + break; + case COLUMN_ID_ORDER: + { + OSL_ENSURE(!isNewField(), "IndexFieldsControl::SaveModified: why the hell ...!!!"); + // selected entry + weld::ComboBox& rSortingListBox = m_pSortingCell->get_widget(); + sal_Int32 nPos = rSortingListBox.get_active(); + OSL_ENSURE(nPos != -1, "IndexFieldsControl::SaveModified: how did you get this selection??"); + // adjust the sort flag in the index field description + OIndexField& rCurrentField = m_aFields[GetCurRow()]; + rCurrentField.bSortAscending = (0 == nPos); + + } + break; + default: + OSL_FAIL("IndexFieldsControl::SaveModified: invalid column id!"); + } + return true; + } + + void IndexFieldsControl::InitController(CellControllerRef& /*_rController*/, long _nRow, sal_uInt16 _nColumnId) + { + IndexFields::const_iterator aFieldDescription; + bool bNewField = !implGetFieldDesc(_nRow, aFieldDescription); + + switch (_nColumnId) + { + case COLUMN_ID_FIELDNAME: + { + weld::ComboBox& rNameListBox = m_pFieldNameCell->get_widget(); + rNameListBox.set_active_text(bNewField ? OUString() : aFieldDescription->sFieldName); + rNameListBox.save_value(); + break; + } + + case COLUMN_ID_ORDER: + { + weld::ComboBox& rSortingListBox = m_pSortingCell->get_widget(); + rSortingListBox.set_active_text(aFieldDescription->bSortAscending ? m_sAscendingText : m_sDescendingText); + rSortingListBox.save_value(); + break; + } + + default: + OSL_FAIL("IndexFieldsControl::InitController: invalid column id!"); + } + } + + IMPL_LINK( IndexFieldsControl, OnListEntrySelected, DbaMouseDownListBoxController&, rController, void ) + { + weld::ComboBox& rListBox = rController.GetListBox(); + if (!rListBox.get_popup_shown()) + m_aModifyHdl.Call(*this); + + if (&rListBox != &m_pFieldNameCell->get_widget()) + return; + +// a field has been selected + if (GetCurRow() >= GetRowCount() - 2) + { // and we're in one of the last two rows + OUString sSelectedEntry = rListBox.get_active_text(); + sal_Int32 nCurrentRow = GetCurRow(); + sal_Int32 rowCount = GetRowCount(); + + OSL_ENSURE((static_cast<sal_Int32>(m_aFields.size() + 1)) == rowCount, "IndexFieldsControl::OnListEntrySelected: inconsistence!"); + + if (!sSelectedEntry.isEmpty() && (nCurrentRow == rowCount - 1) /*&& (!m_nMaxColumnsInIndex || rowCount < m_nMaxColumnsInIndex )*/ ) + { // in the last row, a non-empty string has been selected + // -> insert a new row + m_aFields.emplace_back(); + RowInserted(GetRowCount()); + Invalidate(GetRowRectPixel(nCurrentRow)); + } + else if (sSelectedEntry.isEmpty() && (nCurrentRow == rowCount - 2)) + { // in the (last-1)th row, an empty entry has been selected + // -> remove the last row + m_aFields.pop_back(); + RowRemoved(GetRowCount() - 1); + Invalidate(GetRowRectPixel(nCurrentRow)); + } + } + + SaveModified(); + } + OUString IndexFieldsControl::GetCellText(long _nRow,sal_uInt16 nColId) const + { + IndexFields::const_iterator aRow = m_aFields.end(); + if ( _nRow >= 0 ) + { + aRow = m_aFields.begin() + _nRow; + OSL_ENSURE(aRow <= m_aFields.end(), "IndexFieldsControl::SeekRow: invalid row!"); + } + return GetRowCellText(aRow,nColId); + } + OUString IndexFieldsControl::GetRowCellText(const IndexFields::const_iterator& _rRow,sal_uInt16 nColId) const + { + if (_rRow < m_aFields.end()) + { + switch (nColId) + { + case COLUMN_ID_FIELDNAME: + return _rRow->sFieldName; + case COLUMN_ID_ORDER: + if (_rRow->sFieldName.isEmpty()) + return OUString(); + else + return _rRow->bSortAscending ? m_sAscendingText : m_sDescendingText; + default: + OSL_FAIL("IndexFieldsControl::GetCurrentRowCellText: invalid column id!"); + } + } + return OUString(); + } + bool IndexFieldsControl::IsTabAllowed(bool /*bForward*/) const + { + return false; + } + +} // namespace dbaui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/odbcconfig.cxx b/dbaccess/source/ui/dlg/odbcconfig.cxx new file mode 100644 index 000000000..49b120d13 --- /dev/null +++ b/dbaccess/source/ui/dlg/odbcconfig.cxx @@ -0,0 +1,327 @@ +/* -*- 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 <config_folders.h> +#include "odbcconfig.hxx" + +#include <rtl/bootstrap.hxx> +#include <rtl/ustring.hxx> +#include <osl/diagnose.h> +#include <osl/process.h> +#include <osl/thread.hxx> +#include <vcl/svapp.hxx> + +#ifdef HAVE_ODBC_SUPPORT + +#if defined(_WIN32) +#define ODBC_LIBRARY "ODBC32.DLL" +#endif +#ifdef UNX +#ifdef MACOSX +#define ODBC_LIBRARY "libiodbc.dylib" +#else +#define ODBC_LIBRARY_PLAIN "libodbc.so" +#define ODBC_LIBRARY_1 "libodbc.so.1" +#define ODBC_LIBRARY "libodbc.so.2" +#endif +#endif + +#include <connectivity/odbc.hxx> + +#else + +#define ODBC_LIBRARY "" + +#endif // HAVE_ODBC_SUPPORT + +namespace dbaui +{ + +#ifdef HAVE_ODBC_SUPPORT +typedef SQLRETURN (SQL_API* TSQLManageDataSource) (SQLHWND hwndParent); +typedef SQLRETURN (SQL_API* TSQLAllocHandle) (SQLSMALLINT HandleType, SQLHANDLE InputHandle, SQLHANDLE* OutputHandlePtr); +typedef SQLRETURN (SQL_API* TSQLFreeHandle) (SQLSMALLINT HandleType, SQLHANDLE Handle); +typedef SQLRETURN (SQL_API* TSQLSetEnvAttr) (SQLHENV EnvironmentHandle, SQLINTEGER Attribute, SQLPOINTER ValuePtr, SQLINTEGER StringLength); +typedef SQLRETURN (SQL_API* TSQLDataSources) (SQLHENV EnvironmentHandle, SQLUSMALLINT Direction, SQLCHAR* ServerName, + SQLSMALLINT BufferLength1, SQLSMALLINT* NameLength1Ptr, SQLCHAR* Description, SQLSMALLINT BufferLength2, SQLSMALLINT* NameLength2Ptr); + +#define NSQLAllocHandle(a,b,c) (*reinterpret_cast<TSQLAllocHandle>(m_pAllocHandle))(a,b,c) +#define NSQLFreeHandle(a,b) (*reinterpret_cast<TSQLFreeHandle>(m_pFreeHandle))(a,b) +#define NSQLSetEnvAttr(a,b,c,d) (*reinterpret_cast<TSQLSetEnvAttr>(m_pSetEnvAttr))(a,b,c,d) +#define NSQLDataSources(a,b,c,d,e,f,g,h) (*reinterpret_cast<TSQLDataSources>(m_pDataSources))(a,b,c,d,e,f,g,h) +#endif + +// OOdbcLibWrapper + +bool OOdbcEnumeration::load(const char* _pLibPath) +{ + m_sLibPath = OUString::createFromAscii(_pLibPath); +#if defined(HAVE_ODBC_SUPPORT) && !defined(DISABLE_DYNLOADING) + // load the module + m_pOdbcLib = osl_loadModule(m_sLibPath.pData, SAL_LOADMODULE_NOW); + return (nullptr != m_pOdbcLib); +#else + return sal_False; +#endif +} + +void OOdbcEnumeration::unload() +{ +#if defined(HAVE_ODBC_SUPPORT) && !defined(DISABLE_DYNLOADING) + if (isLoaded()) + { + osl_unloadModule(m_pOdbcLib); + m_pOdbcLib = nullptr; + } +#endif +} + +oslGenericFunction OOdbcEnumeration::loadSymbol(const char* _pFunctionName) +{ + return osl_getFunctionSymbol(m_pOdbcLib, OUString::createFromAscii(_pFunctionName).pData); +} + + +struct OdbcTypesImpl +{ +#ifdef HAVE_ODBC_SUPPORT + SQLHANDLE hEnvironment; + OdbcTypesImpl() : hEnvironment(nullptr) { } +#else + void* pDummy; +#endif +}; + +OOdbcEnumeration::OOdbcEnumeration() + :m_pOdbcLib(nullptr) +#ifdef HAVE_ODBC_SUPPORT + ,m_pAllocHandle(nullptr) + ,m_pFreeHandle(nullptr) + ,m_pSetEnvAttr(nullptr) + ,m_pDataSources(nullptr) + ,m_pImpl(new OdbcTypesImpl) +#endif +{ + bool bLoaded = load(ODBC_LIBRARY); +#ifdef ODBC_LIBRARY_1 + if ( !bLoaded ) + bLoaded = load(ODBC_LIBRARY_1); +#endif +#ifdef ODBC_LIBRARY_PLAIN + if ( !bLoaded ) + bLoaded = load(ODBC_LIBRARY_PLAIN); +#endif + + if ( !bLoaded ) + return; + +#ifdef HAVE_ODBC_SUPPORT + // load the generic functions + m_pAllocHandle = loadSymbol("SQLAllocHandle"); + m_pFreeHandle = loadSymbol("SQLFreeHandle"); + m_pSetEnvAttr = loadSymbol("SQLSetEnvAttr"); + m_pDataSources = loadSymbol("SQLDataSources"); + + // all or nothing + if (!m_pAllocHandle || !m_pSetEnvAttr || !m_pDataSources || !m_pFreeHandle) + { + unload(); + m_pAllocHandle = m_pFreeHandle = m_pSetEnvAttr = m_pDataSources = nullptr; + } +#endif +} + +OOdbcEnumeration::~OOdbcEnumeration() +{ + freeEnv(); + unload(); +} + +// OOdbcEnumeration +bool OOdbcEnumeration::allocEnv() +{ + OSL_ENSURE(isLoaded(), "OOdbcEnumeration::allocEnv: not loaded!"); + if (!isLoaded()) + return false; + +#ifdef HAVE_ODBC_SUPPORT + if (m_pImpl->hEnvironment) + // nothing to do + return true; + SQLRETURN nResult = NSQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &m_pImpl->hEnvironment); + if (SQL_SUCCESS != nResult) + // can't do anything without environment + return false; + + NSQLSetEnvAttr(m_pImpl->hEnvironment, SQL_ATTR_ODBC_VERSION, reinterpret_cast<SQLPOINTER>(SQL_OV_ODBC3), SQL_IS_INTEGER); + return true; +#else + return sal_False; +#endif +} + +void OOdbcEnumeration::freeEnv() +{ +#ifdef HAVE_ODBC_SUPPORT + if (m_pImpl->hEnvironment) + NSQLFreeHandle(SQL_HANDLE_ENV, m_pImpl->hEnvironment); + m_pImpl->hEnvironment = nullptr; +#endif +} + +void OOdbcEnumeration::getDatasourceNames(std::set<OUString>& _rNames) +{ + OSL_ENSURE(isLoaded(), "OOdbcEnumeration::getDatasourceNames: not loaded!"); + if (!isLoaded()) + return; + + if (!allocEnv()) + { + OSL_FAIL("OOdbcEnumeration::getDatasourceNames: could not allocate an ODBC environment!"); + return; + } + +#ifdef HAVE_ODBC_SUPPORT + // now that we have an environment collect the data source names + UCHAR szDSN[SQL_MAX_DSN_LENGTH+1]; + SWORD pcbDSN; + UCHAR szDescription[1024+1]; + SWORD pcbDescription; + SQLRETURN nResult = SQL_SUCCESS; + rtl_TextEncoding nTextEncoding = osl_getThreadTextEncoding(); + + for ( nResult = NSQLDataSources(m_pImpl->hEnvironment, SQL_FETCH_FIRST, szDSN, sizeof(szDSN), &pcbDSN, szDescription, sizeof(szDescription)-1, &pcbDescription); + ; + nResult = NSQLDataSources(m_pImpl->hEnvironment, SQL_FETCH_NEXT, szDSN, sizeof(szDSN), &pcbDSN, szDescription, sizeof(szDescription)-1, &pcbDescription) + ) + { + if (nResult != SQL_SUCCESS) + // no further error handling + break; + else + { + OUString aCurrentDsn(reinterpret_cast<const char*>(szDSN),pcbDSN, nTextEncoding); + _rNames.insert(aCurrentDsn); + } + } +#else + (void) _rNames; +#endif +} + +#ifdef HAVE_ODBC_ADMINISTRATION + +// ProcessTerminationWait +class ProcessTerminationWait : public ::osl::Thread +{ + oslProcess m_hProcessHandle; + Link<void*,void> m_aFinishHdl; + ImplSVEvent* m_nEventId; + +public: + ProcessTerminationWait( oslProcess _hProcessHandle, const Link<void*,void>& _rFinishHdl ) + : m_hProcessHandle( _hProcessHandle ) + , m_aFinishHdl( _rFinishHdl ) + , m_nEventId(nullptr) + { + } + + void disableCallback() + { + // if finished event not posted yet, disable by turning it to a no-op Link + m_aFinishHdl = Link<void*, void>(); + if (m_nEventId) + { + // already posted, remove it + Application::RemoveUserEvent(m_nEventId); + m_nEventId = nullptr; + } + } + + void receivedCallback() + { + m_nEventId = nullptr; + } + +protected: + virtual void SAL_CALL run() override + { + osl_setThreadName("dbaui::ProcessTerminationWait"); + + osl_joinProcess( m_hProcessHandle ); + osl_freeProcessHandle( m_hProcessHandle ); + m_nEventId = Application::PostUserEvent( m_aFinishHdl ); + } +}; + +// OOdbcManagement +OOdbcManagement::OOdbcManagement(const Link<void*,void>& rAsyncFinishCallback) + : m_aAsyncFinishCallback(rAsyncFinishCallback) +{ +} + +OOdbcManagement::~OOdbcManagement() +{ + // wait for our thread to be finished + if ( m_pProcessWait.get() ) + m_pProcessWait->join(); +} + +bool OOdbcManagement::manageDataSources_async() +{ + OSL_PRECOND( !isRunning(), "OOdbcManagement::manageDataSources_async: still running from the previous call!" ); + if ( isRunning() ) + return false; + + // this is done in an external process, due to #i78733# + // (and note this whole functionality is supported on Windows only, ATM) + OUString sExecutableName( "$BRAND_BASE_DIR/" LIBO_LIBEXEC_FOLDER "/odbcconfig.exe" ); + ::rtl::Bootstrap::expandMacros( sExecutableName ); //TODO: detect failure + oslProcess hProcessHandle(nullptr); + oslProcessError eError = osl_executeProcess( sExecutableName.pData, nullptr, 0, 0, nullptr, nullptr, nullptr, 0, &hProcessHandle ); + if ( eError != osl_Process_E_None ) + return false; + + m_pProcessWait.reset( new ProcessTerminationWait( hProcessHandle, m_aAsyncFinishCallback ) ); + m_pProcessWait->create(); + return true; +} + +void OOdbcManagement::disableCallback() +{ + if (m_pProcessWait.get()) + m_pProcessWait->disableCallback(); +} + +void OOdbcManagement::receivedCallback() +{ + if (m_pProcessWait.get()) + m_pProcessWait->receivedCallback(); +} + +bool OOdbcManagement::isRunning() const +{ + return ( m_pProcessWait.get() && m_pProcessWait->isRunning() ); +} + +#endif // HAVE_ODBC_ADMINISTRATION + +} // namespace dbaui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/odbcconfig.hxx b/dbaccess/source/ui/dlg/odbcconfig.hxx new file mode 100644 index 000000000..0b4a78452 --- /dev/null +++ b/dbaccess/source/ui/dlg/odbcconfig.hxx @@ -0,0 +1,109 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_DBACCESS_SOURCE_UI_DLG_ODBCCONFIG_HXX +#define INCLUDED_DBACCESS_SOURCE_UI_DLG_ODBCCONFIG_HXX + +#if defined(_WIN32) || (defined (UNX) && !defined(ANDROID) && !defined(IOS)) +#define HAVE_ODBC_SUPPORT +#endif + +#if defined(_WIN32) && defined(HAVE_ODBC_SUPPORT) +#define HAVE_ODBC_ADMINISTRATION +#endif + +#include <rtl/ustring.hxx> +#include <tools/link.hxx> +#include <osl/module.h> + +#include <memory> +#include <set> + +namespace dbaui +{ + +// OOdbcEnumeration +struct OdbcTypesImpl; +class OOdbcEnumeration final +{ + oslModule m_pOdbcLib; // the library handle + OUString m_sLibPath; // the path to the library + +#ifdef HAVE_ODBC_SUPPORT + // entry points for ODBC administration + oslGenericFunction m_pAllocHandle; + oslGenericFunction m_pFreeHandle; + oslGenericFunction m_pSetEnvAttr; + oslGenericFunction m_pDataSources; + +#endif + std::unique_ptr<OdbcTypesImpl> m_pImpl; + // needed because we can't have a member of type SQLHANDLE: this would require us to include the respective + // ODBC file, which would lead to a lot of conflicts with other includes + +public: + OOdbcEnumeration(); + ~OOdbcEnumeration(); + +#ifdef HAVE_ODBC_SUPPORT + bool isLoaded() const { return nullptr != m_pOdbcLib; } +#else + bool isLoaded() const { return false; } +#endif + const OUString& getLibraryName() const { return m_sLibPath; } + + void getDatasourceNames(std::set<OUString>& _rNames); + +private: + oslGenericFunction loadSymbol(const char* _pFunctionName); + + /// load the lib + bool load(const char* _pLibPath); + /// unload the lib + void unload(); + /// ensure that an ODBC environment is allocated + bool allocEnv(); + /// free any allocated ODBC environment + void freeEnv(); +}; + +// OOdbcManagement +#ifdef HAVE_ODBC_ADMINISTRATION +class ProcessTerminationWait; +class OOdbcManagement +{ + std::unique_ptr< ProcessTerminationWait > m_pProcessWait; + Link<void*,void> m_aAsyncFinishCallback; + +public: + explicit OOdbcManagement( const Link<void*,void>& _rAsyncFinishCallback ); + ~OOdbcManagement(); + + bool manageDataSources_async(); + bool isRunning() const; + void disableCallback(); + void receivedCallback(); +}; +#endif + +} // namespace dbaui + +#endif // INCLUDED_DBACCESS_SOURCE_UI_DLG_ODBCCONFIG_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/optionalboolitem.cxx b/dbaccess/source/ui/dlg/optionalboolitem.cxx new file mode 100644 index 000000000..5eb4b1272 --- /dev/null +++ b/dbaccess/source/ui/dlg/optionalboolitem.cxx @@ -0,0 +1,45 @@ +/* -*- 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 "optionalboolitem.hxx" + +namespace dbaui +{ + + // OptionalBoolItem + OptionalBoolItem::OptionalBoolItem( sal_uInt16 _nWhich ) + :SfxPoolItem( _nWhich ) + ,m_aValue() + { + } + + bool OptionalBoolItem::operator==( const SfxPoolItem& _rItem ) const + { + return SfxPoolItem::operator==(_rItem) && + static_cast<const OptionalBoolItem&>( _rItem ).m_aValue == m_aValue; + } + + OptionalBoolItem* OptionalBoolItem::Clone( SfxItemPool* /*_pPool*/ ) const + { + return new OptionalBoolItem( *this ); + } + +} // namespace dbaui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/optionalboolitem.hxx b/dbaccess/source/ui/dlg/optionalboolitem.hxx new file mode 100644 index 000000000..25aef5cec --- /dev/null +++ b/dbaccess/source/ui/dlg/optionalboolitem.hxx @@ -0,0 +1,54 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_DBACCESS_SOURCE_UI_DLG_OPTIONALBOOLITEM_HXX +#define INCLUDED_DBACCESS_SOURCE_UI_DLG_OPTIONALBOOLITEM_HXX + +#include <svl/poolitem.hxx> + +#include <optional> + +namespace dbaui +{ + + // OptionalBoolItem + class OptionalBoolItem : public SfxPoolItem + { + ::std::optional< bool > m_aValue; + + public: + explicit OptionalBoolItem( sal_uInt16 nWhich ); + + virtual bool operator==( const SfxPoolItem& _rItem ) const override; + virtual OptionalBoolItem* Clone( SfxItemPool* _pPool = nullptr ) const override; + + bool HasValue() const { return !!m_aValue; } + void ClearValue() { m_aValue.reset(); } + bool GetValue() const { return *m_aValue; } + void SetValue(bool _bValue) { m_aValue = _bValue; } + + const ::std::optional< bool >& + GetFullValue() const { return m_aValue; } + }; + +} // namespace dbaui + +#endif // INCLUDED_DBACCESS_SOURCE_UI_DLG_OPTIONALBOOLITEM_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/paramdialog.cxx b/dbaccess/source/ui/dlg/paramdialog.cxx new file mode 100644 index 000000000..a7bd8ae15 --- /dev/null +++ b/dbaccess/source/ui/dlg/paramdialog.cxx @@ -0,0 +1,339 @@ +/* -*- 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 <core_resource.hxx> +#include <paramdialog.hxx> +#include <strings.hrc> +#include <strings.hxx> +#include <com/sun/star/util/NumberFormatter.hpp> +#include <comphelper/types.hxx> +#include <connectivity/dbtools.hxx> +#include <vcl/weld.hxx> +#include <o3tl/safeint.hxx> +#include <osl/diagnose.h> +#include <tools/diagnose_ex.h> + +namespace dbaui +{ + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::container; + using namespace ::com::sun::star::sdbc; + using namespace ::com::sun::star::util; + using namespace ::connectivity; + + // OParameterDialog + + + OParameterDialog::OParameterDialog( + weld::Window* pParent, const Reference< XIndexAccess > & rParamContainer, + const Reference< XConnection > & _rxConnection, const Reference< XComponentContext >& rxContext) + : GenericDialogController(pParent, "dbaccess/ui/parametersdialog.ui", "Parameters") + , m_nCurrentlySelected(-1) + , m_xConnection(_rxConnection) + , m_aPredicateInput( rxContext, _rxConnection, getParseContext() ) + , m_xAllParams(m_xBuilder->weld_tree_view("allParamTreeview")) + , m_xParam(m_xBuilder->weld_entry("paramEntry")) + , m_xTravelNext(m_xBuilder->weld_button("next")) + , m_xOKBtn(m_xBuilder->weld_button("ok")) + , m_xCancelBtn(m_xBuilder->weld_button("cancel")) + { + m_xAllParams->set_size_request(-1, m_xAllParams->get_height_rows(10)); + + if (rxContext.is()) + m_xFormatter.set( NumberFormatter::create( rxContext ), UNO_QUERY_THROW); + else { + OSL_FAIL("OParameterDialog::OParameterDialog: need a service factory!"); + } + + Reference< XNumberFormatsSupplier > xNumberFormats = ::dbtools::getNumberFormats(m_xConnection, true); + if (!xNumberFormats.is()) + ::comphelper::disposeComponent(m_xFormatter); + else + m_xFormatter->attachNumberFormatsSupplier(xNumberFormats); + try + { + OSL_ENSURE(rParamContainer->getCount(), "OParameterDialog::OParameterDialog : can't handle empty containers !"); + + m_aFinalValues.realloc(rParamContainer->getCount()); + PropertyValue* pValues = m_aFinalValues.getArray(); + + for (sal_Int32 i = 0, nCount = rParamContainer->getCount(); i<nCount; ++i, ++pValues) + { + Reference< XPropertySet > xParamAsSet; + rParamContainer->getByIndex(i) >>= xParamAsSet; + OSL_ENSURE(xParamAsSet.is(),"Parameter is null!"); + if(!xParamAsSet.is()) + continue; + pValues->Name = ::comphelper::getString(xParamAsSet->getPropertyValue(PROPERTY_NAME)); + m_xAllParams->append_text(pValues->Name); + + m_aVisitedParams.push_back(VisitFlags::NONE); + // not visited, not dirty + } + + m_xParams = rParamContainer; + } + catch(Exception&) + { + DBG_UNHANDLED_EXCEPTION("dbaccess"); + } + + Construct(); + + m_aResetVisitFlag.SetInvokeHandler(LINK(this, OParameterDialog, OnVisitedTimeout)); + } + + OParameterDialog::~OParameterDialog() + { + if (m_aResetVisitFlag.IsActive()) + m_aResetVisitFlag.Stop(); + } + + void OParameterDialog::Construct() + { + m_xAllParams->connect_changed(LINK(this, OParameterDialog, OnEntryListBoxSelected)); + m_xParam->connect_focus_out(LINK(this, OParameterDialog, OnValueLoseFocusHdl)); + m_xParam->connect_changed(LINK(this, OParameterDialog, OnValueModified)); + m_xTravelNext->connect_clicked(LINK(this, OParameterDialog, OnButtonClicked)); + m_xOKBtn->connect_clicked(LINK(this, OParameterDialog, OnButtonClicked)); + m_xCancelBtn->connect_clicked(LINK(this, OParameterDialog, OnButtonClicked)); + + if (m_xAllParams->n_children()) + { + m_xAllParams->select(0); + OnEntrySelected(); + + if (m_xAllParams->n_children() == 1) + { + m_xTravelNext->set_sensitive(false); + } + + if (m_xAllParams->n_children() > 1) + { + m_xOKBtn->set_has_default(false); + m_xTravelNext->set_has_default(true); + } + } + + m_xParam->grab_focus(); + } + + IMPL_LINK_NOARG(OParameterDialog, OnValueLoseFocusHdl, weld::Widget&, void) + { + CheckValueForError(); + } + + bool OParameterDialog::CheckValueForError() + { + if (m_nCurrentlySelected != -1) + { + if ( !( m_aVisitedParams[ m_nCurrentlySelected ] & VisitFlags::Dirty ) ) + // nothing to do, the value isn't dirty + return false; + } + + bool bRet = false; + + Reference< XPropertySet > xParamAsSet; + m_xParams->getByIndex(m_nCurrentlySelected) >>= xParamAsSet; + if (xParamAsSet.is()) + { + if (m_xConnection.is() && m_xFormatter.is()) + { + OUString sParamValue(m_xParam->get_text()); + bool bValid = m_aPredicateInput.normalizePredicateString( sParamValue, xParamAsSet ); + m_xParam->set_text(sParamValue); + m_xParam->set_message_type(bValid ? weld::EntryMessageType::Normal : weld::EntryMessageType::Error); + OUString sToolTip; + if ( bValid ) + { + // with this the value isn't dirty anymore + if (m_nCurrentlySelected != -1) + m_aVisitedParams[m_nCurrentlySelected] &= ~VisitFlags::Dirty; + } + else + { + OUString sName; + try + { + sName = ::comphelper::getString(xParamAsSet->getPropertyValue(PROPERTY_NAME)); + } + catch(Exception&) + { + DBG_UNHANDLED_EXCEPTION("dbaccess"); + } + + OUString sMessage(DBA_RES(STR_COULD_NOT_CONVERT_PARAM)); + sToolTip = sMessage.replaceAll( "$name$", sName ); + m_xParam->grab_focus(); + bRet = true; + } + m_xParam->set_tooltip_text(sToolTip); + m_xOKBtn->set_sensitive(bValid); + } + } + + return bRet; + } + + IMPL_LINK(OParameterDialog, OnButtonClicked, weld::Button&, rButton, void) + { + if (m_xCancelBtn.get() == &rButton) + { + // no interpreting of the given values anymore... + m_xParam->connect_focus_out(Link<weld::Widget&, void>()); // no direct call from the control anymore ... + m_xDialog->response(RET_CANCEL); + } + else if (m_xOKBtn.get() == &rButton) + { + // transfer the current values into the Any + if (OnEntrySelected()) + { // there was an error interpreting the current text + return; + } + + if (m_xParams.is()) + { + // write the parameters + try + { + PropertyValue* pValues = m_aFinalValues.getArray(); + for (sal_Int32 i = 0, nCount = m_xParams->getCount(); i<nCount; ++i, ++pValues) + { + Reference< XPropertySet > xParamAsSet; + m_xParams->getByIndex(i) >>= xParamAsSet; + + OUString sValue; + pValues->Value >>= sValue; + pValues->Value = m_aPredicateInput.getPredicateValue( sValue, xParamAsSet ); + } + } + catch(Exception&) + { + DBG_UNHANDLED_EXCEPTION("dbaccess"); + } + + } + m_xDialog->response(RET_OK); + } + else if (m_xTravelNext.get() == &rButton) + { + if (sal_Int32 nCount = m_xAllParams->n_children()) + { + sal_Int32 nCurrent = m_xAllParams->get_selected_index(); + OSL_ENSURE(static_cast<size_t>(nCount) == m_aVisitedParams.size(), "OParameterDialog::OnButtonClicked : inconsistent lists !"); + + // search the next entry in list we haven't visited yet + sal_Int32 nNext = (nCurrent + 1) % nCount; + while ((nNext != nCurrent) && ( m_aVisitedParams[nNext] & VisitFlags::Visited )) + nNext = (nNext + 1) % nCount; + + if ( m_aVisitedParams[nNext] & VisitFlags::Visited ) + // there is no such "not visited yet" entry -> simply take the next one + nNext = (nCurrent + 1) % nCount; + + m_xAllParams->select(nNext); + OnEntrySelected(); + } + } + } + + IMPL_LINK_NOARG(OParameterDialog, OnEntryListBoxSelected, weld::TreeView&, void) + { + OnEntrySelected(); + } + + bool OParameterDialog::OnEntrySelected() + { + if (m_aResetVisitFlag.IsActive()) + { + LINK(this, OParameterDialog, OnVisitedTimeout).Call(&m_aResetVisitFlag); + m_aResetVisitFlag.Stop(); + } + // save the old values + if (m_nCurrentlySelected != -1) + { + // do the transformation of the current text + if (CheckValueForError()) + { // there was an error interpreting the text + m_xAllParams->select(m_nCurrentlySelected); + return true; + } + + m_aFinalValues[m_nCurrentlySelected].Value <<= m_xParam->get_text(); + } + + // initialize the controls with the new values + sal_Int32 nSelected = m_xAllParams->get_selected_index(); + OSL_ENSURE(nSelected != -1, "OParameterDialog::OnEntrySelected : no current entry !"); + + m_xParam->set_text(::comphelper::getString(m_aFinalValues[nSelected].Value)); + m_nCurrentlySelected = nSelected; + + // with this the value isn't dirty + OSL_ENSURE(o3tl::make_unsigned(m_nCurrentlySelected) < m_aVisitedParams.size(), "OParameterDialog::OnEntrySelected : invalid current entry !"); + m_aVisitedParams[m_nCurrentlySelected] &= ~VisitFlags::Dirty; + + m_aResetVisitFlag.SetTimeout(1000); + m_aResetVisitFlag.Start(); + + return false; + } + + IMPL_LINK_NOARG(OParameterDialog, OnVisitedTimeout, Timer*, void) + { + OSL_ENSURE(m_nCurrentlySelected != -1, "OParameterDialog::OnVisitedTimeout : invalid call !"); + + // mark the currently selected entry as visited + OSL_ENSURE(o3tl::make_unsigned(m_nCurrentlySelected) < m_aVisitedParams.size(), "OParameterDialog::OnVisitedTimeout : invalid entry !"); + m_aVisitedParams[m_nCurrentlySelected] |= VisitFlags::Visited; + + // was it the last "not visited yet" entry ? + bool bVisited = false; + for (auto const& visitedParam : m_aVisitedParams) + { + if (!(visitedParam & VisitFlags::Visited)) + { + bVisited = true; + break; + } + } + + if (!bVisited) + { + // yes, there isn't another one -> change the "default button" + m_xTravelNext->set_has_default(false); + m_xOKBtn->set_has_default(true); + } + } + + IMPL_LINK(OParameterDialog, OnValueModified, weld::Entry&, rEdit, void) + { + // mark the currently selected entry as dirty + OSL_ENSURE(o3tl::make_unsigned(m_nCurrentlySelected) < m_aVisitedParams.size(), "OParameterDialog::OnValueModified : invalid entry !"); + m_aVisitedParams[m_nCurrentlySelected] |= VisitFlags::Dirty; + rEdit.set_message_type(weld::EntryMessageType::Normal); + } + +} // namespace dbaui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/queryfilter.cxx b/dbaccess/source/ui/dlg/queryfilter.cxx new file mode 100644 index 000000000..5eeb86ef0 --- /dev/null +++ b/dbaccess/source/ui/dlg/queryfilter.cxx @@ -0,0 +1,773 @@ +/* -*- 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 <queryfilter.hxx> +#include <com/sun/star/sdbc/DataType.hpp> +#include <com/sun/star/util/Date.hpp> +#include <com/sun/star/sdbc/ColumnSearch.hpp> +#include <com/sun/star/sdbcx/XColumnsSupplier.hpp> +#include <com/sun/star/sdb/SQLFilterOperator.hpp> +#include <com/sun/star/sdbc/XConnection.hpp> +#include <comphelper/string.hxx> +#include <tools/diagnose_ex.h> +#include <osl/diagnose.h> +#include <connectivity/dbtools.hxx> +#include <strings.hxx> +#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp> + +using namespace dbaui; +using namespace connectivity; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; + +static void Replace_OS_PlaceHolder(OUString& aString) +{ + aString = aString.replaceAll( "*", "%" ); + aString = aString.replaceAll( "?", "_" ); +} + +static void Replace_SQL_PlaceHolder(OUString& aString) +{ + aString = aString.replaceAll( "%", "*" ); + aString = aString.replaceAll( "_", "?" ); +} + +DlgFilterCrit::DlgFilterCrit(weld::Window * pParent, + const Reference< XComponentContext >& rxContext, + const Reference< XConnection>& _rxConnection, + const Reference< XSingleSelectQueryComposer >& _rxComposer, + const Reference< XNameAccess>& _rxCols) + : GenericDialogController(pParent, "dbaccess/ui/queryfilterdialog.ui", "QueryFilterDialog") + , m_xQueryComposer(_rxComposer) + , m_xColumns( _rxCols ) + , m_xConnection( _rxConnection ) + , m_xMetaData( _rxConnection->getMetaData() ) + , m_aPredicateInput( rxContext, _rxConnection, getParseContext() ) + , m_xLB_WHEREFIELD1(m_xBuilder->weld_combo_box("field1")) + , m_xLB_WHERECOMP1(m_xBuilder->weld_combo_box("cond1")) + , m_xET_WHEREVALUE1(m_xBuilder->weld_entry("value1")) + , m_xLB_WHERECOND2(m_xBuilder->weld_combo_box("op2")) + , m_xLB_WHEREFIELD2(m_xBuilder->weld_combo_box("field2")) + , m_xLB_WHERECOMP2(m_xBuilder->weld_combo_box("cond2")) + , m_xET_WHEREVALUE2(m_xBuilder->weld_entry("value2")) + , m_xLB_WHERECOND3(m_xBuilder->weld_combo_box("op3")) + , m_xLB_WHEREFIELD3(m_xBuilder->weld_combo_box("field3")) + , m_xLB_WHERECOMP3(m_xBuilder->weld_combo_box("cond3")) + , m_xET_WHEREVALUE3(m_xBuilder->weld_entry("value3")) +{ + //set all condition preferred width to max width + //if all entries exist + Size aSize(m_xLB_WHERECOMP1->get_preferred_size()); + m_xLB_WHERECOMP1->set_size_request(aSize.Width(), -1); + m_xLB_WHERECOMP2->set_size_request(aSize.Width(), -1); + m_xLB_WHERECOMP3->set_size_request(aSize.Width(), -1); + const sal_Int32 nEntryCount = m_xLB_WHERECOMP1->get_count(); + m_aSTR_COMPARE_OPERATORS.resize(nEntryCount); + for (sal_Int32 i = 0; i < nEntryCount; ++i) + { + m_aSTR_COMPARE_OPERATORS[i] = m_xLB_WHERECOMP1->get_text(i); + } + m_xLB_WHERECOMP1->clear(); + + // ... also write it into the remaining fields + Sequence< OUString> aNames = m_xColumns->getElementNames(); + const OUString* pIter = aNames.getConstArray(); + const OUString* pEnd = pIter + aNames.getLength(); + Reference<XPropertySet> xColumn; + for(;pIter != pEnd;++pIter) + { + try + { + xColumn.set( m_xColumns->getByName( *pIter ), UNO_QUERY_THROW ); + + sal_Int32 nDataType( 0 ); + OSL_VERIFY( xColumn->getPropertyValue( PROPERTY_TYPE ) >>= nDataType ); + sal_Int32 eColumnSearch = ::dbtools::getSearchColumnFlag( m_xConnection, nDataType ); + if ( eColumnSearch == ColumnSearch::NONE ) + continue; + + bool bIsSearchable( true ); + OSL_VERIFY( xColumn->getPropertyValue( PROPERTY_ISSEARCHABLE ) >>= bIsSearchable ); + if ( !bIsSearchable ) + continue; + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("dbaccess"); + } + m_xLB_WHEREFIELD1->append_text( *pIter ); + m_xLB_WHEREFIELD2->append_text( *pIter ); + m_xLB_WHEREFIELD3->append_text( *pIter ); + } + + Reference<XNameAccess> xSelectColumns = Reference<XColumnsSupplier>(m_xQueryComposer,UNO_QUERY_THROW)->getColumns(); + aNames = xSelectColumns->getElementNames(); + pIter = aNames.getConstArray(); + pEnd = pIter + aNames.getLength(); + for(;pIter != pEnd;++pIter) + { + // don't insert a column name twice + if ( !m_xColumns->hasByName(*pIter) ) + { + xColumn.set(xSelectColumns->getByName(*pIter),UNO_QUERY); + OSL_ENSURE(xColumn.is(),"DlgFilterCrit::DlgFilterCrit: Column is null!"); + sal_Int32 nDataType(0); + xColumn->getPropertyValue(PROPERTY_TYPE) >>= nDataType; + sal_Int32 eColumnSearch = dbtools::getSearchColumnFlag(m_xConnection,nDataType); + // TODO + // !pColumn->IsFunction() + if(eColumnSearch != ColumnSearch::NONE) + { + m_xLB_WHEREFIELD1->append_text( *pIter ); + m_xLB_WHEREFIELD2->append_text( *pIter ); + m_xLB_WHEREFIELD3->append_text( *pIter ); + } + } + } + // initialize the listboxes with noEntry + m_xLB_WHEREFIELD1->set_active(0); + m_xLB_WHEREFIELD2->set_active(0); + m_xLB_WHEREFIELD3->set_active(0); + + // insert the criteria into the dialog + Sequence<Sequence<PropertyValue > > aValues = m_xQueryComposer->getStructuredFilter(); + int i(0); + fillLines(i, aValues); + aValues = m_xQueryComposer->getStructuredHavingClause(); + fillLines(i, aValues); + + EnableLines(); + + m_xLB_WHEREFIELD1->connect_changed(LINK(this,DlgFilterCrit,ListSelectHdl)); + m_xLB_WHEREFIELD2->connect_changed(LINK(this,DlgFilterCrit,ListSelectHdl)); + m_xLB_WHEREFIELD3->connect_changed(LINK(this,DlgFilterCrit,ListSelectHdl)); + + m_xLB_WHERECOMP1->connect_changed(LINK(this,DlgFilterCrit,ListSelectCompHdl)); + m_xLB_WHERECOMP2->connect_changed(LINK(this,DlgFilterCrit,ListSelectCompHdl)); + m_xLB_WHERECOMP3->connect_changed(LINK(this,DlgFilterCrit,ListSelectCompHdl)); + + m_xET_WHEREVALUE1->connect_focus_out( LINK( this, DlgFilterCrit, PredicateLoseFocus ) ); + m_xET_WHEREVALUE2->connect_focus_out( LINK( this, DlgFilterCrit, PredicateLoseFocus ) ); + m_xET_WHEREVALUE3->connect_focus_out( LINK( this, DlgFilterCrit, PredicateLoseFocus ) ); + + if (m_xET_WHEREVALUE1->get_sensitive()) + m_xET_WHEREVALUE1->grab_focus(); +} + +DlgFilterCrit::~DlgFilterCrit() +{ +} + +#define LbText(x) ((x).get_active_text()) +#define LbPos(x) ((x).get_active()) + +sal_Int32 DlgFilterCrit::GetOSQLPredicateType( const OUString& _rSelectedPredicate ) const +{ + sal_Int32 nPredicateIndex = -1; + for ( size_t i=0; i < m_aSTR_COMPARE_OPERATORS.size(); ++i) + if ( m_aSTR_COMPARE_OPERATORS[i] == _rSelectedPredicate ) + { + nPredicateIndex = i; + break; + } + + sal_Int32 nPredicateType = SQLFilterOperator::NOT_SQLNULL; + switch ( nPredicateIndex ) + { + case 0: + nPredicateType = SQLFilterOperator::EQUAL; + break; + case 1: + nPredicateType = SQLFilterOperator::NOT_EQUAL; + break; + case 2: + nPredicateType = SQLFilterOperator::LESS; + break; + case 3: + nPredicateType = SQLFilterOperator::LESS_EQUAL; + break; + case 4: + nPredicateType = SQLFilterOperator::GREATER; + break; + case 5: + nPredicateType = SQLFilterOperator::GREATER_EQUAL; + break; + case 6: + nPredicateType = SQLFilterOperator::LIKE; + break; + case 7: + nPredicateType = SQLFilterOperator::NOT_LIKE; + break; + case 8: + nPredicateType = SQLFilterOperator::SQLNULL; + break; + case 9: + nPredicateType = SQLFilterOperator::NOT_SQLNULL; + break; + default: + OSL_FAIL( "DlgFilterCrit::GetOSQLPredicateType: unknown predicate string!" ); + break; + } + + return nPredicateType; +} + +sal_Int32 DlgFilterCrit::GetSelectionPos(sal_Int32 eType, const weld::ComboBox& rListBox) +{ + sal_Int32 nPos; + switch(eType) + { + case SQLFilterOperator::EQUAL: + nPos = 0; + break; + case SQLFilterOperator::NOT_EQUAL: + nPos = 1; + break; + case SQLFilterOperator::LESS: + nPos = 2; + break; + case SQLFilterOperator::LESS_EQUAL: + nPos = 3; + break; + case SQLFilterOperator::GREATER: + nPos = 4; + break; + case SQLFilterOperator::GREATER_EQUAL: + nPos = 5; + break; + case SQLFilterOperator::NOT_LIKE: + nPos = rListBox.get_count() > 2 ? rListBox.get_count()-3 : 0; + break; + case SQLFilterOperator::LIKE: + nPos = rListBox.get_count() > 2 ? rListBox.get_count()-4 : 1; + break; + case SQLFilterOperator::SQLNULL: + nPos = rListBox.get_count()-2; + break; + case SQLFilterOperator::NOT_SQLNULL: + nPos = rListBox.get_count()-1; + break; + default: + // TODO What value should this be? + nPos = 0; + break; + } + return nPos; +} + +bool DlgFilterCrit::getCondition(const weld::ComboBox& _rField,const weld::ComboBox& _rComp,const weld::Entry& _rValue,PropertyValue& _rFilter) const +{ + bool bHaving = false; + try + { + OUString sTableName; + _rFilter.Name = _rField.get_active_text(); + Reference< XPropertySet > xColumn = getQueryColumn(_rFilter.Name); + if ( xColumn.is() ) + { + bool bFunction = false; + Reference< XPropertySetInfo > xInfo = xColumn->getPropertySetInfo(); + if ( xInfo->hasPropertyByName(PROPERTY_REALNAME) ) + { + if ( xInfo->hasPropertyByName(PROPERTY_TABLENAME) ) + { + xColumn->getPropertyValue(PROPERTY_TABLENAME) >>= sTableName; + if ( !sTableName.isEmpty() ) + { + // properly quote all parts of the table name, so + // e.g. <schema>.<table> becomes "<schema>"."<table>" + OUString aCatlog,aSchema,aTable; + ::dbtools::qualifiedNameComponents( m_xMetaData, sTableName, aCatlog, aSchema, aTable, ::dbtools::EComposeRule::InDataManipulation ); + sTableName = ::dbtools::composeTableName( m_xMetaData, aCatlog, aSchema, aTable, true, ::dbtools::EComposeRule::InDataManipulation ); + } + } + xColumn->getPropertyValue(PROPERTY_REALNAME) >>= _rFilter.Name; + static const char sAgg[] = "AggregateFunction"; + if ( xInfo->hasPropertyByName(sAgg) ) + xColumn->getPropertyValue(sAgg) >>= bHaving; + static const char sFunction[] = "Function"; + if ( xInfo->hasPropertyByName(sFunction) ) + xColumn->getPropertyValue(sFunction) >>= bFunction; + } + if ( !bFunction ) + { + const OUString aQuote = m_xMetaData.is() ? m_xMetaData->getIdentifierQuoteString() : OUString(); + _rFilter.Name = ::dbtools::quoteName(aQuote,_rFilter.Name); + if ( !sTableName.isEmpty() ) + { + sTableName += "." + _rFilter.Name; + _rFilter.Name = sTableName; + } + } + } + } + catch(const Exception&) + { + } + + _rFilter.Handle = GetOSQLPredicateType( _rComp.get_active_text() ); + if ( SQLFilterOperator::SQLNULL != _rFilter.Handle && _rFilter.Handle != SQLFilterOperator::NOT_SQLNULL ) + { + OUString sPredicateValue; + m_aPredicateInput.getPredicateValue( _rValue.get_text(), getMatchingColumn( _rValue ) ) >>= sPredicateValue; + if ( _rFilter.Handle == SQLFilterOperator::LIKE || + _rFilter.Handle == SQLFilterOperator::NOT_LIKE ) + ::Replace_OS_PlaceHolder( sPredicateValue ); + _rFilter.Value <<= sPredicateValue; + } + return bHaving; +} + +Reference< XPropertySet > DlgFilterCrit::getColumn( const OUString& _rFieldName ) const +{ + Reference< XPropertySet > xColumn; + try + { + if ( m_xColumns.is() && m_xColumns->hasByName( _rFieldName ) ) + m_xColumns->getByName( _rFieldName ) >>= xColumn; + + Reference< XNameAccess> xColumns = Reference< XColumnsSupplier >(m_xQueryComposer,UNO_QUERY_THROW)->getColumns(); + if ( xColumns.is() && !xColumn.is() ) + { + Sequence< OUString> aSeq = xColumns->getElementNames(); + const OUString* pIter = aSeq.getConstArray(); + const OUString* pEnd = pIter + aSeq.getLength(); + for(;pIter != pEnd;++pIter) + { + Reference<XPropertySet> xProp(xColumns->getByName(*pIter),UNO_QUERY); + if ( xProp.is() && xProp->getPropertySetInfo()->hasPropertyByName(PROPERTY_REALNAME) ) + { + OUString sRealName; + xProp->getPropertyValue(PROPERTY_REALNAME) >>= sRealName; + if ( sRealName == _rFieldName ) + { + if ( m_xColumns.is() && m_xColumns->hasByName( *pIter ) ) + m_xColumns->getByName( *pIter ) >>= xColumn; + break; + } + } + } + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("dbaccess"); + } + + return xColumn; +} + +Reference< XPropertySet > DlgFilterCrit::getQueryColumn( const OUString& _rFieldName ) const +{ + Reference< XPropertySet > xColumn; + try + { + Reference< XNameAccess> xColumns = Reference< XColumnsSupplier >(m_xQueryComposer,UNO_QUERY_THROW)->getColumns(); + if ( xColumns.is() && xColumns->hasByName( _rFieldName ) ) + xColumns->getByName( _rFieldName ) >>= xColumn; + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("dbaccess"); + } + + return xColumn; +} + +Reference< XPropertySet > DlgFilterCrit::getMatchingColumn( const weld::Entry& _rValueInput ) const +{ + // the name + OUString sField; + if ( &_rValueInput == m_xET_WHEREVALUE1.get() ) + { + sField = m_xLB_WHEREFIELD1->get_active_text(); + } + else if ( &_rValueInput == m_xET_WHEREVALUE2.get() ) + { + sField = m_xLB_WHEREFIELD2->get_active_text(); + } + else if ( &_rValueInput == m_xET_WHEREVALUE3.get() ) + { + sField = m_xLB_WHEREFIELD3->get_active_text(); + } + else { + OSL_FAIL( "DlgFilterCrit::getMatchingColumn: invalid event source!" ); + } + + // the field itself + return getColumn( sField ); +} + +IMPL_LINK( DlgFilterCrit, PredicateLoseFocus, weld::Widget&, rControl, void ) +{ + weld::Entry& rField = dynamic_cast<weld::Entry&>(rControl); + // retrieve the field affected + Reference< XPropertySet> xColumn(getMatchingColumn(rField)); + // and normalize its content + if ( xColumn.is() ) + { + OUString sText(rField.get_text()); + m_aPredicateInput.normalizePredicateString(sText, xColumn); + rField.set_text(sText); + } +} + +void DlgFilterCrit::SetLine( int nIdx, const PropertyValue& _rItem, bool _bOr ) +{ + OUString aStr; + _rItem.Value >>= aStr; + if ( _rItem.Handle == SQLFilterOperator::LIKE || + _rItem.Handle == SQLFilterOperator::NOT_LIKE ) + ::Replace_SQL_PlaceHolder(aStr); + aStr = comphelper::string::stripEnd(aStr, ' '); + + Reference< XPropertySet > xColumn = getColumn( _rItem.Name ); + + // to make sure that we only set first three + weld::ComboBox* pColumnListControl = nullptr; + weld::ComboBox* pPredicateListControl = nullptr; + weld::Entry* pPredicateValueControl = nullptr; + switch( nIdx ) + { + case 0: + pColumnListControl = m_xLB_WHEREFIELD1.get(); + pPredicateListControl = m_xLB_WHERECOMP1.get(); + pPredicateValueControl = m_xET_WHEREVALUE1.get(); + break; + case 1: + m_xLB_WHERECOND2->set_active( _bOr ? 1 : 0 ); + + pColumnListControl = m_xLB_WHEREFIELD2.get(); + pPredicateListControl = m_xLB_WHERECOMP2.get(); + pPredicateValueControl = m_xET_WHEREVALUE2.get(); + break; + case 2: + m_xLB_WHERECOND3->set_active( _bOr ? 1 : 0 ); + + pColumnListControl = m_xLB_WHEREFIELD3.get(); + pPredicateListControl = m_xLB_WHERECOMP3.get(); + pPredicateValueControl = m_xET_WHEREVALUE3.get(); + break; + } + + if ( !(pColumnListControl && pPredicateListControl && pPredicateValueControl) ) + return; + + OUString sName; + if ( xColumn.is() ) + xColumn->getPropertyValue(PROPERTY_NAME) >>= sName; + else + sName = _rItem.Name; + // select the appropriate field name + SelectField( *pColumnListControl, sName ); + ListSelectHdl( *pColumnListControl ); + + // select the appropriate condition + pPredicateListControl->set_active( GetSelectionPos( _rItem.Handle, *pPredicateListControl ) ); + + // initially normalize this value + OUString aString( aStr ); + m_aPredicateInput.normalizePredicateString( aString, xColumn ); + pPredicateValueControl->set_text( aString ); +} + +void DlgFilterCrit::SelectField(weld::ComboBox& rBox, const OUString& rField) +{ + const sal_Int32 nCnt = rBox.get_count(); + + for( sal_Int32 i=0 ; i<nCnt ; i++ ) + { + if (rBox.get_text(i) == rField) + { + rBox.set_active(i); + return; + } + } + + rBox.set_active(0); +} + +void DlgFilterCrit::EnableLines() +{ + // enabling/disabling of whole lines + if( LbPos(*m_xLB_WHEREFIELD1) == 0 ) + { + m_xLB_WHEREFIELD2->set_sensitive(false); + m_xLB_WHERECOND2->set_sensitive(false); + m_xLB_WHERECOMP2->set_sensitive(false); + m_xET_WHEREVALUE2->set_sensitive(false); + + m_xLB_WHEREFIELD3->set_sensitive(false); + m_xLB_WHERECOND3->set_sensitive(false); + m_xLB_WHERECOMP3->set_sensitive(false); + m_xET_WHEREVALUE3->set_sensitive(false); + } + else + { + m_xLB_WHEREFIELD2->set_sensitive(true); + m_xLB_WHERECOND2->set_sensitive(true); + m_xLB_WHERECOMP2->set_sensitive(true); + m_xET_WHEREVALUE2->set_sensitive(true); + + m_xLB_WHEREFIELD3->set_sensitive(true); + m_xLB_WHERECOND3->set_sensitive(true); + m_xLB_WHERECOMP3->set_sensitive(true); + m_xET_WHEREVALUE3->set_sensitive(true); + } + + if( LbPos(*m_xLB_WHEREFIELD2) == 0 ) + { + m_xLB_WHEREFIELD3->set_sensitive(false); + m_xLB_WHERECOND3->set_sensitive(false); + m_xLB_WHERECOMP3->set_sensitive(false); + m_xET_WHEREVALUE3->set_sensitive(false); + } + else + { + m_xLB_WHEREFIELD3->set_sensitive(true); + m_xLB_WHERECOND3->set_sensitive(true); + m_xLB_WHERECOMP3->set_sensitive(true); + m_xET_WHEREVALUE3->set_sensitive(true); + } + + // comparison field equal to NOENTRY + if( LbPos(*m_xLB_WHEREFIELD1) == 0 ) + { + m_xLB_WHERECOMP1->set_sensitive(false); + m_xET_WHEREVALUE1->set_sensitive(false); + } + else + { + m_xLB_WHEREFIELD1->set_sensitive(true); + m_xLB_WHERECOMP1->set_sensitive(true); + m_xET_WHEREVALUE1->set_sensitive(true); + } + + if( LbPos(*m_xLB_WHEREFIELD2) == 0 ) + { + m_xLB_WHERECOND2->set_sensitive(false); + m_xLB_WHERECOMP2->set_sensitive(false); + m_xET_WHEREVALUE2->set_sensitive(false); + } + else + { + m_xLB_WHERECOND2->set_sensitive(true); + m_xLB_WHEREFIELD2->set_sensitive(true); + m_xLB_WHERECOMP2->set_sensitive(true); + m_xET_WHEREVALUE2->set_sensitive(true); + } + + if( LbPos(*m_xLB_WHEREFIELD3) == 0 ) + { + m_xLB_WHERECOND3->set_sensitive(false); + m_xLB_WHERECOMP3->set_sensitive(false); + m_xET_WHEREVALUE3->set_sensitive(false); + } + else + { + m_xLB_WHERECOND3->set_sensitive(true); + m_xLB_WHERECOND3->set_sensitive(true); + m_xLB_WHEREFIELD3->set_sensitive(true); + m_xLB_WHERECOMP3->set_sensitive(true); + m_xET_WHEREVALUE3->set_sensitive(true); + } + + // comparison operator equal to ISNULL or ISNOTNULL + if(m_xLB_WHERECOMP1->get_count() > 2 && + ((LbPos(*m_xLB_WHERECOMP1) == m_xLB_WHERECOMP1->get_count()-1) || + (LbPos(*m_xLB_WHERECOMP1) == m_xLB_WHERECOMP1->get_count()-2)) ) + m_xET_WHEREVALUE1->set_sensitive(false); + + if(m_xLB_WHERECOMP2->get_count() > 2 && + ((LbPos(*m_xLB_WHERECOMP2) == m_xLB_WHERECOMP2->get_count()-1) || + (LbPos(*m_xLB_WHERECOMP2) == m_xLB_WHERECOMP2->get_count()-2)) ) + m_xET_WHEREVALUE2->set_sensitive(false); + + if(m_xLB_WHERECOMP3->get_count() > 2 && + ((LbPos(*m_xLB_WHERECOMP3) == m_xLB_WHERECOMP3->get_count()-1) || + (LbPos(*m_xLB_WHERECOMP3) == m_xLB_WHERECOMP3->get_count()-2)) ) + m_xET_WHEREVALUE3->set_sensitive(false); +} + +IMPL_LINK( DlgFilterCrit, ListSelectHdl, weld::ComboBox&, rListBox, void ) +{ + OUString aName; + weld::ComboBox* pComp; + if(&rListBox == m_xLB_WHEREFIELD1.get()) + { + aName = LbText(*m_xLB_WHEREFIELD1); + pComp = m_xLB_WHERECOMP1.get(); + } + else if(&rListBox == m_xLB_WHEREFIELD2.get()) + { + aName = LbText(*m_xLB_WHEREFIELD2); + pComp = m_xLB_WHERECOMP2.get(); + } + else + { + aName = LbText(*m_xLB_WHEREFIELD3); + pComp = m_xLB_WHERECOMP3.get(); + } + + pComp->clear(); + + Reference<XPropertySet> xColumn = getColumn(aName); + if ( xColumn.is() ) + { + sal_Int32 nDataType = 0; + xColumn->getPropertyValue(PROPERTY_TYPE) >>= nDataType; + sal_Int32 eColumnSearch = dbtools::getSearchColumnFlag(m_xConnection,nDataType); + + if(eColumnSearch == ColumnSearch::FULL) + { + for(size_t i=0;i < m_aSTR_COMPARE_OPERATORS.size(); i++) + pComp->append_text(m_aSTR_COMPARE_OPERATORS[i]); + } + else if(eColumnSearch == ColumnSearch::CHAR) + { + for(sal_Int32 i=6; i<10; i++) + pComp->append_text(m_aSTR_COMPARE_OPERATORS[i]); + } + else if(eColumnSearch == ColumnSearch::BASIC) + { + size_t i; + for( i = 0; i < 6; i++ ) + pComp->append_text(m_aSTR_COMPARE_OPERATORS[i]); + for(i=8; i < m_aSTR_COMPARE_OPERATORS.size(); ++i) + pComp->append_text(m_aSTR_COMPARE_OPERATORS[i]); + } + else + { + OSL_FAIL("DlgFilterCrit::ListSelectHdl: This column should not exist at all."); + } + } + pComp->set_active(0); + + EnableLines(); +} + +IMPL_LINK_NOARG(DlgFilterCrit, ListSelectCompHdl, weld::ComboBox&, void) +{ + EnableLines(); +} + +void DlgFilterCrit::BuildWherePart() +{ + Sequence<Sequence<PropertyValue> > aFilter,aHaving; + aFilter.realloc(1); + aHaving.realloc(1); + + if( LbPos(*m_xLB_WHEREFIELD1) != 0 ) + { + PropertyValue aValue; + if ( getCondition(*m_xLB_WHEREFIELD1,*m_xLB_WHERECOMP1,*m_xET_WHEREVALUE1,aValue) ) + { + aHaving[0].realloc(1); + aHaving[0][0] = aValue; + } + else + { + aFilter[0].realloc(1); + aFilter[0][0] = aValue; + } + } + + if( LbPos(*m_xLB_WHEREFIELD2) != 0 ) + { + PropertyValue aValue; + Sequence<Sequence<PropertyValue> >& _rValues = aFilter; + if ( getCondition(*m_xLB_WHEREFIELD2,*m_xLB_WHERECOMP2,*m_xET_WHEREVALUE2,aValue) ) + _rValues = aHaving; + PropertyValue* pPos = nullptr; + if ( m_xLB_WHERECOND2->get_active() ) + { + sal_Int32 nPos = _rValues.getLength(); + _rValues.realloc( nPos + 1); + _rValues[nPos].realloc( 1); + pPos = &_rValues[nPos][0]; + } + else + { + sal_Int32 nPos = _rValues.getLength() - 1; + sal_Int32 nAndPos = _rValues[nPos].getLength(); + _rValues[nPos].realloc( _rValues[nPos].getLength() + 1); + pPos = &_rValues[nPos][nAndPos]; + } + *pPos = aValue; + } + + if( LbPos(*m_xLB_WHEREFIELD3) != 0 ) + { + PropertyValue aValue; + Sequence<Sequence<PropertyValue> >& _rValues = aFilter; + if ( getCondition(*m_xLB_WHEREFIELD3,*m_xLB_WHERECOMP3,*m_xET_WHEREVALUE3,aValue) ) + _rValues = aHaving; + PropertyValue* pPos = nullptr; + if (m_xLB_WHERECOND3->get_active()) + { + sal_Int32 nPos = _rValues.getLength(); + _rValues.realloc( nPos + 1); + _rValues[nPos].realloc( 1); + pPos = &_rValues[nPos][0]; + } + else + { + sal_Int32 nPos = _rValues.getLength() - 1; + sal_Int32 nAndPos = _rValues[nPos].getLength(); + _rValues[nPos].realloc( _rValues[nPos].getLength() + 1); + pPos = &_rValues[nPos][nAndPos]; + } + *pPos = aValue; + } + try + { + m_xQueryComposer->setStructuredFilter(aFilter); + m_xQueryComposer->setStructuredHavingClause(aHaving); + } + catch(const Exception&) + { + DBG_UNHANDLED_EXCEPTION("dbaccess"); + } +} + +void DlgFilterCrit::fillLines(int &i, const Sequence< Sequence< PropertyValue > >& _aValues) +{ + const Sequence<PropertyValue >* pOrIter = _aValues.getConstArray(); + const Sequence<PropertyValue >* pOrEnd = pOrIter + _aValues.getLength(); + bool bOr(i != 0); // WHERE clause and HAVING clause are always ANDed, nor ORed + for(; pOrIter != pOrEnd; ++pOrIter) + { + const PropertyValue* pAndIter = pOrIter->getConstArray(); + const PropertyValue* pAndEnd = pAndIter + pOrIter->getLength(); + for(;pAndIter != pAndEnd; ++pAndIter) + { + SetLine( i++,*pAndIter,bOr); + bOr = false; + } + bOr=true; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/queryorder.cxx b/dbaccess/source/ui/dlg/queryorder.cxx new file mode 100644 index 000000000..f06935f5e --- /dev/null +++ b/dbaccess/source/ui/dlg/queryorder.cxx @@ -0,0 +1,218 @@ +/* -*- 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 <strings.hrc> +#include <strings.hxx> +#include <core_resource.hxx> +#include <queryorder.hxx> +#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp> +#include <com/sun/star/sdbc/ColumnSearch.hpp> +#include <com/sun/star/sdbc/XConnection.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <connectivity/dbtools.hxx> +#include <com/sun/star/sdbcx/XColumnsSupplier.hpp> +#include <tools/diagnose_ex.h> + +using namespace dbaui; +using namespace connectivity; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; + + +DlgOrderCrit::DlgOrderCrit(weld::Window * pParent, + const Reference< XConnection>& _rxConnection, + const Reference< XSingleSelectQueryComposer >& _rxComposer, + const Reference< XNameAccess>& _rxCols) + : GenericDialogController(pParent, "dbaccess/ui/sortdialog.ui", "SortDialog") + , m_xQueryComposer(_rxComposer) + , m_xColumns(_rxCols) + , m_xConnection(_rxConnection) + , m_xLB_ORDERFIELD1(m_xBuilder->weld_combo_box("field1")) + , m_xLB_ORDERVALUE1(m_xBuilder->weld_combo_box("value1")) + , m_xLB_ORDERFIELD2(m_xBuilder->weld_combo_box("field2")) + , m_xLB_ORDERVALUE2(m_xBuilder->weld_combo_box("value2")) + , m_xLB_ORDERFIELD3(m_xBuilder->weld_combo_box("field3")) + , m_xLB_ORDERVALUE3(m_xBuilder->weld_combo_box("value3")) +{ + m_aColumnList[0] = m_xLB_ORDERFIELD1.get(); + m_aColumnList[1] = m_xLB_ORDERFIELD2.get(); + m_aColumnList[2] = m_xLB_ORDERFIELD3.get(); + + m_aValueList[0] = m_xLB_ORDERVALUE1.get(); + m_aValueList[1] = m_xLB_ORDERVALUE2.get(); + m_aValueList[2] = m_xLB_ORDERVALUE3.get(); + + OUString aSTR_NOENTRY(DBA_RES(STR_VALUE_NONE)); + for (auto j : m_aColumnList) + { + j->append_text(aSTR_NOENTRY); + } + + for (int j=0; j < DOG_ROWS; ++j) + { + m_aColumnList[j]->set_active(0); + m_aValueList[j]->set_active(0); + } + try + { + // ... also the remaining fields + Sequence< OUString> aNames = m_xColumns->getElementNames(); + const OUString* pIter = aNames.getConstArray(); + const OUString* pEnd = pIter + aNames.getLength(); + Reference<XPropertySet> xColumn; + for(;pIter != pEnd;++pIter) + { + xColumn.set(m_xColumns->getByName(*pIter),UNO_QUERY); + OSL_ENSURE(xColumn.is(),"Column is null!"); + if ( xColumn.is() ) + { + sal_Int32 nDataType = 0; + xColumn->getPropertyValue(PROPERTY_TYPE) >>= nDataType; + sal_Int32 eColumnSearch = dbtools::getSearchColumnFlag(m_xConnection,nDataType); + if(eColumnSearch != ColumnSearch::NONE) + { + for (auto j : m_aColumnList) + { + j->append_text(*pIter); + } + } + } + } + + m_sOrgOrder = m_xQueryComposer->getOrder(); + impl_initializeOrderList_nothrow(); + } + catch(const Exception&) + { + DBG_UNHANDLED_EXCEPTION("dbaccess"); + } + EnableLines(); + + m_xLB_ORDERFIELD1->connect_changed(LINK(this,DlgOrderCrit,FieldListSelectHdl)); + m_xLB_ORDERFIELD2->connect_changed(LINK(this,DlgOrderCrit,FieldListSelectHdl)); +} + +DlgOrderCrit::~DlgOrderCrit() +{ +} + +IMPL_LINK_NOARG( DlgOrderCrit, FieldListSelectHdl, weld::ComboBox&, void ) +{ + EnableLines(); +} + +void DlgOrderCrit::impl_initializeOrderList_nothrow() +{ + try + { + const OUString sNameProperty = "Name"; + const OUString sAscendingProperty = "IsAscending"; + + Reference< XIndexAccess > xOrderColumns( m_xQueryComposer->getOrderColumns(), UNO_SET_THROW ); + sal_Int32 nColumns = xOrderColumns->getCount(); + if ( nColumns > DOG_ROWS ) + nColumns = DOG_ROWS; + + for ( sal_Int32 i = 0; i < nColumns; ++i ) + { + Reference< XPropertySet > xColumn( xOrderColumns->getByIndex( i ), UNO_QUERY_THROW ); + + OUString sColumnName; + bool bIsAscending( true ); + + xColumn->getPropertyValue( sNameProperty ) >>= sColumnName; + xColumn->getPropertyValue( sAscendingProperty ) >>= bIsAscending; + + m_aColumnList[i]->set_active_text(sColumnName); + m_aValueList[i]->set_active(bIsAscending ? 0 : 1); + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("dbaccess"); + } +} + +void DlgOrderCrit::EnableLines() +{ + + if ( m_xLB_ORDERFIELD1->get_active() == 0 ) + { + m_xLB_ORDERFIELD2->set_sensitive(false); + m_xLB_ORDERVALUE2->set_sensitive(false); + + m_xLB_ORDERFIELD2->set_active( 0 ); + m_xLB_ORDERVALUE2->set_active( 0 ); + } + else + { + m_xLB_ORDERFIELD2->set_sensitive(true); + m_xLB_ORDERVALUE2->set_sensitive(true); + } + + if ( m_xLB_ORDERFIELD2->get_active() == 0 ) + { + m_xLB_ORDERFIELD3->set_sensitive(false); + m_xLB_ORDERVALUE3->set_sensitive(false); + + m_xLB_ORDERFIELD3->set_active( 0 ); + m_xLB_ORDERVALUE3->set_active( 0 ); + } + else + { + m_xLB_ORDERFIELD3->set_sensitive(true); + m_xLB_ORDERVALUE3->set_sensitive(true); + } +} + +OUString DlgOrderCrit::GetOrderList( ) const +{ + Reference<XDatabaseMetaData> xMetaData = m_xConnection->getMetaData(); + OUString sQuote = xMetaData.is() ? xMetaData->getIdentifierQuoteString() : OUString(); + + OUStringBuffer sOrder; + for( sal_uInt16 i=0 ; i<DOG_ROWS; i++ ) + { + if (m_aColumnList[i]->get_active() != 0) + { + if(!sOrder.isEmpty()) + sOrder.append(","); + + OUString sName = m_aColumnList[i]->get_active_text(); + sOrder.append(::dbtools::quoteName(sQuote,sName)); + if (m_aValueList[i]->get_active()) + sOrder.append(" DESC "); + else + sOrder.append(" ASC "); + } + } + return sOrder.makeStringAndClear(); +} + +void DlgOrderCrit::BuildOrderPart() +{ + m_xQueryComposer->setOrder(GetOrderList()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/sqlmessage.cxx b/dbaccess/source/ui/dlg/sqlmessage.cxx new file mode 100644 index 000000000..39ba6dc8e --- /dev/null +++ b/dbaccess/source/ui/dlg/sqlmessage.cxx @@ -0,0 +1,607 @@ +/* -*- 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 <core_resource.hxx> +#include <sqlmessage.hxx> +#include <strings.hrc> +#include <com/sun/star/sdbc/SQLException.hpp> +#include <com/sun/star/sdb/SQLContext.hpp> +#include <vcl/stdtext.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> +#include <osl/diagnose.h> +#include <connectivity/dbexception.hxx> +#include <connectivity/sqlerror.hxx> +#include <unotools/configmgr.hxx> + +#include <tools/urlobj.hxx> + +#define RET_MORE RET_RETRY + 1 + +using namespace dbtools; +using namespace com::sun::star::uno; +using namespace com::sun::star::sdb; +using namespace com::sun::star::sdbc; + +namespace dbaui +{ + +namespace +{ + class ImageProvider + { + private: + OUString m_defaultImageID; + + public: + explicit ImageProvider(const OUString& defaultImageID) + : m_defaultImageID(defaultImageID) + { + } + + const OUString& getImage() const + { + return m_defaultImageID; + } + }; + + class LabelProvider + { + private: + OUString m_label; + public: + explicit LabelProvider(const char* labelResourceID) + : m_label(DBA_RES(labelResourceID)) + { + } + + const OUString& getLabel() const + { + return m_label; + } + }; + + class ProviderFactory + { + private: + mutable std::shared_ptr< ImageProvider > m_pErrorImage; + mutable std::shared_ptr< ImageProvider > m_pWarningsImage; + mutable std::shared_ptr< ImageProvider > m_pInfoImage; + mutable std::shared_ptr< LabelProvider > m_pErrorLabel; + mutable std::shared_ptr< LabelProvider > m_pWarningsLabel; + mutable std::shared_ptr< LabelProvider > m_pInfoLabel; + + public: + ProviderFactory() + { + } + + std::shared_ptr< ImageProvider > const & getImageProvider( SQLExceptionInfo::TYPE _eType ) const + { + std::shared_ptr< ImageProvider >* ppProvider( &m_pErrorImage ); + OUString sNormalImageID("dialog-error"); + + switch ( _eType ) + { + case SQLExceptionInfo::TYPE::SQLWarning: + ppProvider = &m_pWarningsImage; + sNormalImageID = "dialog-warning"; + break; + + case SQLExceptionInfo::TYPE::SQLContext: + ppProvider = &m_pInfoImage; + sNormalImageID = "dialog-information"; + break; + + default: + break; + } + + if ( !ppProvider->get() ) + (*ppProvider) = std::make_shared<ImageProvider>(sNormalImageID); + return *ppProvider; + } + + std::shared_ptr< LabelProvider > const & getLabelProvider( SQLExceptionInfo::TYPE _eType, bool _bSubLabel ) const + { + std::shared_ptr< LabelProvider >* ppProvider( &m_pErrorLabel ); + const char* pLabelID( STR_EXCEPTION_ERROR ); + + switch ( _eType ) + { + case SQLExceptionInfo::TYPE::SQLWarning: + ppProvider = &m_pWarningsLabel; + pLabelID = STR_EXCEPTION_WARNING; + break; + + case SQLExceptionInfo::TYPE::SQLContext: + ppProvider = &m_pInfoLabel; + pLabelID = _bSubLabel ? STR_EXCEPTION_DETAILS : STR_EXCEPTION_INFO; + break; + default: + break; + } + + if ( !ppProvider->get() ) + (*ppProvider) = std::make_shared<LabelProvider>( pLabelID ); + return *ppProvider; + } + + }; + + /// a stripped version of the SQLException, packed for displaying + struct ExceptionDisplayInfo + { + SQLExceptionInfo::TYPE eType; + + std::shared_ptr< ImageProvider > pImageProvider; + std::shared_ptr< LabelProvider > pLabelProvider; + + bool bSubEntry; + + OUString sMessage; + OUString sSQLState; + OUString sErrorCode; + + ExceptionDisplayInfo() : eType( SQLExceptionInfo::TYPE::Undefined ), bSubEntry( false ) { } + explicit ExceptionDisplayInfo( SQLExceptionInfo::TYPE _eType ) : eType( _eType ), bSubEntry( false ) { } + }; + + bool lcl_hasDetails( const ExceptionDisplayInfo& _displayInfo ) + { + return ( !_displayInfo.sErrorCode.isEmpty() ) + || ( !_displayInfo.sSQLState.isEmpty() + && _displayInfo.sSQLState != "S1000" + ); + } + + typedef std::vector< ExceptionDisplayInfo > ExceptionDisplayChain; + + /// strips the [OOoBase] vendor identifier from the given error message, if applicable + OUString lcl_stripOOoBaseVendor( const OUString& _rErrorMessage ) + { + OUString sErrorMessage( _rErrorMessage ); + + const OUString sVendorIdentifier( ::connectivity::SQLError::getMessagePrefix() ); + if ( sErrorMessage.startsWith( sVendorIdentifier ) ) + { + // characters to strip + sal_Int32 nStripLen( sVendorIdentifier.getLength() ); + // usually, there should be a whitespace between the vendor and the real message + while ( ( sErrorMessage.getLength() > nStripLen ) + && ( sErrorMessage[nStripLen] == ' ' ) + ) + ++nStripLen; + sErrorMessage = sErrorMessage.copy( nStripLen ); + } + + return sErrorMessage; + } + + void lcl_buildExceptionChain( const SQLExceptionInfo& _rErrorInfo, const ProviderFactory& _rFactory, ExceptionDisplayChain& _out_rChain ) + { + { + ExceptionDisplayChain empty; + _out_rChain.swap( empty ); + } + + SQLExceptionIteratorHelper iter( _rErrorInfo ); + while ( iter.hasMoreElements() ) + { + // current chain element + SQLExceptionInfo aCurrentElement; + iter.next( aCurrentElement ); + + const SQLException* pCurrentError = aCurrentElement; + OSL_ENSURE( pCurrentError, "lcl_buildExceptionChain: iterator failure!" ); + // hasMoreElements should not have returned <TRUE/> in this case + + ExceptionDisplayInfo aDisplayInfo( aCurrentElement.getType() ); + + aDisplayInfo.sMessage = pCurrentError->Message.trim(); + aDisplayInfo.sSQLState = pCurrentError->SQLState; + if ( pCurrentError->ErrorCode ) + aDisplayInfo.sErrorCode = OUString::number( pCurrentError->ErrorCode ); + + if ( aDisplayInfo.sMessage.isEmpty() + && !lcl_hasDetails( aDisplayInfo ) + ) + { + OSL_FAIL( "lcl_buildExceptionChain: useless exception: no state, no error code, no message!" ); + continue; + } + + aDisplayInfo.pImageProvider = _rFactory.getImageProvider( aCurrentElement.getType() ); + aDisplayInfo.pLabelProvider = _rFactory.getLabelProvider( aCurrentElement.getType(), false ); + + _out_rChain.push_back( aDisplayInfo ); + + if ( aCurrentElement.getType() == SQLExceptionInfo::TYPE::SQLContext ) + { + const SQLContext* pContext = aCurrentElement; + if ( !pContext->Details.isEmpty() ) + { + ExceptionDisplayInfo aSubInfo( aCurrentElement.getType() ); + + aSubInfo.sMessage = pContext->Details; + aSubInfo.pImageProvider = _rFactory.getImageProvider( aCurrentElement.getType() ); + aSubInfo.pLabelProvider = _rFactory.getLabelProvider( aCurrentElement.getType(), true ); + aSubInfo.bSubEntry = true; + + _out_rChain.push_back( aSubInfo ); + } + } + } + } + + void lcl_insertExceptionEntry(weld::TreeView& rList, size_t nElementPos, const ExceptionDisplayInfo& rEntry) + { + rList.append(OUString::number(nElementPos), rEntry.pLabelProvider->getLabel(), rEntry.pImageProvider->getImage()); + } +} + +namespace { + +class OExceptionChainDialog : public weld::GenericDialogController +{ + std::unique_ptr<weld::TreeView> m_xExceptionList; + std::unique_ptr<weld::TextView> m_xExceptionText; + + OUString m_sStatusLabel; + OUString m_sErrorCodeLabel; + + ExceptionDisplayChain m_aExceptions; + +public: + OExceptionChainDialog(weld::Window* pParent, const ExceptionDisplayChain& rExceptions); + +protected: + DECL_LINK(OnExceptionSelected, weld::TreeView&, void); +}; + +} + +OExceptionChainDialog::OExceptionChainDialog(weld::Window* pParent, const ExceptionDisplayChain& rExceptions) + : GenericDialogController(pParent, "dbaccess/ui/sqlexception.ui", "SQLExceptionDialog") + , m_xExceptionList(m_xBuilder->weld_tree_view("list")) + , m_xExceptionText(m_xBuilder->weld_text_view("description")) + , m_aExceptions(rExceptions) +{ + int nListWidth = m_xExceptionText->get_approximate_digit_width() * 28; + int nTextWidth = m_xExceptionText->get_approximate_digit_width() * 42; + int nHeight = m_xExceptionList->get_height_rows(6); + m_xExceptionList->set_size_request(nListWidth, nHeight); + m_xExceptionText->set_size_request(nTextWidth, nHeight); + + m_sStatusLabel = DBA_RES( STR_EXCEPTION_STATUS ); + m_sErrorCodeLabel = DBA_RES( STR_EXCEPTION_ERRORCODE ); + + m_xExceptionList->connect_changed(LINK(this, OExceptionChainDialog, OnExceptionSelected)); + + bool bHave22018 = false; + size_t elementPos = 0; + + for (auto const& elem : m_aExceptions) + { + lcl_insertExceptionEntry(*m_xExceptionList, elementPos, elem); + bHave22018 = elem.sSQLState == "22018"; + ++elementPos; + } + + // if the error has the code 22018, then add an additional explanation + // #i24021# + if ( bHave22018 ) + { + ProviderFactory aProviderFactory; + + ExceptionDisplayInfo aInfo22018; + aInfo22018.sMessage = DBA_RES( STR_EXPLAN_STRINGCONVERSION_ERROR ); + aInfo22018.pLabelProvider = aProviderFactory.getLabelProvider( SQLExceptionInfo::TYPE::SQLContext, false ); + aInfo22018.pImageProvider = aProviderFactory.getImageProvider( SQLExceptionInfo::TYPE::SQLContext ); + m_aExceptions.push_back( aInfo22018 ); + + lcl_insertExceptionEntry(*m_xExceptionList, m_aExceptions.size() - 1, aInfo22018); + } + + if (m_xExceptionList->n_children()) + { + m_xExceptionList->select(0); + OnExceptionSelected(*m_xExceptionList); + } +} + +IMPL_LINK_NOARG(OExceptionChainDialog, OnExceptionSelected, weld::TreeView&, void) +{ + OUString sText; + + OUString sId(m_xExceptionList->get_selected_id()); + if (!sId.isEmpty()) + { + const ExceptionDisplayInfo& aExceptionInfo(m_aExceptions[sId.toUInt32()]); + + if ( !aExceptionInfo.sSQLState.isEmpty() ) + { + sText += m_sStatusLabel + ": " + aExceptionInfo.sSQLState + "\n"; + } + + if ( !aExceptionInfo.sErrorCode.isEmpty() ) + { + sText += m_sErrorCodeLabel + ": " + aExceptionInfo.sErrorCode + "\n"; + } + + if ( !sText.isEmpty() ) + sText += "\n"; + + sText += aExceptionInfo.sMessage; + } + + m_xExceptionText->set_text(sText); +} + +// SQLMessageBox_Impl +struct SQLMessageBox_Impl +{ + ExceptionDisplayChain aDisplayInfo; + + explicit SQLMessageBox_Impl( const SQLExceptionInfo& _rExceptionInfo ) + { + // transform the exception chain to a form more suitable for displaying it here + ProviderFactory aProviderFactory; + lcl_buildExceptionChain( _rExceptionInfo, aProviderFactory, aDisplayInfo ); + } +}; + +namespace +{ + void lcl_addButton(weld::MessageDialog* pDialog, StandardButtonType eType, bool bDefault) + { + sal_uInt16 nButtonID = 0; + switch (eType) + { + case StandardButtonType::Yes: + nButtonID = RET_YES; + pDialog->add_button(GetStandardText(StandardButtonType::Yes), nButtonID); + break; + case StandardButtonType::No: + nButtonID = RET_NO; + pDialog->add_button(GetStandardText(StandardButtonType::No), nButtonID); + break; + case StandardButtonType::OK: + nButtonID = RET_OK; + pDialog->add_button(GetStandardText(StandardButtonType::OK), nButtonID); + break; + case StandardButtonType::Cancel: + nButtonID = RET_CANCEL; + pDialog->add_button(GetStandardText(StandardButtonType::Cancel), nButtonID); + break; + case StandardButtonType::Retry: + nButtonID = RET_RETRY; + pDialog->add_button(GetStandardText(StandardButtonType::Retry), nButtonID); + break; + case StandardButtonType::Help: + nButtonID = RET_HELP; + pDialog->add_button(GetStandardText(StandardButtonType::Help), nButtonID); + break; + default: + OSL_FAIL( "lcl_addButton: invalid button id!" ); + break; + } + if (bDefault) + pDialog->set_default_response(nButtonID); + } +} + +void OSQLMessageBox::impl_fillMessages() +{ + OSL_PRECOND( !m_pImpl->aDisplayInfo.empty(), "OSQLMessageBox::impl_fillMessages: nothing to display at all?" ); + + if ( m_pImpl->aDisplayInfo.empty() ) + return; + const ExceptionDisplayInfo* pSecondInfo = nullptr; + + const ExceptionDisplayInfo& rFirstInfo = *m_pImpl->aDisplayInfo.begin(); + if ( m_pImpl->aDisplayInfo.size() > 1 ) + pSecondInfo = &m_pImpl->aDisplayInfo[1]; + OUString sPrimary, sSecondary; + sPrimary = rFirstInfo.sMessage; + // one or two texts to display? + if ( pSecondInfo ) + { + // we show two elements in the main dialog if and only if one of + // - the first element in the chain is an SQLContext, and the second + // element denotes its sub entry + // - the first and the second element are both independent (i.e. the second + // is no sub entry), and none of them is a context. + bool bFirstElementIsContext = ( rFirstInfo.eType == SQLExceptionInfo::TYPE::SQLContext ); + bool bSecondElementIsContext = ( pSecondInfo->eType == SQLExceptionInfo::TYPE::SQLContext ); + + if ( bFirstElementIsContext && pSecondInfo->bSubEntry ) + sSecondary = pSecondInfo->sMessage; + if ( !bFirstElementIsContext && !bSecondElementIsContext ) + sSecondary = pSecondInfo->sMessage; + } + + // primary text + m_xDialog->set_primary_text(lcl_stripOOoBaseVendor(sPrimary)); + + // secondary text (if applicable) + m_xDialog->set_secondary_text(lcl_stripOOoBaseVendor(sSecondary)); +} + +void OSQLMessageBox::impl_createStandardButtons( MessBoxStyle _nStyle ) +{ + if ( _nStyle & MessBoxStyle::YesNoCancel ) + { + lcl_addButton(m_xDialog.get(), StandardButtonType::Yes, bool(_nStyle & MessBoxStyle::DefaultYes)); + lcl_addButton(m_xDialog.get(), StandardButtonType::No, bool(_nStyle & MessBoxStyle::DefaultNo)); + lcl_addButton(m_xDialog.get(), StandardButtonType::Cancel, bool(_nStyle & MessBoxStyle::DefaultCancel)); + } + else if ( _nStyle & MessBoxStyle::OkCancel ) + { + lcl_addButton(m_xDialog.get(), StandardButtonType::OK, bool(_nStyle & MessBoxStyle::DefaultOk)); + lcl_addButton(m_xDialog.get(), StandardButtonType::Cancel, bool(_nStyle & MessBoxStyle::DefaultCancel)); + } + else if ( _nStyle & MessBoxStyle::YesNo ) + { + lcl_addButton(m_xDialog.get(), StandardButtonType::Yes, bool(_nStyle & MessBoxStyle::DefaultYes)); + lcl_addButton(m_xDialog.get(), StandardButtonType::No, bool(_nStyle & MessBoxStyle::DefaultNo)); + } + else if ( _nStyle & MessBoxStyle::RetryCancel ) + { + lcl_addButton(m_xDialog.get(), StandardButtonType::Retry, bool(_nStyle & MessBoxStyle::DefaultRetry)); + lcl_addButton(m_xDialog.get(), StandardButtonType::Cancel, bool(_nStyle & MessBoxStyle::DefaultCancel)); + } + else if ( _nStyle & MessBoxStyle::Ok ) + { + lcl_addButton(m_xDialog.get(), StandardButtonType::OK, true); + } + + if ( m_sHelpURL.isEmpty() ) + return; + + lcl_addButton(m_xDialog.get(), StandardButtonType::Help, false); + + OUString aTmp; + INetURLObject aHID( m_sHelpURL ); + if ( aHID.GetProtocol() == INetProtocol::Hid ) + aTmp = aHID.GetURLPath(); + else + aTmp = m_sHelpURL; + + m_xDialog->set_help_id(OUStringToOString(aTmp, RTL_TEXTENCODING_UTF8)); +} + +void OSQLMessageBox::impl_addDetailsButton() +{ + size_t nFirstPageVisible = m_xDialog->get_secondary_text().isEmpty() ? 1 : 2; + + bool bMoreDetailsAvailable = m_pImpl->aDisplayInfo.size() > nFirstPageVisible; + if ( !bMoreDetailsAvailable ) + { + // even if the text fits into what we can display, we might need to details button + // if there is more non-trivial information in the errors than the mere messages + for (auto const& error : m_pImpl->aDisplayInfo) + { + if ( lcl_hasDetails(error) ) + { + bMoreDetailsAvailable = true; + break; + } + } + } + + if ( bMoreDetailsAvailable ) + { + m_xDialog->add_button(GetStandardText(StandardButtonType::More), RET_MORE); + m_xMoreButton.reset(m_xDialog->weld_widget_for_response(RET_MORE)); + m_xMoreButton->connect_clicked(LINK(this, OSQLMessageBox, ButtonClickHdl)); + } +} + +void OSQLMessageBox::Construct(weld::Window* pParent, MessBoxStyle _nStyle, MessageType _eImage) +{ + // init the image + MessageType eType( _eImage ); + if ( eType == AUTO ) + { + switch ( m_pImpl->aDisplayInfo[0].eType ) + { + case SQLExceptionInfo::TYPE::SQLException: eType = Error; break; + case SQLExceptionInfo::TYPE::SQLWarning: eType = Warning; break; + case SQLExceptionInfo::TYPE::SQLContext: eType = Info; break; + default: OSL_FAIL( "OSQLMessageBox::Construct: invalid type!" ); + } + } + VclMessageType eMessageType; + switch (eType) + { + default: + OSL_FAIL( "OSQLMessageBox::impl_initImage: unsupported image type!" ); + [[fallthrough]]; + case Info: + eMessageType = VclMessageType::Info; + break; + case Warning: + eMessageType = VclMessageType::Warning; + break; + case Error: + eMessageType = VclMessageType::Error; + break; + case Query: + eMessageType = VclMessageType::Question; + break; + } + + m_xDialog.reset(Application::CreateMessageDialog(pParent, eMessageType, VclButtonsType::NONE, "")); + m_xDialog->set_title(utl::ConfigManager::getProductName() + " Base"); + + impl_fillMessages(); + + // create buttons + impl_createStandardButtons( _nStyle ); + impl_addDetailsButton(); +} + +OSQLMessageBox::OSQLMessageBox(weld::Window* pParent, const SQLExceptionInfo& rException, MessBoxStyle nStyle, const OUString& rHelpURL) + : m_pImpl(new SQLMessageBox_Impl(rException)) + , m_sHelpURL(rHelpURL) +{ + Construct(pParent, nStyle, AUTO); +} + +OSQLMessageBox::OSQLMessageBox(weld::Window* pParent, const OUString& rTitle, const OUString& rMessage, MessBoxStyle nStyle, MessageType eType, const ::dbtools::SQLExceptionInfo* pAdditionalErrorInfo ) +{ + SQLContext aError; + aError.Message = rTitle; + aError.Details = rMessage; + if (pAdditionalErrorInfo) + aError.NextException = pAdditionalErrorInfo->get(); + + m_pImpl.reset(new SQLMessageBox_Impl(SQLExceptionInfo(aError))); + + Construct(pParent, nStyle, eType); +} + +OSQLMessageBox::~OSQLMessageBox() +{ +} + +IMPL_LINK_NOARG(OSQLMessageBox, ButtonClickHdl, weld::Button&, void) +{ + OExceptionChainDialog aDlg(m_xDialog.get(), m_pImpl->aDisplayInfo); + aDlg.run(); +} + +// OSQLWarningBox +OSQLWarningBox::OSQLWarningBox(weld::Window* pParent, const OUString& rMessage, MessBoxStyle nStyle, + const ::dbtools::SQLExceptionInfo* pAdditionalErrorInfo ) + : OSQLMessageBox(pParent, DBA_RES(STR_EXCEPTION_WARNING), rMessage, nStyle, MessageType::Warning, pAdditionalErrorInfo) +{ +} + +// OSQLErrorBox +OSQLErrorBox::OSQLErrorBox(weld::Window* pParent, const OUString& rMessage) + : OSQLMessageBox(pParent, DBA_RES(STR_EXCEPTION_ERROR), rMessage, MessBoxStyle::Ok | MessBoxStyle::DefaultOk, + MessageType::Error, nullptr) +{ +} + +} // namespace dbaui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/tablespage.cxx b/dbaccess/source/ui/dlg/tablespage.cxx new file mode 100644 index 000000000..586cf77bf --- /dev/null +++ b/dbaccess/source/ui/dlg/tablespage.cxx @@ -0,0 +1,496 @@ +/* -*- 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 "tablespage.hxx" +#include <dsitems.hxx> +#include <datasourceconnector.hxx> +#include <comphelper/types.hxx> +#include <connectivity/dbtools.hxx> +#include <connectivity/dbexception.hxx> +#include <stringlistitem.hxx> +#include <svl/stritem.hxx> +#include <strings.hxx> +#include <com/sun/star/sdbc/SQLException.hpp> +#include <com/sun/star/util/XModifiable.hpp> +#include <sqlmessage.hxx> +#include <UITools.hxx> +#include <osl/diagnose.h> +#include <TablesSingleDlg.hxx> +#include <tools/diagnose_ex.h> +#include <cppuhelper/exc_hlp.hxx> + +namespace dbaui +{ + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::sdbc; + using namespace ::com::sun::star::sdbcx; + using namespace ::com::sun::star::sdb; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::container; + using namespace ::com::sun::star::util; + using namespace ::dbtools; + using namespace ::comphelper; + + // OTableSubscriptionPage + OTableSubscriptionPage::OTableSubscriptionPage(weld::Container* pPage, OTableSubscriptionDialog* pTablesDlg, const SfxItemSet& _rCoreAttrs) + : OGenericAdministrationPage(pPage, pTablesDlg, "dbaccess/ui/tablesfilterpage.ui", "TablesFilterPage", _rCoreAttrs) + , m_bCatalogAtStart(true) + , m_pTablesDlg(pTablesDlg) + , m_xTables(m_xBuilder->weld_widget("TablesFilterPage")) + , m_xTablesList(new TableTreeListBox(m_xBuilder->weld_tree_view("treeview"))) + { + m_xTablesList->init(); + + weld::TreeView& rWidget = m_xTablesList->GetWidget(); + + rWidget.set_size_request(rWidget.get_approximate_digit_width() * 48, + rWidget.get_height_rows(12)); + + // initialize the TabListBox + rWidget.set_selection_mode(SelectionMode::Multiple); + + rWidget.connect_toggled(LINK(this, OTableSubscriptionPage, OnTreeEntryChecked)); + } + + OTableSubscriptionPage::~OTableSubscriptionPage() + { + // just to make sure that our connection will be removed + try + { + ::comphelper::disposeComponent(m_xCurrentConnection); + } + catch (RuntimeException&) { } + } + + void OTableSubscriptionPage::implCheckTables(const Sequence< OUString >& _rTables) + { + // the meta data for the current connection, used for splitting up table names + Reference< XDatabaseMetaData > xMeta; + try + { + if (m_xCurrentConnection.is()) + xMeta = m_xCurrentConnection->getMetaData(); + } + catch(SQLException&) + { + OSL_FAIL("OTableSubscriptionPage::implCheckTables : could not retrieve the current connection's meta data!"); + } + + // uncheck all + CheckAll(false); + + // check the ones which are in the list + OUString sCatalog, sSchema, sName; + + std::unique_ptr<weld::TreeIter> xRootEntry(m_xTablesList->getAllObjectsEntry()); + + for (const OUString& rIncludeTable : _rTables) + { + if (xMeta.is()) + qualifiedNameComponents(xMeta, rIncludeTable.getStr(), sCatalog, sSchema, sName,::dbtools::EComposeRule::InDataManipulation); + else + sName = rIncludeTable; + + bool bAllTables = (1 == sName.getLength()) && ('%' == sName[0]); + bool bAllSchemas = (1 == sSchema.getLength()) && ('%' == sSchema[0]); + + // the catalog entry + std::unique_ptr<weld::TreeIter> xCatalog(m_xTablesList->GetEntryPosByName(sCatalog, xRootEntry.get())); + if (!(xCatalog || sCatalog.isEmpty())) + // the table (resp. its catalog) referred in this filter entry does not exist anymore + continue; + + if (bAllSchemas && xCatalog) + { + m_xTablesList->checkWildcard(*xCatalog); + continue; + } + + // the schema entry + std::unique_ptr<weld::TreeIter> xSchema = m_xTablesList->GetEntryPosByName(sSchema, (xCatalog ? xCatalog.get() : xRootEntry.get())); + if (!(xSchema || sSchema.isEmpty())) + // the table (resp. its schema) referred in this filter entry does not exist anymore + continue; + + if (bAllTables && xSchema) + { + m_xTablesList->checkWildcard(*xSchema); + continue; + } + + std::unique_ptr<weld::TreeIter> xEntry(m_xTablesList->GetEntryPosByName(sName, xSchema ? xSchema.get() : (xCatalog ? xCatalog.get() : xRootEntry.get()))); + if (xEntry) + m_xTablesList->GetWidget().set_toggle(*xEntry, TRISTATE_TRUE, 0); + } + m_xTablesList->CheckButtons(); + } + + void OTableSubscriptionPage::implCompleteTablesCheck( const css::uno::Sequence< OUString >& _rTableFilter ) + { + if (!_rTableFilter.hasElements()) + { // no tables visible + CheckAll(false); + } + else + { + if ((1 == _rTableFilter.getLength()) && _rTableFilter[0] == "%") + { // all tables visible + CheckAll(); + } + else + implCheckTables( _rTableFilter ); + } + } + + void OTableSubscriptionPage::implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) + { + // check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa) + bool bValid, bReadonly; + getFlags(_rSet, bValid, bReadonly); + + // get the name of the data source we're working for + const SfxStringItem* pNameItem = _rSet.GetItem<SfxStringItem>(DSID_NAME); + OSL_ENSURE(pNameItem, "OTableSubscriptionPage::implInitControls: missing the name attribute!"); + OUString sDSName = pNameItem->GetValue(); + + if (bValid && !sDSName.isEmpty() && !m_xCurrentConnection.is() ) + { // get the current table list from the connection for the current settings + + // the PropertyValues for the current dialog settings + Sequence< PropertyValue > aConnectionParams; + OSL_ENSURE(m_pTablesDlg, "OTableSubscriptionPage::implInitControls: need a parent dialog doing the translation!"); + if ( m_pTablesDlg ) + { + if (!m_pTablesDlg->getCurrentSettings(aConnectionParams)) + { + m_xTablesList->GetWidget().clear(); + m_pTablesDlg->endExecution(); + return; + } + } + + // fill the table list with this connection information + SQLExceptionInfo aErrorInfo; + // the current DSN + OUString sURL; + if ( m_pTablesDlg ) + sURL = m_pTablesDlg->getConnectionURL(); + + try + { + weld::WaitObject aWaitCursor(GetFrameWeld()); + + Reference<XPropertySet> xProp = m_pTablesDlg->getCurrentDataSource(); + OSL_ENSURE(xProp.is(),"No data source set!"); + if ( xProp.is() ) + { + Any aTableFilter = xProp->getPropertyValue(PROPERTY_TABLEFILTER); + Any aTableTypeFilter = xProp->getPropertyValue(PROPERTY_TABLETYPEFILTER); + + Reference<XModifiable> xModi(getDataSourceOrModel(xProp),UNO_QUERY); + bool bModified = ( xModi.is() && xModi->isModified() ); + + Sequence< OUString > aNewTableFilter { "%" }; + xProp->setPropertyValue(PROPERTY_TABLEFILTER,makeAny(aNewTableFilter)); + + xProp->setPropertyValue( PROPERTY_TABLETYPEFILTER, makeAny( Sequence< OUString >() ) ); + Reference< css::lang::XEventListener> xEvt; + aErrorInfo = ::dbaui::createConnection(xProp, m_xORB, xEvt, m_xCurrentConnection); + + xProp->setPropertyValue(PROPERTY_TABLEFILTER,aTableFilter); + xProp->setPropertyValue(PROPERTY_TABLETYPEFILTER,aTableTypeFilter); + + if ( xModi.is() && !bModified ) + xModi->setModified(false); + + } + + if ( m_xCurrentConnection.is() ) + { + m_xTablesList->UpdateTableList( m_xCurrentConnection ); + if (m_pTablesDlg) + m_pTablesDlg->successfullyConnected(); + } + } + catch (const SQLException&) + { + aErrorInfo = ::cppu::getCaughtException(); + } + + if (aErrorInfo.isValid()) + { + // establishing the connection failed. Show an error window and exit. + OSQLMessageBox aMessageBox(GetFrameWeld(), aErrorInfo); + aMessageBox.run(); + m_xTables->set_sensitive(false); + m_xTablesList->GetWidget().clear(); + + if ( m_pTablesDlg ) + { + m_pTablesDlg->clearPassword(); + m_pTablesDlg->endExecution(); + } + } + else + { + // in addition, we need some infos about the connection used + m_sCatalogSeparator = "."; // (default) + m_bCatalogAtStart = true; // (default) + try + { + Reference< XDatabaseMetaData > xMeta; + if (m_xCurrentConnection.is()) + xMeta = m_xCurrentConnection->getMetaData(); + if (xMeta.is() && xMeta->supportsCatalogsInDataManipulation()) + { + m_sCatalogSeparator = xMeta->getCatalogSeparator(); + m_bCatalogAtStart = xMeta->isCatalogAtStart(); + } + } + catch(Exception&) + { + DBG_UNHANDLED_EXCEPTION("dbaccess"); + } + } + } + + // get the current table filter + const OStringListItem* pTableFilter = _rSet.GetItem<OStringListItem>(DSID_TABLEFILTER); + Sequence< OUString > aTableFilter; + if (pTableFilter) + aTableFilter = pTableFilter->getList(); + + implCompleteTablesCheck( aTableFilter ); + + // expand the first entry by default + std::unique_ptr<weld::TreeIter> xExpand = m_xTablesList->getAllObjectsEntry(); + while (xExpand) + { + m_xTablesList->GetWidget().expand_row(*xExpand); + if (!m_xTablesList->GetWidget().iter_children(*xExpand)) + break; + std::unique_ptr<weld::TreeIter> xSibling(m_xTablesList->GetWidget().make_iterator(xExpand.get())); + if (m_xTablesList->GetWidget().iter_next_sibling(*xSibling)) + xExpand.reset(); + } + + // update the toolbox according the current selection and check state + OGenericAdministrationPage::implInitControls(_rSet, _bSaveValue); + } + + void OTableSubscriptionPage::CheckAll( bool _bCheck ) + { + std::unique_ptr<weld::TreeIter> xEntry(m_xTablesList->GetWidget().make_iterator()); + if (m_xTablesList->GetWidget().get_iter_first(*xEntry)) + { + do + { + m_xTablesList->GetWidget().set_toggle(*xEntry, _bCheck ? TRISTATE_TRUE : TRISTATE_FALSE, 0); + } + while (m_xTablesList->GetWidget().iter_next(*xEntry)); + } + + if (_bCheck) + { + auto xRoot = m_xTablesList->getAllObjectsEntry(); + if (xRoot) + m_xTablesList->checkWildcard(*xRoot); + } + } + + DeactivateRC OTableSubscriptionPage::DeactivatePage(SfxItemSet* _pSet) + { + DeactivateRC nResult = OGenericAdministrationPage::DeactivatePage(_pSet); + + // dispose the connection, we don't need it anymore, so we're not wasting resources + try + { + ::comphelper::disposeComponent(m_xCurrentConnection); + } + catch (RuntimeException&) { } + + return nResult; + } + + IMPL_LINK_NOARG(OTableSubscriptionPage, OnTreeEntryChecked, const row_col&, void) + { + weld::TreeView& rTreeView = m_xTablesList->GetWidget(); + std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator()); + if (rTreeView.get_cursor(xEntry.get())) + m_xTablesList->checkedButton_noBroadcast(*xEntry); + callModifiedHdl(); + } + + Sequence< OUString > OTableSubscriptionPage::collectDetailedSelection() const + { + Sequence< OUString > aTableFilter; + static const char sWildcard[] = "%"; + + std::unique_ptr<weld::TreeIter> xAllObjectsEntry(m_xTablesList->getAllObjectsEntry()); + if (!xAllObjectsEntry) + return aTableFilter; + std::unique_ptr<weld::TreeIter> xEntry(m_xTablesList->GetWidget().make_iterator(xAllObjectsEntry.get())); + if (!m_xTablesList->GetWidget().iter_next(*xEntry)) + xEntry.reset(); + while (xEntry) + { + bool bCatalogWildcard = false; + bool bSchemaWildcard = false; + std::unique_ptr<weld::TreeIter> xSchema; + std::unique_ptr<weld::TreeIter> xCatalog; + + if (m_xTablesList->GetWidget().get_toggle(*xEntry, 0) == TRISTATE_TRUE && !m_xTablesList->GetWidget().iter_has_child(*xEntry)) + { // checked and a leaf, which means it's no catalog, no schema, but a real table + OUStringBuffer sComposedName; + OUString sCatalog; + if (m_xTablesList->GetWidget().get_iter_depth(*xEntry)) + { + xSchema = m_xTablesList->GetWidget().make_iterator(xEntry.get()); + m_xTablesList->GetWidget().iter_parent(*xSchema); + if (xAllObjectsEntry->equal(*xSchema)) + { + // do not want to have the root entry + xSchema.reset(); + } + + if (xSchema) + { // it's a real schema entry, not the "all objects" root + if (m_xTablesList->GetWidget().get_iter_depth(*xSchema)) + { + xCatalog = m_xTablesList->GetWidget().make_iterator(xSchema.get()); + m_xTablesList->GetWidget().iter_parent(*xCatalog); + if (xAllObjectsEntry->equal(*xCatalog)) + { + // do not want to have the root entry + xCatalog.reset(); + } + + if (xCatalog) + { // it's a real catalog entry, not the "all objects" root + bCatalogWildcard = m_xTablesList->isWildcardChecked(*xCatalog); + if (m_bCatalogAtStart) + { + sComposedName.append(m_xTablesList->GetWidget().get_text(*xCatalog)).append(m_sCatalogSeparator); + if (bCatalogWildcard) + sComposedName.append(sWildcard); + } + else + { + if (bCatalogWildcard) + sCatalog = sWildcard; + else + sCatalog.clear(); + sCatalog += m_sCatalogSeparator + m_xTablesList->GetWidget().get_text(*xCatalog) ; + } + } + } + bSchemaWildcard = m_xTablesList->isWildcardChecked(*xSchema); + sComposedName.append(m_xTablesList->GetWidget().get_text(*xSchema)).append("."); + } + + if (bSchemaWildcard) + sComposedName.append(sWildcard); + } + if (!bSchemaWildcard && !bCatalogWildcard) + sComposedName.append(m_xTablesList->GetWidget().get_text(*xEntry)); + + if (!m_bCatalogAtStart && !bCatalogWildcard) + sComposedName.append(sCatalog); + + // need some space + sal_Int32 nOldLen = aTableFilter.getLength(); + aTableFilter.realloc(nOldLen + 1); + // add the new name + aTableFilter[nOldLen] = sComposedName.makeStringAndClear(); + } + + if (bCatalogWildcard) + xEntry = implNextSibling(xCatalog.get()); + else if (bSchemaWildcard) + xEntry = implNextSibling(xSchema.get()); + else + { + if (!m_xTablesList->GetWidget().iter_next(*xEntry)) + xEntry.reset(); + } + } + + return aTableFilter; + } + + std::unique_ptr<weld::TreeIter> OTableSubscriptionPage::implNextSibling(const weld::TreeIter* pEntry) const + { + std::unique_ptr<weld::TreeIter> xReturn; + if (pEntry) + { + xReturn = m_xTablesList->GetWidget().make_iterator(pEntry); + if (!m_xTablesList->GetWidget().iter_next_sibling(*xReturn)) + { + std::unique_ptr<weld::TreeIter> xParent = m_xTablesList->GetWidget().make_iterator(pEntry); + if (m_xTablesList->GetWidget().iter_parent(*xParent)) + xReturn = implNextSibling(xParent.get()); + else + xReturn.reset(); + } + } + return xReturn; + } + + bool OTableSubscriptionPage::FillItemSet( SfxItemSet* _rCoreAttrs ) + { + bool bValid, bReadonly; + getFlags(*_rCoreAttrs, bValid, bReadonly); + + if (!bValid || bReadonly) + // don't store anything if the data we're working with is invalid or readonly + return true; + + // create the output string which contains all the table names + if ( m_xCurrentConnection.is() ) + { // collect the table filter data only if we have a connection - else no tables are displayed at all + Sequence< OUString > aTableFilter; + auto xRoot = m_xTablesList->getAllObjectsEntry(); + if (xRoot && m_xTablesList->isWildcardChecked(*xRoot)) + { + aTableFilter.realloc(1); + aTableFilter[0] = "%"; + } + else + { + aTableFilter = collectDetailedSelection(); + } + _rCoreAttrs->Put( OStringListItem(DSID_TABLEFILTER, aTableFilter) ); + } + + return true; + } + + void OTableSubscriptionPage::fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& /*_rControlList*/) + { + } + + void OTableSubscriptionPage::fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) + { + _rControlList.emplace_back(new ODisableWidgetWrapper<weld::Widget>(m_xTables.get())); + } +} // namespace dbaui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/tablespage.hxx b/dbaccess/source/ui/dlg/tablespage.hxx new file mode 100644 index 000000000..0eb1273d1 --- /dev/null +++ b/dbaccess/source/ui/dlg/tablespage.hxx @@ -0,0 +1,85 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_DBACCESS_SOURCE_UI_DLG_TABLESPAGE_HXX +#define INCLUDED_DBACCESS_SOURCE_UI_DLG_TABLESPAGE_HXX + +#include "adminpages.hxx" +#include <tabletree.hxx> +#include <com/sun/star/sdbc/XConnection.hpp> + +namespace dbaui +{ + + // OTableSubscriptionPage + class OTableSubscriptionDialog; + class OTableSubscriptionPage final + :public OGenericAdministrationPage + { + private: + OUString m_sCatalogSeparator; + bool m_bCatalogAtStart : 1; + + css::uno::Reference< css::sdbc::XConnection > + m_xCurrentConnection; /// valid as long as the page is active + OTableSubscriptionDialog* m_pTablesDlg; + + std::unique_ptr<weld::Widget> m_xTables; + std::unique_ptr<TableTreeListBox> m_xTablesList; + + public: + virtual bool FillItemSet(SfxItemSet* _rCoreAttrs) override; + virtual DeactivateRC DeactivatePage(SfxItemSet* _pSet) override; + + OTableSubscriptionPage(weld::Container* pPage, OTableSubscriptionDialog* pController, const SfxItemSet& _rCoreAttrs); + virtual ~OTableSubscriptionPage() override; + + private: + virtual void fillControls(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override; + virtual void fillWindows(std::vector< std::unique_ptr<ISaveValueWrapper> >& _rControlList) override; + + typedef std::pair<int, int> row_col; + DECL_LINK(OnTreeEntryChecked, const row_col&, void); + + /** check the tables in <member>m_aTablesList</member> according to <arg>_rTables</arg> + */ + void implCheckTables(const css::uno::Sequence< OUString >& _rTables); + + /// returns the next sibling, if not available, the next sibling of the parent, a.s.o. + std::unique_ptr<weld::TreeIter> implNextSibling(const weld::TreeIter* pEntry) const; + + /** return the current selection in <member>m_aTablesList</member> + */ + css::uno::Sequence< OUString > collectDetailedSelection() const; + + /// (un)check all entries + void CheckAll( bool bCheck = true ); + + virtual void implInitControls(const SfxItemSet& _rSet, bool _bSaveValue) override; + + // checks the tables according to the filter given + // in opposite to implCheckTables, this method handles the case of an empty sequence, too ... + void implCompleteTablesCheck( const css::uno::Sequence< OUString >& _rTableFilter ); + }; + +} // namespace dbaui + +#endif // INCLUDED_DBACCESS_SOURCE_UI_DLG_TABLESPAGE_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/textconnectionsettings.cxx b/dbaccess/source/ui/dlg/textconnectionsettings.cxx new file mode 100644 index 000000000..5076b3d32 --- /dev/null +++ b/dbaccess/source/ui/dlg/textconnectionsettings.cxx @@ -0,0 +1,69 @@ +/* -*- 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 <textconnectionsettings.hxx> +#include "TextConnectionHelper.hxx" +#include <dsitems.hxx> +#include <stringconstants.hxx> + +namespace dbaui +{ + // TextConnectionSettingsDialog + TextConnectionSettingsDialog::TextConnectionSettingsDialog(weld::Window* pParent, SfxItemSet& rItems) + : GenericDialogController(pParent, "dbaccess/ui/textconnectionsettings.ui", "TextConnectionSettingsDialog") + , m_rItems(rItems) + , m_xContainer(m_xBuilder->weld_widget("TextPageContainer")) + , m_xOK(m_xBuilder->weld_button("ok")) + , m_xTextConnectionHelper(new OTextConnectionHelper(m_xContainer.get(), TC_HEADER | TC_SEPARATORS | TC_CHARSET)) + { + m_xOK->connect_clicked(LINK(this, TextConnectionSettingsDialog, OnOK)); + } + + TextConnectionSettingsDialog::~TextConnectionSettingsDialog() + { + } + + void TextConnectionSettingsDialog::bindItemStorages( SfxItemSet& _rSet, PropertyValues& _rValues ) + { + _rValues[ PROPERTY_ID_HEADER_LINE ] = std::make_shared<SetItemPropertyStorage>( _rSet, DSID_TEXTFILEHEADER ); + _rValues[ PROPERTY_ID_FIELD_DELIMITER ] = std::make_shared<SetItemPropertyStorage>( _rSet, DSID_FIELDDELIMITER ); + _rValues[ PROPERTY_ID_STRING_DELIMITER ] = std::make_shared<SetItemPropertyStorage>( _rSet, DSID_TEXTDELIMITER ); + _rValues[ PROPERTY_ID_DECIMAL_DELIMITER ] = std::make_shared<SetItemPropertyStorage>( _rSet, DSID_DECIMALDELIMITER ); + _rValues[ PROPERTY_ID_THOUSAND_DELIMITER ] = std::make_shared<SetItemPropertyStorage>( _rSet, DSID_THOUSANDSDELIMITER ); + _rValues[ PROPERTY_ID_ENCODING ] = std::make_shared<SetItemPropertyStorage>( _rSet, DSID_CHARSET ); + } + + short TextConnectionSettingsDialog::run() + { + m_xTextConnectionHelper->implInitControls(m_rItems, true); + return GenericDialogController::run(); + } + + IMPL_LINK_NOARG(TextConnectionSettingsDialog, OnOK, weld::Button&, void) + { + if (m_xTextConnectionHelper->prepareLeave()) + { + m_xTextConnectionHelper->FillItemSet( m_rItems, false/*bUnused*/ ); + m_xDialog->response(RET_OK); + } + } + +} // namespace dbaui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |