/* -*- 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
OUString sNewHaving = xParser->getHavingClause(); if ( sOldVal == sNewVal && (!bFilter || sOldHaving == sNewHaving) ) // nothing to be done return;
if (bFilter)
applyParserFilter(sOldVal, bOldFilterApplied,sOldHaving,xParser); else
applyParserOrder(sOldVal,xParser);
::comphelper::disposeComponent(xParser);
}
void SbaXDataBrowserController::ExecuteSearch()
{ // calculate the control source of the active field
rtl::Reference< SbaXGridControl > xGrid(getBrowserView()->getGridControl());
OSL_ENSURE(xGrid.is(), "SbaXDataBrowserController::ExecuteSearch : the control should have a css::form::XGrid interface !");
// the text within the current cell
OUString sInitialText;
Reference< css::container::XIndexAccess > xColControls(xGridPeer, UNO_QUERY);
Reference< XInterface > xCurControl(xColControls->getByIndex(nViewCol),UNO_QUERY);
OUString aInitialText; if (IsSearchableControl(xCurControl, &aInitialText))
sInitialText = aInitialText;
// prohibit the synchronization of the grid's display with the cursor's position
Reference< XPropertySet > xModelSet(getControlModel(), UNO_QUERY);
OSL_ENSURE(xModelSet.is(), "SbaXDataBrowserController::ExecuteSearch : no model set ?!");
xModelSet->setPropertyValue(u"DisplayIsSynchron"_ustr, css::uno::Any(false));
xModelSet->setPropertyValue(u"AlwaysShowCursor"_ustr, css::uno::Any(true));
xModelSet->setPropertyValue(u"CursorColor"_ustr, Any(COL_LIGHTRED));
// restore the grid's normal operating state
xModelSet->setPropertyValue(u"DisplayIsSynchron"_ustr, css::uno::Any(true));
xModelSet->setPropertyValue(u"AlwaysShowCursor"_ustr, css::uno::Any(false));
xModelSet->setPropertyValue(u"CursorColor"_ustr, Any());
}
case ID_BROWSER_INSERT_ROW: try
{ if (SaveModified())
{
getRowSet()->afterLast(); // check if it is available
Reference< XResultSetUpdate > xUpdateCursor(getRowSet(), UNO_QUERY_THROW);
xUpdateCursor->moveToInsertRow();
}
} catch(Exception&)
{
TOOLS_WARN_EXCEPTION("dbaccess.ui", "" );
} break; case SID_FM_DELETEROWS:
case ID_BROWSER_FILTERED: if (SaveModified())
{
Reference< XPropertySet > xActiveSet(getRowSet(), UNO_QUERY); bool bApplied = ::comphelper::getBOOL(xActiveSet->getPropertyValue(PROPERTY_APPLYFILTER));
xActiveSet->setPropertyValue(PROPERTY_APPLYFILTER, css::uno::Any(!bApplied));
reloadForm(m_xLoadable);
}
InvalidateFeature(ID_BROWSER_FILTERED); break; case ID_BROWSER_EDITDOC:
{
DbGridControlOptions nGridMode = getBrowserView()->getVclControl()->GetOptions(); if (nGridMode == DbGridControlOptions::Readonly)
getBrowserView()->getVclControl()->SetOptions(DbGridControlOptions::Update | DbGridControlOptions::Insert | DbGridControlOptions::Delete); // the options not supported by the data source will be removed automatically else
{ if ( !SaveModified( ) ) // give the user a chance to save the current record (if necessary) break;
// maybe the user wanted to reject the modified record ? if (GetState(ID_BROWSER_UNDORECORD).bEnabled)
Execute(ID_BROWSER_UNDORECORD,Sequence<PropertyValue>());
case ID_BROWSER_ORDERCRIT:
ExecuteFilterSortCrit(false); break;
case ID_BROWSER_FILTERCRIT:
ExecuteFilterSortCrit(true);
InvalidateFeature(ID_BROWSER_FILTERED); break;
case ID_BROWSER_REMOVEFILTER:
{ if (!SaveModified()) break;
bool bNeedPostReload = preReloadForm(); // reset the filter and the sort property simultaneously so only _one_ new statement has to be // sent
Reference< XPropertySet > xSet(getRowSet(), UNO_QUERY); if ( xSet.is() )
{
xSet->setPropertyValue(PROPERTY_FILTER,Any(OUString()));
xSet->setPropertyValue(PROPERTY_HAVING_CLAUSE,Any(OUString()));
xSet->setPropertyValue(PROPERTY_ORDER,Any(OUString()));
} try
{
reloadForm(m_xLoadable); if ( bNeedPostReload )
postReloadForm();
} catch(Exception&)
{
}
InvalidateFeature(ID_BROWSER_REMOVEFILTER);
InvalidateFeature(ID_BROWSER_FILTERED);
} break;
case ID_BROWSER_REFRESH: if ( SaveModified( ) )
{ if (!reloadForm(m_xLoadable))
criticalFail();
} break;
case ID_BROWSER_SAVERECORD: if ( SaveModified( false ) )
setCurrentModified( false ); break;
case ID_BROWSER_UNDORECORD:
{ try
{ // restore the cursor state
Reference< XResultSetUpdate > xCursor(getRowSet(), UNO_QUERY);
Reference< XPropertySet > xSet(xCursor, UNO_QUERY);
Any aVal = xSet->getPropertyValue(PROPERTY_ISNEW); if (aVal.hasValue() && ::comphelper::getBOOL(aVal))
{
xCursor->moveToInsertRow(); // no need to reset the grid model after we moved to the insert row, this is done implicitly by the // form // (and in some cases it may be deadly to do the reset explicitly after the form did it implicitly, // cause the form's reset may be async, and this leads to some nice deadlock scenarios...)
} else
{
xCursor->cancelRowUpdates();
// restore the grids state
Reference< css::form::XReset > xReset(getControlModel(), UNO_QUERY); if (xReset.is())
xReset->reset();
}
} catch(SQLException&)
{
}
// if the invalidation was triggered by the timer, we do not need to invalidate PASTE. // The timer is only for checking the CUT/COPY slots regularly, which depend on the // selection state of the active cell // TODO: get a callback at the Edit which allows to be notified when the selection // changes. This would be much better than this cycle-eating polling mechanism here... if ( _pTimer != &m_aInvalidateClipboard )
InvalidateFeature(ID_BROWSER_PASTE);
}
// get the current column from the grid
rtl::Reference< SbaXGridControl > xGrid(getBrowserView()->getGridControl()); if (!xGrid.is()) return xEmptyReturn;
sal_uInt16 nViewPos = xGrid->getCurrentColumnPosition();
sal_uInt16 nCurrentCol = getBrowserView()->View2ModelPos(nViewPos); if (nCurrentCol == sal_uInt16(-1)) return xEmptyReturn;
// get the according column from the model
Reference< css::container::XIndexContainer > xCols(getControlModel(), UNO_QUERY);
Reference< XPropertySet > xCurrentCol(xCols->getByIndex(nCurrentCol),UNO_QUERY); if (!xCurrentCol.is()) return xEmptyReturn;
// check all grid columns for their control source
Reference< css::container::XIndexAccess > xModelColumns(getFormComponent(), UNO_QUERY);
OSL_ENSURE(xModelColumns.is(), "SbaXDataBrowserController::OnSearchContextRequest : there is a grid control without columns !"); // the case 'no columns' should be indicated with an empty container, I think ...
OSL_ENSURE(xModelColumns->getCount() >= xPeerContainer->getCount(), "SbaXDataBrowserController::OnSearchContextRequest : impossible : have more view than model columns !");
OUString sFieldList; for (sal_Int32 nViewPos=0; nViewPos<xPeerContainer->getCount(); ++nViewPos)
{
Reference< XInterface > xCurrentColumn(xPeerContainer->getByIndex(nViewPos),UNO_QUERY); if (!xCurrentColumn.is()) continue;
// can we use this column control for searching ? if (!IsSearchableControl(xCurrentColumn)) continue;
// if the cursor is in a mode other than STANDARD -> reset
Reference< XPropertySet > xCursorSet(rContext.xCursor, UNO_QUERY);
OSL_ENSURE(xCursorSet.is() && !::comphelper::getBOOL(xCursorSet->getPropertyValue(PROPERTY_ISMODIFIED)), "SbaXDataBrowserController::OnSearchContextRequest : please do not call for cursors with modified rows !"); if (xCursorSet.is() && ::comphelper::getBOOL(xCursorSet->getPropertyValue(PROPERTY_ISNEW)))
{
Reference< XResultSetUpdate > xUpdateCursor(rContext.xCursor, UNO_QUERY);
xUpdateCursor->moveToCurrentRow();
} return rContext.arrFields.size();
}
// move the cursor
xCursor->moveToBookmark(rInfo.aPosition);
// let the grid sync its display with the cursor
Reference< XPropertySet > xModelSet(getControlModel(), UNO_QUERY);
OSL_ENSURE(xModelSet.is(), "SbaXDataBrowserController::OnFoundData : no model set ?!");
Any aOld = xModelSet->getPropertyValue(u"DisplayIsSynchron"_ustr);
xModelSet->setPropertyValue(u"DisplayIsSynchron"_ustr, css::uno::Any(true));
xModelSet->setPropertyValue(u"DisplayIsSynchron"_ustr, aOld);
// and move to the field
Reference< css::container::XIndexAccess > aColumnControls(getBrowserView()->getGridControl()->getPeer(), UNO_QUERY);
sal_Int32 nViewPos;
for ( nViewPos = 0; nViewPos < aColumnControls->getCount(); ++nViewPos )
{
Reference< XInterface > xCurrent(aColumnControls->getByIndex(nViewPos),UNO_QUERY); if (IsSearchableControl(xCurrent))
{ if (rInfo.nFieldPos)
--rInfo.nFieldPos; else break;
}
}
try
{ // let the grid sync its display with the cursor
Reference< XPropertySet > xModelSet(getControlModel(), UNO_QUERY);
OSL_ENSURE(xModelSet.is(), "SbaXDataBrowserController::OnCanceledNotFound : no model set ?!");
Any aOld = xModelSet->getPropertyValue(u"DisplayIsSynchron"_ustr);
xModelSet->setPropertyValue(u"DisplayIsSynchron"_ustr, css::uno::Any(true));
xModelSet->setPropertyValue(u"DisplayIsSynchron"_ustr, aOld);
} catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION("dbaccess");
}
}
IMPL_LINK_NOARG(SbaXDataBrowserController, OnAsyncGetCellFocus, void*, void)
{
SbaGridControl* pVclGrid = getBrowserView() ? getBrowserView()->getVclControl() : nullptr; // if we have a controller, but the window for the controller doesn't have the focus, we correct this if (pVclGrid && pVclGrid->IsEditing() && pVclGrid->HasChildPathFocus())
pVclGrid->Controller()->GetWindow().GrabFocus();
}
// switch the control to alive mode
getBrowserView()->getGridControl()->setDesignMode(false);
initializeParser();
InvalidateAll();
m_aAsyncGetCellFocus.Call();
}
void SbaXDataBrowserController::initializeParser() const
{ if ( m_xParser.is() ) return;
// create a parser (needed for filtering/sorting) try
{ const Reference< XPropertySet > xFormSet(getRowSet(), UNO_QUERY); if (::comphelper::getBOOL(xFormSet->getPropertyValue(PROPERTY_ESCAPE_PROCESSING)))
{ // (only if the statement isn't native) // (it is allowed to use the PROPERTY_ISPASSTHROUGH : _after_ loading a form it is valid)
xFormSet->getPropertyValue(PROPERTY_SINGLESELECTQUERYCOMPOSER) >>= m_xParser;
}
} catch(Exception&)
{
DBG_UNHANDLED_EXCEPTION("dbaccess");
m_xParser = nullptr; // no further handling, we ignore the error
}
}
void SbaXDataBrowserController::loaded(const EventObject& /*aEvent*/)
{ // not interested in // we're loading within a separated thread and have a handling for its "finished event"
}
void SbaXDataBrowserController::unloading(const EventObject& /*aEvent*/)
{ // not interested in
}
void SbaXDataBrowserController::unloaded(const EventObject& /*aEvent*/)
{
m_xParser.clear();
InvalidateAll(); // do this asynchronously, there are other listeners reacting on this message ... // (it's a little hack : the grid columns are listening to this event, too, and their bound field may // change as a reaction on that event. as we have no chance to be notified of this change (which is // the one we're interested in) we give them time to do what they want to before invalidating our // bound-field-dependent slots...
}
void SbaXDataBrowserController::reloading(const EventObject& /*aEvent*/)
{ // not interested in
}
void SbaXDataBrowserController::reloaded(const EventObject& /*aEvent*/)
{
InvalidateAll(); // do this asynchronously, there are other listeners reacting on this message ... // (it's a little hack : the grid columns are listening to this event, too, and their bound field may // change as a reaction on that event. as we have no chance to be notified of this change (which is // the one we're interested in) we give them time to do what they want to before invalidating our // bound-field-dependent slots...
}
void SbaXDataBrowserController::enterFormAction()
{ if ( !m_nFormActionNestingLevel ) // first action -> reset
m_aCurrentError.clear();
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.