/* -*- 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 .
*/
// a helper class implementing a runtime::XFormController, will be aggregated by SbaXDataBrowserController // (we can't derive from XFormController as it's base class is XTabController and the XTabController::getModel collides // with the XController::getModel implemented in our base class SbaXDataBrowserController) class SbaXDataBrowserController::FormControllerImpl
: public ::cppu::WeakAggImplHelper2< css::form::runtime::XFormController,
css::frame::XFrameActionListener >
{ friendclass SbaXDataBrowserController;
::comphelper::OInterfaceContainerHelper3<css::form::XFormControllerListener> m_aActivateListeners;
SbaXDataBrowserController* m_pOwner;
void SAL_CALL SbaXDataBrowserController::FormControllerImpl::dispose( )
{
SAL_WARN("dbaccess.ui", "SbaXDataBrowserController::FormControllerImpl::dispose: no, you do *not* want to do this!" );
}
::sal_Int32 SAL_CALL SbaXDataBrowserController::FormControllerImpl::getCount( )
{ // no sub controllers, never return 0;
}
Any SAL_CALL SbaXDataBrowserController::FormControllerImpl::getByIndex( ::sal_Int32 /*Index*/ )
{ // no sub controllers, never throw IndexOutOfBoundsException( OUString(), *this );
}
Type SAL_CALL SbaXDataBrowserController::FormControllerImpl::getElementType( )
{ return ::cppu::UnoType< runtime::XFormController >::get();
}
sal_Bool SAL_CALL SbaXDataBrowserController::FormControllerImpl::hasElements( )
{ // no sub controllers, never returnfalse;
}
void SAL_CALL SbaXDataBrowserController::FormControllerImpl::autoTabOrder()
{
SAL_WARN("dbaccess.ui","SbaXDataBrowserController::FormControllerImpl::autoTabOrder : nothing to do (always have only one control) !");
}
void SAL_CALL SbaXDataBrowserController::FormControllerImpl::activateTabOrder()
{
SAL_WARN("dbaccess.ui","SbaXDataBrowserController::FormControllerImpl::activateTabOrder : nothing to do (always have only one control) !");
}
void SAL_CALL SbaXDataBrowserController::FormControllerImpl::activateFirst()
{ if (m_pOwner->getBrowserView())
m_pOwner->getBrowserView()->getVclControl()->ActivateCell();
}
void SAL_CALL SbaXDataBrowserController::FormControllerImpl::activateLast()
{ if (m_pOwner->getBrowserView())
m_pOwner->getBrowserView()->getVclControl()->ActivateCell();
}
void SAL_CALL SbaXDataBrowserController::FormControllerImpl::disposing(const css::lang::EventObject& /*Source*/)
{ // nothing to do // we don't add ourself as listener to any broadcasters, so we are not responsible for removing us
}
void SbaXDataBrowserController::initFormatter()
{ // create a formatter working with the connections format supplier
Reference< css::util::XNumberFormatsSupplier > xSupplier(::dbtools::getNumberFormats(::dbtools::getConnection(m_xRowSet), true, getORB()));
if(xSupplier.is())
{ // create a new formatter
m_xFormatter.set(util::NumberFormatter::create(getORB()), UNO_QUERY_THROW);
m_xFormatter->attachNumberFormatsSupplier(xSupplier);
} else// clear the formatter
m_xFormatter = nullptr;
}
bool SbaXDataBrowserController::Construct(vcl::Window* pParent)
{ // create/initialize the form and the grid model
m_xRowSet = CreateForm(); if (!m_xRowSet.is()) returnfalse;
m_xGridModel = CreateGridModel(); if (!m_xGridModel.is()) returnfalse;
// set the formatter if available
initFormatter();
// we want to have a grid with a "flat" border
Reference< XPropertySet > xGridSet(m_xGridModel, UNO_QUERY); if ( xGridSet.is() )
xGridSet->setPropertyValue(PROPERTY_BORDER, Any(sal_Int16(2)));
// create the view
setView( VclPtr<UnoDataBrowserView>::Create( pParent, *this, getORB() ) ); if (!getBrowserView()) returnfalse;
// late construction bool bSuccess = false; try
{
getBrowserView()->Construct(getControlModel());
bSuccess = true;
} catch(SQLException&)
{
} catch(Exception&)
{
SAL_WARN("dbaccess.ui","SbaXDataBrowserController::Construct : the construction of UnoDataBrowserView failed !");
}
if (!bSuccess)
{ // deleteView(); returnfalse;
}
// now that we have a view we can create the clipboard listener
m_aSystemClipboard = TransferableDataHelper::CreateFromSystemClipboard( getView() );
m_aSystemClipboard.StartClipboardListening( );
// this call create the toolbox
SbaXDataBrowserController_Base::Construct(pParent);
getBrowserView()->Show();
// set the callbacks for the grid control
SbaGridControl* pVclGrid = getBrowserView()->getVclControl();
OSL_ENSURE(pVclGrid, "SbaXDataBrowserController::Construct : have no VCL control !");
pVclGrid->SetMasterListener(this);
// add listeners...
// ... to the form model
Reference< XPropertySet > xFormSet(getRowSet(), UNO_QUERY); if (xFormSet.is())
{
xFormSet->addPropertyChangeListener(PROPERTY_ISNEW, static_cast<XPropertyChangeListener*>(this));
xFormSet->addPropertyChangeListener(PROPERTY_ISMODIFIED, static_cast<XPropertyChangeListener*>(this));
xFormSet->addPropertyChangeListener(PROPERTY_ROWCOUNT, static_cast<XPropertyChangeListener*>(this));
xFormSet->addPropertyChangeListener(PROPERTY_ACTIVECOMMAND, static_cast<XPropertyChangeListener*>(this));
xFormSet->addPropertyChangeListener(PROPERTY_ORDER, static_cast<XPropertyChangeListener*>(this));
xFormSet->addPropertyChangeListener(PROPERTY_FILTER, static_cast<XPropertyChangeListener*>(this));
xFormSet->addPropertyChangeListener(PROPERTY_HAVING_CLAUSE, static_cast<XPropertyChangeListener*>(this));
xFormSet->addPropertyChangeListener(PROPERTY_APPLYFILTER, static_cast<XPropertyChangeListener*>(this));
}
Reference< css::sdb::XSQLErrorBroadcaster > xFormError(getRowSet(), UNO_QUERY); if (xFormError.is())
xFormError->addSQLErrorListener(static_cast<css::sdb::XSQLErrorListener*>(this));
if (m_xLoadable.is())
m_xLoadable->addLoadListener(this);
Reference< css::form::XDatabaseParameterBroadcaster > xFormParameter(getRowSet(), UNO_QUERY); if (xFormParameter.is())
xFormParameter->addParameterListener(static_cast<css::form::XDatabaseParameterListener*>(this));
void SbaXDataBrowserController::addModelListeners(const Reference< css::awt::XControlModel > & _xGridControlModel)
{ // ... all the grid columns
addColumnListeners(_xGridControlModel);
// (we are interested in all columns the grid has (and only in these) so we have to listen to the container, too)
Reference< css::container::XContainer > xColContainer(_xGridControlModel, UNO_QUERY); if (xColContainer.is())
xColContainer->addContainerListener(static_cast<css::container::XContainerListener*>(this));
Reference< css::form::XReset > xReset(_xGridControlModel, UNO_QUERY); if (xReset.is())
xReset->addResetListener(static_cast<css::form::XResetListener*>(this));
}
void SbaXDataBrowserController::removeModelListeners(const Reference< XControlModel > & _xGridControlModel)
{ // every single column model
Reference< XIndexContainer > xColumns(_xGridControlModel, UNO_QUERY); if (xColumns.is())
{
sal_Int32 nCount = xColumns->getCount(); for (sal_Int32 i=0; i < nCount; ++i)
{
Reference< XPropertySet > xCol(xColumns->getByIndex(i),UNO_QUERY);
RemoveColumnListener(xCol);
}
}
Reference< XContainer > xColContainer(_xGridControlModel, UNO_QUERY); if (xColContainer.is())
xColContainer->removeContainerListener( this );
Reference< XReset > xReset(_xGridControlModel, UNO_QUERY); if (xReset.is())
xReset->removeResetListener( this );
}
void SbaXDataBrowserController::addControlListeners(const Reference< css::awt::XControl > & _xGridControl)
{ // to ge the 'modified' for the current cell
rtl::Reference< SbaXGridControl > xGridControl(getBrowserView()->getGridControl() ); if (xGridControl.is())
xGridControl->addModifyListener(static_cast<XModifyListener*>(this));
// introduce ourself as dispatch provider for the grid if (xGridControl.is())
xGridControl->registerDispatchProviderInterceptor(static_cast<XDispatchProviderInterceptor*>(this));
// add as focus listener to the control (needed for the form controller functionality)
Reference< XWindow > xWindow(_xGridControl, UNO_QUERY); if (xWindow.is())
xWindow->addFocusListener(this);
}
Reference< XDispatchProviderInterception > xInterception(_xGridControl, UNO_QUERY); if (xInterception.is())
xInterception->releaseDispatchProviderInterceptor(static_cast<XDispatchProviderInterceptor*>(this));
Reference< XWindow > xWindow(_xGridControl, UNO_QUERY); if (xWindow.is())
xWindow->removeFocusListener(this);
}
void SAL_CALL SbaXDataBrowserController::focusGained(const FocusEvent& /*e*/)
{ // notify our activate listeners (registered on the form controller aggregate)
EventObject aEvt(*this);
m_xFormControllerImpl->m_aActivateListeners.notifyEach( &css::form::XFormControllerListener::formActivated, aEvt );
}
void SAL_CALL SbaXDataBrowserController::focusLost(const FocusEvent& e)
{ // some general checks if (!getBrowserView() || !getBrowserView()->getGridControl().is()) return;
Reference< XVclWindowPeer > xMyGridPeer(getBrowserView()->getGridControl()->getPeer(), UNO_QUERY); if (!xMyGridPeer.is()) return;
Reference< XWindowPeer > xNextControlPeer(e.NextFocus, UNO_QUERY); if (!xNextControlPeer.is()) return;
// don't do a notification if it remains in the family (i.e. a child of the grid control gets the focus) if (xMyGridPeer->isChild(xNextControlPeer)) return;
if (xMyGridPeer == xNextControlPeer) return;
// notify the listeners that the "form" we represent has been deactivated
EventObject aEvt(*this);
m_xFormControllerImpl->m_aActivateListeners.notifyEach( &css::form::XFormControllerListener::formDeactivated, aEvt );
// commit the changes of the grid control (as we're deactivated)
rtl::Reference< SbaXGridControl > xCommitable(getBrowserView()->getGridControl()); if (xCommitable.is())
xCommitable->commit(); else
SAL_WARN("dbaccess.ui", "SbaXDataBrowserController::focusLost : why is my control not committable?");
}
void SbaXDataBrowserController::disposing(const EventObject& Source)
{ // if it's a component other than our aggregate, forward it to the aggregate if ( uno::Reference<XInterface>(static_cast<cppu::OWeakObject*>(m_xFormControllerImpl.get()), UNO_QUERY) != Source.Source )
{
Reference< XEventListener > xAggListener;
m_xFormControllerImpl->queryAggregation( cppu::UnoType<decltype(xAggListener)>::get() ) >>= xAggListener; if ( xAggListener.is( ))
xAggListener->disposing( Source );
}
// is it the grid control ? if (getBrowserView())
{
Reference< css::awt::XControl > xSourceControl(Source.Source, UNO_QUERY); if (xSourceControl == cppu::getXWeak(getBrowserView()->getGridControl().get()))
removeControlListeners(getBrowserView()->getGridControl());
}
// its model (the container of the columns) ? if (getControlModel() == Source.Source)
removeModelListeners(getControlModel());
// the form's model ? if (getRowSet() == Source.Source)
disposingFormModel(Source);
// from a single column model ?
Reference< XPropertySet > xSourceSet(Source.Source, UNO_QUERY); if (xSourceSet.is())
{
Reference< XPropertySetInfo > xInfo = xSourceSet->getPropertySetInfo(); // we assume that columns have a Width property and all other sets we are listening to don't have if (xInfo->hasPropertyByName(PROPERTY_WIDTH))
disposingColumnModel(Source);
}
SbaXDataBrowserController_Base::OGenericUnoController::disposing( Source );
}
SolarMutexGuard aGuard; // the IsModified changed to sal_False ? if ( evt.PropertyName == PROPERTY_ISMODIFIED
&& !::comphelper::getBOOL(evt.NewValue)
)
{ // -> the current field isn't modified anymore, too
setCurrentModified( false );
}
// switching to a new record ? if ( evt.PropertyName == PROPERTY_ISNEW
&& ::comphelper::getBOOL(evt.NewValue)
)
{ if (::comphelper::getINT32(xSource->getPropertyValue(PROPERTY_ROWCOUNT)) == 0) // if we're switching to a new record and didn't have any records before we need to invalidate // all slots (as the cursor was invalid before the mode change and so the slots were disabled)
InvalidateAll();
}
void SbaXDataBrowserController::elementInserted(const css::container::ContainerEvent& evt)
{
OSL_ENSURE(Reference< XInterface >(evt.Source, UNO_QUERY).get() == Reference< XInterface >(getControlModel(), UNO_QUERY).get(), "SbaXDataBrowserController::elementInserted: where did this come from (not from the grid model)?!");
Reference< XPropertySet > xNewColumn(evt.Element,UNO_QUERY); if ( xNewColumn.is() )
AddColumnListener(xNewColumn);
}
void SbaXDataBrowserController::elementRemoved(const css::container::ContainerEvent& evt)
{
OSL_ENSURE(Reference< XInterface >(evt.Source, UNO_QUERY).get() == Reference< XInterface >(getControlModel(), UNO_QUERY).get(), "SbaXDataBrowserController::elementRemoved: where did this come from (not from the grid model)?!");
Reference< XPropertySet > xOldColumn(evt.Element,UNO_QUERY); if ( xOldColumn.is() )
RemoveColumnListener(xOldColumn);
}
void SbaXDataBrowserController::elementReplaced(const css::container::ContainerEvent& evt)
{
OSL_ENSURE(Reference< XInterface >(evt.Source, UNO_QUERY).get() == Reference< XInterface >(getControlModel(), UNO_QUERY).get(), "SbaXDataBrowserController::elementReplaced: where did this come from (not from the grid model)?!");
Reference< XPropertySet > xOldColumn(evt.ReplacedElement,UNO_QUERY); if ( xOldColumn.is() )
RemoveColumnListener(xOldColumn);
Reference< XPropertySet > xNewColumn(evt.Element,UNO_QUERY); if ( xNewColumn.is() )
AddColumnListener(xNewColumn);
}
if (getBrowserView())
{
removeControlListeners(getBrowserView()->getGridControl()); // don't delete explicitly, this is done by the owner (and user) of this controller (me hopes ...)
clearView();
}
SQLExceptionInfo aInfo( aEvent.Reason ); if ( !aInfo.isValid() ) return;
if ( m_nFormActionNestingLevel )
{
OSL_ENSURE( !m_aCurrentError.isValid(), "SbaXDataBrowserController::errorOccurred: can handle one error per transaction only!" );
m_aCurrentError = std::move(aInfo);
} else
{
m_aCurrentError = std::move(aInfo);
m_aAsyncDisplayError.Call();
}
}
sal_Bool SbaXDataBrowserController::approveParameter(const css::form::DatabaseParameterEvent& aEvent)
{ if (aEvent.Source != getRowSet())
{ // not my data source -> allow anything
SAL_WARN("dbaccess.ui","SbaXDataBrowserController::approveParameter : invalid event source !"); returntrue;
}
SolarMutexGuard aSolarGuard;
// default handling: instantiate an interaction handler and let it handle the parameter request try
{ // two continuations allowed: OK and Cancel
rtl::Reference<OParameterContinuation> pParamValues = new OParameterContinuation;
rtl::Reference<OInteractionAbort> pAbort = new OInteractionAbort; // the request
ParametersRequest aRequest;
aRequest.Parameters = aEvent.Parameters;
aRequest.Connection = getConnection(Reference< XRowSet >(aEvent.Source, UNO_QUERY));
rtl::Reference<OInteractionRequest> pParamRequest = new OInteractionRequest(Any(aRequest)); // some knittings
pParamRequest->addContinuation(pParamValues);
pParamRequest->addContinuation(pAbort);
// create the handler, let it handle the request
Reference< XInteractionHandler2 > xHandler(InteractionHandler::createWithParent(getORB(), getComponentWindow()));
xHandler->handle(pParamRequest);
if (!pParamValues->wasSelected())
{ // canceled
setLoadingCancelled(); returnfalse;
}
// transfer the values into the parameter supplier
Sequence< PropertyValue > aFinalValues = pParamValues->getValues(); if (aFinalValues.getLength() != aRequest.Parameters->getCount())
{
SAL_WARN("dbaccess.ui","SbaXDataBrowserController::approveParameter: the InteractionHandler returned nonsense!");
setLoadingCancelled(); returnfalse;
} for (sal_Int32 i = 0; i < aFinalValues.getLength(); ++i)
{
Reference< XPropertySet > xParam(
aRequest.Parameters->getByIndex(i), css::uno::UNO_QUERY);
OSL_ENSURE(xParam.is(), "SbaXDataBrowserController::approveParameter: one of the parameters is no property set!"); if (xParam.is())
{ #ifdef DBG_UTIL
OUString sName;
xParam->getPropertyValue(PROPERTY_NAME) >>= sName;
OSL_ENSURE(sName == aFinalValues[i].Name, "SbaXDataBrowserController::approveParameter: suspicious value names!"); #endif try { xParam->setPropertyValue(PROPERTY_VALUE, aFinalValues[i].Value); } catch(Exception&)
{
SAL_WARN("dbaccess.ui", "SbaXDataBrowserController::approveParameter: setting one of the properties failed!");
}
}
}
} catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION("dbaccess");
}
void SbaXDataBrowserController::resetted(const css::lang::EventObject& rEvent)
{
OSL_ENSURE(rEvent.Source == getControlModel(), "SbaXDataBrowserController::resetted : where did this come from ?");
setCurrentModified( false );
}
try
{ // no chance without a view if (!getBrowserView() || !getBrowserView()->getVclControl()) return aReturn;
switch (nId)
{ case ID_BROWSER_REMOVEFILTER: if (!m_xParser.is())
{
aReturn.bEnabled = false; return aReturn;
} // any filter or sort order set ?
aReturn.bEnabled = m_xParser->getFilter().getLength() || m_xParser->getHavingClause().getLength() || m_xParser->getOrder().getLength(); return aReturn;
} // no chance without valid models if (isValid() && !isValidCursor()) return aReturn;
case ID_BROWSER_SORTUP: case ID_BROWSER_SORTDOWN: case ID_BROWSER_AUTOFILTER:
{ // a native statement can't be filtered or sorted const Reference< XPropertySet > xFormSet(getRowSet(), UNO_QUERY); if ( !::comphelper::getBOOL(xFormSet->getPropertyValue(PROPERTY_ESCAPE_PROCESSING)) || !m_xParser.is() ) break;
Reference< XPropertySet > xCurrentField = getBoundField(); if (!xCurrentField.is()) break;
case ID_BROWSER_REFRESH:
aReturn.bEnabled = true; break;
case ID_BROWSER_REDO:
aReturn.bEnabled = false; // simply forget it ;). no redo possible. break;
case ID_BROWSER_UNDORECORD: case ID_BROWSER_SAVERECORD:
{ if (!m_bCurrentlyModified)
{
Reference< XPropertySet > xFormSet(getRowSet(), UNO_QUERY); if (xFormSet.is())
aReturn.bEnabled = ::comphelper::getBOOL(xFormSet->getPropertyValue(PROPERTY_ISMODIFIED));
} else
aReturn.bEnabled = true;
aReturn.sTitle = (ID_BROWSER_UNDORECORD == nId) ? m_sStateUndoRecord : m_sStateSaveRecord;
} break; case ID_BROWSER_EDITDOC:
{ // check if it is available
Reference< XPropertySet > xDataSourceSet(getRowSet(), UNO_QUERY); if (!xDataSourceSet.is()) break; // no datasource -> no edit mode
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.