diff options
Diffstat (limited to '')
27 files changed, 7257 insertions, 0 deletions
diff --git a/extensions/source/bibliography/bib.component b/extensions/source/bibliography/bib.component new file mode 100644 index 000000000..19841cc9e --- /dev/null +++ b/extensions/source/bibliography/bib.component @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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 . + --> + +<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.extensions.Bibliography" + constructor="extensions_BibliographyLoader_get_implementation"> + <service name="com.sun.star.frame.Bibliography"/> + <service name="com.sun.star.frame.FrameLoader"/> + </implementation> +</component> diff --git a/extensions/source/bibliography/bibbeam.cxx b/extensions/source/bibliography/bibbeam.cxx new file mode 100644 index 000000000..a38c72385 --- /dev/null +++ b/extensions/source/bibliography/bibbeam.cxx @@ -0,0 +1,267 @@ +/* -*- 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 <toolkit/helper/vclunohelper.hxx> +#include <comphelper/processfactory.hxx> +#include <com/sun/star/awt/PosSize.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> + +#include <vcl/taskpanelist.hxx> +#include <tools/debug.hxx> +#include "bibbeam.hxx" +#include "datman.hxx" +#include "bibtools.hxx" + +using namespace ::com::sun::star; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::uno; + + +#define ID_TOOLBAR 1 +#define ID_GRIDWIN 2 + +namespace bib +{ + + void HandleTaskPaneList( vcl::Window* pWindow, bool bAddToList ) + { + vcl::Window* pParent = pWindow->GetParent(); + + DBG_ASSERT( pParent, "-GetTaskPaneList(): everybody here should have a parent!" ); + + SystemWindow* pSysWin = pParent->GetSystemWindow(); + if( pSysWin ) + { + TaskPaneList* pTaskPaneList = pSysWin->GetTaskPaneList(); + if( pTaskPaneList ) + { + if( bAddToList ) + pTaskPaneList->AddWindow( pWindow ); + else + pTaskPaneList->RemoveWindow( pWindow ); + } + } + } + + + class BibGridwin + :public vcl::Window //DockingWindow + { + private: + Reference< awt::XWindow > m_xGridWin; + Reference< awt::XControlModel > m_xGridModel; + Reference< awt::XControl > m_xControl; + Reference< awt::XControlContainer > m_xControlContainer; + Reference< frame::XDispatchProviderInterception> m_xDispatchProviderInterception; + + protected: + + virtual void Resize() override; + + public: + + BibGridwin(vcl::Window* pParent, WinBits nStyle ); + virtual ~BibGridwin() override; + virtual void dispose() override; + + void createGridWin(const Reference< awt::XControlModel > & xDbForm); + void disposeGridWin(); + + const Reference< awt::XControlContainer >& getControlContainer() const { return m_xControlContainer; } + const Reference< frame::XDispatchProviderInterception>& getDispatchProviderInterception() const { return m_xDispatchProviderInterception; } + + virtual void GetFocus() override; + }; + + BibGridwin::BibGridwin( vcl::Window* _pParent, WinBits _nStyle ) : Window( _pParent, _nStyle ) + { + m_xControlContainer = VCLUnoHelper::CreateControlContainer(this); + + AddToTaskPaneList( this ); + } + + BibGridwin::~BibGridwin() + { + disposeOnce(); + } + + void BibGridwin::dispose() + { + RemoveFromTaskPaneList( this ); + + disposeGridWin(); + vcl::Window::dispose(); + } + + void BibGridwin::Resize() + { + if(m_xGridWin.is()) + { + ::Size aSize = GetOutputSizePixel(); + m_xGridWin->setPosSize(0, 0, aSize.Width(),aSize.Height(), awt::PosSize::SIZE); + } + } + + void BibGridwin::createGridWin(const uno::Reference< awt::XControlModel > & xGModel) + { + m_xGridModel = xGModel; + + if( !m_xControlContainer.is()) + return; + + uno::Reference< uno::XComponentContext > xContext = comphelper::getProcessComponentContext(); + + if ( !m_xGridModel.is()) + return; + + uno::Reference< XPropertySet > xPropSet( m_xGridModel, UNO_QUERY ); + + if ( xPropSet.is() && m_xGridModel.is() ) + { + uno::Any aAny = xPropSet->getPropertyValue( "DefaultControl" ); + OUString aControlName; + aAny >>= aControlName; + + m_xControl.set( xContext->getServiceManager()->createInstanceWithContext(aControlName, xContext), UNO_QUERY_THROW ); + m_xControl->setModel( m_xGridModel ); + } + + if ( !m_xControl.is() ) + return; + + // Peer as Child to the FrameWindow + m_xControlContainer->addControl("GridControl", m_xControl); + m_xGridWin.set(m_xControl, UNO_QUERY ); + m_xDispatchProviderInterception.set(m_xControl, UNO_QUERY ); + m_xGridWin->setVisible( true ); + m_xControl->setDesignMode( true ); + // initially switch on the design mode - switch it off _after_ loading the form + + ::Size aSize = GetOutputSizePixel(); + m_xGridWin->setPosSize(0, 0, aSize.Width(),aSize.Height(), awt::PosSize::POSSIZE); + } + + void BibGridwin::disposeGridWin() + { + if ( m_xControl.is() ) + { + Reference< awt::XControl > xDel( m_xControl ); + m_xControl = nullptr; + m_xGridWin = nullptr; + + m_xControlContainer->removeControl( xDel ); + xDel->dispose(); + } + } + + void BibGridwin::GetFocus() + { + if(m_xGridWin.is()) + m_xGridWin->setFocus(); + } + + BibBeamer::BibBeamer( vcl::Window* _pParent, BibDataManager* _pDM ) + :BibSplitWindow( _pParent, WB_3DLOOK | WB_NOSPLITDRAW ) + ,pDatMan( _pDM ) + ,pToolBar( nullptr ) + ,pGridWin( nullptr ) + { + createToolBar(); + createGridWin(); + pDatMan->SetToolbar(pToolBar); + pGridWin->Show(); + connectForm( pDatMan ); + } + + BibBeamer::~BibBeamer() + { + disposeOnce(); + } + + void BibBeamer::dispose() + { + if ( isFormConnected() ) + disconnectForm(); + + if ( pToolBar ) + pDatMan->SetToolbar(nullptr); + + pToolBar.disposeAndClear(); + pGridWin.disposeAndClear(); + BibSplitWindow::dispose(); + } + + void BibBeamer::createToolBar() + { + pToolBar= VclPtr<BibToolBar>::Create(this, LINK( this, BibBeamer, RecalcLayout_Impl )); + ::Size aSize=pToolBar->get_preferred_size(); + InsertItem(ID_TOOLBAR, pToolBar, aSize.Height(), 0, 0, SplitWindowItemFlags::Fixed ); + if ( m_xController.is() ) + pToolBar->SetXController( m_xController ); + } + + void BibBeamer::createGridWin() + { + pGridWin = VclPtr<BibGridwin>::Create(this,0); + + InsertItem(ID_GRIDWIN, pGridWin, 40, 1, 0, SplitWindowItemFlags::RelativeSize ); + + pGridWin->createGridWin( pDatMan->updateGridModel() ); + } + + Reference< awt::XControlContainer > BibBeamer::getControlContainer() + { + Reference< awt::XControlContainer > xReturn; + if ( pGridWin ) + xReturn = pGridWin->getControlContainer(); + return xReturn; + } + + Reference< frame::XDispatchProviderInterception > BibBeamer::getDispatchProviderInterception() const + { + Reference< frame::XDispatchProviderInterception > xReturn; + if ( pGridWin ) + xReturn = pGridWin->getDispatchProviderInterception(); + return xReturn; + } + + void BibBeamer::SetXController(const uno::Reference< frame::XController > & xCtr) + { + m_xController = xCtr; + + if ( pToolBar ) + pToolBar->SetXController( m_xController ); + + } + + void BibBeamer::GetFocus() + { + if( pGridWin ) + pGridWin->GrabFocus(); + } + + IMPL_LINK_NOARG( BibBeamer, RecalcLayout_Impl, void*, void ) + { + tools::Long nHeight = pToolBar->get_preferred_size().Height(); + SetItemSize( ID_TOOLBAR, nHeight ); + } + +} // namespace bib + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/bibliography/bibbeam.hxx b/extensions/source/bibliography/bibbeam.hxx new file mode 100644 index 000000000..4cc32d7da --- /dev/null +++ b/extensions/source/bibliography/bibbeam.hxx @@ -0,0 +1,71 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <com/sun/star/awt/XControlContainer.hpp> +#include <com/sun/star/frame/XDispatchProviderInterception.hpp> +#include "toolbar.hxx" +#include "formcontrolcontainer.hxx" +#include "bibshortcuthandler.hxx" + +class BibDataManager; + + +namespace bib +{ + + + class BibGridwin; + class BibBeamer final + :public BibSplitWindow + ,public FormControlContainer + { + css::uno::Reference< css::frame::XController > m_xController; + + BibDataManager* pDatMan; + VclPtr<BibToolBar> pToolBar; + VclPtr<BibGridwin> pGridWin; + + DECL_LINK( RecalcLayout_Impl, void*, void ); + + void createToolBar(); + void createGridWin(); + + // FormControlContainer ---------- + virtual css::uno::Reference< css::awt::XControlContainer > + getControlContainer() override; + public: + css::uno::Reference< css::frame::XDispatchProviderInterception > + getDispatchProviderInterception() const; + + BibBeamer(vcl::Window* pParent,BibDataManager* pDatMan ); + virtual ~BibBeamer() override; + virtual void dispose() override; + + void SetXController(const css::uno::Reference< css::frame::XController > &); + + virtual void GetFocus() override; + }; + + +} // namespace bib + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/bibliography/bibconfig.cxx b/extensions/source/bibliography/bibconfig.cxx new file mode 100644 index 000000000..14203ae6c --- /dev/null +++ b/extensions/source/bibliography/bibconfig.cxx @@ -0,0 +1,297 @@ +/* -*- 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 <memory> +#include "bibconfig.hxx" +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/sdb/DatabaseContext.hpp> +#include <comphelper/processfactory.hxx> +#include <comphelper/propertyvalue.hxx> +#include <o3tl/any.hxx> + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::sdb; + + +constexpr OUStringLiteral cDataSourceHistory = u"DataSourceHistory"; + +Sequence<OUString> const & BibConfig::GetPropertyNames() +{ + static Sequence<OUString> aNames = + { + "CurrentDataSource/DataSourceName", + "CurrentDataSource/Command", + "CurrentDataSource/CommandType", + "BeamerHeight", + "ViewHeight", + "QueryText", + "QueryField", + "ShowColumnAssignmentWarning" + }; + return aNames; +} + +BibConfig::BibConfig() + : ConfigItem("Office.DataAccess/Bibliography", ConfigItemMode::NONE) + , nTblOrQuery(0) + , nBeamerSize(0) + , nViewSize(0) + , bShowColumnAssignmentWarning(false) +{ + //Names of the default columns + aColumnDefaults[0] = "Identifier"; + aColumnDefaults[1] = "BibliographyType"; + aColumnDefaults[2] = "Author"; + aColumnDefaults[3] = "Title"; + aColumnDefaults[4] = "Year"; + aColumnDefaults[5] = "ISBN"; + aColumnDefaults[6] = "Booktitle"; + aColumnDefaults[7] = "Chapter"; + aColumnDefaults[8] = "Edition"; + aColumnDefaults[9] = "Editor"; + aColumnDefaults[10] = "Howpublished"; + aColumnDefaults[11] = "Institution"; + aColumnDefaults[12] = "Journal"; + aColumnDefaults[13] = "Month"; + aColumnDefaults[14] = "Note"; + aColumnDefaults[15] = "Annote"; + aColumnDefaults[16] = "Number"; + aColumnDefaults[17] = "Organizations"; + aColumnDefaults[18] = "Pages"; + aColumnDefaults[19] = "Publisher"; + aColumnDefaults[20] = "Address"; + aColumnDefaults[21] = "School"; + aColumnDefaults[22] = "Series"; + aColumnDefaults[23] = "ReportType"; + aColumnDefaults[24] = "Volume"; + aColumnDefaults[25] = "URL"; + aColumnDefaults[26] = "Custom1"; + aColumnDefaults[27] = "Custom2"; + aColumnDefaults[28] = "Custom3"; + aColumnDefaults[29] = "Custom4"; + aColumnDefaults[30] = "Custom5"; + aColumnDefaults[31] = "LocalURL"; + + + const Sequence< OUString > aPropertyNames = GetPropertyNames(); + const Sequence<Any> aPropertyValues = GetProperties( aPropertyNames ); + const Any* pValues = aPropertyValues.getConstArray(); + if(aPropertyValues.getLength() == aPropertyNames.getLength()) + { + for(int nProp = 0; nProp < aPropertyNames.getLength(); nProp++) + { + if(pValues[nProp].hasValue()) + { + switch(nProp) + { + case 0: pValues[nProp] >>= sDataSource; break; + case 1: pValues[nProp] >>= sTableOrQuery; break; + case 2: pValues[nProp] >>= nTblOrQuery; break; + case 3: pValues[nProp] >>= nBeamerSize; break; + case 4: pValues[nProp] >>= nViewSize ; break; + case 5: pValues[nProp] >>= sQueryText ; break; + case 6: pValues[nProp] >>= sQueryField; break; + case 7: + bShowColumnAssignmentWarning = *o3tl::doAccess<bool>(pValues[nProp]); + break; + } + } + } + } + const Sequence< OUString > aNodeNames = GetNodeNames(cDataSourceHistory); + for(OUString const & nodeName : aNodeNames) + { + Sequence<OUString> aHistoryNames(3); + OUString* pHistoryNames = aHistoryNames.getArray(); + + OUString sPrefix = OUString::Concat(cDataSourceHistory) + "/" + nodeName + "/"; + pHistoryNames[0] = sPrefix + "DataSourceName"; + pHistoryNames[1] = sPrefix + "Command"; + pHistoryNames[2] = sPrefix + "CommandType"; + + Sequence<Any> aHistoryValues = GetProperties( aHistoryNames ); + const Any* pHistoryValues = aHistoryValues.getConstArray(); + + if(aHistoryValues.getLength() == aHistoryNames.getLength()) + { + Mapping* pMapping = new Mapping; + pHistoryValues[0] >>= pMapping->sURL; + pHistoryValues[1] >>= pMapping->sTableName; + pHistoryValues[2] >>= pMapping->nCommandType; + //field assignment is contained in another set + sPrefix += "Fields"; + const Sequence< OUString > aAssignmentNodeNames = GetNodeNames(sPrefix); + Sequence<OUString> aAssignmentPropertyNames(aAssignmentNodeNames.getLength() * 2); + OUString* pAssignmentPropertyNames = aAssignmentPropertyNames.getArray(); + sal_Int16 nFieldIdx = 0; + for(OUString const & assignName : aAssignmentNodeNames) + { + OUString sSubPrefix = sPrefix + "/" + assignName; + pAssignmentPropertyNames[nFieldIdx] = sSubPrefix; + pAssignmentPropertyNames[nFieldIdx++] += "/ProgrammaticFieldName"; + pAssignmentPropertyNames[nFieldIdx] = sSubPrefix; + pAssignmentPropertyNames[nFieldIdx++] += "/AssignedFieldName"; + } + Sequence<Any> aAssignmentValues = GetProperties(aAssignmentPropertyNames); + const Any* pAssignmentValues = aAssignmentValues.getConstArray(); + OUString sTempLogical; + OUString sTempReal; + sal_Int16 nSetMapping = 0; + nFieldIdx = 0; + for(sal_Int32 nFieldVal = 0; nFieldVal < aAssignmentValues.getLength() / 2; nFieldVal++) + { + pAssignmentValues[nFieldIdx++] >>= sTempLogical; + pAssignmentValues[nFieldIdx++] >>= sTempReal; + if(!(sTempLogical.isEmpty() || sTempReal.isEmpty())) + { + pMapping->aColumnPairs[nSetMapping].sLogicalColumnName = sTempLogical; + pMapping->aColumnPairs[nSetMapping++].sRealColumnName = sTempReal; + } + } + mvMappings.push_back(std::unique_ptr<Mapping>(pMapping)); + } + } +} + +BibConfig::~BibConfig() +{ + assert(!IsModified()); // should have been committed +} + +BibDBDescriptor BibConfig::GetBibliographyURL() +{ + BibDBDescriptor aRet; + aRet.sDataSource = sDataSource; + aRet.sTableOrQuery = sTableOrQuery; + aRet.nCommandType = nTblOrQuery; + return aRet; +}; + +void BibConfig::SetBibliographyURL(const BibDBDescriptor& rDesc) +{ + sDataSource = rDesc.sDataSource; + sTableOrQuery = rDesc.sTableOrQuery; + nTblOrQuery = rDesc.nCommandType; + SetModified(); +}; + +void BibConfig::Notify( const css::uno::Sequence<OUString>& ) +{ +} + +void BibConfig::ImplCommit() +{ + PutProperties( + GetPropertyNames(), + {css::uno::Any(sDataSource), css::uno::Any(sTableOrQuery), + css::uno::Any(nTblOrQuery), css::uno::Any(nBeamerSize), + css::uno::Any(nViewSize), css::uno::Any(sQueryText), + css::uno::Any(sQueryField), + css::uno::Any(bShowColumnAssignmentWarning)}); + ClearNodeSet(cDataSourceHistory); + Sequence< PropertyValue > aNodeValues(mvMappings.size() * 3); + PropertyValue* pNodeValues = aNodeValues.getArray(); + + sal_Int32 nIndex = 0; + for(sal_Int32 i = 0; i < static_cast<sal_Int32>(mvMappings.size()); i++) + { + const Mapping* pMapping = mvMappings[i].get(); + OUString sPrefix = OUString::Concat(cDataSourceHistory) + "/_" + OUString::number(i) + "/"; + pNodeValues[nIndex].Name = sPrefix + "DataSourceName"; + pNodeValues[nIndex++].Value <<= pMapping->sURL; + pNodeValues[nIndex].Name = sPrefix + "Command"; + pNodeValues[nIndex++].Value <<= pMapping->sTableName; + pNodeValues[nIndex].Name = sPrefix + "CommandType"; + pNodeValues[nIndex++].Value <<= pMapping->nCommandType; + SetSetProperties(cDataSourceHistory, aNodeValues); + + sPrefix += "Fields"; + sal_Int32 nFieldAssignment = 0; + OUString sFieldName = "/ProgrammaticFieldName"; + OUString sDatabaseFieldName = "/AssignedFieldName"; + ClearNodeSet( sPrefix ); + + while(nFieldAssignment < COLUMN_COUNT && + !pMapping->aColumnPairs[nFieldAssignment].sLogicalColumnName.isEmpty()) + { + OUString sSubPrefix = sPrefix + "/_" + OUString::number(nFieldAssignment); + Sequence< PropertyValue > aAssignmentValues + { + comphelper::makePropertyValue(sSubPrefix + sFieldName, pMapping->aColumnPairs[nFieldAssignment].sLogicalColumnName), + comphelper::makePropertyValue(sSubPrefix + sDatabaseFieldName, pMapping->aColumnPairs[nFieldAssignment].sRealColumnName) + }; + SetSetProperties( sPrefix, aAssignmentValues ); + nFieldAssignment++; + } + } +} + +const Mapping* BibConfig::GetMapping(const BibDBDescriptor& rDesc) const +{ + for(std::unique_ptr<Mapping> const & i : mvMappings) + { + Mapping& rMapping = *i; + bool bURLEqual = rDesc.sDataSource == rMapping.sURL; + if(rDesc.sTableOrQuery == rMapping.sTableName && bURLEqual) + return &rMapping; + } + return nullptr; +} + +void BibConfig::SetMapping(const BibDBDescriptor& rDesc, const Mapping* pSetMapping) +{ + for(size_t i = 0; i < mvMappings.size(); i++) + { + Mapping& rMapping = *mvMappings[i]; + bool bURLEqual = rDesc.sDataSource == rMapping.sURL; + if(rDesc.sTableOrQuery == rMapping.sTableName && bURLEqual) + { + mvMappings.erase(mvMappings.begin()+i); + break; + } + } + mvMappings.push_back(std::make_unique<Mapping>(*pSetMapping)); + SetModified(); +} + +DBChangeDialogConfig_Impl::DBChangeDialogConfig_Impl() +{ +} + +DBChangeDialogConfig_Impl::~DBChangeDialogConfig_Impl() +{ +} + +const Sequence<OUString>& DBChangeDialogConfig_Impl::GetDataSourceNames() +{ + if(!aSourceNames.hasElements()) + { + Reference< XComponentContext > xContext( ::comphelper::getProcessComponentContext() ); + Reference<XDatabaseContext> xDBContext = DatabaseContext::create(xContext); + aSourceNames = xDBContext->getElementNames(); + } + return aSourceNames; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/bibliography/bibconfig.hxx b/extensions/source/bibliography/bibconfig.hxx new file mode 100644 index 000000000..0d81491ff --- /dev/null +++ b/extensions/source/bibliography/bibconfig.hxx @@ -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 . + */ + +#pragma once + +#include <unotools/configitem.hxx> +#include <tools/long.hxx> +#include <vector> +#include <memory> + +struct Mapping; +typedef std::vector<std::unique_ptr<Mapping> > MappingArray; + + +#define COLUMN_COUNT 32 +#define IDENTIFIER_POS 0 +#define AUTHORITYTYPE_POS 1 +#define AUTHOR_POS 2 +#define TITLE_POS 3 +#define YEAR_POS 4 +#define ISBN_POS 5 +#define BOOKTITLE_POS 6 +#define CHAPTER_POS 7 +#define EDITION_POS 8 +#define EDITOR_POS 9 +#define HOWPUBLISHED_POS 10 +#define INSTITUTION_POS 11 +#define JOURNAL_POS 12 +#define MONTH_POS 13 +#define NOTE_POS 14 +#define ANNOTE_POS 15 +#define NUMBER_POS 16 +#define ORGANIZATIONS_POS 17 +#define PAGES_POS 18 +#define PUBLISHER_POS 19 +#define ADDRESS_POS 20 +#define SCHOOL_POS 21 +#define SERIES_POS 22 +#define REPORTTYPE_POS 23 +#define VOLUME_POS 24 +#define URL_POS 25 +#define CUSTOM1_POS 26 +#define CUSTOM2_POS 27 +#define CUSTOM3_POS 28 +#define CUSTOM4_POS 29 +#define CUSTOM5_POS 30 +#define LOCAL_URL_POS 31 + +struct StringPair +{ + OUString sRealColumnName; + OUString sLogicalColumnName; +}; + +struct Mapping +{ + OUString sTableName; + OUString sURL; + sal_Int16 nCommandType; + StringPair aColumnPairs[COLUMN_COUNT]; + + Mapping() : + nCommandType(0){} +}; + +struct BibDBDescriptor +{ + OUString sDataSource; + OUString sTableOrQuery; + sal_Int32 nCommandType; +}; + + +class BibConfig : public utl::ConfigItem +{ + OUString sDataSource; + OUString sTableOrQuery; + sal_Int32 nTblOrQuery; + + OUString sQueryField; + OUString sQueryText; + MappingArray mvMappings; + tools::Long nBeamerSize; + tools::Long nViewSize; + bool bShowColumnAssignmentWarning; + + OUString aColumnDefaults[COLUMN_COUNT]; + + static css::uno::Sequence<OUString> const & GetPropertyNames(); + + virtual void ImplCommit() override; + +public: + BibConfig(); + virtual ~BibConfig() override; + + virtual void Notify( const css::uno::Sequence<OUString>& aPropertyNames) override; + + BibDBDescriptor GetBibliographyURL(); + void SetBibliographyURL(const BibDBDescriptor& rDesc); + + const Mapping* GetMapping(const BibDBDescriptor& rDesc) const; + void SetMapping(const BibDBDescriptor& rDesc, const Mapping* pMapping); + + const OUString& GetDefColumnName(sal_uInt16 nIndex) const + {return aColumnDefaults[nIndex];} + + + void setBeamerSize(tools::Long nSize) {SetModified(); nBeamerSize = nSize;} + tools::Long getBeamerSize()const {return nBeamerSize;} + void setViewSize(tools::Long nSize) {SetModified(); nViewSize = nSize;} + tools::Long getViewSize() const {return nViewSize;} + + const OUString& getQueryField() const {return sQueryField;} + void setQueryField(const OUString& rSet) {SetModified(); sQueryField = rSet;} + + const OUString& getQueryText() const {return sQueryText;} + void setQueryText(const OUString& rSet) {SetModified(); sQueryText = rSet;} + + bool IsShowColumnAssignmentWarning() const + { return bShowColumnAssignmentWarning;} + void SetShowColumnAssignmentWarning(bool bSet) + { bShowColumnAssignmentWarning = bSet;} +}; + +class DBChangeDialogConfig_Impl +{ + css::uno::Sequence<OUString> aSourceNames; +public: + DBChangeDialogConfig_Impl(); + ~DBChangeDialogConfig_Impl(); + + const css::uno::Sequence<OUString>& GetDataSourceNames(); + +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/bibliography/bibcont.cxx b/extensions/source/bibliography/bibcont.cxx new file mode 100644 index 000000000..7c24b0fb3 --- /dev/null +++ b/extensions/source/bibliography/bibcont.cxx @@ -0,0 +1,241 @@ +/* -*- 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 <vcl/event.hxx> +#include "bibconfig.hxx" + + +#include "bibcont.hxx" + + +BibShortCutHandler::~BibShortCutHandler() +{ +} + +bool BibShortCutHandler::HandleShortCutKey( const KeyEvent& ) +{ + return false; +} + + +BibWindow::BibWindow( vcl::Window* pParent, WinBits nStyle ) : Window( pParent, nStyle ), BibShortCutHandler( this ) +{ +} + +BibWindow::~BibWindow() +{ +} + + +BibSplitWindow::BibSplitWindow( vcl::Window* pParent, WinBits nStyle ) : SplitWindow( pParent, nStyle ), BibShortCutHandler( this ) +{ +} + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +//split window size is a percent value +#define WIN_MIN_HEIGHT 10 +#define WIN_STEP_SIZE 5 + +BibWindowContainer::BibWindowContainer( vcl::Window* pParent, BibShortCutHandler* pChildWin ) : + BibWindow( pParent, WB_3DLOOK ), + pChild( pChildWin ) +{ + if(pChild!=nullptr) + { + vcl::Window* pChildWindow = GetChild(); + pChildWindow->SetParent(this); + pChildWindow->Show(); + pChildWindow->SetPosPixel(Point(0,0)); + } +} + +BibWindowContainer::~BibWindowContainer() +{ + disposeOnce(); +} + +void BibWindowContainer::dispose() +{ + if( pChild ) + { + VclPtr<vcl::Window> pDel = GetChild(); + pChild = nullptr; // prevents GetFocus for child while deleting! + pDel.disposeAndClear(); + } + vcl::Window::dispose(); +} + +void BibWindowContainer::Resize() +{ + if( pChild ) + GetChild()->SetSizePixel( GetOutputSizePixel() ); +} + +void BibWindowContainer::GetFocus() +{ + if( pChild ) + GetChild()->GrabFocus(); +} + +bool BibWindowContainer::HandleShortCutKey( const KeyEvent& rKeyEvent ) +{ + return pChild && pChild->HandleShortCutKey( rKeyEvent ); +} + + +BibBookContainer::BibBookContainer(vcl::Window* pParent): + BibSplitWindow(pParent,WB_3DLOOK), + pTopWin(nullptr), + pBottomWin(nullptr), + aIdle("extensions BibBookContainer Split Idle") +{ + pBibMod = OpenBibModul(); + aIdle.SetInvokeHandler(LINK( this, BibBookContainer, SplitHdl)); + aIdle.SetPriority(TaskPriority::LOWEST); +} + +BibBookContainer::~BibBookContainer() +{ + disposeOnce(); +} + +void BibBookContainer::dispose() +{ + if( pTopWin ) + { + VclPtr<vcl::Window> pDel = pTopWin; + pTopWin = nullptr; // prevents GetFocus for child while deleting! + pDel.disposeAndClear(); + } + + if( pBottomWin ) + { + VclPtr<vcl::Window> pDel = pBottomWin; + pBottomWin = nullptr; // prevents GetFocus for child while deleting! + pDel.disposeAndClear(); + } + + CloseBibModul( pBibMod ); + pTopWin.clear(); + pBottomWin.clear(); + BibSplitWindow::dispose(); +} + +void BibBookContainer::Split() +{ + aIdle.Start(); +} +IMPL_LINK_NOARG( BibBookContainer, SplitHdl, Timer*, void) +{ + tools::Long nSize= GetItemSize( TOP_WINDOW); + BibConfig* pConfig = BibModul::GetConfig(); + pConfig->setBeamerSize(nSize); + nSize = GetItemSize( BOTTOM_WINDOW); + pConfig->setViewSize(nSize); +} + +void BibBookContainer::createTopFrame( BibShortCutHandler* pWin ) +{ + if(pTopWin) + { + RemoveItem(TOP_WINDOW); + pTopWin.disposeAndClear(); + } + pTopWin=VclPtr<BibWindowContainer>::Create(this,pWin); + pTopWin->Show(); + BibConfig* pConfig = BibModul::GetConfig(); + tools::Long nSize = pConfig->getBeamerSize(); + InsertItem(TOP_WINDOW, pTopWin, nSize, 1, 0, SplitWindowItemFlags::PercentSize ); + +} + +void BibBookContainer::createBottomFrame( BibShortCutHandler* pWin ) +{ + if(pBottomWin) + { + RemoveItem(BOTTOM_WINDOW); + pBottomWin.disposeAndClear(); + } + + pBottomWin=VclPtr<BibWindowContainer>::Create(this,pWin); + + BibConfig* pConfig = BibModul::GetConfig(); + tools::Long nSize = pConfig->getViewSize(); + InsertItem(BOTTOM_WINDOW, pBottomWin, nSize, 1, 0, SplitWindowItemFlags::PercentSize ); + +} + +void BibBookContainer::GetFocus() +{ + if( pBottomWin ) + pBottomWin->GrabFocus(); +} + +bool BibBookContainer::PreNotify( NotifyEvent& rNEvt ) +{ + bool bHandled = false; + if( MouseNotifyEvent::KEYINPUT == rNEvt.GetType() ) + { + const KeyEvent* pKEvt = rNEvt.GetKeyEvent(); + const vcl::KeyCode aKeyCode = pKEvt->GetKeyCode(); + sal_uInt16 nKey = aKeyCode.GetCode(); + const sal_uInt16 nModifier = aKeyCode.GetModifier(); + + if( KEY_MOD2 == nModifier ) + { + if( KEY_UP == nKey || KEY_DOWN == nKey ) + { + if(pTopWin && pBottomWin) + { + sal_uInt16 nFirstWinId = KEY_UP == nKey ? TOP_WINDOW : BOTTOM_WINDOW; + sal_uInt16 nSecondWinId = KEY_UP == nKey ? BOTTOM_WINDOW : TOP_WINDOW; + tools::Long nHeight = GetItemSize( nFirstWinId ); + nHeight -= WIN_STEP_SIZE; + if(nHeight < WIN_MIN_HEIGHT) + nHeight = WIN_MIN_HEIGHT; + SetItemSize( nFirstWinId, nHeight ); + SetItemSize( nSecondWinId, 100 - nHeight ); + } + bHandled = true; + } + else if( pKEvt->GetCharCode() && HandleShortCutKey( *pKEvt ) ) + bHandled = true; + } + } + + return bHandled; +} + +bool BibBookContainer::HandleShortCutKey( const KeyEvent& rKeyEvent ) +{ + bool bRet = false; + + if( pTopWin ) + bRet = pTopWin->HandleShortCutKey( rKeyEvent ); + + if( !bRet && pBottomWin ) + bRet = pBottomWin->HandleShortCutKey( rKeyEvent ); + + return bRet; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/bibliography/bibcont.hxx b/extensions/source/bibliography/bibcont.hxx new file mode 100644 index 000000000..d90952ac3 --- /dev/null +++ b/extensions/source/bibliography/bibcont.hxx @@ -0,0 +1,93 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <vcl/timer.hxx> +#include <vcl/idle.hxx> +#include "bibshortcuthandler.hxx" + +#include "bibmod.hxx" + +#define TOP_WINDOW 1 +#define BOTTOM_WINDOW 2 + +class BibWindowContainer : public BibWindow //Window +{ + private: + // !BibShortCutHandler is also always a Window! + BibShortCutHandler* pChild; + + protected: + virtual void Resize() override; + + public: + BibWindowContainer( vcl::Window* pParent, BibShortCutHandler* pChild); + virtual ~BibWindowContainer() override; + virtual void dispose() override; + + inline vcl::Window* GetChild(); + + virtual void GetFocus() override; + + virtual bool HandleShortCutKey( const KeyEvent& rKeyEvent ) override; // returns true, if key was handled + + using Window::GetChild; +}; + +inline vcl::Window* BibWindowContainer::GetChild() +{ + return pChild ? pChild->GetWindow() : nullptr; +} + + +class BibBookContainer: public BibSplitWindow +{ + private: + + VclPtr<BibWindowContainer> pTopWin; + VclPtr<BibWindowContainer> pBottomWin; + HdlBibModul pBibMod; + Idle aIdle; + + DECL_LINK( SplitHdl, Timer*, void ); + + protected: + + virtual void Split() override; + + virtual bool PreNotify( NotifyEvent& rNEvt ) override; + + public: + + explicit BibBookContainer(vcl::Window* pParent ); + virtual ~BibBookContainer() override; + virtual void dispose() override; + + // !BibShortCutHandler is also always a Window! + void createTopFrame( BibShortCutHandler* pWin ); + + void createBottomFrame( BibShortCutHandler* pWin ); + + virtual void GetFocus() override; + + virtual bool HandleShortCutKey( const KeyEvent& rKeyEvent ) override; // returns true, if key was handled +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/bibliography/bibload.cxx b/extensions/source/bibliography/bibload.cxx new file mode 100644 index 000000000..82c08e007 --- /dev/null +++ b/extensions/source/bibliography/bibload.cxx @@ -0,0 +1,609 @@ +/* -*- 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 <tools/debug.hxx> +#include <tools/diagnose_ex.h> +#include <cppuhelper/supportsservice.hxx> +#include <svl/itemprop.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <comphelper/processfactory.hxx> +#include <com/sun/star/sdbc/ResultSetType.hpp> +#include <com/sun/star/sdbc/ResultSetConcurrency.hpp> +#include <com/sun/star/sdbc/SQLException.hpp> +#include <com/sun/star/sdb/XColumn.hpp> +#include <com/sun/star/sdbcx/XColumnsSupplier.hpp> +#include <com/sun/star/sdbc/XRowSet.hpp> +#include <com/sun/star/frame/XFrameLoader.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/text/BibliographyDataField.hpp> +#include <com/sun/star/form/XLoadable.hpp> +#include <com/sun/star/frame/XLayoutManager.hpp> +#include <vcl/window.hxx> +#include <vcl/svapp.hxx> + +#include "bibresid.hxx" +#include <strings.hrc> +#include "bibcont.hxx" +#include "bibbeam.hxx" +#include "bibmod.hxx" +#include "bibview.hxx" +#include "framectr.hxx" +#include "datman.hxx" +#include "bibconfig.hxx" +#include <cppuhelper/implbase.hxx> +#include <rtl/ref.hxx> +#include <o3tl/string_view.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::frame; + +namespace { + +class BibliographyLoader : public cppu::WeakImplHelper + < XServiceInfo, XNameAccess, XPropertySet, XFrameLoader > +{ + HdlBibModul m_pBibMod; + rtl::Reference<BibDataManager> m_xDatMan; + Reference< XNameAccess > m_xColumns; + Reference< XResultSet > m_xCursor; + +private: + + void loadView(const Reference< XFrame > & aFrame, + const Reference< XLoadEventListener > & aListener); + + BibDataManager* GetDataManager()const; + Reference< XNameAccess > const & GetDataColumns() const; + Reference< XResultSet > const & GetDataCursor() const; + Reference< sdb::XColumn > GetIdentifierColumn() const; + +public: + BibliographyLoader(); + virtual ~BibliographyLoader() override; + + // XServiceInfo + OUString SAL_CALL getImplementationName() override; + sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override; + Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + + //XNameAccess + virtual Any SAL_CALL getByName(const OUString& aName) override; + virtual Sequence< OUString > SAL_CALL getElementNames() override; + virtual sal_Bool SAL_CALL hasByName(const OUString& aName) override; + + //XElementAccess + virtual Type SAL_CALL getElementType() override; + virtual sal_Bool SAL_CALL hasElements() override; + + //XPropertySet + virtual Reference< XPropertySetInfo > SAL_CALL getPropertySetInfo() override; + virtual void SAL_CALL setPropertyValue(const OUString& PropertyName, const Any& aValue) override; + virtual Any SAL_CALL getPropertyValue(const OUString& PropertyName) override; + virtual void SAL_CALL addPropertyChangeListener(const OUString& PropertyName, const Reference< XPropertyChangeListener > & aListener) override; + virtual void SAL_CALL removePropertyChangeListener(const OUString& PropertyName, const Reference< XPropertyChangeListener > & aListener) override; + virtual void SAL_CALL addVetoableChangeListener(const OUString& PropertyName, const Reference< XVetoableChangeListener > & aListener) override; + virtual void SAL_CALL removeVetoableChangeListener(const OUString& PropertyName, const Reference< XVetoableChangeListener > & aListener) override; + + // XLoader + virtual void SAL_CALL load(const Reference< XFrame > & aFrame, const OUString& aURL, + const Sequence< PropertyValue >& aArgs, + const Reference< XLoadEventListener > & aListener) override; + virtual void SAL_CALL cancel() override; +}; + +} + +BibliographyLoader::BibliographyLoader() : + m_pBibMod(nullptr) +{ +} + +BibliographyLoader::~BibliographyLoader() +{ + Reference< lang::XComponent > xComp(m_xCursor, UNO_QUERY); + if (xComp.is()) + xComp->dispose(); + if(m_pBibMod) + CloseBibModul(m_pBibMod); +} + + +// XServiceInfo +OUString BibliographyLoader::getImplementationName() +{ + return "com.sun.star.extensions.Bibliography"; +} + +// XServiceInfo +sal_Bool BibliographyLoader::supportsService(const OUString& ServiceName) +{ + return cppu::supportsService(this, ServiceName); +} + +// XServiceInfo +Sequence< OUString > BibliographyLoader::getSupportedServiceNames() +{ + return { "com.sun.star.frame.FrameLoader", "com.sun.star.frame.Bibliography" }; +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +extensions_BibliographyLoader_get_implementation( + css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const&) +{ + return cppu::acquire(new BibliographyLoader()); +} + +void BibliographyLoader::cancel() +{ + //! + //! +} + +void BibliographyLoader::load(const Reference< XFrame > & rFrame, const OUString& rURL, + const Sequence< PropertyValue >& /*rArgs*/, + const Reference< XLoadEventListener > & rListener) +{ + + SolarMutexGuard aGuard; + + m_pBibMod = OpenBibModul(); + + std::u16string_view aPartName = o3tl::getToken(rURL, 1, '/' ); + Reference<XPropertySet> xPrSet(rFrame, UNO_QUERY); + if(xPrSet.is()) + { + Any aTitle; + aTitle <<= BibResId(RID_BIB_STR_FRAME_TITLE); + xPrSet->setPropertyValue("Title", aTitle); + } + if(aPartName == u"View" || aPartName == u"View1") + { + loadView(rFrame, rListener); + } +} + + +void BibliographyLoader::loadView(const Reference< XFrame > & rFrame, + const Reference< XLoadEventListener > & rListener) +{ + SolarMutexGuard aGuard; + //! + if(!m_pBibMod) + m_pBibMod = OpenBibModul(); + + m_xDatMan = BibModul::createDataManager(); + BibDBDescriptor aBibDesc = BibModul::GetConfig()->GetBibliographyURL(); + + if(aBibDesc.sDataSource.isEmpty()) + { + DBChangeDialogConfig_Impl aConfig; + const Sequence<OUString> aSources = aConfig.GetDataSourceNames(); + if(aSources.hasElements()) + aBibDesc.sDataSource = aSources.getConstArray()[0]; + } + + m_xDatMan->createDatabaseForm( aBibDesc ); + + Reference<awt::XWindow> aWindow = rFrame->getContainerWindow(); + + VclPtr<vcl::Window> pParent = VCLUnoHelper::GetWindow( aWindow ); + + VclPtrInstance<BibBookContainer> pMyWindow( pParent ); + pMyWindow->Show(); + + VclPtrInstance< ::bib::BibView> pView( pMyWindow, m_xDatMan.get(), WB_VSCROLL | WB_HSCROLL | WB_3DLOOK ); + pView->Show(); + m_xDatMan->SetView( pView ); + + VclPtrInstance< ::bib::BibBeamer> pBeamer( pMyWindow, m_xDatMan.get() ); + pBeamer->Show(); + pMyWindow->createTopFrame(pBeamer); + + pMyWindow->createBottomFrame(pView); + + Reference< awt::XWindow > xWin ( pMyWindow->GetComponentInterface(), UNO_QUERY ); + + Reference< XController > xCtrRef( new BibFrameController_Impl( xWin, m_xDatMan.get() ) ); + + xCtrRef->attachFrame(rFrame); + rFrame->setComponent( xWin, xCtrRef); + pBeamer->SetXController(xCtrRef); + + if (aWindow) + { + // not earlier because SetFocus() is triggered in setVisible() + aWindow->setVisible(true); + } + + Reference<XLoadable>(m_xDatMan)->load(); + m_xDatMan->RegisterInterceptor(pBeamer); + + if ( rListener.is() ) + rListener->loadFinished( this ); + + // attach menu bar + Reference< XPropertySet > xPropSet( rFrame, UNO_QUERY ); + Reference< css::frame::XLayoutManager > xLayoutManager; + if ( xPropSet.is() ) + { + try + { + Any a = xPropSet->getPropertyValue("LayoutManager"); + a >>= xLayoutManager; + } + catch ( const uno::Exception& ) + { + } + } + + if ( xLayoutManager.is() ) + xLayoutManager->createElement( "private:resource/menubar/menubar" ); +} + +BibDataManager* BibliographyLoader::GetDataManager()const +{ + if(!m_xDatMan.is()) + { + if(!m_pBibMod) + const_cast< BibliographyLoader* >( this )->m_pBibMod = OpenBibModul(); + const_cast< BibliographyLoader* >( this )->m_xDatMan = BibModul::createDataManager(); + } + return m_xDatMan.get(); +} + +Reference< XNameAccess > const & BibliographyLoader::GetDataColumns() const +{ + if (!m_xColumns.is()) + { + Reference< XMultiServiceFactory > xMgr = comphelper::getProcessServiceFactory(); + Reference< XRowSet > xRowSet(xMgr->createInstance("com.sun.star.sdb.RowSet"), UNO_QUERY); + Reference< XPropertySet > xResultSetProps(xRowSet, UNO_QUERY); + DBG_ASSERT(xResultSetProps.is() , "BibliographyLoader::GetDataCursor : invalid row set (no XResultSet or no XPropertySet) !"); + + BibDBDescriptor aBibDesc = BibModul::GetConfig()->GetBibliographyURL(); + + Any aBibUrlAny; aBibUrlAny <<= aBibDesc.sDataSource; + xResultSetProps->setPropertyValue("DataSourceName", aBibUrlAny); + Any aCommandType; aCommandType <<= aBibDesc.nCommandType; + xResultSetProps->setPropertyValue("CommandType", aCommandType); + Any aTableName; aTableName <<= aBibDesc.sTableOrQuery; + xResultSetProps->setPropertyValue("Command", aTableName); + Any aResultSetType; aResultSetType <<= sal_Int32(ResultSetType::SCROLL_INSENSITIVE); + xResultSetProps->setPropertyValue("ResultSetType", aResultSetType); + Any aResultSetCurrency; aResultSetCurrency <<= sal_Int32(ResultSetConcurrency::UPDATABLE); + xResultSetProps->setPropertyValue("ResultSetConcurrency", aResultSetCurrency); + + bool bSuccess = false; + try + { + xRowSet->execute(); + bSuccess = true; + } + catch(const SQLException&) + { + DBG_UNHANDLED_EXCEPTION("extensions.biblio"); + } + catch(const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("extensions.biblio"); + bSuccess = false; + } + + if (!bSuccess) + { + Reference< XComponent > xSetComp(xRowSet, UNO_QUERY); + if (xSetComp.is()) + xSetComp->dispose(); + xRowSet = nullptr; + } + else + const_cast<BibliographyLoader*>(this)->m_xCursor = xRowSet.get(); + + Reference< sdbcx::XColumnsSupplier > xSupplyCols(m_xCursor, UNO_QUERY); + if (xSupplyCols.is()) + const_cast<BibliographyLoader*>(this)->m_xColumns = xSupplyCols->getColumns(); + } + + return m_xColumns; +} + +Reference< sdb::XColumn > BibliographyLoader::GetIdentifierColumn() const +{ + BibDataManager* pDatMan = GetDataManager(); + Reference< XNameAccess > xColumns = GetDataColumns(); + OUString sIdentifierColumnName = pDatMan->GetIdentifierMapping(); + + Reference< sdb::XColumn > xReturn; + if (xColumns.is() && xColumns->hasByName(sIdentifierColumnName)) + { + xReturn.set(xColumns->getByName(sIdentifierColumnName), UNO_QUERY); + } + return xReturn; +} + +Reference< XResultSet > const & BibliographyLoader::GetDataCursor() const +{ + if (!m_xCursor.is()) + GetDataColumns(); + if (m_xCursor.is()) + m_xCursor->first(); + return m_xCursor; +} + +static OUString lcl_AddProperty(const Reference< XNameAccess >& xColumns, + const Mapping* pMapping, const OUString& rColumnName) +{ + OUString sColumnName(rColumnName); + if(pMapping) + { + for(const auto & aColumnPair : pMapping->aColumnPairs) + { + if(aColumnPair.sLogicalColumnName == rColumnName) + { + sColumnName = aColumnPair.sRealColumnName; + break; + } + } + } + OUString uColumnName(sColumnName); + OUString uRet; + Reference< sdb::XColumn > xCol; + if (xColumns->hasByName(uColumnName)) + xCol.set(xColumns->getByName(uColumnName), UNO_QUERY); + if (xCol.is()) + uRet = xCol->getString(); + return uRet; +} + +Any BibliographyLoader::getByName(const OUString& rName) +{ + Any aRet; + try + { + BibDataManager* pDatMan = GetDataManager(); + Reference< XResultSet > xCursor = GetDataCursor(); + Reference< sdbcx::XColumnsSupplier > xSupplyCols(xCursor, UNO_QUERY); + Reference< XNameAccess > xColumns; + if (!xSupplyCols.is()) + return aRet; + xColumns = xSupplyCols->getColumns(); + DBG_ASSERT(xSupplyCols.is(), "BibliographyLoader::getByName : invalid columns returned by the data cursor (may be the result set is not alive ?) !"); + if (!xColumns.is()) + return aRet; + + const OUString sIdentifierMapping = pDatMan->GetIdentifierMapping(); + Reference< sdb::XColumn > xColumn; + if (xColumns->hasByName(sIdentifierMapping)) + xColumn.set(xColumns->getByName(sIdentifierMapping), UNO_QUERY); + if (xColumn.is()) + { + do + { + if ((rName == xColumn->getString()) && !xColumn->wasNull()) + { + Sequence<PropertyValue> aPropSequ(COLUMN_COUNT); + PropertyValue* pValues = aPropSequ.getArray(); + BibConfig* pConfig = BibModul::GetConfig(); + BibDBDescriptor aBibDesc = BibModul::GetConfig()->GetBibliographyURL(); + const Mapping* pMapping = pConfig->GetMapping(aBibDesc); + for(sal_uInt16 nEntry = 0; nEntry < COLUMN_COUNT; nEntry++) + { + const OUString& sColName = pConfig->GetDefColumnName( + nEntry); + pValues[nEntry].Name = sColName; + pValues[nEntry].Value <<= lcl_AddProperty(xColumns, pMapping, sColName); + } + aRet <<= aPropSequ; + + break; + } + } + while(xCursor->next()); + } + } + catch(const Exception&) + { + DBG_UNHANDLED_EXCEPTION("extensions.biblio"); + } + return aRet; +} + +Sequence< OUString > BibliographyLoader::getElementNames() +{ + Sequence< OUString > aRet(10); + int nRealNameCount = 0; + try + { + Reference< XResultSet > xCursor(GetDataCursor()); + Reference< sdb::XColumn > xIdColumn(GetIdentifierColumn()); + if (xIdColumn.is()) // implies xCursor.is() + { + do + { + OUString sTemp = xIdColumn->getString(); + if (!sTemp.isEmpty() && !xIdColumn->wasNull()) + { + int nLen = aRet.getLength(); + if(nLen == nRealNameCount) + aRet.realloc(nLen + 10); + OUString* pArray = aRet.getArray(); + pArray[nRealNameCount] = sTemp; + nRealNameCount++; + } + } + while (xCursor->next()); + } + } + catch(const Exception&) + { + DBG_UNHANDLED_EXCEPTION("extensions.biblio"); + } + + aRet.realloc(nRealNameCount); + return aRet; +} + +sal_Bool BibliographyLoader::hasByName(const OUString& rName) +{ + bool bRet = false; + try + { + Reference< XResultSet > xCursor = GetDataCursor(); + Reference< sdb::XColumn > xIdColumn = GetIdentifierColumn(); + + if (xIdColumn.is()) // implies xCursor.is() + { + do + { + OUString sCurrentId = xIdColumn->getString(); + if (!xIdColumn->wasNull() && rName.startsWith(sCurrentId)) + { + bRet = true; + break; + } + } + while(xCursor->next()); + } + } + catch(const Exception&) + { + DBG_UNHANDLED_EXCEPTION("extensions.biblio"); + } + return bRet; +} + +Type BibliographyLoader::getElementType() +{ + return cppu::UnoType<Sequence<PropertyValue>>::get(); +} + +sal_Bool BibliographyLoader::hasElements() +{ + Reference< XNameAccess > xColumns = GetDataColumns(); + return xColumns.is() && xColumns->getElementNames().hasElements(); +} + +Reference< XPropertySetInfo > BibliographyLoader::getPropertySetInfo() +{ + static const SfxItemPropertyMapEntry aBibProps_Impl[] = + { + { u"BibliographyDataFieldNames", 0, cppu::UnoType<Sequence<PropertyValue>>::get(), PropertyAttribute::READONLY, 0}, + { u"", 0, css::uno::Type(), 0, 0 } + }; + static Reference< XPropertySetInfo > xRet = + SfxItemPropertySet(aBibProps_Impl).getPropertySetInfo(); + return xRet; +} + +void BibliographyLoader::setPropertyValue(const OUString& /*PropertyName*/, + const Any& /*aValue*/) +{ + throw UnknownPropertyException(); + //no changeable properties +} + +Any BibliographyLoader::getPropertyValue(const OUString& rPropertyName) +{ + Any aRet; + static const sal_uInt16 aInternalMapping[] = + { + IDENTIFIER_POS , // BibliographyDataField_IDENTIFIER + AUTHORITYTYPE_POS , // BibliographyDataField_BIBILIOGRAPHIC_TYPE + ADDRESS_POS , // BibliographyDataField_ADDRESS + ANNOTE_POS , // BibliographyDataField_ANNOTE + AUTHOR_POS , // BibliographyDataField_AUTHOR + BOOKTITLE_POS , // BibliographyDataField_BOOKTITLE + CHAPTER_POS , // BibliographyDataField_CHAPTER + EDITION_POS , // BibliographyDataField_EDITION + EDITOR_POS , // BibliographyDataField_EDITOR + HOWPUBLISHED_POS , // BibliographyDataField_HOWPUBLISHED + INSTITUTION_POS , // BibliographyDataField_INSTITUTION + JOURNAL_POS , // BibliographyDataField_JOURNAL + MONTH_POS , // BibliographyDataField_MONTH + NOTE_POS , // BibliographyDataField_NOTE + NUMBER_POS , // BibliographyDataField_NUMBER + ORGANIZATIONS_POS , // BibliographyDataField_ORGANIZATIONS + PAGES_POS , // BibliographyDataField_PAGES + PUBLISHER_POS , // BibliographyDataField_PUBLISHER + SCHOOL_POS , // BibliographyDataField_SCHOOL + SERIES_POS , // BibliographyDataField_SERIES + TITLE_POS , // BibliographyDataField_TITLE + REPORTTYPE_POS , // BibliographyDataField_REPORT_TYPE + VOLUME_POS , // BibliographyDataField_VOLUME + YEAR_POS , // BibliographyDataField_YEAR + URL_POS , // BibliographyDataField_URL + CUSTOM1_POS , // BibliographyDataField_CUSTOM1 + CUSTOM2_POS , // BibliographyDataField_CUSTOM2 + CUSTOM3_POS , // BibliographyDataField_CUSTOM3 + CUSTOM4_POS , // BibliographyDataField_CUSTOM4 + CUSTOM5_POS , // BibliographyDataField_CUSTOM5 + ISBN_POS , // BibliographyDataField_ISBN + LOCAL_URL_POS // BibliographyDataField_LOCAL_URL + }; + if(rPropertyName != "BibliographyDataFieldNames") + throw UnknownPropertyException(rPropertyName); + Sequence<PropertyValue> aSeq(COLUMN_COUNT); + PropertyValue* pArray = aSeq.getArray(); + BibConfig* pConfig = BibModul::GetConfig(); + for(sal_uInt16 i = 0; i <= text::BibliographyDataField::LOCAL_URL ; i++) + { + pArray[i].Name = pConfig->GetDefColumnName(aInternalMapping[i]); + pArray[i].Value <<= static_cast<sal_Int16>(i); + } + aRet <<= aSeq; + return aRet; +} + +void BibliographyLoader::addPropertyChangeListener( + const OUString& /*PropertyName*/, const Reference< XPropertyChangeListener > & /*aListener*/) +{ + //no bound properties +} + +void BibliographyLoader::removePropertyChangeListener( + const OUString& /*PropertyName*/, const Reference< XPropertyChangeListener > & /*aListener*/) +{ + //no bound properties +} + +void BibliographyLoader::addVetoableChangeListener( + const OUString& /*PropertyName*/, const Reference< XVetoableChangeListener > & /*aListener*/) +{ + //no vetoable properties +} + +void BibliographyLoader::removeVetoableChangeListener( + const OUString& /*PropertyName*/, const Reference< XVetoableChangeListener > & /*aListener*/) +{ + //no vetoable properties +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/bibliography/bibmod.cxx b/extensions/source/bibliography/bibmod.cxx new file mode 100644 index 000000000..3a6d06672 --- /dev/null +++ b/extensions/source/bibliography/bibmod.cxx @@ -0,0 +1,89 @@ +/* -*- 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 <unotools/resmgr.hxx> + +#include "bibmod.hxx" +#include "bibresid.hxx" +#include "datman.hxx" +#include "bibconfig.hxx" +#include <ucbhelper/content.hxx> + +static BibModul* pBibModul=nullptr; +static sal_uInt32 nBibModulCount=0; + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::ucb; + +HdlBibModul OpenBibModul() +{ + if(pBibModul==nullptr) + { + pBibModul=new BibModul(); + } + nBibModulCount++; + return &pBibModul; +} + +void CloseBibModul(HdlBibModul ppBibModul) +{ + nBibModulCount--; + if(nBibModulCount==0 && ppBibModul!=nullptr) + { + delete pBibModul; + pBibModul=nullptr; + } +} + +OUString BibResId(TranslateId aId) +{ + return Translate::get(aId, pBibModul->GetResLocale()); +} + +BibConfig* BibModul::pBibConfig = nullptr; + +BibModul::BibModul() + : m_aResLocale(Translate::Create("pcr")) +{ +} + +BibModul::~BibModul() +{ + if (pBibConfig && pBibConfig->IsModified()) + pBibConfig->Commit(); + delete pBibConfig; + pBibConfig = nullptr; +} + +rtl::Reference<BibDataManager> BibModul::createDataManager() +{ + return new BibDataManager(); +} + +BibConfig* BibModul::GetConfig() +{ + if(! pBibConfig) + pBibConfig = new BibConfig; + return pBibConfig; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/bibliography/bibmod.hxx b/extensions/source/bibliography/bibmod.hxx new file mode 100644 index 000000000..a695f93d6 --- /dev/null +++ b/extensions/source/bibliography/bibmod.hxx @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <locale> +#include <rtl/ref.hxx> + +class BibDataManager; +class BibConfig; + +class BibModul +{ + private: + std::locale m_aResLocale; + static BibConfig* pBibConfig; + + public: + BibModul(); + ~BibModul(); + + const std::locale& GetResLocale() const { return m_aResLocale; } + static BibConfig* GetConfig(); + + static rtl::Reference<BibDataManager> createDataManager(); + +}; + +typedef BibModul** HdlBibModul; + +HdlBibModul OpenBibModul(); +void CloseBibModul(HdlBibModul ppBibModul); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/bibliography/bibresid.hxx b/extensions/source/bibliography/bibresid.hxx new file mode 100644 index 000000000..6e17e76f2 --- /dev/null +++ b/extensions/source/bibliography/bibresid.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 . + */ + +#pragma once + +#include <rtl/ustring.hxx> +#include <unotools/resmgr.hxx> + +OUString BibResId(TranslateId aId); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/bibliography/bibshortcuthandler.hxx b/extensions/source/bibliography/bibshortcuthandler.hxx new file mode 100644 index 000000000..79563543b --- /dev/null +++ b/extensions/source/bibliography/bibshortcuthandler.hxx @@ -0,0 +1,66 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <vcl/window.hxx> +#include <vcl/splitwin.hxx> + +// additional classes to handle shortcuts +// code in bibcont.cxx + + +class BibShortCutHandler +{ +private: + VclPtr<vcl::Window> pBaseClass; // in cases, where BibShortCutHandler also has to be a window + +protected: + explicit BibShortCutHandler( vcl::Window* pBaseClass ); + +public: + virtual ~BibShortCutHandler(); + virtual bool HandleShortCutKey( const KeyEvent& rKeyEvent ); // returns true, if key was handled + + inline vcl::Window* GetWindow(); +}; + +inline BibShortCutHandler::BibShortCutHandler( vcl::Window* _pBaseClass ) : pBaseClass( _pBaseClass ) +{ +} + +inline vcl::Window* BibShortCutHandler::GetWindow() +{ + return pBaseClass; +} + +class BibWindow : public vcl::Window, public BibShortCutHandler +{ +public: + BibWindow( vcl::Window* pParent, WinBits nStyle); + virtual ~BibWindow() override; +}; + +class BibSplitWindow : public SplitWindow, public BibShortCutHandler +{ +public: + BibSplitWindow( vcl::Window* pParent, WinBits nStyle); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/bibliography/bibtools.hxx b/extensions/source/bibliography/bibtools.hxx new file mode 100644 index 000000000..9b0d388fa --- /dev/null +++ b/extensions/source/bibliography/bibtools.hxx @@ -0,0 +1,42 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <vcl/window.hxx> + +namespace bib +{ + // source in bibbeam.cxx + + void HandleTaskPaneList( vcl::Window* pWindow, bool bAddToList ); + // pWindow: just an system window or something which is child of a system window + + inline void AddToTaskPaneList( vcl::Window* pWindowToBeHandled ) + { + HandleTaskPaneList( pWindowToBeHandled, true ); + } + + inline void RemoveFromTaskPaneList( vcl::Window* pWindowToBeHandled ) + { + HandleTaskPaneList( pWindowToBeHandled, false ); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/bibliography/bibview.cxx b/extensions/source/bibliography/bibview.cxx new file mode 100644 index 000000000..b175fb78a --- /dev/null +++ b/extensions/source/bibliography/bibview.cxx @@ -0,0 +1,189 @@ +/* -*- 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 "general.hxx" +#include "bibview.hxx" +#include "datman.hxx" +#include "bibresid.hxx" +#include "bibmod.hxx" +#include "bibconfig.hxx" + + +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; + +namespace +{ + class MessageWithCheck : public weld::MessageDialogController + { + private: + std::unique_ptr<weld::CheckButton> m_xWarningOnBox; + public: + MessageWithCheck(weld::Window *pParent) + : MessageDialogController(pParent, "modules/sbibliography/ui/querydialog.ui", "QueryDialog", "ask") + , m_xWarningOnBox(m_xBuilder->weld_check_button("ask")) + { + } + bool get_active() const { return m_xWarningOnBox->get_active(); } + }; +} + +namespace bib +{ + + + BibView::BibView( vcl::Window* _pParent, BibDataManager* _pManager, WinBits _nStyle ) + :BibWindow( _pParent, _nStyle ) + ,m_pDatMan( _pManager ) + ,m_xDatMan( _pManager ) + ,m_pGeneralPage( nullptr ) + ,m_aFormControlContainer(this) + { + if ( m_xDatMan.is() ) + m_aFormControlContainer.connectForm( m_xDatMan ); + } + + + BibView::~BibView() + { + disposeOnce(); + } + + void BibView::dispose() + { + VclPtr<BibGeneralPage> pGeneralPage = m_pGeneralPage; + m_pGeneralPage.clear(); + pGeneralPage.disposeAndClear(); // dispose will commit any uncommitted weld::Entry changes + + if ( m_aFormControlContainer.isFormConnected() ) + m_aFormControlContainer.disconnectForm(); + + BibWindow::dispose(); + } + + void BibView::UpdatePages() + { + // TODO: + // this is _strange_: Why not updating the existent general page? + // I consider the current behaviour a HACK. + if ( m_pGeneralPage ) + { + m_pGeneralPage->Hide(); + m_pGeneralPage.disposeAndClear(); + } + + m_pGeneralPage = VclPtr<BibGeneralPage>::Create( this, m_pDatMan ); + m_pGeneralPage->Show(); + + if( HasFocus() ) + // "delayed" GetFocus() because GetFocus() is initially called before GeneralPage is created + m_pGeneralPage->GrabFocus(); + + OUString sErrorString( m_pGeneralPage->GetErrorString() ); + if ( sErrorString.isEmpty() ) + return; + + bool bExecute = BibModul::GetConfig()->IsShowColumnAssignmentWarning(); + if(!m_pDatMan->HasActiveConnection()) + { + //no connection is available -> the data base has to be assigned + m_pDatMan->DispatchDBChangeDialog(); + bExecute = false; + } + else if(bExecute) + { + sErrorString += "\n" + BibResId(RID_MAP_QUESTION); + + MessageWithCheck aQueryBox(GetFrameWeld()); + aQueryBox.set_primary_text(sErrorString); + + short nResult = aQueryBox.run(); + BibModul::GetConfig()->SetShowColumnAssignmentWarning(!aQueryBox.get_active()); + + if( RET_YES != nResult ) + { + bExecute = false; + } + } + if(bExecute) + { + Application::PostUserEvent( LINK( this, BibView, CallMappingHdl ), nullptr, true ); + } + } + + BibViewFormControlContainer::BibViewFormControlContainer(BibView *pBibView) : mpBibView(pBibView) {} + + void BibViewFormControlContainer::_loaded( const EventObject& _rEvent ) + { + mpBibView->UpdatePages(); + FormControlContainer::_loaded( _rEvent ); + mpBibView->Resize(); + } + + void BibViewFormControlContainer::_reloaded( const EventObject& _rEvent ) + { + mpBibView->UpdatePages(); + FormControlContainer::_loaded( _rEvent ); + mpBibView->Resize(); + } + + IMPL_LINK_NOARG( BibView, CallMappingHdl, void*, void) + { + m_pDatMan->CreateMappingDialog(GetFrameWeld()); + } + + void BibView::Resize() + { + if ( m_pGeneralPage ) + { + ::Size aSz( GetOutputSizePixel() ); + m_pGeneralPage->SetSizePixel( aSz ); + } + Window::Resize(); + } + + Reference< awt::XControlContainer > BibViewFormControlContainer::getControlContainer() + { + return nullptr; + } + + void BibView::GetFocus() + { + if( m_pGeneralPage ) + m_pGeneralPage->GrabFocus(); + } + + bool BibView::HandleShortCutKey( const KeyEvent& rKeyEvent ) + { + return m_pGeneralPage && m_pGeneralPage->HandleShortCutKey( rKeyEvent ); + } + + +} // namespace bib + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/bibliography/bibview.hxx b/extensions/source/bibliography/bibview.hxx new file mode 100644 index 000000000..3bed8ed13 --- /dev/null +++ b/extensions/source/bibliography/bibview.hxx @@ -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 . + */ +#pragma once + +#include <com/sun/star/awt/XControlContainer.hpp> +#include "formcontrolcontainer.hxx" +#include "bibshortcuthandler.hxx" + +class BibGeneralPage; +class BibDataManager; + +namespace com::sun::star::awt{ class XFocusListener;} + +namespace bib +{ + class BibView; + class BibViewFormControlContainer : public FormControlContainer + { + private: + VclPtr<BibView> mpBibView; + protected: + // FormControlContainer + virtual css::uno::Reference< css::awt::XControlContainer > + getControlContainer() override; + // XLoadListener equivalents + virtual void _loaded( const css::lang::EventObject& _rEvent ) override; + virtual void _reloaded( const css::lang::EventObject& _rEvent ) override; + public: + using FormControlContainer::connectForm; + using FormControlContainer::disconnectForm; + using FormControlContainer::isFormConnected; + explicit BibViewFormControlContainer(BibView *pBibView); + }; + + class BibView : public BibWindow + { + private: + BibDataManager* m_pDatMan; + css::uno::Reference< css::form::XLoadable> m_xDatMan; + VclPtr<BibGeneralPage> m_pGeneralPage; + BibViewFormControlContainer m_aFormControlContainer; + + private: + DECL_LINK(CallMappingHdl, void*, void); + + public: + // Window overridables + virtual void Resize() override; + + public: + BibView( vcl::Window* _pParent, BibDataManager* _pDatMan, WinBits nStyle ); + virtual ~BibView() override; + virtual void dispose() override; + + void UpdatePages(); + + virtual void GetFocus() override; + + virtual bool HandleShortCutKey( const KeyEvent& rKeyEvent ) override; // returns true, if key was handled + }; + + +} // namespace bib + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/bibliography/datman.cxx b/extensions/source/bibliography/datman.cxx new file mode 100644 index 000000000..e010f8185 --- /dev/null +++ b/extensions/source/bibliography/datman.cxx @@ -0,0 +1,1390 @@ +/* -*- 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 <o3tl/any.hxx> +#include <sal/log.hxx> +#include <tools/diagnose_ex.h> +#include <comphelper/processfactory.hxx> +#include <com/sun/star/sdbc/ResultSetType.hpp> +#include <com/sun/star/sdbc/ResultSetConcurrency.hpp> +#include <com/sun/star/sdbcx/XRowLocate.hpp> +#include <com/sun/star/sdbc/DataType.hpp> +#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp> +#include <com/sun/star/sdbc/XDatabaseMetaData.hpp> +#include <com/sun/star/sdbc/XDataSource.hpp> +#include <com/sun/star/sdb/CommandType.hpp> +#include <com/sun/star/sdb/DatabaseContext.hpp> +#include <com/sun/star/sdbcx/XTablesSupplier.hpp> +#include <com/sun/star/sdbc/XConnection.hpp> +#include <com/sun/star/sdb/XCompletedConnection.hpp> +#include <com/sun/star/sdbc/SQLException.hpp> +#include <com/sun/star/task/InteractionHandler.hpp> +#include <com/sun/star/form/ListSourceType.hpp> +#include <com/sun/star/form/XLoadable.hpp> +#include <com/sun/star/form/runtime/FormController.hpp> +#include <com/sun/star/sdbcx/XColumnsSupplier.hpp> +#include <com/sun/star/form/XGridColumnFactory.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <tools/debug.hxx> +#include <tools/urlobj.hxx> +#include <vcl/weld.hxx> +#include "datman.hxx" +#include "bibresid.hxx" +#include "bibmod.hxx" +#include "bibview.hxx" +#include "toolbar.hxx" +#include "bibconfig.hxx" +#include "bibbeam.hxx" +#include "general.hxx" +#include <strings.hrc> +#include <helpids.h> +#include <connectivity/dbtools.hxx> +#include <memory> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::lang; + +// PropertyNames +constexpr OUStringLiteral FM_PROP_LABEL = u"Label"; +constexpr OUStringLiteral FM_PROP_CONTROLSOURCE = u"DataField"; +constexpr OUStringLiteral FM_PROP_NAME = u"Name"; + +static Reference< XConnection > getConnection(const OUString& _rURL) +{ + // first get the sdb::DataSource corresponding to the url + Reference< XDataSource > xDataSource; + // is it a favorite title ? + Reference<XComponentContext> xContext = comphelper::getProcessComponentContext(); + Reference< XDatabaseContext > xNamingContext = DatabaseContext::create(xContext); + if (xNamingContext->hasByName(_rURL)) + { + DBG_ASSERT(xNamingContext.is(), "::getDataSource : no NamingService interface on the sdb::DatabaseAccessContext !"); + try + { + xDataSource.set(xNamingContext->getRegisteredObject(_rURL), UNO_QUERY); + } + catch (const Exception&) + { + TOOLS_WARN_EXCEPTION("extensions.biblio", ""); + } + } + // build the connection from the data source + Reference< XConnection > xConn; + if (xDataSource.is()) + { + // need user/pwd for this + Reference< XCompletedConnection > xComplConn(xDataSource, UNO_QUERY); + try + { + Reference<task::XInteractionHandler> xIHdl( task::InteractionHandler::createWithParent(xContext, nullptr), UNO_QUERY_THROW); + xConn = xComplConn->connectWithCompletion(xIHdl); + } + catch (const SQLException&) + { + // TODO : a real error handling + } + catch (const Exception&) + { + } + } + return xConn; +} + +static Reference< XConnection > getConnection(const Reference< XInterface > & xRowSet) +{ + Reference< XConnection > xConn; + try + { + Reference< XPropertySet > xFormProps(xRowSet, UNO_QUERY); + if (!xFormProps.is()) + return xConn; + + xConn.set(xFormProps->getPropertyValue("ActiveConnection"), UNO_QUERY); + if (!xConn.is()) + { + SAL_INFO("extensions.biblio", "no active connection"); + } + } + catch (const Exception&) + { + TOOLS_WARN_EXCEPTION("extensions.biblio", ""); + } + + return xConn; +} + +static Reference< XNameAccess > getColumns(const Reference< XForm > & _rxForm) +{ + Reference< XNameAccess > xReturn; + // check if the form is alive + Reference< XColumnsSupplier > xSupplyCols( _rxForm, UNO_QUERY ); + if (xSupplyCols.is()) + xReturn = xSupplyCols->getColumns(); + + if (!xReturn.is() || !xReturn->getElementNames().hasElements()) + { // no... + xReturn = nullptr; + // -> get the table the form is bound to and ask it for their columns + Reference< XTablesSupplier > xSupplyTables( getConnection( _rxForm ), UNO_QUERY ); + Reference< XPropertySet > xFormProps( _rxForm, UNO_QUERY ); + if (xFormProps.is() && xSupplyTables.is()) + { + try + { + DBG_ASSERT(*o3tl::forceAccess<sal_Int32>(xFormProps->getPropertyValue("CommandType")) == CommandType::TABLE, + "::getColumns : invalid form (has no table as data source) !"); + OUString sTable; + xFormProps->getPropertyValue("Command") >>= sTable; + Reference< XNameAccess > xTables = xSupplyTables->getTables(); + if (xTables.is() && xTables->hasByName(sTable)) + xSupplyCols.set(xTables->getByName(sTable), UNO_QUERY); + if (xSupplyCols.is()) + xReturn = xSupplyCols->getColumns(); + } + catch (const Exception&) + { + TOOLS_WARN_EXCEPTION( "extensions.biblio", "::getColumns"); + } + + } + } + return xReturn; +} + +namespace { + +class MappingDialog_Impl : public weld::GenericDialogController +{ + BibDataManager* pDatMan; + + OUString sNone; + bool bModified; + + std::unique_ptr<weld::Button> m_xOKBT; + std::unique_ptr<weld::ComboBox> m_xIdentifierLB; + std::unique_ptr<weld::ComboBox> m_xAuthorityTypeLB; + std::unique_ptr<weld::ComboBox> m_xAuthorLB; + std::unique_ptr<weld::ComboBox> m_xTitleLB; + std::unique_ptr<weld::ComboBox> m_xMonthLB; + std::unique_ptr<weld::ComboBox> m_xYearLB; + std::unique_ptr<weld::ComboBox> m_xISBNLB; + std::unique_ptr<weld::ComboBox> m_xBooktitleLB; + std::unique_ptr<weld::ComboBox> m_xChapterLB; + std::unique_ptr<weld::ComboBox> m_xEditionLB; + std::unique_ptr<weld::ComboBox> m_xEditorLB; + std::unique_ptr<weld::ComboBox> m_xHowpublishedLB; + std::unique_ptr<weld::ComboBox> m_xInstitutionLB; + std::unique_ptr<weld::ComboBox> m_xJournalLB; + std::unique_ptr<weld::ComboBox> m_xNoteLB; + std::unique_ptr<weld::ComboBox> m_xAnnoteLB; + std::unique_ptr<weld::ComboBox> m_xNumberLB; + std::unique_ptr<weld::ComboBox> m_xOrganizationsLB; + std::unique_ptr<weld::ComboBox> m_xPagesLB; + std::unique_ptr<weld::ComboBox> m_xPublisherLB; + std::unique_ptr<weld::ComboBox> m_xAddressLB; + std::unique_ptr<weld::ComboBox> m_xSchoolLB; + std::unique_ptr<weld::ComboBox> m_xSeriesLB; + std::unique_ptr<weld::ComboBox> m_xReportTypeLB; + std::unique_ptr<weld::ComboBox> m_xVolumeLB; + std::unique_ptr<weld::ComboBox> m_xURLLB; + std::unique_ptr<weld::ComboBox> m_xCustom1LB; + std::unique_ptr<weld::ComboBox> m_xCustom2LB; + std::unique_ptr<weld::ComboBox> m_xCustom3LB; + std::unique_ptr<weld::ComboBox> m_xCustom4LB; + std::unique_ptr<weld::ComboBox> m_xCustom5LB; + std::unique_ptr<weld::ComboBox> m_xLocalURLLB; + weld::ComboBox* aListBoxes[COLUMN_COUNT]; + + DECL_LINK(OkHdl, weld::Button&, void); + DECL_LINK(ListBoxSelectHdl, weld::ComboBox&, void); + +public: + MappingDialog_Impl(weld::Window* pParent, BibDataManager* pDatMan); +}; + +} + +static sal_uInt16 lcl_FindLogicalName(BibConfig const * pConfig , + std::u16string_view rLogicalColumnName) +{ + for(sal_uInt16 i = 0; i < COLUMN_COUNT; i++) + { + if(rLogicalColumnName == pConfig->GetDefColumnName(i)) + return i; + } + return USHRT_MAX; +} + +MappingDialog_Impl::MappingDialog_Impl(weld::Window* pParent, BibDataManager* pMan) + : GenericDialogController(pParent, "modules/sbibliography/ui/mappingdialog.ui", "MappingDialog") + , pDatMan(pMan) + , sNone(BibResId(RID_BIB_STR_NONE)) + , bModified(false) + , m_xOKBT(m_xBuilder->weld_button("ok")) + , m_xIdentifierLB(m_xBuilder->weld_combo_box("identifierCombobox")) + , m_xAuthorityTypeLB(m_xBuilder->weld_combo_box("authorityTypeCombobox")) + , m_xAuthorLB(m_xBuilder->weld_combo_box("authorCombobox")) + , m_xTitleLB(m_xBuilder->weld_combo_box("titleCombobox")) + , m_xMonthLB(m_xBuilder->weld_combo_box("monthCombobox")) + , m_xYearLB(m_xBuilder->weld_combo_box("yearCombobox")) + , m_xISBNLB(m_xBuilder->weld_combo_box("ISBNCombobox")) + , m_xBooktitleLB(m_xBuilder->weld_combo_box("bookTitleCombobox")) + , m_xChapterLB(m_xBuilder->weld_combo_box("chapterCombobox")) + , m_xEditionLB(m_xBuilder->weld_combo_box("editionCombobox")) + , m_xEditorLB(m_xBuilder->weld_combo_box("editorCombobox")) + , m_xHowpublishedLB(m_xBuilder->weld_combo_box("howPublishedCombobox")) + , m_xInstitutionLB(m_xBuilder->weld_combo_box("institutionCombobox")) + , m_xJournalLB(m_xBuilder->weld_combo_box("journalCombobox")) + , m_xNoteLB(m_xBuilder->weld_combo_box("noteCombobox")) + , m_xAnnoteLB(m_xBuilder->weld_combo_box("annoteCombobox")) + , m_xNumberLB(m_xBuilder->weld_combo_box("numberCombobox")) + , m_xOrganizationsLB(m_xBuilder->weld_combo_box("organizationCombobox")) + , m_xPagesLB(m_xBuilder->weld_combo_box("pagesCombobox")) + , m_xPublisherLB(m_xBuilder->weld_combo_box("publisherCombobox")) + , m_xAddressLB(m_xBuilder->weld_combo_box("addressCombobox")) + , m_xSchoolLB(m_xBuilder->weld_combo_box("schoolCombobox")) + , m_xSeriesLB(m_xBuilder->weld_combo_box("seriesCombobox")) + , m_xReportTypeLB(m_xBuilder->weld_combo_box("reportTypeCombobox")) + , m_xVolumeLB(m_xBuilder->weld_combo_box("volumeCombobox")) + , m_xURLLB(m_xBuilder->weld_combo_box("URLCombobox")) + , m_xCustom1LB(m_xBuilder->weld_combo_box("custom1Combobox")) + , m_xCustom2LB(m_xBuilder->weld_combo_box("custom2Combobox")) + , m_xCustom3LB(m_xBuilder->weld_combo_box("custom3Combobox")) + , m_xCustom4LB(m_xBuilder->weld_combo_box("custom4Combobox")) + , m_xCustom5LB(m_xBuilder->weld_combo_box("custom5Combobox")) + , m_xLocalURLLB(m_xBuilder->weld_combo_box("LocalURLCombobox")) +{ + m_xOKBT->connect_clicked(LINK(this, MappingDialog_Impl, OkHdl)); + OUString sTitle = m_xDialog->get_title(); + sTitle = sTitle.replaceFirst("%1", pDatMan->getActiveDataTable()); + m_xDialog->set_title(sTitle); + + aListBoxes[0] = m_xIdentifierLB.get(); + aListBoxes[1] = m_xAuthorityTypeLB.get(); + aListBoxes[2] = m_xAuthorLB.get(); + aListBoxes[3] = m_xTitleLB.get(); + aListBoxes[4] = m_xYearLB.get(); + aListBoxes[5] = m_xISBNLB.get(); + aListBoxes[6] = m_xBooktitleLB.get(); + aListBoxes[7] = m_xChapterLB.get(); + aListBoxes[8] = m_xEditionLB.get(); + aListBoxes[9] = m_xEditorLB.get(); + aListBoxes[10] = m_xHowpublishedLB.get(); + aListBoxes[11] = m_xInstitutionLB.get(); + aListBoxes[12] = m_xJournalLB.get(); + aListBoxes[13] = m_xMonthLB.get(); + aListBoxes[14] = m_xNoteLB.get(); + aListBoxes[15] = m_xAnnoteLB.get(); + aListBoxes[16] = m_xNumberLB.get(); + aListBoxes[17] = m_xOrganizationsLB.get(); + aListBoxes[18] = m_xPagesLB.get(); + aListBoxes[19] = m_xPublisherLB.get(); + aListBoxes[20] = m_xAddressLB.get(); + aListBoxes[21] = m_xSchoolLB.get(); + aListBoxes[22] = m_xSeriesLB.get(); + aListBoxes[23] = m_xReportTypeLB.get(); + aListBoxes[24] = m_xVolumeLB.get(); + aListBoxes[25] = m_xURLLB.get(); + aListBoxes[26] = m_xCustom1LB.get(); + aListBoxes[27] = m_xCustom2LB.get(); + aListBoxes[28] = m_xCustom3LB.get(); + aListBoxes[29] = m_xCustom4LB.get(); + aListBoxes[30] = m_xCustom5LB.get(); + aListBoxes[31] = m_xLocalURLLB.get(); + + aListBoxes[0]->append_text(sNone); + Reference< XNameAccess > xFields = getColumns( pDatMan->getForm() ); + DBG_ASSERT(xFields.is(), "MappingDialog_Impl::MappingDialog_Impl : gave me an invalid form !"); + if (xFields.is()) + { + const Sequence<OUString> aFieldNames = xFields->getElementNames(); + for(const OUString& rName : aFieldNames) + aListBoxes[0]->append_text(rName); + } + + Link<weld::ComboBox&,void> aLnk = LINK(this, MappingDialog_Impl, ListBoxSelectHdl); + + aListBoxes[0]->set_active(0); + aListBoxes[0]->connect_changed(aLnk); + for(sal_uInt16 i = 1; i < COLUMN_COUNT; i++) + { + for(sal_Int32 j = 0, nEntryCount = aListBoxes[0]->get_count(); j < nEntryCount; ++j) + aListBoxes[i]->append_text(aListBoxes[0]->get_text(j)); + aListBoxes[i]->set_active(0); + aListBoxes[i]->connect_changed(aLnk); + } + BibConfig* pConfig = BibModul::GetConfig(); + BibDBDescriptor aDesc; + aDesc.sDataSource = pDatMan->getActiveDataSource(); + aDesc.sTableOrQuery = pDatMan->getActiveDataTable(); + aDesc.nCommandType = CommandType::TABLE; + const Mapping* pMapping = pConfig->GetMapping(aDesc); + if(pMapping) + { + for(const auto & aColumnPair : pMapping->aColumnPairs) + { + sal_uInt16 nListBoxIndex = lcl_FindLogicalName( pConfig, aColumnPair.sLogicalColumnName); + if(nListBoxIndex < COLUMN_COUNT) + { + aListBoxes[nListBoxIndex]->set_active_text(aColumnPair.sRealColumnName); + } + } + } +} + +IMPL_LINK(MappingDialog_Impl, ListBoxSelectHdl, weld::ComboBox&, rListBox, void) +{ + const sal_Int32 nEntryPos = rListBox.get_active(); + if (0 < nEntryPos) + { + for(auto & pListBoxe : aListBoxes) + { + if (&rListBox != pListBoxe && pListBoxe->get_active() == nEntryPos) + pListBoxe->set_active(0); + } + } + bModified = true; +} + +IMPL_LINK_NOARG(MappingDialog_Impl, OkHdl, weld::Button&, void) +{ + if(bModified) + { + Mapping aNew; + aNew.sTableName = pDatMan->getActiveDataTable(); + aNew.sURL = pDatMan->getActiveDataSource(); + + sal_uInt16 nWriteIndex = 0; + BibConfig* pConfig = BibModul::GetConfig(); + for(sal_uInt16 nEntry = 0; nEntry < COLUMN_COUNT; nEntry++) + { + OUString sSel = aListBoxes[nEntry]->get_active_text(); + if(sSel != sNone) + { + aNew.aColumnPairs[nWriteIndex].sRealColumnName = sSel; + aNew.aColumnPairs[nWriteIndex].sLogicalColumnName = pConfig->GetDefColumnName(nEntry); + nWriteIndex++; + } + } + BibDBDescriptor aDesc; + aDesc.sDataSource = pDatMan->getActiveDataSource(); + aDesc.sTableOrQuery = pDatMan->getActiveDataTable(); + aDesc.nCommandType = CommandType::TABLE; + pDatMan->ResetIdentifierMapping(); + pConfig->SetMapping(aDesc, &aNew); + } + m_xDialog->response(bModified ? RET_OK : RET_CANCEL); +} + +namespace { + +class DBChangeDialog_Impl : public weld::GenericDialogController +{ + DBChangeDialogConfig_Impl aConfig; + + std::unique_ptr<weld::TreeView> m_xSelectionLB; + + DECL_LINK(DoubleClickHdl, weld::TreeView&, bool); +public: + DBChangeDialog_Impl(weld::Window* pParent, const BibDataManager* pMan); + + OUString GetCurrentURL()const; +}; + +} + +DBChangeDialog_Impl::DBChangeDialog_Impl(weld::Window* pParent, const BibDataManager* pDatMan ) + : GenericDialogController(pParent, "modules/sbibliography/ui/choosedatasourcedialog.ui", "ChooseDataSourceDialog") + , m_xSelectionLB(m_xBuilder->weld_tree_view("treeview")) +{ + m_xSelectionLB->set_size_request(-1, m_xSelectionLB->get_height_rows(6)); + m_xSelectionLB->connect_row_activated(LINK(this, DBChangeDialog_Impl, DoubleClickHdl)); + m_xSelectionLB->make_sorted(); + + try + { + OUString sActiveSource = pDatMan->getActiveDataSource(); + for (const OUString& rSourceName : aConfig.GetDataSourceNames()) + m_xSelectionLB->append_text(rSourceName); + m_xSelectionLB->select_text(sActiveSource); + } + catch (const Exception&) + { + TOOLS_WARN_EXCEPTION("extensions.biblio", ""); + } +} + +IMPL_LINK_NOARG(DBChangeDialog_Impl, DoubleClickHdl, weld::TreeView&, bool) +{ + m_xDialog->response(RET_OK); + return true; +} + +OUString DBChangeDialog_Impl::GetCurrentURL()const +{ + return m_xSelectionLB->get_selected_text(); +} + +// XDispatchProvider +BibInterceptorHelper::BibInterceptorHelper( const ::bib::BibBeamer* pBibBeamer, css::uno::Reference< css::frame::XDispatch > const & xDispatch) +{ + if( pBibBeamer ) + { + xInterception = pBibBeamer->getDispatchProviderInterception(); + if( xInterception.is() ) + xInterception->registerDispatchProviderInterceptor( this ); + } + if( xDispatch.is() ) + xFormDispatch = xDispatch; +} + +BibInterceptorHelper::~BibInterceptorHelper( ) +{ +} + +void BibInterceptorHelper::ReleaseInterceptor() +{ + if ( xInterception.is() ) + xInterception->releaseDispatchProviderInterceptor( this ); + xInterception.clear(); +} + +css::uno::Reference< css::frame::XDispatch > SAL_CALL + BibInterceptorHelper::queryDispatch( const css::util::URL& aURL, const OUString& aTargetFrameName, sal_Int32 nSearchFlags ) +{ + Reference< XDispatch > xReturn; + + OUString aCommand( aURL.Path ); + if ( aCommand == "FormSlots/ConfirmDeletion" ) + xReturn = xFormDispatch; + else + if ( xSlaveDispatchProvider.is() ) + xReturn = xSlaveDispatchProvider->queryDispatch( aURL, aTargetFrameName, nSearchFlags); + + return xReturn; +} + +css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL + BibInterceptorHelper::queryDispatches( const css::uno::Sequence< css::frame::DispatchDescriptor >& aDescripts ) +{ + Sequence< Reference< XDispatch> > aReturn( aDescripts.getLength() ); + Reference< XDispatch >* pReturn = aReturn.getArray(); + for ( const DispatchDescriptor& rDescript : aDescripts ) + { + *pReturn++ = queryDispatch( rDescript.FeatureURL, rDescript.FrameName, rDescript.SearchFlags ); + } + return aReturn; +} + +// XDispatchProviderInterceptor +css::uno::Reference< css::frame::XDispatchProvider > SAL_CALL + BibInterceptorHelper::getSlaveDispatchProvider( ) +{ + return xSlaveDispatchProvider; +} + +void SAL_CALL BibInterceptorHelper::setSlaveDispatchProvider( const css::uno::Reference< css::frame::XDispatchProvider >& xNewSlaveDispatchProvider ) +{ + xSlaveDispatchProvider = xNewSlaveDispatchProvider; +} + +css::uno::Reference< css::frame::XDispatchProvider > SAL_CALL + BibInterceptorHelper::getMasterDispatchProvider( ) +{ + return xMasterDispatchProvider; +} + +void SAL_CALL BibInterceptorHelper::setMasterDispatchProvider( const css::uno::Reference< css::frame::XDispatchProvider >& xNewMasterDispatchProvider ) +{ + xMasterDispatchProvider = xNewMasterDispatchProvider; +} + + +constexpr OUStringLiteral gGridName(u"theGrid"); + +BibDataManager::BibDataManager() + :BibDataManager_Base( GetMutex() ) + ,m_aLoadListeners(m_aMutex) + ,pBibView( nullptr ) + ,pToolbar(nullptr) +{ +} + + +BibDataManager::~BibDataManager() +{ + Reference< XLoadable > xLoad( m_xForm, UNO_QUERY ); + Reference< XPropertySet > xPrSet( m_xForm, UNO_QUERY ); + Reference< XComponent > xComp( m_xForm, UNO_QUERY ); + if ( m_xForm.is() ) + { + Reference< XComponent > xConnection; + xPrSet->getPropertyValue("ActiveConnection") >>= xConnection; + if (xLoad.is()) + xLoad->unload(); + if (xComp.is()) + xComp->dispose(); + if(xConnection.is()) + xConnection->dispose(); + m_xForm = nullptr; + } + if( m_xInterceptorHelper.is() ) + { + m_xInterceptorHelper->ReleaseInterceptor(); + m_xInterceptorHelper.clear(); + } +} + +void BibDataManager::InsertFields(const Reference< XFormComponent > & _rxGrid) +{ + if ( !_rxGrid.is() ) + return; + + try + { + Reference< XNameContainer > xColContainer( _rxGrid, UNO_QUERY ); + // remove the old fields + if ( xColContainer->hasElements() ) + { + const Sequence<OUString> aOldNames = xColContainer->getElementNames(); + for ( const OUString& rName : aOldNames ) + xColContainer->removeByName( rName ); + } + + Reference< XNameAccess > xFields = getColumns( m_xForm ); + if (!xFields.is()) + return; + + Reference< XGridColumnFactory > xColFactory( _rxGrid, UNO_QUERY ); + + Reference< XPropertySet > xField; + + const Sequence<OUString> aFieldNames = xFields->getElementNames(); + for ( const OUString& rField : aFieldNames ) + { + xFields->getByName( rField ) >>= xField; + + OUString sCurrentModelType; + sal_Int32 nType = 0; + bool bIsFormatted = false; + bool bFormattedIsNumeric = true; + xField->getPropertyValue("Type") >>= nType; + switch(nType) + { + case DataType::BIT: + case DataType::BOOLEAN: + sCurrentModelType = "CheckBox"; + break; + + case DataType::BINARY: + case DataType::VARBINARY: + case DataType::LONGVARBINARY: + case DataType::BLOB: + sCurrentModelType = "TextField"; + break; + + case DataType::VARCHAR: + case DataType::LONGVARCHAR: + case DataType::CHAR: + case DataType::CLOB: + bFormattedIsNumeric = false; + [[fallthrough]]; + default: + sCurrentModelType = "FormattedField"; + bIsFormatted = true; + break; + } + + Reference< XPropertySet > xCurrentCol = xColFactory->createColumn(sCurrentModelType); + if (bIsFormatted) + { + OUString sFormatKey("FormatKey"); + xCurrentCol->setPropertyValue(sFormatKey, xField->getPropertyValue(sFormatKey)); + Any aFormatted(bFormattedIsNumeric); + xCurrentCol->setPropertyValue("TreatAsNumber", aFormatted); + } + Any aColName( rField ); + xCurrentCol->setPropertyValue(FM_PROP_CONTROLSOURCE, aColName); + xCurrentCol->setPropertyValue(FM_PROP_LABEL, aColName); + + xColContainer->insertByName( rField, Any( xCurrentCol ) ); + } + } + catch (const Exception&) + { + TOOLS_WARN_EXCEPTION("extensions.biblio", ""); + } +} + +Reference< awt::XControlModel > BibDataManager::updateGridModel() +{ + return updateGridModel( m_xForm ); +} + +Reference< awt::XControlModel > const & BibDataManager::updateGridModel(const Reference< XForm > & xDbForm) +{ + try + { + Reference< XPropertySet > aFormPropSet( xDbForm, UNO_QUERY ); + OUString sName; + aFormPropSet->getPropertyValue("Command") >>= sName; + + if ( !m_xGridModel.is() ) + { + m_xGridModel = createGridModel( gGridName ); + + Reference< XNameContainer > xNameCont(xDbForm, UNO_QUERY); + xNameCont->insertByName( sName, Any( m_xGridModel ) ); + } + + // insert the fields + Reference< XFormComponent > xFormComp( m_xGridModel, UNO_QUERY ); + InsertFields( xFormComp ); + } + catch (const Exception&) + { + OSL_FAIL("::updateGridModel: something went wrong !"); + } + + return m_xGridModel; +} + +Reference< XForm > BibDataManager::createDatabaseForm(BibDBDescriptor& rDesc) +{ + Reference< XForm > xResult; + try + { + Reference< XMultiServiceFactory > xMgr = comphelper::getProcessServiceFactory(); + m_xForm.set( xMgr->createInstance( "com.sun.star.form.component.Form" ), UNO_QUERY ); + + Reference< XPropertySet > aPropertySet( m_xForm, UNO_QUERY ); + + aDataSourceURL = rDesc.sDataSource; + if(aPropertySet.is()) + { + Any aVal; + aVal <<= sal_Int32(ResultSetType::SCROLL_INSENSITIVE); + aPropertySet->setPropertyValue("ResultSetType",aVal ); + aVal <<= sal_Int32(ResultSetConcurrency::READ_ONLY); + aPropertySet->setPropertyValue("ResultSetConcurrency", aVal); + + //Caching for Performance + aVal <<= sal_Int32(50); + aPropertySet->setPropertyValue("FetchSize", aVal); + + Reference< XConnection > xConnection = getConnection(rDesc.sDataSource); + aVal <<= xConnection; + aPropertySet->setPropertyValue("ActiveConnection", aVal); + + Reference< XTablesSupplier > xSupplyTables(xConnection, UNO_QUERY); + Reference< XNameAccess > xTables = xSupplyTables.is() ? + xSupplyTables->getTables() : Reference< XNameAccess > (); + + Sequence< OUString > aTableNameSeq; + if (xTables.is()) + aTableNameSeq = xTables->getElementNames(); + + if(aTableNameSeq.hasElements()) + { + if(!rDesc.sTableOrQuery.isEmpty()) + aActiveDataTable = rDesc.sTableOrQuery; + else + { + rDesc.sTableOrQuery = aActiveDataTable = aTableNameSeq[0]; + rDesc.nCommandType = CommandType::TABLE; + } + + aVal <<= aActiveDataTable; + aPropertySet->setPropertyValue("Command", aVal); + aVal <<= rDesc.nCommandType; + aPropertySet->setPropertyValue("CommandType", aVal); + + + Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData(); + aQuoteChar = xMetaData->getIdentifierQuoteString(); + + Reference< XMultiServiceFactory > xFactory(xConnection, UNO_QUERY); + if ( xFactory.is() ) + m_xParser.set( xFactory->createInstance("com.sun.star.sdb.SingleSelectQueryComposer"), UNO_QUERY ); + + OUString aString("SELECT * FROM "); + + OUString sCatalog, sSchema, sName; + ::dbtools::qualifiedNameComponents( xMetaData, aActiveDataTable, sCatalog, sSchema, sName, ::dbtools::EComposeRule::InDataManipulation ); + aString += ::dbtools::composeTableNameForSelect( xConnection, sCatalog, sSchema, sName ); + + m_xParser->setElementaryQuery(aString); + BibConfig* pConfig = BibModul::GetConfig(); + pConfig->setQueryField(getQueryField()); + startQueryWith(pConfig->getQueryText()); + + xResult = m_xForm; + } + } + } + catch (const Exception&) + { + OSL_FAIL("::createDatabaseForm: something went wrong !"); + } + + return xResult; +} + +Sequence< OUString > BibDataManager::getDataSources() const +{ + Sequence< OUString > aTableNameSeq; + + try + { + Reference< XTablesSupplier > xSupplyTables( getConnection( m_xForm ), UNO_QUERY ); + Reference< XNameAccess > xTables; + if (xSupplyTables.is()) + xTables = xSupplyTables->getTables(); + if (xTables.is()) + aTableNameSeq = xTables->getElementNames(); + } + catch (const Exception&) + { + OSL_FAIL("::getDataSources: something went wrong !"); + } + + return aTableNameSeq; +} + + +void BibDataManager::setFilter(const OUString& rQuery) +{ + if(!m_xParser.is()) + return; + try + { + m_xParser->setFilter( rQuery ); + OUString aQuery = m_xParser->getFilter(); + Reference< XPropertySet > xFormProps( m_xForm, UNO_QUERY_THROW ); + xFormProps->setPropertyValue( "Filter", Any( aQuery ) ); + xFormProps->setPropertyValue( "ApplyFilter", Any( true ) ); + reload(); + } + catch (const Exception&) + { + DBG_UNHANDLED_EXCEPTION("extensions.biblio"); + } + + +} + +OUString BibDataManager::getFilter() const +{ + + OUString aQueryString; + try + { + Reference< XPropertySet > xFormProps( m_xForm, UNO_QUERY_THROW ); + OSL_VERIFY( xFormProps->getPropertyValue( "Filter" ) >>= aQueryString ); + } + catch (const Exception&) + { + DBG_UNHANDLED_EXCEPTION("extensions.biblio"); + } + + + return aQueryString; + +} + +Sequence< OUString > BibDataManager::getQueryFields() const +{ + Sequence< OUString > aFieldSeq; + Reference< XNameAccess > xFields = getColumns( m_xForm ); + if (xFields.is()) + aFieldSeq = xFields->getElementNames(); + return aFieldSeq; +} + +OUString BibDataManager::getQueryField() const +{ + BibConfig* pConfig = BibModul::GetConfig(); + OUString aFieldString = pConfig->getQueryField(); + if(aFieldString.isEmpty()) + { + const Sequence< OUString > aSeq = getQueryFields(); + if(aSeq.hasElements()) + { + aFieldString=aSeq[0]; + } + } + return aFieldString; +} + +void BibDataManager::startQueryWith(const OUString& rQuery) +{ + BibConfig* pConfig = BibModul::GetConfig(); + pConfig->setQueryText( rQuery ); + + OUString aQueryString; + if(!rQuery.isEmpty()) + { + aQueryString=aQuoteChar + getQueryField() + aQuoteChar + " like '"; + OUString sQuery = rQuery.replaceAll("?","_").replaceAll("*","%"); + aQueryString += sQuery + "%'"; + } + setFilter(aQueryString); +} + +void BibDataManager::setActiveDataSource(const OUString& rURL) +{ + OUString sTmp(aDataSourceURL); + aDataSourceURL = rURL; + + Reference< XPropertySet > aPropertySet( m_xForm, UNO_QUERY ); + if(!aPropertySet.is()) + return; + + unload(); + + Reference< XComponent > xOldConnection; + aPropertySet->getPropertyValue("ActiveConnection") >>= xOldConnection; + + Reference< XConnection > xConnection = getConnection(rURL); + if(!xConnection.is()) + { + aDataSourceURL = sTmp; + return; + } + Any aVal; aVal <<= xConnection; + aPropertySet->setPropertyValue("ActiveConnection", aVal); + Reference< XMultiServiceFactory > xFactory(xConnection, UNO_QUERY); + if ( xFactory.is() ) + m_xParser.set( xFactory->createInstance("com.sun.star.sdb.SingleSelectQueryComposer"), UNO_QUERY ); + + if(xOldConnection.is()) + xOldConnection->dispose(); + + Sequence< OUString > aTableNameSeq; + Reference< XTablesSupplier > xSupplyTables(xConnection, UNO_QUERY); + if(xSupplyTables.is()) + { + Reference< XNameAccess > xAccess = xSupplyTables->getTables(); + aTableNameSeq = xAccess->getElementNames(); + } + if(aTableNameSeq.hasElements()) + { + aActiveDataTable = aTableNameSeq[0]; + aVal <<= aActiveDataTable; + aPropertySet->setPropertyValue("Command", aVal); + aPropertySet->setPropertyValue("CommandType", Any(CommandType::TABLE)); + //Caching for Performance + aVal <<= sal_Int32(50); + aPropertySet->setPropertyValue("FetchSize", aVal); + OUString aString("SELECT * FROM "); + // quote the table name which may contain catalog.schema.table + Reference<XDatabaseMetaData> xMetaData = xConnection->getMetaData(); + aQuoteChar = xMetaData->getIdentifierQuoteString(); + + OUString sCatalog, sSchema, sName; + ::dbtools::qualifiedNameComponents( xMetaData, aActiveDataTable, sCatalog, sSchema, sName, ::dbtools::EComposeRule::InDataManipulation ); + aString += ::dbtools::composeTableNameForSelect( xConnection, sCatalog, sSchema, sName ); + + m_xParser->setElementaryQuery(aString); + BibConfig* pConfig = BibModul::GetConfig(); + pConfig->setQueryField(getQueryField()); + startQueryWith(pConfig->getQueryText()); + setActiveDataTable(aActiveDataTable); + } + FeatureStateEvent aEvent; + util::URL aURL; + aEvent.IsEnabled = true; + aEvent.Requery = false; + aEvent.FeatureDescriptor = getActiveDataTable(); + + aEvent.State <<= getDataSources(); + + if(pToolbar) + { + aURL.Complete =".uno:Bib/source"; + aEvent.FeatureURL = aURL; + pToolbar->statusChanged( aEvent ); + } + + updateGridModel(); + load(); +} + + +void BibDataManager::setActiveDataTable(const OUString& rTable) +{ + ResetIdentifierMapping(); + try + { + Reference< XPropertySet > aPropertySet( m_xForm, UNO_QUERY ); + + if(aPropertySet.is()) + { + Reference< XConnection > xConnection = getConnection( m_xForm ); + Reference< XTablesSupplier > xSupplyTables(xConnection, UNO_QUERY); + Reference< XNameAccess > xAccess = xSupplyTables->getTables(); + Sequence< OUString > aTableNameSeq = xAccess->getElementNames(); + sal_uInt32 nCount = aTableNameSeq.getLength(); + + const OUString* pTableNames = aTableNameSeq.getConstArray(); + const OUString* pTableNamesEnd = pTableNames + nCount; + + for ( ; pTableNames != pTableNamesEnd; ++pTableNames ) + { + if ( rTable == *pTableNames ) + { + aActiveDataTable = rTable; + Any aVal; aVal <<= rTable; + aPropertySet->setPropertyValue( "Command", aVal ); + break; + } + } + if (pTableNames != pTableNamesEnd) + { + Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData(); + aQuoteChar = xMetaData->getIdentifierQuoteString(); + + Reference< XMultiServiceFactory > xFactory(xConnection, UNO_QUERY); + if ( xFactory.is() ) + m_xParser.set( xFactory->createInstance("com.sun.star.sdb.SingleSelectQueryComposer"), UNO_QUERY ); + + OUString aString("SELECT * FROM "); + + OUString sCatalog, sSchema, sName; + ::dbtools::qualifiedNameComponents( xMetaData, aActiveDataTable, sCatalog, sSchema, sName, ::dbtools::EComposeRule::InDataManipulation ); + aString += ::dbtools::composeTableNameForSelect( xConnection, sCatalog, sSchema, sName ); + + m_xParser->setElementaryQuery(aString); + + BibConfig* pConfig = BibModul::GetConfig(); + pConfig->setQueryField(getQueryField()); + startQueryWith(pConfig->getQueryText()); + + BibDBDescriptor aDesc; + aDesc.sDataSource = aDataSourceURL; + aDesc.sTableOrQuery = aActiveDataTable; + aDesc.nCommandType = CommandType::TABLE; + BibModul::GetConfig()->SetBibliographyURL(aDesc); + } + } + } + catch (const Exception&) + { + OSL_FAIL("::setActiveDataTable: something went wrong !"); + } +} + + +void SAL_CALL BibDataManager::load( ) +{ + if ( isLoaded() ) + // nothing to do + return; + + Reference< XLoadable > xFormAsLoadable( m_xForm, UNO_QUERY ); + DBG_ASSERT( xFormAsLoadable.is() || !m_xForm.is(), "BibDataManager::load: invalid form!"); + if ( xFormAsLoadable.is() ) + { + xFormAsLoadable->load(); + + EventObject aEvt( static_cast< XWeak* >( this ) ); + m_aLoadListeners.notifyEach( &XLoadListener::loaded, aEvt ); + } +} + + +void SAL_CALL BibDataManager::unload( ) +{ + if ( !isLoaded() ) + // nothing to do + return; + + Reference< XLoadable >xFormAsLoadable( m_xForm, UNO_QUERY ); + DBG_ASSERT( xFormAsLoadable.is() || !m_xForm.is(), "BibDataManager::unload: invalid form!"); + if ( !xFormAsLoadable.is() ) + return; + + EventObject aEvt( static_cast< XWeak* >( this ) ); + + { + m_aLoadListeners.notifyEach( &XLoadListener::unloading, aEvt ); + } + + xFormAsLoadable->unload(); + + { + m_aLoadListeners.notifyEach( &XLoadListener::unloaded, aEvt ); + } +} + + +void SAL_CALL BibDataManager::reload( ) +{ + if ( !isLoaded() ) + // nothing to do + return; + + Reference< XLoadable >xFormAsLoadable( m_xForm, UNO_QUERY ); + DBG_ASSERT( xFormAsLoadable.is() || !m_xForm.is(), "BibDataManager::unload: invalid form!"); + if ( !xFormAsLoadable.is() ) + return; + + EventObject aEvt( static_cast< XWeak* >( this ) ); + + { + m_aLoadListeners.notifyEach( &XLoadListener::reloading, aEvt ); + } + + xFormAsLoadable->reload(); + + { + m_aLoadListeners.notifyEach( &XLoadListener::reloaded, aEvt ); + } +} + + +sal_Bool SAL_CALL BibDataManager::isLoaded( ) +{ + Reference< XLoadable >xFormAsLoadable( m_xForm, UNO_QUERY ); + DBG_ASSERT( xFormAsLoadable.is() || !m_xForm.is(), "BibDataManager::isLoaded: invalid form!"); + + bool bLoaded = false; + if ( xFormAsLoadable.is() ) + bLoaded = xFormAsLoadable->isLoaded(); + return bLoaded; +} + + +void SAL_CALL BibDataManager::addLoadListener( const Reference< XLoadListener >& aListener ) +{ + m_aLoadListeners.addInterface( aListener ); +} + + +void SAL_CALL BibDataManager::removeLoadListener( const Reference< XLoadListener >& aListener ) +{ + m_aLoadListeners.removeInterface( aListener ); +} + + +Reference< awt::XControlModel > BibDataManager::createGridModel(const OUString& rName) +{ + Reference< awt::XControlModel > xModel; + + try + { + // create the control model + Reference< XMultiServiceFactory > xMgr = ::comphelper::getProcessServiceFactory(); + Reference< XInterface > xObject = xMgr->createInstance("com.sun.star.form.component.GridControl"); + xModel.set( xObject, UNO_QUERY ); + + // set the + Reference< XPropertySet > xPropSet( xModel, UNO_QUERY ); + xPropSet->setPropertyValue( "Name", Any( rName ) ); + + // set the name of the to-be-created control + Any aAny(OUString("com.sun.star.form.control.InteractionGridControl")); + xPropSet->setPropertyValue( "DefaultControl",aAny ); + + // the helpURL + OUString uProp("HelpURL"); + Reference< XPropertySetInfo > xPropInfo = xPropSet->getPropertySetInfo(); + if (xPropInfo->hasPropertyByName(uProp)) + { + xPropSet->setPropertyValue( + uProp, Any(OUString(INET_HID_SCHEME + HID_BIB_DB_GRIDCTRL))); + } + } + catch (const Exception&) + { + OSL_FAIL("::createGridModel: something went wrong !"); + } + + return xModel; +} + +OUString BibDataManager::getControlName(sal_Int32 nFormatKey ) +{ + OUString aResStr; + switch (nFormatKey) + { + case DataType::BIT: + case DataType::BOOLEAN: + aResStr="CheckBox"; + break; + case DataType::TINYINT: + case DataType::SMALLINT: + case DataType::INTEGER: + aResStr="NumericField"; + break; + case DataType::REAL: + case DataType::DOUBLE: + case DataType::NUMERIC: + case DataType::DECIMAL: + aResStr="FormattedField"; + break; + case DataType::TIMESTAMP: + aResStr="FormattedField"; + break; + case DataType::DATE: + aResStr="DateField"; + break; + case DataType::TIME: + aResStr="TimeField"; + break; + case DataType::CHAR: + case DataType::VARCHAR: + case DataType::LONGVARCHAR: + default: + aResStr="TextField"; + break; + } + return aResStr; +} + +Reference< awt::XControlModel > BibDataManager::loadControlModel( + const OUString& rName, bool bForceListBox) +{ + Reference< awt::XControlModel > xModel; + OUString aName = "View_" + rName; + + try + { + Reference< XNameAccess > xFields = getColumns( m_xForm ); + if (!xFields.is()) + return xModel; + Reference< XPropertySet > xField; + + Any aElement; + + if(xFields->hasByName(rName)) + { + aElement = xFields->getByName(rName); + aElement >>= xField; + + sal_Int32 nFormatKey = 0; + xField->getPropertyValue("Type") >>= nFormatKey; + + OUString aInstanceName("com.sun.star.form.component."); + + if (bForceListBox) + aInstanceName += "ListBox"; + else + aInstanceName += getControlName(nFormatKey); + + Reference< XComponentContext > xContext = comphelper::getProcessComponentContext(); + Reference< XInterface > xObject = xContext->getServiceManager()->createInstanceWithContext(aInstanceName, xContext); + xModel.set( xObject, UNO_QUERY ); + Reference< XPropertySet > xPropSet( xModel, UNO_QUERY ); + Any aFieldName; aFieldName <<= aName; + + xPropSet->setPropertyValue( FM_PROP_NAME,aFieldName); + xPropSet->setPropertyValue( FM_PROP_CONTROLSOURCE, Any( rName ) ); + xPropSet->setPropertyValue("NativeWidgetLook", Any( true ) ); + + if (bForceListBox) + { + uno::Any aAny; + + //uno::Reference< beans::XPropertySet > xPropSet(xControl, UNO_QUERY); + aAny <<= sal_Int16(1); + xPropSet->setPropertyValue("BoundColumn", aAny); + aAny <<= ListSourceType_VALUELIST; + xPropSet->setPropertyValue("ListSourceType", aAny); + + uno::Sequence<OUString> aListSource(TYPE_COUNT); + OUString* pListSourceArr = aListSource.getArray(); + //pListSourceArr[0] = "select TypeName, TypeIndex from TypeNms"; + for(sal_Int32 i = 0; i < TYPE_COUNT; ++i) + pListSourceArr[i] = OUString::number(i); + aAny <<= aListSource; + + xPropSet->setPropertyValue("ListSource", aAny); + + uno::Sequence<OUString> aValues(TYPE_COUNT + 1); + OUString* pValuesArr = aValues.getArray(); + pValuesArr[0] = BibResId(ST_TYPE_ARTICLE); + pValuesArr[1] = BibResId(ST_TYPE_BOOK); + pValuesArr[2] = BibResId(ST_TYPE_BOOKLET); + pValuesArr[3] = BibResId(ST_TYPE_CONFERENCE); + pValuesArr[4] = BibResId(ST_TYPE_INBOOK ); + pValuesArr[5] = BibResId(ST_TYPE_INCOLLECTION); + pValuesArr[6] = BibResId(ST_TYPE_INPROCEEDINGS); + pValuesArr[7] = BibResId(ST_TYPE_JOURNAL ); + pValuesArr[8] = BibResId(ST_TYPE_MANUAL ); + pValuesArr[9] = BibResId(ST_TYPE_MASTERSTHESIS); + pValuesArr[10] = BibResId(ST_TYPE_MISC ); + pValuesArr[11] = BibResId(ST_TYPE_PHDTHESIS ); + pValuesArr[12] = BibResId(ST_TYPE_PROCEEDINGS ); + pValuesArr[13] = BibResId(ST_TYPE_TECHREPORT ); + pValuesArr[14] = BibResId(ST_TYPE_UNPUBLISHED ); + pValuesArr[15] = BibResId(ST_TYPE_EMAIL ); + pValuesArr[16] = BibResId(ST_TYPE_WWW ); + pValuesArr[17] = BibResId(ST_TYPE_CUSTOM1 ); + pValuesArr[18] = BibResId(ST_TYPE_CUSTOM2 ); + pValuesArr[19] = BibResId(ST_TYPE_CUSTOM3 ); + pValuesArr[20] = BibResId(ST_TYPE_CUSTOM4 ); + pValuesArr[21] = BibResId(ST_TYPE_CUSTOM5 ); + // empty string if an invalid value no values is set + pValuesArr[TYPE_COUNT].clear(); + + aAny <<= aValues; + + xPropSet->setPropertyValue("StringItemList", aAny); + + xPropSet->setPropertyValue( "Dropdown", Any(true) ); + } + + Reference< XFormComponent > aFormComp(xModel,UNO_QUERY ); + + Reference< XNameContainer > xNameCont( m_xForm, UNO_QUERY ); + xNameCont->insertByName(aName, Any( aFormComp ) ); + + // now if the form where we inserted the new model is already loaded, notify the model of this + // Note that this implementation below is a HACK as it relies on the fact that the model adds itself + // as load listener to its parent, which is an implementation detail of the model. + // + // the better solution would be the following: + // in the current scenario, we insert a control model into a form. This results in the control model + // adding itself as load listener to the form. Now, the form should realize that it's already loaded + // and notify the model (which it knows as XLoadListener only) immediately. This seems to make sense. + // (as an analogon to the XStatusListener semantics). + // + // But this would be way too risky for this last-day fix here. + Reference< XLoadable > xLoad( m_xForm, UNO_QUERY ); + if ( xLoad.is() && xLoad->isLoaded() ) + { + Reference< XLoadListener > xListener( aFormComp, UNO_QUERY ); + if ( xListener.is() ) + { + EventObject aLoadSource; + aLoadSource.Source = xLoad; + xListener->loaded( aLoadSource ); + } + } + } + } + catch (const Exception&) + { + OSL_FAIL("::loadControlModel: something went wrong !"); + } + return xModel; +} + +void BibDataManager::CreateMappingDialog(weld::Window* pParent) +{ + MappingDialog_Impl aDlg(pParent, this); + if (RET_OK == aDlg.run() && pBibView) + { + reload(); + } +} + +OUString BibDataManager::CreateDBChangeDialog(weld::Window* pParent) +{ + OUString uRet; + DBChangeDialog_Impl aDlg(pParent, this); + if (aDlg.run() == RET_OK) + { + OUString sNewURL = aDlg.GetCurrentURL(); + if(sNewURL != getActiveDataSource()) + { + uRet = sNewURL; + } + } + return uRet; +} + +void BibDataManager::DispatchDBChangeDialog() +{ + if (pToolbar) + pToolbar->SendDispatch(pToolbar->GetChangeSourceId(), Sequence< PropertyValue >()); +} + +const OUString& BibDataManager::GetIdentifierMapping() +{ + if(sIdentifierMapping.isEmpty()) + { + BibConfig* pConfig = BibModul::GetConfig(); + BibDBDescriptor aDesc; + aDesc.sDataSource = getActiveDataSource(); + aDesc.sTableOrQuery = getActiveDataTable(); + aDesc.nCommandType = CommandType::TABLE; + const Mapping* pMapping = pConfig->GetMapping(aDesc); + sIdentifierMapping = pConfig->GetDefColumnName(IDENTIFIER_POS); + if(pMapping) + { + for(const auto & aColumnPair : pMapping->aColumnPairs) + { + if(aColumnPair.sLogicalColumnName == sIdentifierMapping) + { + sIdentifierMapping = aColumnPair.sRealColumnName; + break; + } + } + } + } + return sIdentifierMapping; +} + +void BibDataManager::SetToolbar(BibToolBar* pSet) +{ + pToolbar = pSet; + if(pToolbar) + pToolbar->SetDatMan(*this); +} + +uno::Reference< form::runtime::XFormController > const & BibDataManager::GetFormController() +{ + if(!m_xFormCtrl.is()) + { + Reference< uno::XComponentContext > xContext = comphelper::getProcessComponentContext(); + m_xFormCtrl = form::runtime::FormController::create(xContext); + m_xFormCtrl->setModel(uno::Reference< awt::XTabControllerModel > (getForm(), UNO_QUERY)); + m_xFormDispatch.set( m_xFormCtrl, UNO_QUERY); + } + return m_xFormCtrl; +} + +void BibDataManager::RegisterInterceptor( const ::bib::BibBeamer* pBibBeamer) +{ + DBG_ASSERT( !m_xInterceptorHelper.is(), "BibDataManager::RegisterInterceptor: called twice!" ); + + if( pBibBeamer ) + m_xInterceptorHelper = new BibInterceptorHelper( pBibBeamer, m_xFormDispatch); +} + + +bool BibDataManager::HasActiveConnection() const +{ + return getConnection( m_xForm ).is(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/bibliography/datman.hxx b/extensions/source/bibliography/datman.hxx new file mode 100644 index 000000000..36cbdcd59 --- /dev/null +++ b/extensions/source/bibliography/datman.hxx @@ -0,0 +1,169 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include "bibview.hxx" + +#include <com/sun/star/awt/XControlModel.hpp> +#include <com/sun/star/form/XForm.hpp> +#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp> +#include <com/sun/star/form/runtime/XFormController.hpp> +#include <cppuhelper/compbase.hxx> +#include <comphelper/interfacecontainer2.hxx> +#include <com/sun/star/form/XLoadable.hpp> +#include <comphelper/broadcasthelper.hxx> +#include <com/sun/star/frame/XDispatchProviderInterceptor.hpp> +#include <com/sun/star/frame/XDispatchProviderInterception.hpp> +#include <cppuhelper/implbase.hxx> +#include <vcl/vclptr.hxx> + +namespace weld { class Window; } + +namespace bib +{ + class BibView; + class BibBeamer; +} + +class BibToolBar; +struct BibDBDescriptor; + +class BibInterceptorHelper + :public cppu::WeakImplHelper< css::frame::XDispatchProviderInterceptor > +{ +private: + css::uno::Reference< css::frame::XDispatchProvider > xMasterDispatchProvider; + css::uno::Reference< css::frame::XDispatchProvider > xSlaveDispatchProvider; + css::uno::Reference< css::frame::XDispatch > xFormDispatch; + css::uno::Reference< css::frame::XDispatchProviderInterception > xInterception; + +protected: + virtual ~BibInterceptorHelper( ) override; + +public: + BibInterceptorHelper( const ::bib::BibBeamer* pBibBeamer, css::uno::Reference< css::frame::XDispatch > const & xDispatch); + + void ReleaseInterceptor(); + + // XDispatchProvider + virtual css::uno::Reference< css::frame::XDispatch > SAL_CALL queryDispatch( const css::util::URL& aURL, const OUString& aTargetFrameName, sal_Int32 nSearchFlags ) override; + virtual css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL queryDispatches( const css::uno::Sequence< css::frame::DispatchDescriptor >& aDescripts ) override; + // XDispatchProviderInterceptor + virtual css::uno::Reference< css::frame::XDispatchProvider > SAL_CALL getSlaveDispatchProvider( ) override; + virtual void SAL_CALL setSlaveDispatchProvider( const css::uno::Reference< css::frame::XDispatchProvider >& xNewSlaveDispatchProvider ) override; + virtual css::uno::Reference< css::frame::XDispatchProvider > SAL_CALL getMasterDispatchProvider( ) override; + virtual void SAL_CALL setMasterDispatchProvider( const css::uno::Reference< css::frame::XDispatchProvider >& xNewMasterDispatchProvider ) override; +}; + +typedef cppu::WeakComponentImplHelper < css::form::XLoadable + > BibDataManager_Base; +class BibDataManager final + :public ::comphelper::OMutexAndBroadcastHelper + ,public BibDataManager_Base +{ +private: + css::uno::Reference< css::form::XForm > m_xForm; + css::uno::Reference< css::awt::XControlModel > m_xGridModel; + css::uno::Reference< css::sdb::XSingleSelectQueryComposer > m_xParser; + css::uno::Reference< css::form::runtime::XFormController > m_xFormCtrl; + css::uno::Reference< css::frame::XDispatch > m_xFormDispatch; + rtl::Reference<BibInterceptorHelper> m_xInterceptorHelper; + + OUString aActiveDataTable; + OUString aDataSourceURL; + OUString aQuoteChar; + + ::comphelper::OInterfaceContainerHelper2 m_aLoadListeners; + + VclPtr< ::bib::BibView> pBibView; + VclPtr<BibToolBar> pToolbar; + + OUString sIdentifierMapping; + + void InsertFields(const css::uno::Reference< css::form::XFormComponent > & xGrid); + + css::uno::Reference< css::awt::XControlModel > const & + updateGridModel(const css::uno::Reference< css::form::XForm > & xDbForm); + static css::uno::Reference< css::awt::XControlModel > + createGridModel( const OUString& rName ); + + // XLoadable + virtual void SAL_CALL load( ) override; + virtual void SAL_CALL unload( ) override; + virtual void SAL_CALL reload( ) override; + virtual sal_Bool SAL_CALL isLoaded( ) override; + virtual void SAL_CALL addLoadListener( const css::uno::Reference< css::form::XLoadListener >& aListener ) override; + virtual void SAL_CALL removeLoadListener( const css::uno::Reference< css::form::XLoadListener >& aListener ) override; + + using WeakComponentImplHelperBase::disposing; + +public: + + BibDataManager(); + virtual ~BibDataManager() override; + + css::uno::Reference< css::form::XForm > createDatabaseForm( BibDBDescriptor& aDesc); + + css::uno::Reference< css::awt::XControlModel > updateGridModel(); + + css::uno::Sequence< OUString> getDataSources() const; + + const OUString& getActiveDataSource() const {return aDataSourceURL;} + void setActiveDataSource(const OUString& rURL); + + const OUString& getActiveDataTable() const { return aActiveDataTable;} + void setActiveDataTable(const OUString& rTable); + + void setFilter(const OUString& rQuery); + OUString getFilter() const; + + css::uno::Sequence< OUString> getQueryFields() const; + OUString getQueryField() const; + void startQueryWith(const OUString& rQuery); + + const css::uno::Reference< css::sdb::XSingleSelectQueryComposer >& getParser() const { return m_xParser; } + const css::uno::Reference< css::form::XForm >& getForm() const { return m_xForm; } + + + static OUString getControlName(sal_Int32 nFormatKey ); + + css::uno::Reference< css::awt::XControlModel > loadControlModel(const OUString& rName, + bool bForceListBox); + + void CreateMappingDialog(weld::Window* pParent); + OUString CreateDBChangeDialog(weld::Window* pParent); + + void DispatchDBChangeDialog(); + + void SetView( ::bib::BibView* pView ) { pBibView = pView; } + + void SetToolbar(BibToolBar* pSet); + + const OUString& GetIdentifierMapping(); + void ResetIdentifierMapping() {sIdentifierMapping.clear();} + + css::uno::Reference< css::form::runtime::XFormController > const & GetFormController(); + void RegisterInterceptor( const ::bib::BibBeamer* pBibBeamer); + + bool HasActiveConnection() const; +}; + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/bibliography/formcontrolcontainer.cxx b/extensions/source/bibliography/formcontrolcontainer.cxx new file mode 100644 index 000000000..c6ec73700 --- /dev/null +++ b/extensions/source/bibliography/formcontrolcontainer.cxx @@ -0,0 +1,136 @@ +/* -*- 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 "formcontrolcontainer.hxx" +#include <sal/log.hxx> +#include <tools/diagnose_ex.h> + +#include <algorithm> + +namespace bib +{ + + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::form; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::awt; + + FormControlContainer::FormControlContainer( ) + :OLoadListener( m_aMutex ) + { + } + + FormControlContainer::~FormControlContainer( ) + { + SAL_WARN_IF( isFormConnected(), "extensions.biblio", "FormControlContainer::~FormControlContainer: you should disconnect in your derived class!" ); + if ( isFormConnected() ) + disconnectForm(); + } + + void FormControlContainer::disconnectForm() + { + ::osl::MutexGuard aGuard( m_aMutex ); + SAL_WARN_IF( !isFormConnected(), "extensions.biblio", "FormControlContainer::connectForm: not connected!" ); + if ( isFormConnected() ) + { + m_xFormAdapter->dispose(); + m_xFormAdapter.clear(); + } + } + + void FormControlContainer::connectForm( const Reference< XLoadable >& _rxForm ) + { + SAL_WARN_IF( isFormConnected(), "extensions.biblio", "FormControlContainer::connectForm: already connected!" ); + + SAL_WARN_IF( !_rxForm.is(), "extensions.biblio", "FormControlContainer::connectForm: invalid form!" ); + if ( !isFormConnected() && _rxForm.is() ) + { + m_xFormAdapter = new OLoadListenerAdapter( _rxForm ); + m_xFormAdapter->Init( this ); + + implSetDesignMode( !m_xForm.is() || !m_xForm->isLoaded() ); + } + + m_xForm = _rxForm; + } + + namespace { + + struct ControlModeSwitch + { + bool bDesign; + explicit ControlModeSwitch( bool _bDesign ) : bDesign( _bDesign ) { } + + void operator() ( const Reference< XControl >& _rxControl ) const + { + if ( _rxControl.is() ) + _rxControl->setDesignMode( bDesign ); + } + }; + + } + + void FormControlContainer::implSetDesignMode( bool _bDesign ) + { + try + { + Reference< XControlContainer > xControlCont = getControlContainer(); + if ( xControlCont.is() ) + { + const Sequence<Reference<XControl>> aControls = xControlCont->getControls(); + + std::for_each( + aControls.begin(), + aControls.end(), + ControlModeSwitch( _bDesign ) + ); + } + } + catch( const Exception&) + { + TOOLS_WARN_EXCEPTION( "extensions.biblio", "FormControlContainer::implSetDesignMode" ); + } + } + + void FormControlContainer::_loaded( const css::lang::EventObject& /*_rEvent*/ ) + { + implSetDesignMode( false ); + } + + void FormControlContainer::_unloading( const css::lang::EventObject& /*_rEvent*/ ) + { + implSetDesignMode( true ); + } + + void FormControlContainer::_reloading( const css::lang::EventObject& /*_rEvent*/ ) + { + implSetDesignMode( true ); + } + + void FormControlContainer::_reloaded( const css::lang::EventObject& /*_rEvent*/ ) + { + implSetDesignMode( false ); + } + + +} // namespace bib + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/bibliography/formcontrolcontainer.hxx b/extensions/source/bibliography/formcontrolcontainer.hxx new file mode 100644 index 000000000..b15105ad0 --- /dev/null +++ b/extensions/source/bibliography/formcontrolcontainer.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 . + */ + +#pragma once + +#include <cppuhelper/basemutex.hxx> +#include "loadlisteneradapter.hxx" +#include <com/sun/star/awt/XControlContainer.hpp> +#include <rtl/ref.hxx> + + +namespace bib +{ + + class FormControlContainer + :public ::cppu::BaseMutex + ,public ::bib::OLoadListener + { + private: + rtl::Reference<OLoadListenerAdapter> m_xFormAdapter; + css::uno::Reference< css::form::XLoadable > m_xForm; + private: + void implSetDesignMode( bool _bDesign ); + + protected: + FormControlContainer( ); + virtual ~FormControlContainer( ) override; + + bool isFormConnected() const { return m_xFormAdapter.is(); } + void connectForm( const css::uno::Reference< css::form::XLoadable >& _rxForm ); + void disconnectForm(); + + virtual css::uno::Reference< css::awt::XControlContainer > + getControlContainer() = 0; + + protected: + // XLoadListener equivalents + virtual void _loaded( const css::lang::EventObject& _rEvent ) override; + virtual void _unloading( const css::lang::EventObject& _rEvent ) override; + virtual void _reloading( const css::lang::EventObject& _rEvent ) override; + virtual void _reloaded( const css::lang::EventObject& _rEvent ) override; + + }; + + +} // namespace bib + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/bibliography/framectr.cxx b/extensions/source/bibliography/framectr.cxx new file mode 100644 index 000000000..a273635d9 --- /dev/null +++ b/extensions/source/bibliography/framectr.cxx @@ -0,0 +1,869 @@ +/* -*- 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 <comphelper/types.hxx> +#include <comphelper/propertyvalue.hxx> +#include <comphelper/sequence.hxx> +#include "framectr.hxx" +#include "datman.hxx" +#include <toolkit/helper/vclunohelper.hxx> +#include "bibconfig.hxx" +#include <cppuhelper/implbase.hxx> +#include <vcl/event.hxx> +#include <vcl/svapp.hxx> +#include <comphelper/processfactory.hxx> +#include <com/sun/star/awt/XTextComponent.hpp> +#include <com/sun/star/form/XConfirmDeleteListener.hpp> +#include <com/sun/star/form/runtime/XFormController.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp> +#include <com/sun/star/sdbcx/Privilege.hpp> +#include <com/sun/star/sdbc/XResultSetUpdate.hpp> +#include <com/sun/star/sdb/FilterDialog.hpp> +#include <com/sun/star/sdb/RowChangeAction.hpp> +#include <com/sun/star/frame/CommandGroup.hpp> +#include <com/sun/star/datatransfer/clipboard/XClipboard.hpp> +#include <comphelper/multicontainer2.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <sot/exchange.hxx> +#include <sot/formats.hxx> +#include <tools/diagnose_ex.h> +#include <vcl/weld.hxx> +#include <osl/mutex.hxx> + +#include <unordered_map> + +using namespace osl; +using namespace cppu; +using namespace com::sun::star::sdbc; +using namespace com::sun::star::frame; +using namespace com::sun::star::uno; +using namespace com::sun::star; + +namespace { + +struct DispatchInfo +{ + const char* pCommand; + sal_Int16 nGroupId; + bool bActiveConnection; +}; + +struct CacheDispatchInfo +{ + sal_Int16 nGroupId; + bool bActiveConnection; +}; + +} + +// Attention: commands must be sorted by command groups. Implementation is dependent +// on this!! +const DispatchInfo SupportedCommandsArray[] = +{ + { ".uno:Undo" , frame::CommandGroup::EDIT , false }, + { ".uno:Cut" , frame::CommandGroup::EDIT , false }, + { ".uno:Copy" , frame::CommandGroup::EDIT , false }, + { ".uno:Paste" , frame::CommandGroup::EDIT , false }, + { ".uno:SelectAll" , frame::CommandGroup::EDIT , false }, + { ".uno:CloseDoc" , frame::CommandGroup::DOCUMENT , false }, + { ".uno:StatusBarVisible" , frame::CommandGroup::VIEW , false }, + { ".uno:AvailableToolbars" , frame::CommandGroup::VIEW , false }, + { ".uno:Bib/standardFilter" , frame::CommandGroup::DATA , true }, + { ".uno:Bib/DeleteRecord" , frame::CommandGroup::DATA , true }, + { ".uno:Bib/InsertRecord" , frame::CommandGroup::DATA , true }, + { ".uno:Bib/query" , frame::CommandGroup::DATA , true }, + { ".uno:Bib/autoFilter" , frame::CommandGroup::DATA , true }, + { ".uno:Bib/source" , frame::CommandGroup::DATA , true }, + { ".uno:Bib/removeFilter" , frame::CommandGroup::DATA , true }, + { ".uno:Bib/sdbsource" , frame::CommandGroup::DATA , true }, + { ".uno:Bib/Mapping" , frame::CommandGroup::DATA , true }, +}; + +typedef std::unordered_map< OUString, CacheDispatchInfo > CmdToInfoCache; + +static const CmdToInfoCache& GetCommandToInfoCache() +{ + static CmdToInfoCache aCmdToInfoCache = []() { + CmdToInfoCache aCache; + for (const auto& command : SupportedCommandsArray) + { + OUString aCommand(OUString::createFromAscii(command.pCommand)); + + CacheDispatchInfo aDispatchInfo; + aDispatchInfo.nGroupId = command.nGroupId; + aDispatchInfo.bActiveConnection = command.bActiveConnection; + aCache.emplace(aCommand, aDispatchInfo); + } + return aCache; + }(); + + return aCmdToInfoCache; +} + + +class BibFrameCtrl_Impl : public cppu::WeakImplHelper < XFrameActionListener > +{ +public: + Mutex aMutex; + comphelper::OMultiTypeInterfaceContainerHelper2 aLC; + + BibFrameController_Impl* pController; + + BibFrameCtrl_Impl() + : aLC( aMutex ) + , pController(nullptr) + {} + + virtual void SAL_CALL frameAction(const FrameActionEvent& aEvent) override; + virtual void SAL_CALL disposing( const lang::EventObject& Source ) override; +}; + +void BibFrameCtrl_Impl::frameAction(const FrameActionEvent& ) +{ +} + +void BibFrameCtrl_Impl::disposing( const lang::EventObject& /*Source*/ ) +{ + ::SolarMutexGuard aGuard; + if ( pController ) + pController->getFrame()->removeFrameActionListener( this ); +} + +BibFrameController_Impl::BibFrameController_Impl( const uno::Reference< awt::XWindow > & xComponent, + BibDataManager* pDataManager) + :m_xWindow( xComponent ) + ,m_xDatMan( pDataManager ) +{ + m_bDisposing = false; + m_xImpl = new BibFrameCtrl_Impl; + m_xImpl->pController = this; +} + +BibFrameController_Impl::~BibFrameController_Impl() +{ + m_xImpl->pController = nullptr; + m_xDatMan.clear(); +} + +OUString SAL_CALL BibFrameController_Impl::getImplementationName() +{ + return "com.sun.star.comp.extensions.Bibliography"; +} + +sal_Bool SAL_CALL BibFrameController_Impl::supportsService( const OUString& sServiceName ) +{ + return cppu::supportsService( this, sServiceName ); +} + +css::uno::Sequence< OUString > SAL_CALL BibFrameController_Impl::getSupportedServiceNames() +{ + // return only top level services ... + // base services are included there and should be asked by uno-rtti. + return { "com.sun.star.frame.Bibliography" }; +} + +void BibFrameController_Impl::attachFrame( const uno::Reference< XFrame > & xArg ) +{ + m_xFrame = xArg; + m_xFrame->addFrameActionListener( m_xImpl ); +} + +sal_Bool BibFrameController_Impl::attachModel( const uno::Reference< XModel > & /*xModel*/ ) +{ + return false; +} + +sal_Bool BibFrameController_Impl::suspend( sal_Bool bSuspend ) +{ + if ( bSuspend ) + getFrame()->removeFrameActionListener( m_xImpl ); + else + getFrame()->addFrameActionListener( m_xImpl ); + return true; +} + +uno::Any BibFrameController_Impl::getViewData() +{ + return uno::Any(); +} + +void BibFrameController_Impl::restoreViewData( const uno::Any& /*Value*/ ) +{ +} + +uno::Reference< XFrame > BibFrameController_Impl::getFrame() +{ + return m_xFrame; +} + +uno::Reference< XModel > BibFrameController_Impl::getModel() +{ + return uno::Reference< XModel > (); +} + +void BibFrameController_Impl::dispose() +{ + m_bDisposing = true; + lang::EventObject aObject; + uno::Reference< XFrame > xFrame = getFrame(); + + if (xFrame.is()) + xFrame->removeFrameActionListener( m_xImpl ); + + aObject.Source = static_cast<XController*>(this); + m_xImpl->aLC.disposeAndClear(aObject); + m_xDatMan.clear(); + m_aStatusListeners.clear(); + m_xLastQueriedFocusWin.clear(); +} + +void BibFrameController_Impl::addEventListener( const uno::Reference< lang::XEventListener > & aListener ) +{ + m_xImpl->aLC.addInterface( cppu::UnoType<lang::XEventListener>::get(), aListener ); +} + +void BibFrameController_Impl::removeEventListener( const uno::Reference< lang::XEventListener > & aListener ) +{ + m_xImpl->aLC.removeInterface( cppu::UnoType<lang::XEventListener>::get(), aListener ); +} + +uno::Reference< frame::XDispatch > BibFrameController_Impl::queryDispatch( const util::URL& aURL, const OUString& /*aTarget*/, sal_Int32 /*nSearchFlags*/ ) +{ + if ( !m_bDisposing ) + { + const CmdToInfoCache& rCmdCache = GetCommandToInfoCache(); + CmdToInfoCache::const_iterator pIter = rCmdCache.find( aURL.Complete ); + if ( pIter != rCmdCache.end() ) + { + if (( m_xDatMan->HasActiveConnection() ) || + ( !pIter->second.bActiveConnection )) + return static_cast<frame::XDispatch*>(this); + } + } + + return uno::Reference< frame::XDispatch > (); +} + +uno::Sequence<uno::Reference< XDispatch > > BibFrameController_Impl::queryDispatches( const uno::Sequence<DispatchDescriptor>& aDescripts ) +{ + uno::Sequence< uno::Reference< XDispatch > > aDispatches( aDescripts.getLength() ); + auto aDispatchesRange = asNonConstRange(aDispatches); + for ( sal_Int32 i=0; i<aDescripts.getLength(); ++i ) + aDispatchesRange[i] = queryDispatch( aDescripts[i].FeatureURL, aDescripts[i].FrameName, aDescripts[i].SearchFlags ); + return aDispatches; +} + +uno::Sequence< ::sal_Int16 > SAL_CALL BibFrameController_Impl::getSupportedCommandGroups() +{ + uno::Sequence< ::sal_Int16 > aDispatchInfo{ frame::CommandGroup::EDIT, + frame::CommandGroup::DOCUMENT, + frame::CommandGroup::DATA, + frame::CommandGroup::VIEW }; + + return aDispatchInfo; +} + +uno::Sequence< frame::DispatchInformation > SAL_CALL BibFrameController_Impl::getConfigurableDispatchInformation( ::sal_Int16 nCommandGroup ) +{ + const CmdToInfoCache& rCmdCache = GetCommandToInfoCache(); + + frame::DispatchInformation aDispatchInfo; + std::vector< frame::DispatchInformation > aDispatchInfoVector; + + if (( nCommandGroup == frame::CommandGroup::EDIT ) || + ( nCommandGroup == frame::CommandGroup::DOCUMENT ) || + ( nCommandGroup == frame::CommandGroup::DATA ) || + ( nCommandGroup == frame::CommandGroup::VIEW )) + { + bool bGroupFound = false; + for (auto const& item : rCmdCache) + { + if ( item.second.nGroupId == nCommandGroup ) + { + bGroupFound = true; + aDispatchInfo.Command = item.first; + aDispatchInfo.GroupId = item.second.nGroupId; + aDispatchInfoVector.push_back( aDispatchInfo ); + } + else if ( bGroupFound ) + break; + } + } + + return comphelper::containerToSequence( aDispatchInfoVector ); +} + +static bool canInsertRecords(const Reference< beans::XPropertySet>& _rxCursorSet) +{ + sal_Int32 nPriv = 0; + _rxCursorSet->getPropertyValue("Privileges") >>= nPriv; + return _rxCursorSet.is() && (nPriv & sdbcx::Privilege::INSERT) != 0; +} + +bool BibFrameController_Impl::SaveModified(const Reference< form::runtime::XFormController>& xController) +{ + if (!xController.is()) + return false; + + Reference< XResultSetUpdate> _xCursor(xController->getModel(), UNO_QUERY); + + if (!_xCursor.is()) + return false; + + Reference< beans::XPropertySet> _xSet(_xCursor, UNO_QUERY); + if (!_xSet.is()) + return false; + + // need to save? + bool bIsNew = ::comphelper::getBOOL(_xSet->getPropertyValue("IsNew")); + bool bIsModified = ::comphelper::getBOOL(_xSet->getPropertyValue("IsModified")); + bool bResult = !bIsModified; + if (bIsModified) + { + try + { + if (bIsNew) + _xCursor->insertRow(); + else + _xCursor->updateRow(); + bResult = true; + } + catch(const Exception&) + { + TOOLS_WARN_EXCEPTION("extensions.biblio", ""); + } + } + return bResult; +} + +static vcl::Window* lcl_GetFocusChild( vcl::Window const * pParent ) +{ + sal_uInt16 nChildren = pParent->GetChildCount(); + for( sal_uInt16 nChild = 0; nChild < nChildren; ++nChild) + { + vcl::Window* pChild = pParent->GetChild( nChild ); + if(pChild->HasFocus()) + return pChild; + vcl::Window* pSubChild = lcl_GetFocusChild( pChild ); + if(pSubChild) + return pSubChild; + } + return nullptr; +} + +//class XDispatch +void BibFrameController_Impl::dispatch(const util::URL& _rURL, const uno::Sequence< beans::PropertyValue >& aArgs) +{ + if ( m_bDisposing ) + return; + + ::SolarMutexGuard aGuard; + weld::Window* pParent = Application::GetFrameWeld(m_xWindow); + weld::WaitObject aWaitObject(pParent); + + OUString aCommand( _rURL.Path); + if(aCommand == "Bib/Mapping") + { + m_xDatMan->CreateMappingDialog(pParent); + } + else if(aCommand == "Bib/source") + { + ChangeDataSource(aArgs); + } + else if(aCommand == "Bib/sdbsource") + { + OUString aURL = m_xDatMan->CreateDBChangeDialog(pParent); + if(!aURL.isEmpty()) + { + try + { + uno::Sequence< beans::PropertyValue > aNewDataSource + { + comphelper::makePropertyValue( {}, OUString() ), + comphelper::makePropertyValue( {}, aURL ) + }; + ChangeDataSource(aNewDataSource); + } + catch(const Exception&) + { + TOOLS_WARN_EXCEPTION("extensions.biblio", + "Exception caught while changing the data source"); + } + } + } + else if(aCommand == "Bib/autoFilter") + { + sal_uInt16 nCount = m_aStatusListeners.size(); + for ( sal_uInt16 n=0; n<nCount; n++ ) + { + BibStatusDispatch *pObj = m_aStatusListeners[n].get(); + if ( pObj->aURL.Path == "Bib/removeFilter" ) + { + FeatureStateEvent aEvent; + aEvent.FeatureURL = pObj->aURL; + aEvent.IsEnabled = true; + aEvent.Requery = false; + aEvent.Source = static_cast<XDispatch *>(this); + pObj->xListener->statusChanged( aEvent ); + //break; because there are more than one + } + } + + const beans::PropertyValue* pPropertyValue = aArgs.getConstArray(); + uno::Any aValue=pPropertyValue[0].Value; + OUString aQuery; + aValue >>= aQuery; + + aValue=pPropertyValue[1].Value; + OUString aQueryField; + aValue >>= aQueryField; + BibConfig* pConfig = BibModul::GetConfig(); + pConfig->setQueryField(aQueryField); + m_xDatMan->startQueryWith(aQuery); + } + else if(aCommand == "Bib/standardFilter") + { + try + { + uno::Reference< uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext(); + + // create the dialog object + uno::Reference< ui::dialogs::XExecutableDialog > xDialog = sdb::FilterDialog::createWithQuery(xContext, m_xDatMan->getParser(), + Reference<sdbc::XRowSet>(m_xDatMan->getForm(), uno::UNO_QUERY_THROW), m_xWindow); + // execute it + if ( xDialog->execute( ) ) + { + // the dialog has been executed successfully, and the filter on the query composer + // has been changed + OUString sNewFilter = m_xDatMan->getParser()->getFilter(); + m_xDatMan->setFilter( sNewFilter ); + } + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION( "extensions.biblio", "BibFrameController_Impl::dispatch" ); + } + + sal_uInt16 nCount = m_aStatusListeners.size(); + for ( sal_uInt16 n=0; n<nCount; n++ ) + { + BibStatusDispatch *pObj = m_aStatusListeners[n].get(); + if ( pObj->aURL.Path == "Bib/removeFilter" && m_xDatMan->getParser().is()) + { + FeatureStateEvent aEvent; + aEvent.FeatureURL = pObj->aURL; + aEvent.IsEnabled = !m_xDatMan->getParser()->getFilter().isEmpty(); + aEvent.Requery = false; + aEvent.Source = static_cast<XDispatch *>(this); + pObj->xListener->statusChanged( aEvent ); + } + } + } + else if(aCommand == "Bib/removeFilter") + { + RemoveFilter(); + } + else if( _rURL.Complete == "slot:5503" || aCommand == "CloseDoc" ) + { + Application::PostUserEvent( LINK( this, BibFrameController_Impl, + DisposeHdl ) ); + + } + else if(aCommand == "Bib/InsertRecord") + { + Reference<form::runtime::XFormController > xFormCtrl = m_xDatMan->GetFormController(); + if(SaveModified(xFormCtrl)) + { + try + { + Reference< sdbc::XResultSet > xCursor( m_xDatMan->getForm(), UNO_QUERY ); + xCursor->last(); + + Reference< XResultSetUpdate > xUpdateCursor( m_xDatMan->getForm(), UNO_QUERY ); + xUpdateCursor->moveToInsertRow(); + } + catch(const Exception&) + { + TOOLS_WARN_EXCEPTION("extensions.biblio", + "Exception in last() or moveToInsertRow()"); + } + } + } + else if(aCommand == "Bib/DeleteRecord") + { + Reference< css::sdbc::XResultSet > xCursor(m_xDatMan->getForm(), UNO_QUERY); + Reference< XResultSetUpdate > xUpdateCursor(xCursor, UNO_QUERY); + Reference< beans::XPropertySet > xSet(m_xDatMan->getForm(), UNO_QUERY); + bool bIsNew = ::comphelper::getBOOL(xSet->getPropertyValue("IsNew")); + if(!bIsNew) + { + sal_uInt32 nCount = 0; + xSet->getPropertyValue("RowCount") >>= nCount; + // determine next position + bool bSuccess = false; + bool bLeft = false; + bool bRight = false; + try + { + bLeft = xCursor->isLast() && nCount > 1; + bRight= !xCursor->isLast(); + // ask for confirmation + Reference< form::XConfirmDeleteListener > xConfirm(m_xDatMan->GetFormController(),UNO_QUERY); + if (xConfirm.is()) + { + sdb::RowChangeEvent aEvent; + aEvent.Source.set(xCursor, UNO_QUERY); + aEvent.Action = sdb::RowChangeAction::DELETE; + aEvent.Rows = 1; + bSuccess = xConfirm->confirmDelete(aEvent); + } + + // delete it + if (bSuccess) + xUpdateCursor->deleteRow(); + } + catch(const Exception&) + { + bSuccess = false; + } + if (bSuccess) + { + if (bLeft || bRight) + xCursor->relative(bRight ? 1 : -1); + else + { + bool bCanInsert = canInsertRecords(xSet); + // can another entry be inserted? + try + { + if (bCanInsert) + xUpdateCursor->moveToInsertRow(); + else + // move data entry to reset state + xCursor->first(); + } + catch(const Exception&) + { + TOOLS_WARN_EXCEPTION("extensions.biblio", + "DeleteRecord: exception caught!"); + } + } + } + } + } + else if(aCommand == "Cut") + { + vcl::Window* pChild = m_xLastQueriedFocusWin.get(); + if(pChild) + { + KeyEvent aEvent( 0, KeyFuncType::CUT ); + pChild->KeyInput( aEvent ); + } + } + else if(aCommand == "Copy") + { + vcl::Window* pChild = m_xLastQueriedFocusWin.get(); + if(pChild) + { + KeyEvent aEvent( 0, KeyFuncType::COPY ); + pChild->KeyInput( aEvent ); + } + } + else if(aCommand == "Paste") + { + vcl::Window* pChild = m_xLastQueriedFocusWin.get(); + if(pChild) + { + KeyEvent aEvent( 0, KeyFuncType::PASTE ); + pChild->KeyInput( aEvent ); + } + } +} +IMPL_LINK_NOARG( BibFrameController_Impl, DisposeHdl, void*, void ) +{ + if (m_xFrame.is()) + m_xFrame->dispose(); +}; + +void BibFrameController_Impl::addStatusListener( + const uno::Reference< frame::XStatusListener > & aListener, + const util::URL& aURL) +{ + BibConfig* pConfig = BibModul::GetConfig(); + // create a new Reference and insert into listener array + m_aStatusListeners.push_back( std::make_unique<BibStatusDispatch>( aURL, aListener ) ); + + // send first status synchronously + FeatureStateEvent aEvent; + aEvent.FeatureURL = aURL; + aEvent.Requery = false; + aEvent.Source = static_cast<XDispatch *>(this); + if ( aURL.Path == "StatusBarVisible" ) + { + aEvent.IsEnabled = false; + aEvent.State <<= false; + } + else if ( aURL.Path == "Bib/hierarchical" ) + { + aEvent.IsEnabled = true; + aEvent.State <<= OUString(); + } + else if(aURL.Path == "Bib/MenuFilter") + { + aEvent.IsEnabled = true; + aEvent.FeatureDescriptor=m_xDatMan->getQueryField(); + + aEvent.State <<= m_xDatMan->getQueryFields(); + + } + else if ( aURL.Path == "Bib/source") + { + aEvent.IsEnabled = true; + aEvent.FeatureDescriptor=m_xDatMan->getActiveDataTable(); + + aEvent.State <<= m_xDatMan->getDataSources(); + } + else if( aURL.Path == "Bib/sdbsource" || + aURL.Path == "Bib/Mapping" || + aURL.Path == "Bib/autoFilter" || + aURL.Path == "Bib/standardFilter" ) + { + aEvent.IsEnabled = true; + } + else if(aURL.Path == "Bib/query") + { + aEvent.IsEnabled = true; + aEvent.State <<= pConfig->getQueryText(); + } + else if (aURL.Path == "Bib/removeFilter" ) + { + OUString aFilterStr=m_xDatMan->getFilter(); + aEvent.IsEnabled = !aFilterStr.isEmpty(); + } + else if(aURL.Path == "Cut") + { + m_xLastQueriedFocusWin = lcl_GetFocusChild( VCLUnoHelper::GetWindow( m_xWindow ) ); + if (m_xLastQueriedFocusWin) + { + Reference<css::awt::XTextComponent> xEdit(m_xLastQueriedFocusWin->GetComponentInterface(), css::uno::UNO_QUERY); + aEvent.IsEnabled = xEdit && xEdit->isEditable() && !xEdit->getSelectedText().isEmpty(); + } + } + if(aURL.Path == "Copy") + { + m_xLastQueriedFocusWin = lcl_GetFocusChild( VCLUnoHelper::GetWindow( m_xWindow ) ); + if (m_xLastQueriedFocusWin) + { + Reference<css::awt::XTextComponent> xEdit(m_xLastQueriedFocusWin->GetComponentInterface(), css::uno::UNO_QUERY); + aEvent.IsEnabled = xEdit && !xEdit->getSelectedText().isEmpty(); + } + } + else if(aURL.Path == "Paste" ) + { + aEvent.IsEnabled = false; + m_xLastQueriedFocusWin = lcl_GetFocusChild( VCLUnoHelper::GetWindow( m_xWindow ) ); + if (m_xLastQueriedFocusWin) + { + Reference<css::awt::XTextComponent> xEdit(m_xLastQueriedFocusWin->GetComponentInterface(), css::uno::UNO_QUERY); + if (xEdit && !xEdit->isEditable()) + { + uno::Reference< datatransfer::clipboard::XClipboard > xClip = m_xLastQueriedFocusWin->GetClipboard(); + if(xClip.is()) + { + uno::Reference< datatransfer::XTransferable > xDataObj; + + try + { + SolarMutexReleaser aReleaser; + xDataObj = xClip->getContents(); + } + catch( const uno::Exception& ) + { + } + + if ( xDataObj.is() ) + { + datatransfer::DataFlavor aFlavor; + SotExchange::GetFormatDataFlavor( SotClipboardFormatId::STRING, aFlavor ); + try + { + uno::Any aData = xDataObj->getTransferData( aFlavor ); + OUString aText; + aData >>= aText; + aEvent.IsEnabled = !aText.isEmpty(); + } + catch( const uno::Exception& ) + { + } + } + } + } + } + } + else if(aURL.Path == "Bib/DeleteRecord") + { + Reference< beans::XPropertySet > xSet(m_xDatMan->getForm(), UNO_QUERY); + bool bIsNew = ::comphelper::getBOOL(xSet->getPropertyValue("IsNew")); + if(!bIsNew) + { + sal_uInt32 nCount = 0; + xSet->getPropertyValue("RowCount") >>= nCount; + aEvent.IsEnabled = nCount > 0; + } + } + else if (aURL.Path == "Bib/InsertRecord") + { + Reference< beans::XPropertySet > xSet(m_xDatMan->getForm(), UNO_QUERY); + aEvent.IsEnabled = canInsertRecords(xSet); + } + aListener->statusChanged( aEvent ); +} + +void BibFrameController_Impl::removeStatusListener( + const uno::Reference< frame::XStatusListener > & aObject, const util::URL& aURL) +{ + // search listener array for given listener + // for checking equality always "cast" to XInterface + if ( m_bDisposing ) + return; + + sal_uInt16 nCount = m_aStatusListeners.size(); + for ( sal_uInt16 n=0; n<nCount; n++ ) + { + BibStatusDispatch *pObj = m_aStatusListeners[n].get(); + bool bFlag=pObj->xListener.is(); + if (!bFlag || (pObj->xListener == aObject && + ( aURL.Complete.isEmpty() || pObj->aURL.Path == aURL.Path ))) + { + m_aStatusListeners.erase( m_aStatusListeners.begin() + n ); + break; + } + } +} + +void BibFrameController_Impl::RemoveFilter() +{ + OUString aQuery; + m_xDatMan->startQueryWith(aQuery); + + sal_uInt16 nCount = m_aStatusListeners.size(); + + bool bRemoveFilter=false; + bool bQueryText=false; + + for ( sal_uInt16 n=0; n<nCount; n++ ) + { + BibStatusDispatch *pObj = m_aStatusListeners[n].get(); + if ( pObj->aURL.Path == "Bib/removeFilter" ) + { + FeatureStateEvent aEvent; + aEvent.FeatureURL = pObj->aURL; + aEvent.IsEnabled = false; + aEvent.Requery = false; + aEvent.Source = static_cast<XDispatch *>(this); + pObj->xListener->statusChanged( aEvent ); + bRemoveFilter=true; + } + else if(pObj->aURL.Path == "Bib/query") + { + FeatureStateEvent aEvent; + aEvent.FeatureURL = pObj->aURL; + aEvent.IsEnabled = true; + aEvent.Requery = false; + aEvent.Source = static_cast<XDispatch *>(this); + aEvent.State <<= aQuery; + pObj->xListener->statusChanged( aEvent ); + bQueryText=true; + } + + if(bRemoveFilter && bQueryText) + break; + + } +} + +void BibFrameController_Impl::ChangeDataSource(const uno::Sequence< beans::PropertyValue >& aArgs) +{ + const beans::PropertyValue* pPropertyValue = aArgs.getConstArray(); + uno::Any aValue=pPropertyValue[0].Value; + OUString aDBTableName; + aValue >>= aDBTableName; + + + if(aArgs.getLength() > 1) + { + uno::Any aDB = pPropertyValue[1].Value; + OUString aURL; + aDB >>= aURL; + m_xDatMan->setActiveDataSource(aURL); + aDBTableName = m_xDatMan->getActiveDataTable(); + } + else + { + Reference<css::form::XLoadable> xLoadable(m_xDatMan); + xLoadable->unload(); + m_xDatMan->setActiveDataTable(aDBTableName); + m_xDatMan->updateGridModel(); + xLoadable->load(); + } + + + sal_uInt16 nCount = m_aStatusListeners.size(); + + bool bMenuFilter=false; + bool bQueryText=false; + for ( sal_uInt16 n=0; n<nCount; n++ ) + { + BibStatusDispatch *pObj = m_aStatusListeners[n].get(); + if (pObj->aURL.Path == "Bib/MenuFilter") + { + FeatureStateEvent aEvent; + aEvent.FeatureURL = pObj->aURL; + aEvent.IsEnabled = true; + aEvent.Requery = false; + aEvent.Source = static_cast<XDispatch *>(this); + aEvent.FeatureDescriptor=m_xDatMan->getQueryField(); + + uno::Sequence<OUString> aStringSeq=m_xDatMan->getQueryFields(); + aEvent.State <<= aStringSeq; + + pObj->xListener->statusChanged( aEvent ); + bMenuFilter=true; + } + else if (pObj->aURL.Path == "Bib/query") + { + FeatureStateEvent aEvent; + aEvent.FeatureURL = pObj->aURL; + aEvent.IsEnabled = true; + aEvent.Requery = false; + aEvent.Source = static_cast<XDispatch *>(this); + BibConfig* pConfig = BibModul::GetConfig(); + aEvent.State <<= pConfig->getQueryText(); + pObj->xListener->statusChanged( aEvent ); + bQueryText=true; + } + + if (bMenuFilter && bQueryText) + break; + + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/bibliography/framectr.hxx b/extensions/source/bibliography/framectr.hxx new file mode 100644 index 000000000..be91982cc --- /dev/null +++ b/extensions/source/bibliography/framectr.hxx @@ -0,0 +1,117 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/frame/XController.hpp> +#include <com/sun/star/frame/XDispatch.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/frame/XDispatchInformationProvider.hpp> +#include <cppuhelper/implbase.hxx> +#include <rtl/ref.hxx> +#include <tools/link.hxx> +#include <vcl/window.hxx> +#include <vector> +#include <memory> + +#include "bibmod.hxx" +class BibDataManager; +class BibFrameCtrl_Impl; +namespace com::sun::star{ + namespace form::runtime { + class XFormController; + } +} +class BibStatusDispatch +{ +public: + css::util::URL aURL; + css::uno::Reference< css::frame::XStatusListener > xListener; + BibStatusDispatch( const css::util::URL& rURL, const css::uno::Reference< css::frame::XStatusListener >& rRef ) + : aURL( rURL ) + , xListener( rRef ) + {} +}; + +typedef std::vector<std::unique_ptr<BibStatusDispatch> > BibStatusDispatchArr; + +class BibFrameController_Impl : public cppu::WeakImplHelper < + css::lang::XServiceInfo, + css::frame::XController, + css::frame::XDispatch, + css::frame::XDispatchProvider, + css::frame::XDispatchInformationProvider +> +{ +friend class BibFrameCtrl_Impl; + rtl::Reference<BibFrameCtrl_Impl> m_xImpl; + BibStatusDispatchArr m_aStatusListeners; + css::uno::Reference< css::awt::XWindow > m_xWindow; + css::uno::Reference< css::frame::XFrame > m_xFrame; + bool m_bDisposing; + rtl::Reference<BibDataManager> m_xDatMan; + VclPtr<vcl::Window> m_xLastQueriedFocusWin; + + DECL_LINK( DisposeHdl, void*, void ); + + static bool SaveModified(const css::uno::Reference< css::form::runtime::XFormController>& xController); +public: + BibFrameController_Impl( const css::uno::Reference< css::awt::XWindow > & xComponent, + BibDataManager* pDatMan); + virtual ~BibFrameController_Impl() override; + + + void ChangeDataSource(const css::uno::Sequence< css::beans::PropertyValue >& aArgs); + void RemoveFilter(); + + // css::lang::XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService( const OUString& sServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + + // css::frame::XController + virtual void SAL_CALL attachFrame( const css::uno::Reference< css::frame::XFrame > & xFrame ) override; + virtual sal_Bool SAL_CALL attachModel( const css::uno::Reference< css::frame::XModel > & xModel ) override; + virtual sal_Bool SAL_CALL suspend( sal_Bool bSuspend ) override; + virtual css::uno::Any SAL_CALL getViewData() override; + virtual void SAL_CALL restoreViewData( const css::uno::Any& Value ) override; + virtual css::uno::Reference< css::frame::XFrame > SAL_CALL getFrame() override; + virtual css::uno::Reference< css::frame::XModel > SAL_CALL getModel() override; + + // css::lang::XComponent + virtual void SAL_CALL dispose() override; + virtual void SAL_CALL addEventListener( const css::uno::Reference< css::lang::XEventListener > & aListener ) override; + virtual void SAL_CALL removeEventListener( const css::uno::Reference< css::lang::XEventListener > & aListener ) override; + + // css::frame::XDispatchProvider + virtual css::uno::Reference< css::frame::XDispatch > SAL_CALL queryDispatch( const css::util::URL& aURL, const OUString& aTargetFrameName, sal_Int32 nSearchFlags) override; + virtual css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL queryDispatches( const css::uno::Sequence< css::frame::DispatchDescriptor >& aDescripts) override; + + //class css::frame::XDispatch + virtual void SAL_CALL dispatch(const css::util::URL& aURL, const css::uno::Sequence< css::beans::PropertyValue >& aArgs) override; + virtual void SAL_CALL addStatusListener(const css::uno::Reference< css::frame::XStatusListener > & xControl, const css::util::URL& aURL) override; + virtual void SAL_CALL removeStatusListener(const css::uno::Reference< css::frame::XStatusListener > & xControl, const css::util::URL& aURL) override; + + // css::frame::XDispatchInformationProvider + virtual css::uno::Sequence< ::sal_Int16 > SAL_CALL getSupportedCommandGroups( ) override; + virtual css::uno::Sequence< css::frame::DispatchInformation > SAL_CALL getConfigurableDispatchInformation( ::sal_Int16 CommandGroup ) override; + }; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/bibliography/general.cxx b/extensions/source/bibliography/general.cxx new file mode 100644 index 000000000..ff3625d30 --- /dev/null +++ b/extensions/source/bibliography/general.cxx @@ -0,0 +1,876 @@ +/* -*- 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 <comphelper/processfactory.hxx> +#include <com/sun/star/beans/XPropertyChangeListener.hpp> +#include <com/sun/star/form/XBoundComponent.hpp> +#include <com/sun/star/sdbc/XRowSet.hpp> +#include <com/sun/star/sdb/XColumn.hpp> +#include <com/sun/star/sdb/CommandType.hpp> +#include <com/sun/star/ui/dialogs/TemplateDescription.hpp> +#include <com/sun/star/uri/UriReferenceFactory.hpp> + +#include <o3tl/safeint.hxx> +#include <o3tl/string_view.hxx> +#include <sal/log.hxx> +#include <cppuhelper/implbase.hxx> +#include <vcl/event.hxx> +#include <vcl/mnemonic.hxx> +#include "general.hxx" +#include "bibresid.hxx" +#include "datman.hxx" +#include "bibconfig.hxx" +#include <strings.hrc> +#include "bibmod.hxx" +#include <helpids.h> +#include <algorithm> +#include <sfx2/filedlghelper.hxx> +#include <sfx2/objsh.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::sdb; + +namespace +{ +/// Tries to split rText into rURL and nPageNumber. +bool SplitUrlAndPage(const OUString& rText, OUString& rUrl, int& nPageNumber) +{ + uno::Reference<uri::XUriReferenceFactory> xUriReferenceFactory + = uri::UriReferenceFactory::create(comphelper::getProcessComponentContext()); + uno::Reference<uri::XUriReference> xUriRef; + try + { + xUriRef = xUriReferenceFactory->parse(rText); + } + catch (const uno::Exception& rException) + { + SAL_WARN("extensions.biblio", + "SplitUrlAndPage: failed to parse url: " << rException.Message); + return false; + } + + OUString aPagePrefix("page="); + if (!xUriRef->getFragment().startsWith(aPagePrefix)) + { + return false; + } + + nPageNumber = o3tl::toInt32(xUriRef->getFragment().subView(aPagePrefix.getLength())); + xUriRef->clearFragment(); + rUrl = xUriRef->getUriReference(); + return true; +} + +/// Merges rUrl and rPageSB to a URL string. +OUString MergeUrlAndPage(const OUString& rUrl, const weld::SpinButton& rPageSB) +{ + if (!rPageSB.get_sensitive()) + { + return rUrl; + } + + uno::Reference<uri::XUriReferenceFactory> xUriReferenceFactory + = uri::UriReferenceFactory::create(comphelper::getProcessComponentContext()); + uno::Reference<uri::XUriReference> xUriRef; + try + { + xUriRef = xUriReferenceFactory->parse(rUrl); + } + catch (const uno::Exception& rException) + { + SAL_WARN("extensions.biblio", + "MergeUrlAndPage: failed to parse url: " << rException.Message); + return rUrl; + } + + OUString aFragment("page=" + OUString::number(rPageSB.get_value())); + xUriRef->setFragment(aFragment); + return xUriRef->getUriReference(); +} +} + +static OUString lcl_GetColumnName( const Mapping* pMapping, sal_uInt16 nIndexPos ) +{ + BibConfig* pBibConfig = BibModul::GetConfig(); + OUString sRet = pBibConfig->GetDefColumnName(nIndexPos); + if(pMapping) + for(const auto & aColumnPair : pMapping->aColumnPairs) + { + if(aColumnPair.sLogicalColumnName == sRet) + { + sRet = aColumnPair.sRealColumnName; + break; + } + } + return sRet; +} + +BibGeneralPage::BibGeneralPage(vcl::Window* pParent, BibDataManager* pMan) + : InterimItemWindow(pParent, "modules/sbibliography/ui/generalpage.ui", "GeneralPage") + , BibShortCutHandler(this) + , xScrolledWindow(m_xBuilder->weld_scrolled_window("scrolledwindow")) + , xGrid(m_xBuilder->weld_widget("grid")) + , xIdentifierFT(m_xBuilder->weld_label("shortname")) + , xIdentifierED(m_xBuilder->weld_entry("shortnamecontrol")) + , xAuthTypeFT(m_xBuilder->weld_label("authtype")) + , xAuthTypeLB(m_xBuilder->weld_combo_box("authtypecontrol")) + , xYearFT(m_xBuilder->weld_label("year")) + , xYearED(m_xBuilder->weld_entry("yearcontrol")) + , xAuthorFT(m_xBuilder->weld_label("authors")) + , xAuthorED(m_xBuilder->weld_entry("authorscontrol")) + , xTitleFT(m_xBuilder->weld_label("title")) + , xTitleED(m_xBuilder->weld_entry("titlecontrol")) + , xPublisherFT(m_xBuilder->weld_label("publisher")) + , xPublisherED(m_xBuilder->weld_entry("publishercontrol")) + , xAddressFT(m_xBuilder->weld_label("address")) + , xAddressED(m_xBuilder->weld_entry("addresscontrol")) + , xISBNFT(m_xBuilder->weld_label("isbn")) + , xISBNED(m_xBuilder->weld_entry("isbncontrol")) + , xChapterFT(m_xBuilder->weld_label("chapter")) + , xChapterED(m_xBuilder->weld_entry("chaptercontrol")) + , xPagesFT(m_xBuilder->weld_label("pages")) + , xPagesED(m_xBuilder->weld_entry("pagescontrol")) + , xEditorFT(m_xBuilder->weld_label("editor")) + , xEditorED(m_xBuilder->weld_entry("editorcontrol")) + , xEditionFT(m_xBuilder->weld_label("edition")) + , xEditionED(m_xBuilder->weld_entry("editioncontrol")) + , xBooktitleFT(m_xBuilder->weld_label("booktitle")) + , xBooktitleED(m_xBuilder->weld_entry("booktitlecontrol")) + , xVolumeFT(m_xBuilder->weld_label("volume")) + , xVolumeED(m_xBuilder->weld_entry("volumecontrol")) + , xHowpublishedFT(m_xBuilder->weld_label("publicationtype")) + , xHowpublishedED(m_xBuilder->weld_entry("publicationtypecontrol")) + , xOrganizationsFT(m_xBuilder->weld_label("organization")) + , xOrganizationsED(m_xBuilder->weld_entry("organizationcontrol")) + , xInstitutionFT(m_xBuilder->weld_label("institution")) + , xInstitutionED(m_xBuilder->weld_entry("institutioncontrol")) + , xSchoolFT(m_xBuilder->weld_label("university")) + , xSchoolED(m_xBuilder->weld_entry("universitycontrol")) + , xReportTypeFT(m_xBuilder->weld_label("reporttype")) + , xReportTypeED(m_xBuilder->weld_entry("reporttypecontrol")) + , xMonthFT(m_xBuilder->weld_label("month")) + , xMonthED(m_xBuilder->weld_entry("monthcontrol")) + , xJournalFT(m_xBuilder->weld_label("journal")) + , xJournalED(m_xBuilder->weld_entry("journalcontrol")) + , xNumberFT(m_xBuilder->weld_label("number")) + , xNumberED(m_xBuilder->weld_entry("numbercontrol")) + , xSeriesFT(m_xBuilder->weld_label("series")) + , xSeriesED(m_xBuilder->weld_entry("seriescontrol")) + , xAnnoteFT(m_xBuilder->weld_label("annotation")) + , xAnnoteED(m_xBuilder->weld_entry("annotationcontrol")) + , xNoteFT(m_xBuilder->weld_label("note")) + , xNoteED(m_xBuilder->weld_entry("notecontrol")) + , xURLFT(m_xBuilder->weld_label("url")) + , xURLED(m_xBuilder->weld_entry("urlcontrol")) + , xCustom1FT(m_xBuilder->weld_label("custom1")) + , xCustom1ED(m_xBuilder->weld_entry("custom1control")) + , xCustom2FT(m_xBuilder->weld_label("custom2")) + , xCustom2ED(m_xBuilder->weld_entry("custom2control")) + , xCustom3FT(m_xBuilder->weld_label("custom3")) + , xCustom3ED(m_xBuilder->weld_entry("custom3control")) + , xCustom4FT(m_xBuilder->weld_label("custom4")) + , xCustom4ED(m_xBuilder->weld_entry("custom4control")) + , xCustom5FT(m_xBuilder->weld_label("custom5")) + , xCustom5ED(m_xBuilder->weld_entry("custom5control")) + , m_xLocalURLFT(m_xBuilder->weld_label("localurl")) + , m_xLocalURLED(m_xBuilder->weld_entry("localurlcontrol")) + , m_xLocalBrowseButton(m_xBuilder->weld_button("localbrowse")) + , m_xLocalPageCB(m_xBuilder->weld_check_button("localpagecb")) + , m_xLocalPageSB(m_xBuilder->weld_spin_button("localpagesb")) + , pDatMan(pMan) +{ + SetStyle(GetStyle() | WB_DIALOGCONTROL); + + BibConfig* pBibConfig = BibModul::GetConfig(); + BibDBDescriptor aDesc; + aDesc.sDataSource = pDatMan->getActiveDataSource(); + aDesc.sTableOrQuery = pDatMan->getActiveDataTable(); + aDesc.nCommandType = CommandType::TABLE; + const Mapping* pMapping = pBibConfig->GetMapping(aDesc); + + xIdentifierED->connect_key_press(LINK(this, BibGeneralPage, FirstElementKeyInputHdl)); + + AddControlWithError(lcl_GetColumnName(pMapping, IDENTIFIER_POS), + xIdentifierFT->get_label(), *xIdentifierED, + sTableErrorString, HID_BIB_IDENTIFIER_POS); + + AddControlWithError(lcl_GetColumnName(pMapping, AUTHORITYTYPE_POS), + xAuthTypeFT->get_label(), *xAuthTypeLB, + sTableErrorString, HID_BIB_AUTHORITYTYPE_POS); + + AddControlWithError(lcl_GetColumnName(pMapping, YEAR_POS), + xYearFT->get_label(), *xYearED, + sTableErrorString, HID_BIB_YEAR_POS); + + AddControlWithError(lcl_GetColumnName(pMapping, AUTHOR_POS), + xAuthorFT->get_label(), *xAuthorED, + sTableErrorString, HID_BIB_AUTHOR_POS); + + AddControlWithError(lcl_GetColumnName(pMapping, TITLE_POS), + xTitleFT->get_label(), *xTitleED, + sTableErrorString, HID_BIB_TITLE_POS); + + AddControlWithError(lcl_GetColumnName(pMapping, PUBLISHER_POS), + xPublisherFT->get_label(), *xPublisherED, + sTableErrorString, HID_BIB_PUBLISHER_POS); + + AddControlWithError(lcl_GetColumnName(pMapping, ADDRESS_POS), + xAddressFT->get_label(), *xAddressED, + sTableErrorString, HID_BIB_ADDRESS_POS); + + AddControlWithError(lcl_GetColumnName(pMapping, ISBN_POS), + xISBNFT->get_label(), *xISBNED, + sTableErrorString, HID_BIB_ISBN_POS); + + AddControlWithError(lcl_GetColumnName(pMapping, CHAPTER_POS), + xChapterFT->get_label(), *xChapterED, + sTableErrorString, HID_BIB_CHAPTER_POS); + + AddControlWithError(lcl_GetColumnName(pMapping, PAGES_POS), + xPagesFT->get_label(), *xPagesED, + sTableErrorString, HID_BIB_PAGES_POS); + + AddControlWithError(lcl_GetColumnName(pMapping, EDITOR_POS), + xEditorFT->get_label(), *xEditorED, + sTableErrorString, HID_BIB_EDITOR_POS); + + AddControlWithError(lcl_GetColumnName(pMapping, EDITION_POS), + xEditionFT->get_label(), *xEditionED, + sTableErrorString, HID_BIB_EDITION_POS); + + AddControlWithError(lcl_GetColumnName(pMapping, BOOKTITLE_POS), + xBooktitleFT->get_label(), *xBooktitleED, + sTableErrorString, HID_BIB_BOOKTITLE_POS); + + AddControlWithError(lcl_GetColumnName(pMapping, VOLUME_POS), + xVolumeFT->get_label(), *xVolumeED, + sTableErrorString, HID_BIB_VOLUME_POS); + + AddControlWithError(lcl_GetColumnName(pMapping, HOWPUBLISHED_POS), + xHowpublishedFT->get_label(), *xHowpublishedED, + sTableErrorString, HID_BIB_HOWPUBLISHED_POS); + + AddControlWithError(lcl_GetColumnName(pMapping, ORGANIZATIONS_POS), + xOrganizationsFT->get_label(), *xOrganizationsED, + sTableErrorString, HID_BIB_ORGANIZATIONS_POS); + + AddControlWithError(lcl_GetColumnName(pMapping, INSTITUTION_POS), + xInstitutionFT->get_label(), *xInstitutionED, + sTableErrorString, HID_BIB_INSTITUTION_POS); + + AddControlWithError(lcl_GetColumnName(pMapping, SCHOOL_POS), + xSchoolFT->get_label(), *xSchoolED, + sTableErrorString, HID_BIB_SCHOOL_POS); + + AddControlWithError(lcl_GetColumnName(pMapping, REPORTTYPE_POS), + xReportTypeFT->get_label(), *xReportTypeED, + sTableErrorString, HID_BIB_REPORTTYPE_POS); + + AddControlWithError(lcl_GetColumnName(pMapping, MONTH_POS), + xMonthFT->get_label(), *xMonthED, + sTableErrorString, HID_BIB_MONTH_POS); + + AddControlWithError(lcl_GetColumnName(pMapping, JOURNAL_POS), + xJournalFT->get_label(), *xJournalED, + sTableErrorString, HID_BIB_JOURNAL_POS); + + AddControlWithError(lcl_GetColumnName(pMapping, NUMBER_POS), + xNumberFT->get_label(), *xNumberED, + sTableErrorString, HID_BIB_NUMBER_POS); + + AddControlWithError(lcl_GetColumnName(pMapping, SERIES_POS), + xSeriesFT->get_label(), *xSeriesED, + sTableErrorString, HID_BIB_SERIES_POS); + + AddControlWithError(lcl_GetColumnName(pMapping, ANNOTE_POS), + xAnnoteFT->get_label(), *xAnnoteED, + sTableErrorString, HID_BIB_ANNOTE_POS); + + AddControlWithError(lcl_GetColumnName(pMapping, NOTE_POS), + xNoteFT->get_label(), *xNoteED, + sTableErrorString, HID_BIB_NOTE_POS); + + AddControlWithError(lcl_GetColumnName(pMapping, URL_POS), + xURLFT->get_label(), *xURLED, + sTableErrorString, HID_BIB_URL_POS); + + AddControlWithError(lcl_GetColumnName(pMapping, CUSTOM1_POS), + xCustom1FT->get_label(), *xCustom1ED, + sTableErrorString, HID_BIB_CUSTOM1_POS); + + AddControlWithError(lcl_GetColumnName(pMapping, CUSTOM2_POS), + xCustom2FT->get_label(), *xCustom2ED, + sTableErrorString, HID_BIB_CUSTOM2_POS); + + AddControlWithError(lcl_GetColumnName(pMapping, CUSTOM3_POS), + xCustom3FT->get_label(), *xCustom3ED, + sTableErrorString, HID_BIB_CUSTOM3_POS); + + AddControlWithError(lcl_GetColumnName(pMapping, CUSTOM4_POS), + xCustom4FT->get_label(), *xCustom4ED, + sTableErrorString, HID_BIB_CUSTOM4_POS); + + AddControlWithError(lcl_GetColumnName(pMapping, CUSTOM5_POS), + xCustom5FT->get_label(), *xCustom5ED, + sTableErrorString, HID_BIB_CUSTOM5_POS); + + AddControlWithError(lcl_GetColumnName(pMapping, LOCAL_URL_POS), + m_xLocalURLFT->get_label(), *m_xLocalURLED, + sTableErrorString, HID_BIB_LOCAL_URL_POS); + + m_xLocalBrowseButton->connect_clicked(LINK(this, BibGeneralPage, BrowseHdl)); + m_xLocalPageCB->connect_toggled(LINK(this, BibGeneralPage, PageNumHdl)); + + m_xLocalURLED->connect_key_press(LINK(this, BibGeneralPage, LastElementKeyInputHdl)); + + if(!sTableErrorString.isEmpty()) + sTableErrorString = BibResId(ST_ERROR_PREFIX) + sTableErrorString; + + SetText(BibResId(ST_TYPE_TITLE)); + + Size aSize(LogicToPixel(Size(0, 209), MapMode(MapUnit::MapAppFont))); + set_height_request(aSize.Height()); +} + +IMPL_LINK_NOARG(BibGeneralPage, BrowseHdl, weld::Button&, void) +{ + sfx2::FileDialogHelper aFileDlg(ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE, + FileDialogFlags::NONE, GetFrameWeld()); + OUString aPath = m_xLocalURLED->get_text(); + if (!aPath.isEmpty()) + { + aFileDlg.SetDisplayDirectory(aPath); + } + else + { + OUString aBaseURL; + if (SfxObjectShell* pShell = SfxObjectShell::Current()) + { + aBaseURL = pShell->getDocumentBaseURL(); + } + if (!aBaseURL.isEmpty()) + { + aFileDlg.SetDisplayDirectory(aBaseURL); + } + } + + if (aFileDlg.Execute() != ERRCODE_NONE) + { + return; + } + + weld::Entry& rEntry = *m_xLocalURLED; + rEntry.set_text(aFileDlg.GetPath()); +}; + +IMPL_LINK(BibGeneralPage, PageNumHdl, weld::Toggleable&, rPageCB, void) +{ + weld::SpinButton& rPageSB = *m_xLocalPageSB; + if (rPageCB.get_active()) + { + rPageSB.set_sensitive(true); + rPageSB.set_value(1); + } + else + { + rPageSB.set_sensitive(false); + } +} + +IMPL_LINK(BibGeneralPage, FirstElementKeyInputHdl, const KeyEvent&, rKeyEvent, bool) +{ + sal_uInt16 nCode = rKeyEvent.GetKeyCode().GetCode(); + bool bShift = rKeyEvent.GetKeyCode().IsShift(); + bool bCtrl = rKeyEvent.GetKeyCode().IsMod1(); + bool bAlt = rKeyEvent.GetKeyCode().IsMod2(); + if (KEY_TAB == nCode && bShift && !bCtrl && !bAlt) + { + SaveChanges(); + uno::Reference<sdbc::XRowSet> xRowSet(pDatMan->getForm(), UNO_QUERY); + if (xRowSet.is() && !xRowSet->isFirst()) + xRowSet->previous(); + m_xLocalURLED->grab_focus(); + m_xLocalURLED->select_region(0, -1); + GainFocusHdl(*m_xLocalURLED); + return true; + } + return false; +} + +void BibGeneralPage::SaveChanges() +{ + Reference< XForm > xForm = pDatMan->getForm(); + Reference< beans::XPropertySet > xProps( xForm, UNO_QUERY ); + Reference< sdbc::XResultSetUpdate > xResUpd( xProps, UNO_QUERY ); + if (!xResUpd.is() ) + return; + + Any aModified = xProps->getPropertyValue( "IsModified" ); + bool bFlag = false; + if ( !( aModified >>= bFlag ) || !bFlag ) + return; + + try + { + Any aNew = xProps->getPropertyValue( "IsNew" ); + aNew >>= bFlag; + if ( bFlag ) + xResUpd->insertRow(); + else + xResUpd->updateRow(); + } + catch( const uno::Exception&) {} +} + +IMPL_LINK(BibGeneralPage, LastElementKeyInputHdl, const KeyEvent&, rKeyEvent, bool) +{ + sal_uInt16 nCode = rKeyEvent.GetKeyCode().GetCode(); + bool bShift = rKeyEvent.GetKeyCode().IsShift(); + bool bCtrl = rKeyEvent.GetKeyCode().IsMod1(); + bool bAlt = rKeyEvent.GetKeyCode().IsMod2(); + if (KEY_TAB != nCode || bShift || bCtrl || bAlt) + return false; + SaveChanges(); + uno::Reference<sdbc::XRowSet> xRowSet(pDatMan->getForm(), UNO_QUERY); + if (xRowSet.is()) + { + if (xRowSet->isLast()) + { + uno::Reference<sdbc::XResultSetUpdate> xUpdateCursor(xRowSet, UNO_QUERY); + if (xUpdateCursor.is()) + xUpdateCursor->moveToInsertRow(); + } + else + (void)xRowSet->next(); + } + xIdentifierED->grab_focus(); + xIdentifierED->select_region(0, -1); + GainFocusHdl(*xIdentifierED); + return true; +} + +BibGeneralPage::~BibGeneralPage() +{ + disposeOnce(); +} + +class ChangeListener : public cppu::WeakImplHelper<css::beans::XPropertyChangeListener> +{ +public: + explicit ChangeListener(const css::uno::Reference<css::beans::XPropertySet>& rPropSet) + : m_xPropSet(rPropSet) + , m_bSelfChanging(false) + { + } + + virtual void SAL_CALL disposing(lang::EventObject const &) override + { + } + + virtual void start() = 0; + virtual void stop() + { + WriteBack(); + } + + virtual void WriteBack() = 0; + +protected: + css::uno::Reference<css::beans::XPropertySet> m_xPropSet; + bool m_bSelfChanging; +}; + +namespace +{ + class EntryChangeListener : public ChangeListener + { + public: + explicit EntryChangeListener(weld::Entry& rEntry, const css::uno::Reference<css::beans::XPropertySet>& rPropSet, + BibGeneralPage& rPage) + : ChangeListener(rPropSet) + , m_rEntry(rEntry) + , m_rPage(rPage) + { + rEntry.connect_focus_out(LINK(this, EntryChangeListener, LoseFocusHdl)); + setValue(rPropSet->getPropertyValue("Text")); + } + + virtual void SAL_CALL propertyChange(const css::beans::PropertyChangeEvent& evt) override + { + if (m_bSelfChanging) + return; + setValue(evt.NewValue); + } + + virtual void start() override + { + m_xPropSet->addPropertyChangeListener("Text", this); + } + + virtual void stop() override + { + m_xPropSet->removePropertyChangeListener("Text", this); + ChangeListener::stop(); + } + + private: + weld::Entry& m_rEntry; + BibGeneralPage& m_rPage; + + DECL_LINK(LoseFocusHdl, weld::Widget&, void); + + /// Updates the UI widget(s) based on rValue. + void setValue(const css::uno::Any& rValue) + { + OUString sNewName; + rValue >>= sNewName; + if (&m_rEntry == &m_rPage.GetLocalURLED()) + { + OUString aUrl; + int nPageNumber; + if (SplitUrlAndPage(sNewName, aUrl, nPageNumber)) + { + m_rEntry.set_text(aUrl); + m_rPage.GetLocalPageCB().set_active(true); + m_rPage.GetLocalPageSB().set_sensitive(true); + m_rPage.GetLocalPageSB().set_value(nPageNumber); + } + else + { + m_rEntry.set_text(sNewName); + m_rPage.GetLocalPageCB().set_active(false); + m_rPage.GetLocalPageSB().set_sensitive(false); + m_rPage.GetLocalPageSB().set_value(0); + } + } + else + { + m_rEntry.set_text(sNewName); + } + + m_rEntry.save_value(); + if (&m_rEntry == &m_rPage.GetLocalURLED()) + { + m_rPage.GetLocalPageSB().save_value(); + } + } + + /// Updates m_xPropSet based on the UI widget(s). + virtual void WriteBack() override + { + bool bLocalURL = &m_rEntry == &m_rPage.GetLocalURLED() + && m_rPage.GetLocalPageSB().get_value_changed_from_saved(); + if (!m_rEntry.get_value_changed_from_saved() && !bLocalURL) + return; + + m_bSelfChanging = true; + + OUString aText; + if (&m_rEntry == &m_rPage.GetLocalURLED()) + { + aText = MergeUrlAndPage(m_rEntry.get_text(), m_rPage.GetLocalPageSB()); + } + else + { + aText = m_rEntry.get_text(); + } + m_xPropSet->setPropertyValue("Text", Any(aText)); + + css::uno::Reference<css::form::XBoundComponent> xBound(m_xPropSet, css::uno::UNO_QUERY); + if (xBound.is()) + xBound->commit(); + + m_bSelfChanging = false; + m_rEntry.save_value(); + if (&m_rEntry == &m_rPage.GetLocalURLED()) + { + m_rPage.GetLocalPageSB().save_value(); + } + } + + }; + + IMPL_LINK_NOARG(EntryChangeListener, LoseFocusHdl, weld::Widget&, void) + { + WriteBack(); + } + + class ComboBoxChangeListener : public ChangeListener + { + public: + explicit ComboBoxChangeListener(weld::ComboBox& rComboBox, const css::uno::Reference<css::beans::XPropertySet>& rPropSet) + : ChangeListener(rPropSet) + , m_rComboBox(rComboBox) + { + rComboBox.connect_changed(LINK(this, ComboBoxChangeListener, ChangeHdl)); + setValue(rPropSet->getPropertyValue("SelectedItems")); + } + + virtual void SAL_CALL propertyChange(const css::beans::PropertyChangeEvent& evt) override + { + if (m_bSelfChanging) + return; + setValue(evt.NewValue); + } + + virtual void start() override + { + m_xPropSet->addPropertyChangeListener("SelectedItems", this); + } + + virtual void stop() override + { + m_xPropSet->removePropertyChangeListener("SelectedItems", this); + ChangeListener::stop(); + } + + private: + weld::ComboBox& m_rComboBox; + + DECL_LINK(ChangeHdl, weld::ComboBox&, void); + + void setValue(const css::uno::Any& rValue) + { + sal_Int16 nSelection = -1; + Sequence<sal_Int16> aSelection; + rValue >>= aSelection; + if (aSelection.hasElements()) + nSelection = aSelection[0]; + + m_rComboBox.set_active(nSelection); + m_rComboBox.save_value(); + } + + virtual void WriteBack() override + { + if (!m_rComboBox.get_value_changed_from_saved()) + return; + m_bSelfChanging = true; + + Sequence<sal_Int16> aSelection{ o3tl::narrowing<sal_Int16>(m_rComboBox.get_active()) }; + m_xPropSet->setPropertyValue("SelectedItems", Any(aSelection)); + + css::uno::Reference<css::form::XBoundComponent> xBound(m_xPropSet, css::uno::UNO_QUERY); + if (xBound.is()) + xBound->commit(); + + m_bSelfChanging = false; + m_rComboBox.save_value(); + } + }; + + IMPL_LINK_NOARG(ComboBoxChangeListener, ChangeHdl, weld::ComboBox&, void) + { + WriteBack(); + } +} + +void BibGeneralPage::dispose() +{ + for (auto& listener : maChangeListeners) + listener->stop(); + maChangeListeners.clear(); + + SaveChanges(); + + xScrolledWindow.reset(); + xGrid.reset(); + xIdentifierFT.reset(); + xIdentifierED.reset(); + xAuthTypeFT.reset(); + xAuthTypeLB.reset(); + xYearFT.reset(); + xYearED.reset(); + xAuthorFT.reset(); + xAuthorED.reset(); + xTitleFT.reset(); + xTitleED.reset(); + xPublisherFT.reset(); + xPublisherED.reset(); + xAddressFT.reset(); + xAddressED.reset(); + xISBNFT.reset(); + xISBNED.reset(); + xChapterFT.reset(); + xChapterED.reset(); + xPagesFT.reset(); + xPagesED.reset(); + xEditorFT.reset(); + xEditorED.reset(); + xEditionFT.reset(); + xEditionED.reset(); + xBooktitleFT.reset(); + xBooktitleED.reset(); + xVolumeFT.reset(); + xVolumeED.reset(); + xHowpublishedFT.reset(); + xHowpublishedED.reset(); + xOrganizationsFT.reset(); + xOrganizationsED.reset(); + xInstitutionFT.reset(); + xInstitutionED.reset(); + xSchoolFT.reset(); + xSchoolED.reset(); + xReportTypeFT.reset(); + xReportTypeED.reset(); + xMonthFT.reset(); + xMonthED.reset(); + xJournalFT.reset(); + xJournalED.reset(); + xNumberFT.reset(); + xNumberED.reset(); + xSeriesFT.reset(); + xSeriesED.reset(); + xAnnoteFT.reset(); + xAnnoteED.reset(); + xNoteFT.reset(); + xNoteED.reset(); + xURLFT.reset(); + xURLED.reset(); + xCustom1FT.reset(); + xCustom1ED.reset(); + xCustom2FT.reset(); + xCustom2ED.reset(); + xCustom3FT.reset(); + xCustom3ED.reset(); + xCustom4FT.reset(); + xCustom4ED.reset(); + xCustom5FT.reset(); + xCustom5ED.reset(); + m_xLocalURLFT.reset(); + m_xLocalURLED.reset(); + m_xLocalBrowseButton.reset(); + m_xLocalPageCB.reset(); + m_xLocalPageSB.reset(); + InterimItemWindow::dispose(); +} + +weld::Entry& BibGeneralPage::GetLocalURLED() { return *m_xLocalURLED; } + +weld::CheckButton& BibGeneralPage::GetLocalPageCB() { return *m_xLocalPageCB; } + +weld::SpinButton& BibGeneralPage::GetLocalPageSB() { return *m_xLocalPageSB; } + +bool BibGeneralPage::AddXControl(const OUString& rName, weld::Entry& rEntry) +{ + uno::Reference< awt::XControlModel > xCtrModel; + try + { + xCtrModel = pDatMan->loadControlModel(rName, false); + if ( xCtrModel.is() ) + { + uno::Reference< beans::XPropertySet > xPropSet( xCtrModel, UNO_QUERY ); + + if( xPropSet.is()) + { + maChangeListeners.emplace_back(new EntryChangeListener(rEntry, xPropSet, *this)); + maChangeListeners.back()->start(); + if (&rEntry == m_xLocalURLED.get()) + { + m_aURLListener = maChangeListeners.back(); + m_xLocalPageSB->connect_focus_out(LINK(this, BibGeneralPage, LosePageFocusHdl)); + } + } + } + } + catch(const Exception&) + { + OSL_FAIL("BibGeneralPage::AddXControl: something went wrong!"); + } + return xCtrModel.is(); +} + +IMPL_LINK_NOARG(BibGeneralPage, LosePageFocusHdl, weld::Widget&, void) +{ + m_aURLListener->WriteBack(); +} + +IMPL_LINK(BibGeneralPage, GainFocusHdl, weld::Widget&, rWidget, void) +{ + int x, y, width, height; + if (!rWidget.get_extents_relative_to(*xGrid, x, y, width, height)) + return; + + int bottom = y + height; + int nVScrollPos = xScrolledWindow->vadjustment_get_value(); + if (y < nVScrollPos || bottom > nVScrollPos + xScrolledWindow->vadjustment_get_page_size()) + xScrolledWindow->vadjustment_set_value(y); + + int right = x + width; + int nHScrollPos = xScrolledWindow->hadjustment_get_value(); + if (x < nHScrollPos || right > nHScrollPos + xScrolledWindow->hadjustment_get_page_size()) + xScrolledWindow->hadjustment_set_value(x); +} + +template<class Target> void BibGeneralPage::AddControlWithError(const OUString& rColumnName, const OUString& rColumnUIName, + Target& rWidget, OUString& rErrorString, const OString& rHelpId) +{ + rWidget.set_help_id(rHelpId); + rWidget.connect_focus_in(LINK(this, BibGeneralPage, GainFocusHdl)); + bool bSuccess = AddXControl(rColumnName, rWidget); + if (!bSuccess) + { + if( !rErrorString.isEmpty() ) + rErrorString += "\n"; + + rErrorString += MnemonicGenerator::EraseAllMnemonicChars(rColumnUIName); + } +} + +bool BibGeneralPage::AddXControl(const OUString& rName, weld::ComboBox& rList) +{ + uno::Reference< awt::XControlModel > xCtrModel; + try + { + xCtrModel = pDatMan->loadControlModel(rName, true); + if ( xCtrModel.is() ) + { + uno::Reference< beans::XPropertySet > xPropSet( xCtrModel, UNO_QUERY ); + + if( xPropSet.is()) + { + css::uno::Sequence<OUString> aEntries; + xPropSet->getPropertyValue("StringItemList") >>= aEntries; + for (const OUString& rString : std::as_const(aEntries)) + rList.append_text(rString); + + sal_Int16 nSelection = -1; + Sequence<sal_Int16> aSelection; + xPropSet->getPropertyValue("SelectedItems") >>= aSelection; + if (aSelection.hasElements()) + nSelection = aSelection[0]; + + rList.set_active(nSelection); + rList.save_value(); + + maChangeListeners.emplace_back(new ComboBoxChangeListener(rList, xPropSet)); + maChangeListeners.back()->start(); + } + } + } + catch(const Exception&) + { + OSL_FAIL("BibGeneralPage::AddXControl: something went wrong!"); + } + return xCtrModel.is(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/bibliography/general.hxx b/extensions/source/bibliography/general.hxx new file mode 100644 index 000000000..b4d981955 --- /dev/null +++ b/extensions/source/bibliography/general.hxx @@ -0,0 +1,158 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <sal/config.h> + +#include <vcl/InterimItemWindow.hxx> +#include "bibshortcuthandler.hxx" + + +class BibDataManager; +#define TYPE_COUNT 22 +#define FIELD_COUNT 31 + +class ChangeListener; + +class BibGeneralPage : public InterimItemWindow + , public BibShortCutHandler +{ + std::unique_ptr<weld::ScrolledWindow> xScrolledWindow; + std::unique_ptr<weld::Widget> xGrid; + + std::unique_ptr<weld::Label> xIdentifierFT; + std::unique_ptr<weld::Entry> xIdentifierED; + + std::unique_ptr<weld::Label> xAuthTypeFT; + std::unique_ptr<weld::ComboBox> xAuthTypeLB; + std::unique_ptr<weld::Label> xYearFT; + std::unique_ptr<weld::Entry> xYearED; + + std::unique_ptr<weld::Label> xAuthorFT; + std::unique_ptr<weld::Entry> xAuthorED; + std::unique_ptr<weld::Label> xTitleFT; + std::unique_ptr<weld::Entry> xTitleED; + + std::unique_ptr<weld::Label> xPublisherFT; + std::unique_ptr<weld::Entry> xPublisherED; + std::unique_ptr<weld::Label> xAddressFT; + std::unique_ptr<weld::Entry> xAddressED; + std::unique_ptr<weld::Label> xISBNFT; + std::unique_ptr<weld::Entry> xISBNED; + + std::unique_ptr<weld::Label> xChapterFT; + std::unique_ptr<weld::Entry> xChapterED; + std::unique_ptr<weld::Label> xPagesFT; + std::unique_ptr<weld::Entry> xPagesED; + + std::unique_ptr<weld::Label> xEditorFT; + std::unique_ptr<weld::Entry> xEditorED; + std::unique_ptr<weld::Label> xEditionFT; + std::unique_ptr<weld::Entry> xEditionED; + + std::unique_ptr<weld::Label> xBooktitleFT; + std::unique_ptr<weld::Entry> xBooktitleED; + std::unique_ptr<weld::Label> xVolumeFT; + std::unique_ptr<weld::Entry> xVolumeED; + std::unique_ptr<weld::Label> xHowpublishedFT; + std::unique_ptr<weld::Entry> xHowpublishedED; + + std::unique_ptr<weld::Label> xOrganizationsFT; + std::unique_ptr<weld::Entry> xOrganizationsED; + std::unique_ptr<weld::Label> xInstitutionFT; + std::unique_ptr<weld::Entry> xInstitutionED; + std::unique_ptr<weld::Label> xSchoolFT; + std::unique_ptr<weld::Entry> xSchoolED; + + std::unique_ptr<weld::Label> xReportTypeFT; + std::unique_ptr<weld::Entry> xReportTypeED; + std::unique_ptr<weld::Label> xMonthFT; + std::unique_ptr<weld::Entry> xMonthED; + + std::unique_ptr<weld::Label> xJournalFT; + std::unique_ptr<weld::Entry> xJournalED; + std::unique_ptr<weld::Label> xNumberFT; + std::unique_ptr<weld::Entry> xNumberED; + std::unique_ptr<weld::Label> xSeriesFT; + std::unique_ptr<weld::Entry> xSeriesED; + + std::unique_ptr<weld::Label> xAnnoteFT; + std::unique_ptr<weld::Entry> xAnnoteED; + std::unique_ptr<weld::Label> xNoteFT; + std::unique_ptr<weld::Entry> xNoteED; + std::unique_ptr<weld::Label> xURLFT; + std::unique_ptr<weld::Entry> xURLED; + + std::unique_ptr<weld::Label> xCustom1FT; + std::unique_ptr<weld::Entry> xCustom1ED; + std::unique_ptr<weld::Label> xCustom2FT; + std::unique_ptr<weld::Entry> xCustom2ED; + std::unique_ptr<weld::Label> xCustom3FT; + std::unique_ptr<weld::Entry> xCustom3ED; + std::unique_ptr<weld::Label> xCustom4FT; + std::unique_ptr<weld::Entry> xCustom4ED; + std::unique_ptr<weld::Label> xCustom5FT; + std::unique_ptr<weld::Entry> xCustom5ED; + std::unique_ptr<weld::Label> m_xLocalURLFT; + std::unique_ptr<weld::Entry> m_xLocalURLED; + std::unique_ptr<weld::Button> m_xLocalBrowseButton; + std::unique_ptr<weld::CheckButton> m_xLocalPageCB; + std::unique_ptr<weld::SpinButton> m_xLocalPageSB; + + OUString sTableErrorString; + + std::vector<rtl::Reference<ChangeListener>> maChangeListeners; + rtl::Reference<ChangeListener> m_aURLListener; + + BibDataManager* pDatMan; + + bool AddXControl(const OUString& rName, weld::Entry& rEntry); + bool AddXControl(const OUString& rName, weld::ComboBox& rList); + + template<class Target> void AddControlWithError(const OUString& rColumnName, const OUString& rColumnUIName, + Target& rWidget, OUString& rErrorString, const OString& rHelpId); + + void SaveChanges(); + + DECL_LINK(GainFocusHdl, weld::Widget&, void); + + DECL_LINK(FirstElementKeyInputHdl, const KeyEvent&, bool); + DECL_LINK(LastElementKeyInputHdl, const KeyEvent&, bool); + DECL_LINK(BrowseHdl, weld::Button&, void); + DECL_LINK(PageNumHdl, weld::Toggleable&, void); + DECL_LINK(LosePageFocusHdl, weld::Widget&, void); + +public: + BibGeneralPage(vcl::Window* pParent, BibDataManager* pDatMan); + virtual ~BibGeneralPage() override; + virtual void dispose() override; + + const OUString& GetErrorString() const + { + return sTableErrorString; + } + + weld::Entry& GetLocalURLED(); + weld::CheckButton& GetLocalPageCB(); + weld::SpinButton& GetLocalPageSB(); +}; + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/bibliography/loadlisteneradapter.cxx b/extensions/source/bibliography/loadlisteneradapter.cxx new file mode 100644 index 000000000..27f4ea2e5 --- /dev/null +++ b/extensions/source/bibliography/loadlisteneradapter.cxx @@ -0,0 +1,185 @@ +/* -*- 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 "loadlisteneradapter.hxx" +#include <osl/diagnose.h> +#include <rtl/ref.hxx> + + +namespace bib +{ + + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::form; + + OComponentListener::~OComponentListener() + { + ::osl::MutexGuard aGuard( m_rMutex ); + if ( m_xAdapter.is() ) + m_xAdapter->dispose(); + } + + + void OComponentListener::setAdapter( OComponentAdapterBase* pAdapter ) + { + ::osl::MutexGuard aGuard( m_rMutex ); + m_xAdapter = pAdapter; + } + + OComponentAdapterBase::OComponentAdapterBase( const Reference< XComponent >& _rxComp ) + :m_xComponent( _rxComp ) + ,m_pListener( nullptr ) + ,m_bListening( false ) + { + OSL_ENSURE( m_xComponent.is(), "OComponentAdapterBase::OComponentAdapterBase: invalid component!" ); + } + + + void OComponentAdapterBase::Init( OComponentListener* _pListener ) + { + OSL_ENSURE( !m_pListener, "OComponentAdapterBase::Init: already initialized!" ); + OSL_ENSURE( _pListener, "OComponentAdapterBase::Init: invalid listener!" ); + + m_pListener = _pListener; + if ( m_pListener ) + m_pListener->setAdapter( this ); + + startComponentListening( ); + m_bListening = true; + } + + + OComponentAdapterBase::~OComponentAdapterBase() + { + } + + + void OComponentAdapterBase::dispose() + { + if ( !m_bListening ) + return; + + ::rtl::Reference< OComponentAdapterBase > xPreventDelete(this); + + disposing(); + + m_pListener->setAdapter(nullptr); + + m_pListener = nullptr; + m_bListening = false; + + m_xComponent = nullptr; + } + + // XEventListener + + + void SAL_CALL OComponentAdapterBase::disposing( const EventObject& ) + { + if (m_pListener) + { + // disconnect the listener + m_pListener->setAdapter( nullptr ); + m_pListener = nullptr; + } + + m_bListening = false; + m_xComponent = nullptr; + } + + OLoadListenerAdapter::OLoadListenerAdapter( const Reference< XLoadable >& _rxLoadable ) + :OComponentAdapterBase( Reference< XComponent >( _rxLoadable, UNO_QUERY ) ) + { + } + + + void OLoadListenerAdapter::startComponentListening() + { + Reference< XLoadable > xLoadable( getComponent(), UNO_QUERY ); + OSL_ENSURE( xLoadable.is(), "OLoadListenerAdapter::OLoadListenerAdapter: invalid object!" ); + if ( xLoadable.is() ) + xLoadable->addLoadListener( this ); + } + + + void SAL_CALL OLoadListenerAdapter::acquire( ) noexcept + { + OLoadListenerAdapter_Base::acquire(); + } + + + void SAL_CALL OLoadListenerAdapter::release( ) noexcept + { + OLoadListenerAdapter_Base::release(); + } + + + void SAL_CALL OLoadListenerAdapter::disposing( const EventObject& _rSource ) + { + OComponentAdapterBase::disposing( _rSource ); + } + + + void OLoadListenerAdapter::disposing() + { + Reference< XLoadable > xLoadable( getComponent(), UNO_QUERY ); + if ( xLoadable.is() ) + xLoadable->removeLoadListener( this ); + } + + + void SAL_CALL OLoadListenerAdapter::loaded( const EventObject& _rEvent ) + { + if ( getLoadListener( ) ) + getLoadListener( )->_loaded( _rEvent ); + } + + + void SAL_CALL OLoadListenerAdapter::unloading( const EventObject& _rEvent ) + { + if ( getLoadListener( ) ) + getLoadListener( )->_unloading( _rEvent ); + } + + + void SAL_CALL OLoadListenerAdapter::unloaded( const EventObject& ) + { + } + + + void SAL_CALL OLoadListenerAdapter::reloading( const EventObject& _rEvent ) + { + if ( getLoadListener( ) ) + getLoadListener( )->_reloading( _rEvent ); + } + + + void SAL_CALL OLoadListenerAdapter::reloaded( const EventObject& _rEvent ) + { + if ( getLoadListener( ) ) + getLoadListener( )->_reloaded( _rEvent ); + } + + +} // namespace bib + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/bibliography/loadlisteneradapter.hxx b/extensions/source/bibliography/loadlisteneradapter.hxx new file mode 100644 index 000000000..1031dedca --- /dev/null +++ b/extensions/source/bibliography/loadlisteneradapter.hxx @@ -0,0 +1,151 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <osl/mutex.hxx> +#include <com/sun/star/lang/XComponent.hpp> +#include <cppuhelper/implbase.hxx> +#include <com/sun/star/form/XLoadable.hpp> +#include <rtl/ref.hxx> + + +namespace bib +{ + + + class OComponentAdapterBase; + + class OComponentListener + { + friend class OComponentAdapterBase; + + private: + rtl::Reference<OComponentAdapterBase> m_xAdapter; + ::osl::Mutex& m_rMutex; + protected: + explicit OComponentListener( ::osl::Mutex& _rMutex ) + :m_rMutex( _rMutex ) + { + } + + virtual ~OComponentListener(); + + protected: + void setAdapter( OComponentAdapterBase* _pAdapter ); + }; + + class OComponentAdapterBase + { + friend class OComponentListener; + + private: + css::uno::Reference< css::lang::XComponent > m_xComponent; + OComponentListener* m_pListener; + bool m_bListening : 1; + + // impl method for dispose - virtual, 'cause you at least need to remove the listener from the broadcaster + virtual void disposing() = 0; + + protected: + // attribute access for derivees + const css::uno::Reference< css::lang::XComponent >& + getComponent() const { return m_xComponent; } + OComponentListener* getListener() { return m_pListener; } + + // to be called by derivees which started listening at the component + virtual void startComponentListening() = 0; + + virtual ~OComponentAdapterBase(); + + public: + explicit OComponentAdapterBase( + const css::uno::Reference< css::lang::XComponent >& _rxComp + ); + + // late construction + // can be called from within you ctor, to have you're object fully initialized at the moment of + // the call (which would not be the case when calling this ctor) + void Init( OComponentListener* _pListener ); + + // base for ref-counting, implemented by OComponentAdapter + virtual void SAL_CALL acquire( ) noexcept = 0; + virtual void SAL_CALL release( ) noexcept = 0; + + /// dispose the object - stop listening and such + void dispose(); + + protected: + // XEventListener + /// @throws css::uno::RuntimeException + virtual void SAL_CALL disposing( const css::lang::EventObject& Source ); + }; + + class OLoadListener : public OComponentListener + { + friend class OLoadListenerAdapter; + + protected: + explicit OLoadListener( ::osl::Mutex& _rMutex ) : OComponentListener( _rMutex ) { } + + // XLoadListener equivalents + virtual void _loaded( const css::lang::EventObject& aEvent ) = 0; + virtual void _unloading( const css::lang::EventObject& aEvent ) = 0; + virtual void _reloading( const css::lang::EventObject& aEvent ) = 0; + virtual void _reloaded( const css::lang::EventObject& aEvent ) = 0; + }; + + typedef ::cppu::WeakImplHelper< css::form::XLoadListener > OLoadListenerAdapter_Base; + class OLoadListenerAdapter + :public OLoadListenerAdapter_Base + ,public OComponentAdapterBase + { + protected: + OLoadListener* getLoadListener( ) { return static_cast< OLoadListener* >( getListener() ); } + + protected: + virtual void disposing() override; + virtual void startComponentListening() override; + + public: + explicit OLoadListenerAdapter( + const css::uno::Reference< css::form::XLoadable >& _rxLoadable + ); + + + virtual void SAL_CALL acquire( ) noexcept override; + virtual void SAL_CALL release( ) noexcept override; + + protected: + // XEventListener + virtual void SAL_CALL disposing( const css::lang::EventObject& _rSource ) override; + + // XLoadListener + virtual void SAL_CALL loaded( const css::lang::EventObject& aEvent ) override; + virtual void SAL_CALL unloading( const css::lang::EventObject& aEvent ) override; + virtual void SAL_CALL unloaded( const css::lang::EventObject& aEvent ) override; + virtual void SAL_CALL reloading( const css::lang::EventObject& aEvent ) override; + virtual void SAL_CALL reloaded( const css::lang::EventObject& aEvent ) override; + }; + + +} // namespace bib + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/bibliography/toolbar.cxx b/extensions/source/bibliography/toolbar.cxx new file mode 100644 index 000000000..fd74a04e6 --- /dev/null +++ b/extensions/source/bibliography/toolbar.cxx @@ -0,0 +1,620 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <comphelper/propertyvalue.hxx> +#include <comphelper/processfactory.hxx> +#include <com/sun/star/frame/XDispatch.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/util/URLTransformer.hpp> +#include <com/sun/star/util/XURLTransformer.hpp> +#include <com/sun/star/frame/FrameSearchFlag.hpp> +#include "datman.hxx" +#include "toolbar.hxx" +#include <o3tl/any.hxx> +#include <svtools/miscopt.hxx> +#include <svtools/imgdef.hxx> +#include <vcl/svapp.hxx> +#include <vcl/settings.hxx> +#include <vcl/mnemonic.hxx> +#include <vcl/event.hxx> +#include <vcl/weldutils.hxx> +#include <bitmaps.hlst> + +#include "bibtools.hxx" + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; + + +// Constants -------------------------------------------------------------- + + +BibToolBarListener::BibToolBarListener(BibToolBar *pTB, const OUString& aStr, ToolBoxItemId nId): + nIndex(nId), + aCommand(aStr), + pToolBar(pTB) +{ +} + +BibToolBarListener::~BibToolBarListener() +{ +} + +void BibToolBarListener::statusChanged(const css::frame::FeatureStateEvent& rEvt) +{ + if(rEvt.FeatureURL.Complete == aCommand) + { + SolarMutexGuard aGuard; + pToolBar->EnableItem(nIndex,rEvt.IsEnabled); + + css::uno::Any aState=rEvt.State; + if(auto bChecked = o3tl::tryAccess<bool>(aState)) + { + pToolBar->CheckItem(nIndex, *bChecked); + } + + } +}; + + +BibTBListBoxListener::BibTBListBoxListener(BibToolBar *pTB, const OUString& aStr, ToolBoxItemId nId): + BibToolBarListener(pTB,aStr,nId) +{ +} + +BibTBListBoxListener::~BibTBListBoxListener() +{ +} + +void BibTBListBoxListener::statusChanged(const css::frame::FeatureStateEvent& rEvt) +{ + if(rEvt.FeatureURL.Complete != GetCommand()) + return; + + SolarMutexGuard aGuard; + pToolBar->EnableSourceList(rEvt.IsEnabled); + + Any aState = rEvt.State; + if(auto pStringSeq = o3tl::tryAccess<Sequence<OUString>>(aState)) + { + pToolBar->UpdateSourceList(false); + pToolBar->ClearSourceList(); + + const OUString* pStringArray = pStringSeq->getConstArray(); + + sal_uInt32 nCount = pStringSeq->getLength(); + OUString aEntry; + for( sal_uInt32 i=0; i<nCount; i++ ) + { + aEntry = pStringArray[i]; + pToolBar->InsertSourceEntry(aEntry); + } + pToolBar->UpdateSourceList(true); + } + + pToolBar->SelectSourceEntry(rEvt.FeatureDescriptor); +}; + +BibTBQueryMenuListener::BibTBQueryMenuListener(BibToolBar *pTB, const OUString& aStr, ToolBoxItemId nId): + BibToolBarListener(pTB,aStr,nId) +{ +} + +BibTBQueryMenuListener::~BibTBQueryMenuListener() +{ +} + +void BibTBQueryMenuListener::statusChanged(const frame::FeatureStateEvent& rEvt) +{ + if(rEvt.FeatureURL.Complete != GetCommand()) + return; + + SolarMutexGuard aGuard; + pToolBar->EnableSourceList(rEvt.IsEnabled); + + uno::Any aState=rEvt.State; + auto pStringSeq = o3tl::tryAccess<Sequence<OUString>>(aState); + if(!pStringSeq) + return; + + pToolBar->ClearFilterMenu(); + + const OUString* pStringArray = pStringSeq->getConstArray(); + + sal_uInt32 nCount = pStringSeq->getLength(); + for( sal_uInt32 i=0; i<nCount; i++ ) + { + sal_uInt16 nID = pToolBar->InsertFilterItem(pStringArray[i]); + if(pStringArray[i]==rEvt.FeatureDescriptor) + { + pToolBar->SelectFilterItem(nID); + } + } +}; + +BibTBEditListener::BibTBEditListener(BibToolBar *pTB, const OUString& aStr, ToolBoxItemId nId): + BibToolBarListener(pTB,aStr,nId) +{ +} + +BibTBEditListener::~BibTBEditListener() +{ +} + +void BibTBEditListener::statusChanged(const frame::FeatureStateEvent& rEvt) +{ + if(rEvt.FeatureURL.Complete == GetCommand()) + { + SolarMutexGuard aGuard; + pToolBar->EnableQuery(rEvt.IsEnabled); + + uno::Any aState=rEvt.State; + if(auto aStr = o3tl::tryAccess<OUString>(aState)) + { + pToolBar->SetQueryString(*aStr); + } + } +} + +ComboBoxControl::ComboBoxControl(vcl::Window* pParent) + : InterimItemWindow(pParent, "modules/sbibliography/ui/combobox.ui", "ComboBox") + , m_xFtSource(m_xBuilder->weld_label("label")) + , m_xLBSource(m_xBuilder->weld_combo_box("combobox")) +{ + m_xFtSource->set_toolbar_background(); + m_xLBSource->set_toolbar_background(); + m_xLBSource->set_size_request(100, -1); + SetSizePixel(get_preferred_size()); +} + +void ComboBoxControl::dispose() +{ + m_xLBSource.reset(); + m_xFtSource.reset(); + InterimItemWindow::dispose(); +} + +ComboBoxControl::~ComboBoxControl() +{ + disposeOnce(); +} + +EditControl::EditControl(vcl::Window* pParent) + : InterimItemWindow(pParent, "modules/sbibliography/ui/editbox.ui", "EditBox") + , m_xFtQuery(m_xBuilder->weld_label("label")) + , m_xEdQuery(m_xBuilder->weld_entry("entry")) +{ + m_xFtQuery->set_toolbar_background(); + m_xEdQuery->set_toolbar_background(); + m_xEdQuery->set_size_request(100, -1); + SetSizePixel(get_preferred_size()); +} + +void EditControl::dispose() +{ + m_xEdQuery.reset(); + m_xFtQuery.reset(); + InterimItemWindow::dispose(); +} + +EditControl::~EditControl() +{ + disposeOnce(); +} + +BibToolBar::BibToolBar(vcl::Window* pParent, Link<void*,void> aLink) + : ToolBox(pParent, "toolbar", "modules/sbibliography/ui/toolbar.ui") + , aIdle("BibToolBar") + , xSource(VclPtr<ComboBoxControl>::Create(this)) + , pLbSource(xSource->get_widget()) + , xQuery(VclPtr<EditControl>::Create(this)) + , pEdQuery(xQuery->get_widget()) + , xBuilder(Application::CreateBuilder(nullptr, "modules/sbibliography/ui/autofiltermenu.ui")) + , xPopupMenu(xBuilder->weld_menu("menu")) + , nMenuId(0) + , aLayoutManager(aLink) + , nSymbolsSize(SFX_SYMBOLS_SIZE_SMALL) +{ + SvtMiscOptions aSvtMiscOptions; + nSymbolsSize = aSvtMiscOptions.GetCurrentSymbolsSize(); + + xSource->Show(); + pLbSource->connect_changed(LINK( this, BibToolBar, SelHdl)); + + SvtMiscOptions().AddListenerLink( LINK( this, BibToolBar, OptionsChanged_Impl ) ); + Application::AddEventListener( LINK( this, BibToolBar, SettingsChanged_Impl ) ); + + aIdle.SetInvokeHandler(LINK( this, BibToolBar, SendSelHdl)); + aIdle.SetPriority(TaskPriority::LOWEST); + + SetDropdownClickHdl( LINK( this, BibToolBar, MenuHdl)); + + xQuery->Show(); + + nTBC_SOURCE = GetItemId(".uno:Bib/source"); + nTBC_QUERY = GetItemId(".uno:Bib/query"); + nTBC_BT_AUTOFILTER = GetItemId(".uno:Bib/autoFilter"); + nTBC_BT_COL_ASSIGN = GetItemId("TBC_BT_COL_ASSIGN"); + nTBC_BT_CHANGESOURCE = GetItemId(".uno:Bib/sdbsource"); + nTBC_BT_FILTERCRIT = GetItemId(".uno:Bib/standardFilter"); + nTBC_BT_REMOVEFILTER = GetItemId(".uno:Bib/removeFilter"); + + SetItemWindow(nTBC_SOURCE, xSource.get()); + SetItemWindow(nTBC_QUERY , xQuery.get()); + + ApplyImageList(); + + ::bib::AddToTaskPaneList( this ); +} + +BibToolBar::~BibToolBar() +{ + disposeOnce(); +} + +void BibToolBar::dispose() +{ + SvtMiscOptions().RemoveListenerLink( LINK( this, BibToolBar, OptionsChanged_Impl ) ); + Application::RemoveEventListener( LINK( this, BibToolBar, SettingsChanged_Impl ) ); + ::bib::RemoveFromTaskPaneList( this ); + pEdQuery = nullptr; + xQuery.disposeAndClear(); + pLbSource = nullptr; + xSource.disposeAndClear(); + xPopupMenu.reset(); + xBuilder.reset(); + ToolBox::dispose(); +} + +void BibToolBar::InitListener() +{ + ToolBox::ImplToolItems::size_type nCount=GetItemCount(); + + uno::Reference< frame::XDispatch > xDisp(xController,UNO_QUERY); + uno::Reference< util::XURLTransformer > xTrans( util::URLTransformer::create(comphelper::getProcessComponentContext()) ); + if( !xTrans.is() ) + return; + + util::URL aQueryURL; + aQueryURL.Complete = ".uno:Bib/MenuFilter"; + xTrans->parseStrict( aQueryURL); + rtl::Reference<BibToolBarListener> pQuery=new BibTBQueryMenuListener(this, aQueryURL.Complete, nTBC_BT_AUTOFILTER); + xDisp->addStatusListener(pQuery, aQueryURL); + + for(ToolBox::ImplToolItems::size_type nPos=0;nPos<nCount;nPos++) + { + ToolBoxItemId nId=GetItemId(nPos); + if (!nId) + continue; + + util::URL aURL; + aURL.Complete = GetItemCommand(nId); + if(aURL.Complete.isEmpty()) + continue; + + xTrans->parseStrict( aURL ); + + css::uno::Reference< css::frame::XStatusListener> xListener; + if (nId == nTBC_SOURCE) + { + xListener=new BibTBListBoxListener(this,aURL.Complete,nId); + } + else if (nId == nTBC_QUERY) + { + xListener=new BibTBEditListener(this,aURL.Complete,nId); + } + else + { + xListener=new BibToolBarListener(this,aURL.Complete,nId); + } + + aListenerArr.push_back( xListener ); + xDisp->addStatusListener(xListener,aURL); + } +} + +void BibToolBar::SetXController(const uno::Reference< frame::XController > & xCtr) +{ + xController=xCtr; + InitListener(); + +} + +void BibToolBar::Select() +{ + ToolBoxItemId nId=GetCurItemId(); + + if (nId != nTBC_BT_AUTOFILTER) + { + SendDispatch(nId,Sequence<PropertyValue>() ); + } + else + { + Sequence<PropertyValue> aPropVal + { + comphelper::makePropertyValue("QueryText", pEdQuery->get_text()), + comphelper::makePropertyValue("QueryField", aQueryField) + }; + SendDispatch(nId,aPropVal); + } +} + +void BibToolBar::SendDispatch(ToolBoxItemId nId, const Sequence< PropertyValue >& rArgs) +{ + OUString aCommand = GetItemCommand(nId); + + uno::Reference< frame::XDispatchProvider > xDSP( xController, UNO_QUERY ); + + if( !xDSP.is() || aCommand.isEmpty() ) + return; + + uno::Reference< util::XURLTransformer > xTrans( util::URLTransformer::create(comphelper::getProcessComponentContext()) ); + if( !xTrans.is() ) + return; + + // load the file + util::URL aURL; + aURL.Complete = aCommand; + + xTrans->parseStrict( aURL ); + + uno::Reference< frame::XDispatch > xDisp = xDSP->queryDispatch( aURL, OUString(), frame::FrameSearchFlag::SELF ); + + if ( xDisp.is() ) + xDisp->dispatch( aURL, rArgs); + +} + +void BibToolBar::Click() +{ + ToolBoxItemId nId = GetCurItemId(); + + vcl::Window* pWin = GetParent(); + + if (nId == nTBC_BT_COL_ASSIGN ) + { + if (pDatMan) + pDatMan->CreateMappingDialog(pWin ? pWin->GetFrameWeld() : nullptr); + CheckItem( nId, false ); + } + else if (nId == nTBC_BT_CHANGESOURCE) + { + if (pDatMan) + { + OUString sNew = pDatMan->CreateDBChangeDialog(pWin ? pWin->GetFrameWeld() : nullptr); + if (!sNew.isEmpty()) + pDatMan->setActiveDataSource(sNew); + } + CheckItem( nId, false ); + } +} + +void BibToolBar::ClearFilterMenu() +{ + xPopupMenu->clear(); + nMenuId=0; +} + +sal_uInt16 BibToolBar::InsertFilterItem(const OUString& rMenuEntry) +{ + nMenuId++; + xPopupMenu->append_check(OUString::number(nMenuId), rMenuEntry); + return nMenuId; +} + +void BibToolBar::SelectFilterItem(sal_uInt16 nId) +{ + OString sId = OString::number(nId); + xPopupMenu->set_active(sId, true); + sSelMenuItem = sId; + aQueryField = MnemonicGenerator::EraseAllMnemonicChars(xPopupMenu->get_label(sId)); +} + +void BibToolBar::EnableSourceList(bool bFlag) +{ + xSource->set_sensitive(bFlag); +} + +void BibToolBar::ClearSourceList() +{ + pLbSource->clear(); +} + +void BibToolBar::UpdateSourceList(bool bFlag) +{ + if (bFlag) + pLbSource->thaw(); + else + pLbSource->freeze(); +} + +void BibToolBar::InsertSourceEntry(const OUString& aEntry) +{ + pLbSource->append_text(aEntry); +} + +void BibToolBar::SelectSourceEntry(const OUString& aStr) +{ + pLbSource->set_active_text(aStr); +} + +void BibToolBar::EnableQuery(bool bFlag) +{ + xQuery->set_sensitive(bFlag); +} + +void BibToolBar::SetQueryString(const OUString& aStr) +{ + pEdQuery->set_text(aStr); +} + +bool BibToolBar::PreNotify( NotifyEvent& rNEvt ) +{ + bool bResult = true; + + MouseNotifyEvent nSwitch=rNEvt.GetType(); + if (pEdQuery && pEdQuery->has_focus() && nSwitch == MouseNotifyEvent::KEYINPUT) + { + const vcl::KeyCode& aKeyCode=rNEvt.GetKeyEvent()->GetKeyCode(); + sal_uInt16 nKey = aKeyCode.GetCode(); + if(nKey == KEY_RETURN) + { + Sequence<PropertyValue> aPropVal + { + comphelper::makePropertyValue("QueryText", pEdQuery->get_text()), + comphelper::makePropertyValue("QueryField", aQueryField) + }; + SendDispatch(nTBC_BT_AUTOFILTER, aPropVal); + return bResult; + } + + } + + bResult=ToolBox::PreNotify(rNEvt); + + return bResult; +} + +IMPL_LINK_NOARG( BibToolBar, SelHdl, weld::ComboBox&, void ) +{ + aIdle.Start(); +} + +IMPL_LINK_NOARG( BibToolBar, SendSelHdl, Timer*, void ) +{ + Sequence<PropertyValue> aPropVal + { + comphelper::makePropertyValue("DataSourceName", MnemonicGenerator::EraseAllMnemonicChars( pLbSource->get_active_text() )) + }; + SendDispatch(nTBC_SOURCE, aPropVal); +} + +IMPL_LINK_NOARG(BibToolBar, MenuHdl, ToolBox*, void) +{ + ToolBoxItemId nId = GetCurItemId(); + if (nId != nTBC_BT_AUTOFILTER) + return; + + EndSelection(); // before SetDropMode (SetDropMode calls SetItemImage) + + SetItemDown(nTBC_BT_AUTOFILTER, true); + + tools::Rectangle aRect(GetItemRect(nTBC_BT_AUTOFILTER)); + weld::Window* pParent = weld::GetPopupParent(*this, aRect); + OString sId = xPopupMenu->popup_at_rect(pParent, aRect); + + if (!sId.isEmpty()) + { + xPopupMenu->set_active(sSelMenuItem, false); + xPopupMenu->set_active(sId, true); + sSelMenuItem = sId; + aQueryField = MnemonicGenerator::EraseAllMnemonicChars(xPopupMenu->get_label(sId)); + Sequence<PropertyValue> aPropVal + { + comphelper::makePropertyValue("QueryText", pEdQuery->get_text()), + comphelper::makePropertyValue("QueryField", aQueryField) + }; + SendDispatch(nTBC_BT_AUTOFILTER, aPropVal); + } + + MouseEvent aLeave( Point(), 0, MouseEventModifiers::LEAVEWINDOW | MouseEventModifiers::SYNTHETIC ); + MouseMove( aLeave ); + SetItemDown(nTBC_BT_AUTOFILTER, false); +} + +void BibToolBar::statusChanged(const frame::FeatureStateEvent& rEvent) +{ + for(uno::Reference<frame::XStatusListener> & rListener : aListenerArr) + { + rListener->statusChanged(rEvent); + } +} + +void BibToolBar::DataChanged( const DataChangedEvent& rDCEvt ) +{ + if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && + (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) ) + ApplyImageList(); + ToolBox::DataChanged( rDCEvt ); +} + +IMPL_LINK_NOARG( BibToolBar, OptionsChanged_Impl, LinkParamNone*, void ) +{ + bool bRebuildToolBar = false; + sal_Int16 eSymbolsSize = SvtMiscOptions().GetCurrentSymbolsSize(); + if ( nSymbolsSize != eSymbolsSize ) + { + nSymbolsSize = eSymbolsSize; + bRebuildToolBar = true; + } + + if ( bRebuildToolBar ) + RebuildToolbar(); +} + +IMPL_LINK_NOARG( BibToolBar, SettingsChanged_Impl, VclSimpleEvent&, void ) +{ + // Check if toolbar button size have changed and we have to use system settings + sal_Int16 eSymbolsSize = SvtMiscOptions().GetCurrentSymbolsSize(); + if ( eSymbolsSize != nSymbolsSize ) + { + nSymbolsSize = eSymbolsSize; + RebuildToolbar(); + } +} + +void BibToolBar::RebuildToolbar() +{ + ApplyImageList(); + // We have to call parent asynchronously as SetSize works also asynchronously! + Application::PostUserEvent( aLayoutManager ); +} + +void BibToolBar::ApplyImageList() +{ + SetItemImage(nTBC_BT_AUTOFILTER, Image(StockImage::Yes, nSymbolsSize == SFX_SYMBOLS_SIZE_SMALL ? OUString(RID_EXTBMP_AUTOFILTER_SC) : OUString(RID_EXTBMP_AUTOFILTER_LC))); + SetItemImage(nTBC_BT_FILTERCRIT, Image(StockImage::Yes, nSymbolsSize == SFX_SYMBOLS_SIZE_SMALL ? OUString(RID_EXTBMP_FILTERCRIT_SC) : OUString(RID_EXTBMP_FILTERCRIT_LC))); + SetItemImage(nTBC_BT_REMOVEFILTER, Image(StockImage::Yes, nSymbolsSize == SFX_SYMBOLS_SIZE_SMALL ? OUString(RID_EXTBMP_REMOVE_FILTER_SORT_SC) : OUString(RID_EXTBMP_REMOVE_FILTER_SORT_LC))); + AdjustToolBox(); +} + +void BibToolBar::AdjustToolBox() +{ + Size aOldSize = GetSizePixel(); + Size aSize = CalcWindowSizePixel(); + if ( !aSize.Width() ) + aSize.setWidth( aOldSize.Width() ); + else if ( !aSize.Height() ) + aSize.setHeight( aOldSize.Height() ); + + Size aTbSize = GetSizePixel(); + if ( + (aSize.Width() && aSize.Width() != aTbSize.Width()) || + (aSize.Height() && aSize.Height() != aTbSize.Height()) + ) + { + SetPosSizePixel( GetPosPixel(), aSize ); + Invalidate(); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/extensions/source/bibliography/toolbar.hxx b/extensions/source/bibliography/toolbar.hxx new file mode 100644 index 000000000..4f800f050 --- /dev/null +++ b/extensions/source/bibliography/toolbar.hxx @@ -0,0 +1,217 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <com/sun/star/frame/XController.hpp> +#include <com/sun/star/frame/XStatusListener.hpp> + +#include <vcl/InterimItemWindow.hxx> +#include <vcl/toolbox.hxx> +#include <vcl/timer.hxx> +#include <cppuhelper/implbase.hxx> +#include <vector> + +class BibDataManager; +class BibToolBar; + +class BibToolBarListener: public cppu::WeakImplHelper < css::frame::XStatusListener> +{ +private: + + ToolBoxItemId nIndex; + OUString aCommand; + +protected: + + VclPtr<BibToolBar> pToolBar; + +public: + + BibToolBarListener(BibToolBar *pTB, const OUString& aStr, ToolBoxItemId nId); + virtual ~BibToolBarListener() override; + + const OUString& GetCommand() const { return aCommand;} + + // css::lang::XEventListener + // we do not hold References to dispatches, so there is nothing to do on disposal + virtual void SAL_CALL disposing(const css::lang::EventObject& /*Source*/) override {}; + + // css::frame::XStatusListener + virtual void SAL_CALL statusChanged(const css::frame::FeatureStateEvent& Event) override; + +}; + +class BibTBListBoxListener: public BibToolBarListener +{ +public: + + BibTBListBoxListener(BibToolBar *pTB, const OUString& aStr, ToolBoxItemId nId); + virtual ~BibTBListBoxListener() override; + + virtual void SAL_CALL statusChanged(const css::frame::FeatureStateEvent& Event) override; + +}; + +class BibTBEditListener: public BibToolBarListener +{ +public: + + BibTBEditListener(BibToolBar *pTB, const OUString& aStr, ToolBoxItemId nId); + virtual ~BibTBEditListener() override; + + virtual void SAL_CALL statusChanged(const css::frame::FeatureStateEvent& Event) override; + +}; + +class BibTBQueryMenuListener: public BibToolBarListener +{ +public: + + BibTBQueryMenuListener(BibToolBar *pTB, const OUString& aStr, ToolBoxItemId nId); + virtual ~BibTBQueryMenuListener() override; + + virtual void SAL_CALL statusChanged(const css::frame::FeatureStateEvent& Event) override; + +}; + + +typedef std::vector< css::uno::Reference< css::frame::XStatusListener> > BibToolBarListenerArr; + +class ComboBoxControl final : public InterimItemWindow +{ +public: + ComboBoxControl(vcl::Window* pParent); + virtual ~ComboBoxControl() override; + virtual void dispose() override; + + weld::ComboBox* get_widget() { return m_xLBSource.get(); } + + void set_sensitive(bool bSensitive) + { + m_xFtSource->set_sensitive(bSensitive); + m_xLBSource->set_sensitive(bSensitive); + Enable(bSensitive); + } + +private: + std::unique_ptr<weld::Label> m_xFtSource; + std::unique_ptr<weld::ComboBox> m_xLBSource; +}; + +class EditControl final : public InterimItemWindow +{ +public: + EditControl(vcl::Window* pParent); + virtual ~EditControl() override; + virtual void dispose() override; + + weld::Entry* get_widget() { return m_xEdQuery.get(); } + + void set_sensitive(bool bSensitive) + { + m_xFtQuery->set_sensitive(bSensitive); + m_xEdQuery->set_sensitive(bSensitive); + Enable(bSensitive); + } + +private: + std::unique_ptr<weld::Label> m_xFtQuery; + std::unique_ptr<weld::Entry> m_xEdQuery; +}; + +class BibToolBar: public ToolBox +{ + private: + + BibToolBarListenerArr aListenerArr; + css::uno::Reference< css::frame::XController > xController; + Idle aIdle; + VclPtr<ComboBoxControl> xSource; + weld::ComboBox* pLbSource; + VclPtr<EditControl> xQuery; + weld::Entry* pEdQuery; + std::unique_ptr<weld::Builder> xBuilder; + std::unique_ptr<weld::Menu> xPopupMenu; + sal_uInt16 nMenuId; + OString sSelMenuItem; + OUString aQueryField; + Link<void*,void> aLayoutManager; + sal_Int16 nSymbolsSize; + + ToolBoxItemId nTBC_SOURCE; + ToolBoxItemId nTBC_QUERY; + ToolBoxItemId nTBC_BT_AUTOFILTER; + ToolBoxItemId nTBC_BT_COL_ASSIGN; + ToolBoxItemId nTBC_BT_CHANGESOURCE; + ToolBoxItemId nTBC_BT_FILTERCRIT; + ToolBoxItemId nTBC_BT_REMOVEFILTER; + + BibDataManager* pDatMan; + DECL_LINK( SelHdl, weld::ComboBox&, void ); + DECL_LINK( SendSelHdl, Timer*, void ); + DECL_LINK( MenuHdl, ToolBox*, void ); + DECL_LINK( OptionsChanged_Impl, LinkParamNone*, void ); + DECL_LINK( SettingsChanged_Impl, VclSimpleEvent&, void ); + + void ApplyImageList(); + void RebuildToolbar(); + + protected: + + void DataChanged( const DataChangedEvent& rDCEvt ) override; + void InitListener(); + virtual void Select() override; + virtual void Click() override; + virtual bool PreNotify( NotifyEvent& rNEvt ) override; + + + public: + + BibToolBar(vcl::Window* pParent, Link<void*,void> aLink); + virtual ~BibToolBar() override; + virtual void dispose() override; + + ToolBoxItemId GetChangeSourceId() const { return nTBC_BT_CHANGESOURCE; } + + void SetXController(const css::uno::Reference< css::frame::XController > &); + + void ClearSourceList(); + void UpdateSourceList(bool bFlag); + void EnableSourceList(bool bFlag); + void InsertSourceEntry(const OUString& ); + void SelectSourceEntry(const OUString& ); + + void EnableQuery(bool bFlag); + void SetQueryString(const OUString& ); + void AdjustToolBox(); + + void ClearFilterMenu(); + sal_uInt16 InsertFilterItem(const OUString& ); + void SelectFilterItem(sal_uInt16 nId); + + /// @throws css::uno::RuntimeException + void statusChanged(const css::frame::FeatureStateEvent& Event); + + void SetDatMan(BibDataManager& rDatMan) {pDatMan = &rDatMan;} + void SendDispatch(ToolBoxItemId nId, const css::uno::Sequence< css::beans::PropertyValue >& rArgs); +}; + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |