ed0b12f4ea
we can just take a "const &". (found by running clang-tidy with the performance-unnecessary-copy-initialization warning) Change-Id: I20fd208c65303da78170b1ac06c638fdf3aa094b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176267 Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk> Tested-by: Jenkins
870 lines
29 KiB
C++
870 lines
29 KiB
C++
/* -*- 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 <utility>
|
|
#include <vcl/event.hxx>
|
|
#include <vcl/svapp.hxx>
|
|
#include <comphelper/processfactory.hxx>
|
|
#include <com/sun/star/awt/XTextComponent.hpp>
|
|
#include <com/sun/star/awt/XVclWindowPeer.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 <comphelper/diagnose_ex.hxx>
|
|
#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( uno::Reference< awt::XWindow > xComponent,
|
|
BibDataManager* pDataManager)
|
|
:m_xWindow(std::move( 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 u"com.sun.star.comp.extensions.Bibliography"_ustr;
|
|
}
|
|
|
|
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 { u"com.sun.star.frame.Bibliography"_ustr };
|
|
}
|
|
|
|
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 );
|
|
m_xFrame.clear();
|
|
|
|
aObject.Source = static_cast<XController*>(this);
|
|
m_xImpl->aLC.disposeAndClear(aObject);
|
|
m_xDatMan.clear();
|
|
m_aStatusListeners.clear();
|
|
m_xLastQueriedFocusWin.clear();
|
|
m_xWindow.clear();
|
|
m_xImpl.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(u"Privileges"_ustr) >>= 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(u"IsNew"_ustr));
|
|
bool bIsModified = ::comphelper::getBOOL(_xSet->getPropertyValue(u"IsModified"_ustr));
|
|
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
|
|
}
|
|
}
|
|
|
|
OUString aQuery;
|
|
aArgs[0].Value >>= aQuery;
|
|
|
|
OUString aQueryField;
|
|
aArgs[1].Value >>= aQueryField;
|
|
BibConfig* pConfig = BibModul::GetConfig();
|
|
pConfig->setQueryField(aQueryField);
|
|
m_xDatMan->startQueryWith(aQuery);
|
|
}
|
|
else if(aCommand == "Bib/standardFilter")
|
|
{
|
|
try
|
|
{
|
|
const 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 == ".uno:CloseDoc" || 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(u"IsNew"_ustr));
|
|
if(!bIsNew)
|
|
{
|
|
sal_uInt32 nCount = 0;
|
|
xSet->getPropertyValue(u"RowCount"_ustr) >>= 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(u"IsNew"_ustr));
|
|
if(!bIsNew)
|
|
{
|
|
sal_uInt32 nCount = 0;
|
|
xSet->getPropertyValue(u"RowCount"_ustr) >>= 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)
|
|
{
|
|
uno::Any aValue = aArgs[0].Value;
|
|
OUString aDBTableName;
|
|
aValue >>= aDBTableName;
|
|
|
|
|
|
if(aArgs.getLength() > 1)
|
|
{
|
|
uno::Any aDB = aArgs[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: */
|