2009-11-06 13:10:39 +0000 msc r277387 : minor fix for automatic test 2009-11-06 13:09:33 +0000 msc r277385 : minor fix for automatic test 2009-11-06 12:30:57 +0000 fs r277383 : argh. On some virtual machines, waiting 5 seconds for the event to arrive is not enough. Increasing the timeout ... 2009-11-06 12:13:34 +0000 fs r277382 : this diagnostic code should not have slipped in 2009-11-05 13:21:06 +0000 fs r277369 : SHL2NOCHECK=TRUE (requested by hjs) 2009-11-04 14:09:46 +0000 msc r277355 : minor fix for automatic testing 2009-11-04 13:23:02 +0000 msc r277352 : minor fix for automatic testing 2009-11-04 10:53:28 +0000 msc r277341 : minor fix for automated testscript 2009-11-04 08:30:58 +0000 msc r277333 : minor fix for automatic test 2009-11-04 08:15:43 +0000 msc r277332 : minor fix for automatic test 2009-11-03 14:25:44 +0000 fs r277324 : #i10000# 2009-11-03 09:47:47 +0000 fs r277315 : found yet another help ID zombie ... moved formhelpid.hrc content to propctrlr.hrc, where it belongs 2009-11-03 08:50:24 +0000 fs r277312 : use createTempFileURL, which cares for some more specialities ... 2009-11-03 08:44:55 +0000 fs r277311 : when creating a temp file for purpose of getting a temp file URL, the delete the file immediately. On some machines/JVMs, the file exists, with write access denied, which isn't Good (TM) 2009-10-22 13:06:17 +0000 fs r277126 : removed wrong assertion 2009-10-21 08:10:35 +0000 fs r277077 : reverted the previous change, which was nonsense 2009-10-21 07:19:43 +0000 fs r277076 : export the component_foo functions, now that some of the objects are built with VISIBILITY_HIDDEN=TRUE 2009-10-21 07:08:35 +0000 fs r277075 : spare useless call 2009-10-20 21:26:31 +0000 fs r277072 : #i10000# 2009-10-20 08:06:04 +0000 fs r277039 : CWS-TOOLING: rebase CWS dba33a to trunk@277035 (milestone: DEV300:m62) 2009-10-16 09:55:25 +0000 fs r276960 : remove one of the superfluous implts_doLayout calls introduced with the previous patch 2009-10-15 13:18:52 +0000 fs r276941 : removed the basic tests. According to cn, they're not used anymore (for a long time), and according to 'du -h', they take up 6.0M on my hard disc. For too much for useless code, /me thinks. 2009-10-15 13:06:51 +0000 fs r276940 : #i10000# remove useless include (otherwise the compiler warning it provokes would need to be fixed by declaring VISIBILITY_HIDDEN=TRUE in the makefile.mk) 2009-10-15 12:52:39 +0000 fs r276939 : #i10000# 2009-10-15 12:44:26 +0000 fs r276938 : #i10000# 2009-10-15 12:00:33 +0000 fs r276936 : #i10000# 2009-10-15 10:31:37 +0000 fs r276934 : #i105259# prepare for the Hidden arg 2009-10-15 10:31:05 +0000 fs r276933 : IsMaximized -> const 2009-10-15 09:50:15 +0000 fs r276932 : during #i105259#: introduce an option to the layout manager to preserve, if possible, the size of the content window when layouting. Enable this option for embedded (SFX-based) documents opened for outplace editing. (the option is incompatible with in-place editing, anyway) This is because such embedded objects couple the (content) window size to the VisAreaSize, in that both are used interchangeably. When an embedded object is closed, it remembers the VisAreaSize, and restores it upon next open. This, however, leads to different content window sizes when the window is closed with another toolbar set than used during opening. This patch here prevents those different content window sizes. Also, now the content window size doesn't change when, explicitly or implicitly, a toolbar is shown or hidden. Instead, the content window size stays the same, and the container window size is adjusted. 2009-10-15 09:32:41 +0000 fs r276931 : during #i105259#: UNO access to more attributes of top windows 2009-10-15 09:30:28 +0000 fs r276930 : indention corrected (better readable) 2009-10-15 09:26:46 +0000 fs r276929 : during #i105259#: access to more attributes of top windows 2009-10-14 10:04:39 +0000 fs r276889 : connecting via services manager, not naming service 2009-10-12 11:31:08 +0000 fs r276831 : during #i105806# FillPropertySet: do not attempt to set *AutoStyleName if it doesn't exist 2009-10-12 11:24:44 +0000 fs r276830 : #i105806# getPropertyValue: throw an UnknownPropertyException for, well, unknown properties 2009-10-08 08:20:58 +0000 fs r276774 : implSubmit: re-throw WrappedTargetExceptions unmodified 2009-10-07 19:19:42 +0000 fs r276770 : #i105198# do not pass an CommandType if we do not have a command 2009-10-07 17:39:36 +0000 fs r276768 : export the OWeakObject::disposeWeakConnectionPoint symbol 2009-10-07 12:59:17 +0000 fs r276754 : #i87693# 2009-10-07 11:19:22 +0000 fs r276752 : #i10000# 2009-10-07 10:21:08 +0000 fs r276748 : #105482# do not require a controller, at least not in *all* circumstances (executed reports have a model, the ReportDefinition, but no Controller) 2009-10-07 10:04:08 +0000 fs r276747 : copying the changes from CWS fwk121 herein, in particular the fix for issue #i105371# 2009-10-07 09:58:30 +0000 fs r276746 : copying the changes from CWS fwk121 herein, in particular the fix for issue #i105371# 2009-10-07 09:48:14 +0000 fs r276744 : removed (now) pointless assertion 2009-10-07 06:59:19 +0000 fs r276740 : export the OWeakObject::disposeWeakConnectionPoint symbol 2009-10-07 06:44:43 +0000 fs r276739 : OComponentHelper::release & WeakAggComponentImplHelperBase::release: when our ref count drops to 0, call OWeakObject's disposeWeakConnectionPoint before (temporarily) incrementing the ref count, again. This ensures that our adapter cannot create references to the dying object anymore. (A complex test case in dbaccess (#i105505#) triggered such a situation, but in another class using an analogous release/dispose/destroy pattern, namely WeakComponentImplHelperBase) 2009-10-07 06:37:20 +0000 fs r276738 : found during some new complex test cases: call disposeWeakConnectionPoint before actually starting to destroy the object, this ensures no other threads will resurrect it while it is dying 2009-10-06 21:58:24 +0000 fs r276734 : oops, two small corrections to the previous fix (hey, complex test cases are cool) 2009-10-06 21:51:16 +0000 fs r276733 : log the name of the data source which cannot be revoked 2009-10-06 21:50:41 +0000 fs r276732 : more detailed error message when cleanup fails 2009-10-06 21:50:01 +0000 fs r276731 : reworked the ModelImpl caching. The new and improved UNO API test for css.sdb.RowSet revealed some inconsistencies, in whether the objects are cached by their URL, or by their registration name. This has been changed to caching by registration name. 2009-10-06 13:50:34 +0000 fs r276714 : print diagnostics when we cannot clean up the test case 2009-10-06 13:45:02 +0000 fs r276713 : this test failed all the time, since the core (rightfully) threw an exception. Disabled it for the moment, until issue 84253 is fixed 2009-10-06 12:52:46 +0000 fs r276711 : rewrote this test. Now we do not re-use the same .odb across different test cases, as this leads to unreliable (timing-dependent) results/failures. Instead, every test sets up a new odb file. Also, did some re-factoring, improved the cleanup code, and caught a few more errors. 2009-10-06 12:51:07 +0000 fs r276710 : DBTools taking a logger now 2009-10-06 12:50:42 +0000 fs r276709 : taking a PrintWriter for logging purpose 2009-10-06 12:50:03 +0000 fs r276708 : DBTools taking a logger now 2009-10-06 12:49:22 +0000 fs r276707 : typo 2009-10-06 12:49:03 +0000 fs r276706 : typo 2009-10-06 12:48:52 +0000 fs r276705 : wrappers around some database-related services - initial versions only, to evolve over time, and intended to finally replace the DBTools class 2009-10-06 12:48:02 +0000 fs r276704 : typo 2009-10-06 12:38:42 +0000 fs r276702 : some better diagnostics, done during getting the API tests to work more reliably 2009-10-06 10:35:51 +0000 fs r276698 : when living in, e.g., the DataSourceBrowser, we can't expect to find an XModifiable2, so don't assert its existence 2009-10-05 12:47:52 +0000 oj r276677 : #i105607# check for read moved into if scope 2009-10-05 11:37:06 +0000 fs r276676 : when saving a file fails, retrieve the error message from the InteractionRequestStringResolver - this is better than any generic message we can create 2009-10-05 10:04:23 +0000 oj r276673 : #i105607# check for read moved into if scope 2009-10-05 09:46:17 +0000 fs r276671 : #i10000# 2009-10-05 08:43:58 +0000 fs r276664 : #i105505# release: dispose the (base classes) weak connection point before disposing ourself, and in particular before temporarily incrementing our ref count, again. This way, we prevent that a separate thread re-surrects us (using the weak connection point's queryAdapted) while we're in the process of destruction 2009-10-05 08:41:49 +0000 fs r276663 : #i105505# +disposeWeakConnectionPoint (outsourced into dedicated method from ::release) 2009-10-05 08:40:26 +0000 fs r276662 : no need to derived from OSubComponent, its features are not used, directly derive from WeakComponentImplFoo instead 2009-10-05 08:39:38 +0000 fs r276661 : #i105505# diagnostics 2009-10-05 08:39:16 +0000 fs r276660 : #i105505# +testDocumentRevenants 2009-10-05 08:36:01 +0000 fs r276659 : #i105560# reverted the removal of GenericController::openHelpAgent - this is needed in module reportdesign 2009-10-04 19:53:30 +0000 fs r276657 : #105560# remove unused code thanks to cmc@openoffice.org for submitting the patch 2009-10-04 19:50:28 +0000 fs r276656 : #i105550# remove unused 'fire' method (thanks to cmc) 2009-10-03 16:13:15 +0000 fs r276655 : CWS-TOOLING: rebase CWS dba33a to trunk@276429 (milestone: DEV300:m60) 2009-10-02 19:20:48 +0000 fs r276651 : #i104117# lotta changed IDs ... 2009-10-02 10:52:24 +0000 fs r276634 : #i105505# If a model is created, and is a revenant of a previous incarnation, then ensure it is properly initialized. In particular, in its ctor, set the state to "Initializing", not "Initialized", and then let the ModelImpl call attachResource. This ensures that the model is initialized completely, including firing the necessary events. 2009-10-02 10:51:08 +0000 fs r276633 : #i105505# always do an attachResource at the newly loaded model, even if it (internally) was not really loaded, but only a revenant of a previous incarnation of this document 2009-10-01 11:10:13 +0000 fs r276597 : do not rely on the name 'Standard' for the one and only form in a document 2009-10-01 10:36:29 +0000 fs r276590 : #i105509# don't rely on default form component names, use indexes 2009-10-01 09:12:20 +0000 fs r276582 : #i105505# 2009-09-30 07:55:21 +0000 fs r276542 : removed some unsed methods / spared some unnecessary pixel<->logic conversion 2009-09-30 07:53:22 +0000 fs r276541 : removed unneeded methods 2009-09-30 06:35:59 +0000 fs r276538 : #i10000# 2009-09-29 13:45:02 +0000 fs r276531 : refactored the Roadmap* classes, to be able to fix above-mentioned #i105113# 2009-09-29 10:27:10 +0000 fs r276520 : #i105367# 2009-09-29 08:46:45 +0000 fs r276510 : #i104956# cleaned up the makefiles 2009-09-28 21:00:07 +0000 fs r276505 : #i104117# sourced those IDs out from extension.hrc 2009-09-28 20:59:05 +0000 fs r276504 : no need to let one FREE... 2009-09-28 20:53:36 +0000 fs r276503 : #i104117# cleaned up the mess with help IDs in module extensions. Formerly, extensions used to use help IDs which were declared in module svx, and vice versa. Also, help ID ranges were not respected. 2009-09-28 11:25:36 +0000 fs r276489 : typo 2009-09-28 11:25:10 +0000 fs r276488 : #i105235# 2009-09-24 11:53:16 +0000 fs r276423 : #i105234# do not zoom the control when they view information is still uninitialized (happens at least in Writer when opening a form document) 2009-09-24 09:42:28 +0000 fs r276415 : #i105234# proper zoom handling for the nav bar 2009-09-24 09:42:19 +0000 fs r276414 : #i105234# setZoom: care for precision errors caused by implicit conversion float->double 2009-09-16 11:11:43 +0000 fs r276195 : #i105082# consolidated the sub storage handling, by delegating more functionality into the DocumentStorageAccess class. As a result, there won't be that many unnecessary commits anymore. Also, the two different storage caches (in ModelImpl::m_aStorages and DocumentStorageAccess::m_aExposedStorages) have been consolidated. This is not really part of the fix of issue 105082, but it helped reducing the calls to the storage/package implementation. 2009-09-15 21:42:27 +0000 fs r276190 : don't calculate space for BOLD if the text is not really bold (speeds up rendering for large tree structures) 2009-09-15 20:20:23 +0000 fs r276188 : getTypeInfo: fill m_aTypeInfoRows only if really all type infos could be retrieved 2009-09-15 20:19:29 +0000 fs r276187 : do not continue loading when the controller initialization throws an error 2009-09-14 12:25:57 +0000 fs r276119 : oops, this patch was not intended for this CWS 2009-09-14 12:13:57 +0000 fs r276114 : #cr6875455# introduce a ReferenceDevice property for various control models 2009-09-14 10:33:02 +0000 fs r276106 : removed dead file 2009-09-09 08:37:31 +0000 fs r275972 : remove OSL_TRACE in VCLXButton dtor 2009-09-08 11:19:17 +0000 oj r275926 : i76534# remove mnemonic from fixed text 2009-09-07 08:39:37 +0000 fs r275874 : create CWS dba33a from cws/dba32g@275857 (CWS: dba32g)
4164 lines
156 KiB
C++
4164 lines
156 KiB
C++
/*************************************************************************
|
|
*
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* Copyright 2008 by Sun Microsystems, Inc.
|
|
*
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
|
*
|
|
* $RCSfile: DatabaseForm.cxx,v $
|
|
* $Revision: 1.87 $
|
|
*
|
|
* This file is part of OpenOffice.org.
|
|
*
|
|
* OpenOffice.org is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License version 3
|
|
* only, as published by the Free Software Foundation.
|
|
*
|
|
* OpenOffice.org is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License version 3 for more details
|
|
* (a copy is included in the LICENSE file that accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* version 3 along with OpenOffice.org. If not, see
|
|
* <http://www.openoffice.org/license.html>
|
|
* for a copy of the LGPLv3 License.
|
|
*
|
|
************************************************************************/
|
|
|
|
// MARKER(update_precomp.py): autogen include statement, do not remove
|
|
#include "precompiled_forms.hxx"
|
|
|
|
#include "componenttools.hxx"
|
|
#include "DatabaseForm.hxx"
|
|
#include "EventThread.hxx"
|
|
#include "frm_module.hxx"
|
|
#include "frm_resource.hrc"
|
|
#include "frm_resource.hxx"
|
|
#include "GroupManager.hxx"
|
|
#include "property.hrc"
|
|
#include "property.hxx"
|
|
#include "services.hxx"
|
|
|
|
#include <com/sun/star/awt/XControlContainer.hpp>
|
|
#include <com/sun/star/awt/XTextComponent.hpp>
|
|
#include <com/sun/star/form/DataSelectionType.hpp>
|
|
#include <com/sun/star/form/FormComponentType.hpp>
|
|
#include <com/sun/star/form/TabulatorCycle.hpp>
|
|
#include <com/sun/star/frame/FrameSearchFlag.hpp>
|
|
#include <com/sun/star/frame/XDispatch.hpp>
|
|
#include <com/sun/star/frame/XDispatchProvider.hpp>
|
|
#include <com/sun/star/frame/XModel.hpp>
|
|
#include <com/sun/star/io/XObjectInputStream.hpp>
|
|
#include <com/sun/star/io/XObjectOutputStream.hpp>
|
|
#include <com/sun/star/sdb/CommandType.hpp>
|
|
#include <com/sun/star/sdb/RowSetVetoException.hpp>
|
|
#include <com/sun/star/sdb/SQLContext.hpp>
|
|
#include <com/sun/star/sdb/XColumnUpdate.hpp>
|
|
#include <com/sun/star/sdbc/DataType.hpp>
|
|
#include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
|
|
#include <com/sun/star/sdbc/ResultSetType.hpp>
|
|
#include <com/sun/star/sdbc/XRowSet.hpp>
|
|
#include <com/sun/star/sdbcx/Privilege.hpp>
|
|
#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
|
|
#include <com/sun/star/util/XCancellable.hpp>
|
|
#include <com/sun/star/util/XURLTransformer.hpp>
|
|
#include <com/sun/star/util/XModifiable2.hpp>
|
|
|
|
#include <comphelper/basicio.hxx>
|
|
#include <comphelper/container.hxx>
|
|
#include <comphelper/enumhelper.hxx>
|
|
#include <comphelper/extract.hxx>
|
|
#include <comphelper/seqstream.hxx>
|
|
#include <comphelper/sequence.hxx>
|
|
#include <comphelper/stl_types.hxx>
|
|
#include <comphelper/uno3.hxx>
|
|
#include <connectivity/dbtools.hxx>
|
|
#include <cppuhelper/exc_hlp.hxx>
|
|
#include <cppuhelper/implbase2.hxx>
|
|
#include <osl/mutex.hxx>
|
|
#include <rtl/math.hxx>
|
|
#include <rtl/tencinfo.h>
|
|
#include <svtools/inetstrm.hxx>
|
|
#include <svtools/inettype.hxx>
|
|
#include <tools/debug.hxx>
|
|
#include <tools/diagnose_ex.h>
|
|
#include <tools/fsys.hxx>
|
|
#include <tools/inetmsg.hxx>
|
|
#include <tools/urlobj.hxx>
|
|
#include <unotools/ucblockbytes.hxx>
|
|
#include <unotools/ucbstreamhelper.hxx>
|
|
#include <vcl/svapp.hxx>
|
|
#include <vcl/timer.hxx>
|
|
#include <vos/mutex.hxx>
|
|
|
|
#include <ctype.h>
|
|
#include <hash_map>
|
|
//#include <stdio.h>
|
|
|
|
// compatiblity: DatabaseCursorType is dead, but for compatiblity reasons we still have to write it ...
|
|
namespace com {
|
|
namespace sun {
|
|
namespace star {
|
|
namespace data {
|
|
|
|
enum DatabaseCursorType
|
|
{
|
|
DatabaseCursorType_FORWARD = 0,
|
|
DatabaseCursorType_SNAPSHOT = 1,
|
|
DatabaseCursorType_KEYSET = 2,
|
|
DatabaseCursorType_DYNAMIC = 3,
|
|
DatabaseCursorType_MAKE_FIXED_SIZE = SAL_MAX_ENUM
|
|
};
|
|
|
|
} } } }
|
|
|
|
using namespace ::dbtools;
|
|
using namespace ::comphelper;
|
|
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::beans;
|
|
using namespace ::com::sun::star::container;
|
|
using namespace ::com::sun::star::task;
|
|
using namespace ::com::sun::star::frame;
|
|
using namespace ::com::sun::star::form;
|
|
using namespace ::com::sun::star::awt;
|
|
using namespace ::com::sun::star::io;
|
|
using namespace ::com::sun::star::lang;
|
|
using namespace ::com::sun::star::data;
|
|
using namespace ::com::sun::star::util;
|
|
|
|
//--------------------------------------------------------------------------
|
|
extern "C" void SAL_CALL createRegistryInfo_ODatabaseForm()
|
|
{
|
|
static ::frm::OMultiInstanceAutoRegistration< ::frm::ODatabaseForm > aAutoRegistration;
|
|
}
|
|
|
|
//.........................................................................
|
|
namespace frm
|
|
{
|
|
//.........................................................................
|
|
|
|
//==================================================================
|
|
//= DocumentModifyGuard
|
|
//==================================================================
|
|
class DocumentModifyGuard
|
|
{
|
|
public:
|
|
DocumentModifyGuard( const Reference< XInterface >& _rxFormComponent )
|
|
:m_xDocumentModify( getXModel( _rxFormComponent ), UNO_QUERY )
|
|
{
|
|
impl_changeModifiableFlag_nothrow( false );
|
|
}
|
|
~DocumentModifyGuard()
|
|
{
|
|
impl_changeModifiableFlag_nothrow( true );
|
|
}
|
|
|
|
private:
|
|
void impl_changeModifiableFlag_nothrow( const bool _enable )
|
|
{
|
|
try
|
|
{
|
|
if ( m_xDocumentModify.is() )
|
|
_enable ? m_xDocumentModify->enableSetModified() : m_xDocumentModify->disableSetModified();
|
|
}
|
|
catch( const Exception& )
|
|
{
|
|
DBG_UNHANDLED_EXCEPTION();
|
|
}
|
|
}
|
|
|
|
private:
|
|
Reference< XModifiable2 > m_xDocumentModify;
|
|
};
|
|
|
|
//==================================================================
|
|
//= OFormSubmitResetThread
|
|
//=-----------------------------------------------------------------
|
|
//= submitting and resetting html-forms asynchronously
|
|
//==================================================================
|
|
|
|
//------------------------------------------------------------------
|
|
class OFormSubmitResetThread: public OComponentEventThread
|
|
{
|
|
protected:
|
|
|
|
// duplicate an event with respect to it's type
|
|
virtual EventObject *cloneEvent( const EventObject *pEvt ) const;
|
|
|
|
// process an event. while processing the mutex isn't locked, and pCompImpl
|
|
// is made sure to remain valid
|
|
virtual void processEvent( ::cppu::OComponentHelper* _pCompImpl,
|
|
const EventObject* _pEvt,
|
|
const Reference<XControl>& _rControl,
|
|
sal_Bool _bSubmit);
|
|
|
|
public:
|
|
|
|
OFormSubmitResetThread(ODatabaseForm* pControl) : OComponentEventThread(pControl) { }
|
|
};
|
|
|
|
//------------------------------------------------------------------
|
|
EventObject* OFormSubmitResetThread::cloneEvent(
|
|
const EventObject *pEvt ) const
|
|
{
|
|
return new ::com::sun::star::awt::MouseEvent( *(::com::sun::star::awt::MouseEvent *)pEvt );
|
|
}
|
|
|
|
//------------------------------------------------------------------
|
|
void OFormSubmitResetThread::processEvent(
|
|
::cppu::OComponentHelper* pCompImpl,
|
|
const EventObject *_pEvt,
|
|
const Reference<XControl>& _rControl,
|
|
sal_Bool _bSubmit)
|
|
{
|
|
if (_bSubmit)
|
|
((ODatabaseForm *)pCompImpl)->submit_impl(_rControl, *static_cast<const ::com::sun::star::awt::MouseEvent*>(_pEvt), true);
|
|
else
|
|
((ODatabaseForm *)pCompImpl)->reset_impl(true);
|
|
}
|
|
|
|
//==================================================================
|
|
//= ODatabaseForm
|
|
//==================================================================
|
|
|
|
//------------------------------------------------------------------
|
|
Reference< XInterface > SAL_CALL ODatabaseForm::Create( const Reference< XMultiServiceFactory >& _rxFactory )
|
|
{
|
|
return *( new ODatabaseForm( _rxFactory ) );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
Sequence<sal_Int8> SAL_CALL ODatabaseForm::getImplementationId() throw(RuntimeException)
|
|
{
|
|
return OImplementationIds::getImplementationId(getTypes());
|
|
}
|
|
|
|
//------------------------------------------------------------------
|
|
Sequence<Type> SAL_CALL ODatabaseForm::getTypes() throw(RuntimeException)
|
|
{
|
|
// ask the aggregate
|
|
Sequence<Type> aAggregateTypes;
|
|
Reference<XTypeProvider> xAggregateTypes;
|
|
if (query_aggregation(m_xAggregate, xAggregateTypes))
|
|
aAggregateTypes = xAggregateTypes->getTypes();
|
|
|
|
Sequence< Type > aRet = concatSequences(
|
|
aAggregateTypes, ODatabaseForm_BASE1::getTypes(), OFormComponents::getTypes()
|
|
);
|
|
aRet = concatSequences( aRet, ODatabaseForm_BASE2::getTypes(), ODatabaseForm_BASE3::getTypes() );
|
|
return concatSequences( aRet, OPropertySetAggregationHelper::getTypes() );
|
|
}
|
|
|
|
//------------------------------------------------------------------
|
|
Any SAL_CALL ODatabaseForm::queryAggregation(const Type& _rType) throw(RuntimeException)
|
|
{
|
|
Any aReturn = ODatabaseForm_BASE1::queryInterface(_rType);
|
|
// our own interfaces
|
|
if (!aReturn.hasValue())
|
|
{
|
|
aReturn = ODatabaseForm_BASE2::queryInterface(_rType);
|
|
// property set related interfaces
|
|
if (!aReturn.hasValue())
|
|
{
|
|
aReturn = OPropertySetAggregationHelper::queryInterface(_rType);
|
|
|
|
// form component collection related interfaces
|
|
if (!aReturn.hasValue())
|
|
{
|
|
aReturn = OFormComponents::queryAggregation(_rType);
|
|
|
|
// interfaces already present in the aggregate which we want to reroute
|
|
// only available if we could create the aggregate
|
|
if (!aReturn.hasValue() && m_xAggregateAsRowSet.is())
|
|
aReturn = ODatabaseForm_BASE3::queryInterface(_rType);
|
|
|
|
// aggregate interfaces
|
|
// (ask the aggregated object _after_ the OComponentHelper (base of OFormComponents),
|
|
// so calls to the XComponent interface reach us and not the aggreagtion)
|
|
if (!aReturn.hasValue() && m_xAggregate.is())
|
|
aReturn = m_xAggregate->queryAggregation(_rType);
|
|
}
|
|
}
|
|
}
|
|
|
|
return aReturn;
|
|
}
|
|
|
|
DBG_NAME(ODatabaseForm);
|
|
//------------------------------------------------------------------
|
|
ODatabaseForm::ODatabaseForm(const Reference<XMultiServiceFactory>& _rxFactory)
|
|
:OFormComponents(_rxFactory)
|
|
,OPropertySetAggregationHelper(OComponentHelper::rBHelper)
|
|
,OPropertyChangeListener(m_aMutex)
|
|
,m_aLoadListeners(m_aMutex)
|
|
,m_aRowSetApproveListeners(m_aMutex)
|
|
,m_aRowSetListeners(m_aMutex)
|
|
,m_aSubmitListeners(m_aMutex)
|
|
,m_aErrorListeners(m_aMutex)
|
|
,m_aResetListeners( *this, m_aMutex )
|
|
,m_aPropertyBagHelper( *this )
|
|
,m_pAggregatePropertyMultiplexer(NULL)
|
|
,m_pGroupManager( NULL )
|
|
,m_aParameterManager( m_aMutex, _rxFactory )
|
|
,m_aFilterManager( _rxFactory )
|
|
,m_pLoadTimer(NULL)
|
|
,m_pThread(NULL)
|
|
,m_nResetsPending(0)
|
|
,m_nPrivileges(0)
|
|
,m_bInsertOnly( sal_False )
|
|
,m_eSubmitMethod(FormSubmitMethod_GET)
|
|
,m_eSubmitEncoding(FormSubmitEncoding_URL)
|
|
,m_eNavigation(NavigationBarMode_CURRENT)
|
|
,m_bAllowInsert(sal_True)
|
|
,m_bAllowUpdate(sal_True)
|
|
,m_bAllowDelete(sal_True)
|
|
,m_bLoaded(sal_False)
|
|
,m_bSubForm(sal_False)
|
|
,m_bForwardingConnection(sal_False)
|
|
,m_bSharingConnection( sal_False )
|
|
{
|
|
DBG_CTOR( ODatabaseForm, NULL );
|
|
impl_construct();
|
|
}
|
|
|
|
//------------------------------------------------------------------
|
|
ODatabaseForm::ODatabaseForm( const ODatabaseForm& _cloneSource )
|
|
:OFormComponents( _cloneSource )
|
|
,OPropertySetAggregationHelper( OComponentHelper::rBHelper )
|
|
,OPropertyChangeListener( m_aMutex )
|
|
,ODatabaseForm_BASE1()
|
|
,ODatabaseForm_BASE2()
|
|
,ODatabaseForm_BASE3()
|
|
,IPropertyBagHelperContext()
|
|
,m_aLoadListeners( m_aMutex )
|
|
,m_aRowSetApproveListeners( m_aMutex )
|
|
,m_aRowSetListeners( m_aMutex )
|
|
,m_aSubmitListeners( m_aMutex )
|
|
,m_aErrorListeners( m_aMutex )
|
|
,m_aResetListeners( *this, m_aMutex )
|
|
,m_aPropertyBagHelper( *this )
|
|
,m_pAggregatePropertyMultiplexer( NULL )
|
|
,m_pGroupManager( NULL )
|
|
,m_aParameterManager( m_aMutex, _cloneSource.m_xServiceFactory )
|
|
,m_aFilterManager( _cloneSource.m_xServiceFactory )
|
|
,m_pLoadTimer( NULL )
|
|
,m_pThread( NULL )
|
|
,m_nResetsPending( 0 )
|
|
,m_nPrivileges( 0 )
|
|
,m_bInsertOnly( _cloneSource.m_bInsertOnly )
|
|
,m_aControlBorderColorFocus( _cloneSource.m_aControlBorderColorFocus )
|
|
,m_aControlBorderColorMouse( _cloneSource.m_aControlBorderColorMouse )
|
|
,m_aControlBorderColorInvalid( _cloneSource.m_aControlBorderColorInvalid )
|
|
,m_aDynamicControlBorder( _cloneSource.m_aDynamicControlBorder )
|
|
,m_sName( _cloneSource.m_sName )
|
|
,m_aTargetURL( _cloneSource.m_aTargetURL )
|
|
,m_aTargetFrame( _cloneSource.m_aTargetFrame )
|
|
,m_eSubmitMethod( _cloneSource.m_eSubmitMethod )
|
|
,m_eSubmitEncoding( _cloneSource.m_eSubmitEncoding )
|
|
,m_eNavigation( _cloneSource.m_eNavigation )
|
|
,m_bAllowInsert( _cloneSource.m_bAllowInsert )
|
|
,m_bAllowUpdate( _cloneSource.m_bAllowUpdate )
|
|
,m_bAllowDelete( _cloneSource.m_bAllowDelete )
|
|
,m_bLoaded( sal_False )
|
|
,m_bSubForm( sal_False )
|
|
,m_bForwardingConnection( sal_False )
|
|
,m_bSharingConnection( sal_False )
|
|
{
|
|
DBG_CTOR( ODatabaseForm, NULL );
|
|
|
|
impl_construct();
|
|
|
|
osl_incrementInterlockedCount( &m_refCount );
|
|
{
|
|
// our aggregated rowset itself is not cloneable, so simply copy the properties
|
|
::comphelper::copyProperties( _cloneSource.m_xAggregateSet, m_xAggregateSet );
|
|
|
|
// also care for the dynamic properties: If the clone source has properties which we do not have,
|
|
// then add them
|
|
try
|
|
{
|
|
Reference< XPropertySet > xSourceProps( const_cast< ODatabaseForm& >( _cloneSource ).queryAggregation(
|
|
XPropertySet::static_type() ), UNO_QUERY_THROW );
|
|
Reference< XPropertySetInfo > xSourcePSI( xSourceProps->getPropertySetInfo(), UNO_SET_THROW );
|
|
Reference< XPropertyState > xSourcePropState( xSourceProps, UNO_QUERY );
|
|
|
|
Reference< XPropertySetInfo > xDestPSI( getPropertySetInfo(), UNO_QUERY_THROW );
|
|
|
|
Sequence< Property > aSourceProperties( xSourcePSI->getProperties() );
|
|
for ( const Property* pSourceProperty = aSourceProperties.getConstArray();
|
|
pSourceProperty != aSourceProperties.getConstArray() + aSourceProperties.getLength();
|
|
++pSourceProperty
|
|
)
|
|
{
|
|
if ( xDestPSI->hasPropertyByName( pSourceProperty->Name ) )
|
|
continue;
|
|
|
|
// the initial value passed to XPropertyContainer is also used as default, usually. So, try
|
|
// to retrieve the default of the source property
|
|
Any aInitialValue;
|
|
if ( xSourcePropState.is() )
|
|
{
|
|
aInitialValue = xSourcePropState->getPropertyDefault( pSourceProperty->Name );
|
|
}
|
|
else
|
|
{
|
|
aInitialValue = xSourceProps->getPropertyValue( pSourceProperty->Name );
|
|
}
|
|
addProperty( pSourceProperty->Name, pSourceProperty->Attributes, aInitialValue );
|
|
setPropertyValue( pSourceProperty->Name, xSourceProps->getPropertyValue( pSourceProperty->Name ) );
|
|
}
|
|
}
|
|
catch( const Exception& )
|
|
{
|
|
throw WrappedTargetException(
|
|
::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Could not clone the given database form." ) ),
|
|
*const_cast< ODatabaseForm* >( &_cloneSource ),
|
|
::cppu::getCaughtException()
|
|
);
|
|
}
|
|
}
|
|
osl_decrementInterlockedCount( &m_refCount );
|
|
}
|
|
|
|
//------------------------------------------------------------------
|
|
void ODatabaseForm::impl_construct()
|
|
{
|
|
// aggregate a row set
|
|
increment(m_refCount);
|
|
{
|
|
m_xAggregate = Reference< XAggregation >( m_xServiceFactory->createInstance( SRV_SDB_ROWSET ), UNO_QUERY_THROW );
|
|
m_xAggregateAsRowSet.set( m_xAggregate, UNO_QUERY_THROW );
|
|
setAggregation( m_xAggregate );
|
|
}
|
|
|
|
// listen for the properties, important for Parameters
|
|
if ( m_xAggregateSet.is() )
|
|
{
|
|
m_pAggregatePropertyMultiplexer = new OPropertyChangeMultiplexer(this, m_xAggregateSet, sal_False);
|
|
m_pAggregatePropertyMultiplexer->acquire();
|
|
m_pAggregatePropertyMultiplexer->addProperty(PROPERTY_COMMAND);
|
|
m_pAggregatePropertyMultiplexer->addProperty(PROPERTY_ACTIVE_CONNECTION);
|
|
}
|
|
|
|
{
|
|
Reference< XWarningsSupplier > xRowSetWarnings( m_xAggregate, UNO_QUERY );
|
|
m_aWarnings.setExternalWarnings( xRowSetWarnings );
|
|
}
|
|
|
|
if ( m_xAggregate.is() )
|
|
{
|
|
m_xAggregate->setDelegator( static_cast< XWeak* >( this ) );
|
|
}
|
|
|
|
{
|
|
m_aFilterManager.initialize( m_xAggregateSet );
|
|
m_aParameterManager.initialize( this, m_xAggregate );
|
|
|
|
declareForwardedProperty( PROPERTY_ID_ACTIVE_CONNECTION );
|
|
}
|
|
decrement( m_refCount );
|
|
|
|
m_pGroupManager = new OGroupManager( this );
|
|
m_pGroupManager->acquire();
|
|
}
|
|
|
|
//------------------------------------------------------------------
|
|
ODatabaseForm::~ODatabaseForm()
|
|
{
|
|
DBG_DTOR(ODatabaseForm,NULL);
|
|
|
|
m_pGroupManager->release();
|
|
m_pGroupManager = NULL;
|
|
|
|
if (m_xAggregate.is())
|
|
m_xAggregate->setDelegator( NULL );
|
|
|
|
m_aWarnings.setExternalWarnings( NULL );
|
|
|
|
if (m_pAggregatePropertyMultiplexer)
|
|
{
|
|
m_pAggregatePropertyMultiplexer->dispose();
|
|
m_pAggregatePropertyMultiplexer->release();
|
|
m_pAggregatePropertyMultiplexer = NULL;
|
|
}
|
|
}
|
|
|
|
//==============================================================================
|
|
// html tools
|
|
//------------------------------------------------------------------------
|
|
::rtl::OUString ODatabaseForm::GetDataURLEncoded(const Reference<XControl>& SubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt)
|
|
{
|
|
return GetDataEncoded(true,SubmitButton,MouseEvt);
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
::rtl::OUString ODatabaseForm::GetDataEncoded(bool _bURLEncoded,const Reference<XControl>& SubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt)
|
|
{
|
|
// Liste von successful Controls fuellen
|
|
HtmlSuccessfulObjList aSuccObjList;
|
|
FillSuccessfulList( aSuccObjList, SubmitButton, MouseEvt );
|
|
|
|
|
|
// Liste zu ::rtl::OUString zusammensetzen
|
|
::rtl::OUStringBuffer aResult;
|
|
::rtl::OUString aName;
|
|
::rtl::OUString aValue;
|
|
|
|
for ( HtmlSuccessfulObjListIterator pSuccObj = aSuccObjList.begin();
|
|
pSuccObj < aSuccObjList.end();
|
|
++pSuccObj
|
|
)
|
|
{
|
|
aName = pSuccObj->aName;
|
|
aValue = pSuccObj->aValue;
|
|
if( pSuccObj->nRepresentation == SUCCESSFUL_REPRESENT_FILE && aValue.getLength() )
|
|
{
|
|
// Bei File-URLs wird der Dateiname und keine URL uebertragen,
|
|
// weil Netscape dies so macht.
|
|
INetURLObject aURL;
|
|
aURL.SetSmartProtocol(INET_PROT_FILE);
|
|
aURL.SetSmartURL(aValue);
|
|
if( INET_PROT_FILE == aURL.GetProtocol() )
|
|
aValue = INetURLObject::decode(aURL.PathToFileName(), '%', INetURLObject::DECODE_UNAMBIGUOUS);
|
|
}
|
|
Encode( aName );
|
|
Encode( aValue );
|
|
|
|
aResult.append(aName);
|
|
aResult.append(sal_Unicode('='));
|
|
aResult.append(aValue);
|
|
|
|
if (pSuccObj < aSuccObjList.end() - 1)
|
|
{
|
|
if ( _bURLEncoded )
|
|
aResult.append(sal_Unicode('&'));
|
|
else
|
|
aResult.appendAscii("\r\n");
|
|
}
|
|
}
|
|
|
|
|
|
aSuccObjList.clear();
|
|
|
|
return aResult.makeStringAndClear();
|
|
}
|
|
|
|
//==============================================================================
|
|
// html tools
|
|
//------------------------------------------------------------------------
|
|
::rtl::OUString ODatabaseForm::GetDataTextEncoded(const Reference<XControl>& SubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt)
|
|
{
|
|
return GetDataEncoded(false,SubmitButton,MouseEvt);
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
Sequence<sal_Int8> ODatabaseForm::GetDataMultiPartEncoded(const Reference<XControl>& SubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt, ::rtl::OUString& rContentType)
|
|
{
|
|
|
|
// Parent erzeugen
|
|
INetMIMEMessage aParent;
|
|
aParent.EnableAttachChild( INETMSG_MULTIPART_FORM_DATA );
|
|
|
|
|
|
// Liste von successful Controls fuellen
|
|
HtmlSuccessfulObjList aSuccObjList;
|
|
FillSuccessfulList( aSuccObjList, SubmitButton, MouseEvt );
|
|
|
|
|
|
// Liste zu ::rtl::OUString zusammensetzen
|
|
::rtl::OUString aResult;
|
|
for ( HtmlSuccessfulObjListIterator pSuccObj = aSuccObjList.begin();
|
|
pSuccObj < aSuccObjList.end();
|
|
++pSuccObj
|
|
)
|
|
{
|
|
if( pSuccObj->nRepresentation == SUCCESSFUL_REPRESENT_TEXT )
|
|
InsertTextPart( aParent, pSuccObj->aName, pSuccObj->aValue );
|
|
else if( pSuccObj->nRepresentation == SUCCESSFUL_REPRESENT_FILE )
|
|
InsertFilePart( aParent, pSuccObj->aName, pSuccObj->aValue );
|
|
}
|
|
|
|
|
|
// Liste loeschen
|
|
aSuccObjList.clear();
|
|
|
|
// Fuer Parent MessageStream erzeugen
|
|
INetMIMEMessageStream aMessStream;
|
|
aMessStream.SetSourceMessage( &aParent );
|
|
aMessStream.GenerateHeader( sal_False );
|
|
|
|
// MessageStream in SvStream kopieren
|
|
SvMemoryStream aMemStream;
|
|
char* pBuf = new char[1025];
|
|
int nRead;
|
|
while( (nRead = aMessStream.Read(pBuf, 1024)) > 0 )
|
|
aMemStream.Write( pBuf, nRead );
|
|
delete[] pBuf;
|
|
|
|
aMemStream.Flush();
|
|
aMemStream.Seek( 0 );
|
|
void* pData = (void*)aMemStream.GetData();
|
|
sal_Int32 nLen = aMemStream.Seek(STREAM_SEEK_TO_END);
|
|
|
|
rContentType = UniString(aParent.GetContentType());
|
|
return Sequence<sal_Int8>((sal_Int8*)pData, nLen);
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
namespace
|
|
{
|
|
static void appendDigits( sal_Int32 _nNumber, sal_Int8 nDigits, ::rtl::OUStringBuffer& _rOut )
|
|
{
|
|
sal_Int32 nCurLen = _rOut.getLength();
|
|
_rOut.append( _nNumber );
|
|
while ( _rOut.getLength() - nCurLen < nDigits )
|
|
_rOut.insert( nCurLen, (sal_Unicode)'0' );
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
void ODatabaseForm::AppendComponent(HtmlSuccessfulObjList& rList, const Reference<XPropertySet>& xComponentSet, const ::rtl::OUString& rNamePrefix,
|
|
const Reference<XControl>& rxSubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt)
|
|
{
|
|
if (!xComponentSet.is())
|
|
return;
|
|
|
|
// MIB 25.6.98: Geschachtelte Formulare abfangen ... oder muesste
|
|
// man sie submitten?
|
|
if (!hasProperty(PROPERTY_CLASSID, xComponentSet))
|
|
return;
|
|
|
|
// Namen ermitteln
|
|
if (!hasProperty(PROPERTY_NAME, xComponentSet))
|
|
return;
|
|
|
|
sal_Int16 nClassId = 0;
|
|
xComponentSet->getPropertyValue(PROPERTY_CLASSID) >>= nClassId;
|
|
::rtl::OUString aName;
|
|
xComponentSet->getPropertyValue( PROPERTY_NAME ) >>= aName;
|
|
if( !aName.getLength() && nClassId != FormComponentType::IMAGEBUTTON)
|
|
return;
|
|
else // Name um den Prefix erweitern
|
|
aName = rNamePrefix + aName;
|
|
|
|
switch( nClassId )
|
|
{
|
|
// Buttons
|
|
case FormComponentType::COMMANDBUTTON:
|
|
{
|
|
// Es wird nur der gedrueckte Submit-Button ausgewertet
|
|
// MIB: Sofern ueberhaupt einer uebergeben wurde
|
|
if( rxSubmitButton.is() )
|
|
{
|
|
Reference<XPropertySet> xSubmitButtonComponent(rxSubmitButton->getModel(), UNO_QUERY);
|
|
if (xSubmitButtonComponent == xComponentSet && hasProperty(PROPERTY_LABEL, xComponentSet))
|
|
{
|
|
// <name>=<label>
|
|
::rtl::OUString aLabel;
|
|
xComponentSet->getPropertyValue( PROPERTY_LABEL ) >>= aLabel;
|
|
rList.push_back( HtmlSuccessfulObj(aName, aLabel) );
|
|
}
|
|
}
|
|
} break;
|
|
|
|
// ImageButtons
|
|
case FormComponentType::IMAGEBUTTON:
|
|
{
|
|
// Es wird nur der gedrueckte Submit-Button ausgewertet
|
|
// MIB: Sofern ueberhaupt einer uebergeben wurde
|
|
if( rxSubmitButton.is() )
|
|
{
|
|
Reference<XPropertySet> xSubmitButtonComponent(rxSubmitButton->getModel(), UNO_QUERY);
|
|
if (xSubmitButtonComponent == xComponentSet)
|
|
{
|
|
// <name>.x=<pos.X>&<name>.y=<pos.Y>
|
|
::rtl::OUString aLhs = aName;
|
|
::rtl::OUString aRhs = ::rtl::OUString::valueOf( MouseEvt.X );
|
|
|
|
// nur wenn ein Name vorhanden ist, kann ein name.x
|
|
aLhs += aName.getLength() ? UniString::CreateFromAscii(".x") : UniString::CreateFromAscii("x");
|
|
rList.push_back( HtmlSuccessfulObj(aLhs, aRhs) );
|
|
|
|
aLhs = aName;
|
|
aRhs = ::rtl::OUString::valueOf( MouseEvt.Y );
|
|
aLhs += aName.getLength() ? UniString::CreateFromAscii(".y") : UniString::CreateFromAscii("y");
|
|
rList.push_back( HtmlSuccessfulObj(aLhs, aRhs) );
|
|
|
|
}
|
|
}
|
|
} break;
|
|
|
|
// CheckBoxen / RadioButtons
|
|
case FormComponentType::CHECKBOX:
|
|
case FormComponentType::RADIOBUTTON:
|
|
{
|
|
// <name>=<refValue>
|
|
if( !hasProperty(PROPERTY_STATE, xComponentSet) )
|
|
break;
|
|
sal_Int16 nChecked = 0;
|
|
xComponentSet->getPropertyValue( PROPERTY_STATE ) >>= nChecked;
|
|
if( nChecked != 1 )
|
|
break;
|
|
|
|
::rtl::OUString aStrValue;
|
|
if( hasProperty(PROPERTY_REFVALUE, xComponentSet) )
|
|
xComponentSet->getPropertyValue( PROPERTY_REFVALUE ) >>= aStrValue;
|
|
|
|
rList.push_back( HtmlSuccessfulObj(aName, aStrValue) );
|
|
} break;
|
|
|
|
// Edit
|
|
case FormComponentType::TEXTFIELD:
|
|
{
|
|
// <name>=<text>
|
|
if( !hasProperty(PROPERTY_TEXT, xComponentSet) )
|
|
break;
|
|
|
|
// MIB: Spezial-Behandlung fuer Multiline-Edit nur dann, wenn
|
|
// es auch ein Control dazu gibt.
|
|
Any aTmp = xComponentSet->getPropertyValue( PROPERTY_MULTILINE );
|
|
sal_Bool bMulti = rxSubmitButton.is()
|
|
&& (aTmp.getValueType().getTypeClass() == TypeClass_BOOLEAN)
|
|
&& getBOOL(aTmp);
|
|
::rtl::OUString sText;
|
|
if ( bMulti ) // Bei MultiLineEdit Text am Control abholen
|
|
{
|
|
|
|
Reference<XControlContainer> xControlContainer(rxSubmitButton->getContext(), UNO_QUERY);
|
|
if( !xControlContainer.is() ) break;
|
|
|
|
Sequence<Reference<XControl> > aControlSeq = xControlContainer->getControls();
|
|
Reference<XControl> xControl;
|
|
Reference<XFormComponent> xControlComponent;
|
|
|
|
// Richtiges Control suchen
|
|
sal_Int32 i;
|
|
for( i=0; i<aControlSeq.getLength(); i++ )
|
|
{
|
|
xControl = aControlSeq.getConstArray()[i];
|
|
Reference<XPropertySet> xModel(xControl->getModel(), UNO_QUERY);
|
|
if (xModel == xComponentSet)
|
|
{
|
|
Reference<XTextComponent> xTextComponent(xControl, UNO_QUERY);
|
|
if( xTextComponent.is() )
|
|
sText = xTextComponent->getText();
|
|
break;
|
|
}
|
|
}
|
|
// Control nicht gefunden oder nicht existent, (Edit im Grid)
|
|
if (i == aControlSeq.getLength())
|
|
xComponentSet->getPropertyValue( PROPERTY_TEXT ) >>= sText;
|
|
}
|
|
else
|
|
xComponentSet->getPropertyValue( PROPERTY_TEXT ) >>= sText;
|
|
|
|
rList.push_back( HtmlSuccessfulObj(aName, sText) );
|
|
} break;
|
|
|
|
// ComboBox, Patternfield
|
|
case FormComponentType::COMBOBOX:
|
|
case FormComponentType::PATTERNFIELD:
|
|
{
|
|
// <name>=<text>
|
|
if( hasProperty(PROPERTY_TEXT, xComponentSet) )
|
|
{
|
|
::rtl::OUString aText;
|
|
xComponentSet->getPropertyValue( PROPERTY_TEXT ) >>= aText;
|
|
rList.push_back( HtmlSuccessfulObj(aName, aText) );
|
|
}
|
|
} break;
|
|
case FormComponentType::CURRENCYFIELD:
|
|
case FormComponentType::NUMERICFIELD:
|
|
{
|
|
// <name>=<wert> // wert wird als double mit Punkt als Decimaltrenner
|
|
// kein Wert angegeben (NULL) -> wert leer
|
|
if( hasProperty(PROPERTY_VALUE, xComponentSet) )
|
|
{
|
|
::rtl::OUString aText;
|
|
Any aVal = xComponentSet->getPropertyValue( PROPERTY_VALUE );
|
|
|
|
double aDoubleVal = 0;
|
|
if (aVal >>= aDoubleVal)
|
|
{
|
|
sal_Int16 nScale = 0;
|
|
xComponentSet->getPropertyValue( PROPERTY_DECIMAL_ACCURACY ) >>= nScale;
|
|
aText = ::rtl::math::doubleToUString(aDoubleVal, rtl_math_StringFormat_F, nScale, '.', sal_True);
|
|
}
|
|
rList.push_back( HtmlSuccessfulObj(aName, aText) );
|
|
}
|
|
} break;
|
|
case FormComponentType::DATEFIELD:
|
|
{
|
|
// <name>=<wert> // Wert wird als Datum im Format (MM-DD-YYYY)
|
|
// kein Wert angegeben (NULL) -> wert leer
|
|
if( hasProperty(PROPERTY_DATE, xComponentSet) )
|
|
{
|
|
::rtl::OUString aText;
|
|
Any aVal = xComponentSet->getPropertyValue( PROPERTY_DATE );
|
|
sal_Int32 nInt32Val = 0;
|
|
if (aVal >>= nInt32Val)
|
|
{
|
|
::Date aDate( nInt32Val );
|
|
::rtl::OUStringBuffer aBuffer;
|
|
appendDigits( aDate.GetMonth(), 2, aBuffer );
|
|
aBuffer.append( (sal_Unicode)'-' );
|
|
appendDigits( aDate.GetDay(), 2, aBuffer );
|
|
aBuffer.append( (sal_Unicode)'-' );
|
|
appendDigits( aDate.GetYear(), 4, aBuffer );
|
|
aText = aBuffer.makeStringAndClear();
|
|
}
|
|
rList.push_back( HtmlSuccessfulObj(aName, aText) );
|
|
}
|
|
} break;
|
|
case FormComponentType::TIMEFIELD:
|
|
{
|
|
// <name>=<wert> // Wert wird als Zeit im Format (HH:MM:SS) angegeben
|
|
// kein Wert angegeben (NULL) -> wert leer
|
|
if( hasProperty(PROPERTY_TIME, xComponentSet) )
|
|
{
|
|
::rtl::OUString aText;
|
|
Any aVal = xComponentSet->getPropertyValue( PROPERTY_TIME );
|
|
sal_Int32 nInt32Val = 0;
|
|
if (aVal >>= nInt32Val)
|
|
{
|
|
::Time aTime(nInt32Val);
|
|
::rtl::OUStringBuffer aBuffer;
|
|
appendDigits( aTime.GetHour(), 2, aBuffer );
|
|
aBuffer.append( (sal_Unicode)'-' );
|
|
appendDigits( aTime.GetMin(), 2, aBuffer );
|
|
aBuffer.append( (sal_Unicode)'-' );
|
|
appendDigits( aTime.GetSec(), 2, aBuffer );
|
|
aText = aBuffer.makeStringAndClear();
|
|
}
|
|
rList.push_back( HtmlSuccessfulObj(aName, aText) );
|
|
}
|
|
} break;
|
|
|
|
// starform
|
|
case FormComponentType::HIDDENCONTROL:
|
|
{
|
|
|
|
// <name>=<value>
|
|
if( hasProperty(PROPERTY_HIDDEN_VALUE, xComponentSet) )
|
|
{
|
|
::rtl::OUString aText;
|
|
xComponentSet->getPropertyValue( PROPERTY_HIDDEN_VALUE ) >>= aText;
|
|
rList.push_back( HtmlSuccessfulObj(aName, aText) );
|
|
}
|
|
} break;
|
|
|
|
// starform
|
|
case FormComponentType::FILECONTROL:
|
|
{
|
|
// <name>=<text>
|
|
if( hasProperty(PROPERTY_TEXT, xComponentSet) )
|
|
{
|
|
|
|
::rtl::OUString aText;
|
|
xComponentSet->getPropertyValue( PROPERTY_TEXT ) >>= aText;
|
|
rList.push_back( HtmlSuccessfulObj(aName, aText, SUCCESSFUL_REPRESENT_FILE) );
|
|
}
|
|
} break;
|
|
|
|
// starform
|
|
case FormComponentType::LISTBOX:
|
|
{
|
|
|
|
// <name>=<Token0>&<name>=<Token1>&...&<name>=<TokenN> (Mehrfachselektion)
|
|
if (!hasProperty(PROPERTY_SELECT_SEQ, xComponentSet) ||
|
|
!hasProperty(PROPERTY_STRINGITEMLIST, xComponentSet))
|
|
break;
|
|
|
|
// angezeigte Werte
|
|
Sequence< ::rtl::OUString > aVisibleList;
|
|
xComponentSet->getPropertyValue( PROPERTY_STRINGITEMLIST ) >>= aVisibleList;
|
|
sal_Int32 nStringCnt = aVisibleList.getLength();
|
|
const ::rtl::OUString* pStrings = aVisibleList.getConstArray();
|
|
|
|
// Werte-Liste
|
|
Sequence< ::rtl::OUString > aValueList;
|
|
xComponentSet->getPropertyValue( PROPERTY_VALUE_SEQ ) >>= aValueList;
|
|
sal_Int32 nValCnt = aValueList.getLength();
|
|
const ::rtl::OUString* pVals = aValueList.getConstArray();
|
|
|
|
// Selektion
|
|
Sequence<sal_Int16> aSelectList;
|
|
xComponentSet->getPropertyValue( PROPERTY_SELECT_SEQ ) >>= aSelectList;
|
|
sal_Int32 nSelCount = aSelectList.getLength();
|
|
const sal_Int16* pSels = aSelectList.getConstArray();
|
|
|
|
// Einfach- oder Mehrfach-Selektion
|
|
// Bei Einfach-Selektionen beruecksichtigt MT nur den ersten Eintrag
|
|
// in der Liste.
|
|
if (nSelCount > 1 && !getBOOL(xComponentSet->getPropertyValue(PROPERTY_MULTISELECTION)))
|
|
nSelCount = 1;
|
|
|
|
// Die Indizes in der Selektions-Liste koennen auch ungueltig sein,
|
|
// also muss man die gueltigen erstmal raussuchen um die Laenge
|
|
// der neuen Liste zu bestimmen.
|
|
sal_Int32 nCurCnt = 0;
|
|
sal_Int32 i;
|
|
for( i=0; i<nSelCount; ++i )
|
|
{
|
|
if( pSels[i] < nStringCnt )
|
|
++nCurCnt;
|
|
}
|
|
|
|
::rtl::OUString aSubValue;
|
|
for(i=0; i<nCurCnt; ++i )
|
|
{
|
|
sal_Int16 nSelPos = pSels[i];
|
|
if (nSelPos < nValCnt && pVals[nSelPos].getLength())
|
|
{
|
|
aSubValue = pVals[nSelPos];
|
|
}
|
|
else
|
|
{
|
|
aSubValue = pStrings[nSelPos];
|
|
}
|
|
rList.push_back( HtmlSuccessfulObj(aName, aSubValue) );
|
|
}
|
|
} break;
|
|
case FormComponentType::GRIDCONTROL:
|
|
{
|
|
// Die einzelnen Spaltenwerte werden verschickt,
|
|
// der Name wird mit dem Prefix des Names des Grids erweitert
|
|
Reference<XIndexAccess> xContainer(xComponentSet, UNO_QUERY);
|
|
if (!xContainer.is())
|
|
break;
|
|
|
|
aName += UniString('.');
|
|
|
|
Reference<XPropertySet> xSet;
|
|
sal_Int32 nCount = xContainer->getCount();
|
|
// we know already how many objects should be appended,
|
|
// so why not allocate the space for them
|
|
rList.reserve( nCount + rList.capacity() ); // not size()
|
|
for (sal_Int32 i = 0; i < nCount; ++i)
|
|
{
|
|
xContainer->getByIndex(i) >>= xSet;
|
|
if (xSet.is())
|
|
AppendComponent(rList, xSet, aName, rxSubmitButton, MouseEvt);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
void ODatabaseForm::FillSuccessfulList( HtmlSuccessfulObjList& rList,
|
|
const Reference<XControl>& rxSubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt )
|
|
{
|
|
// Liste loeschen
|
|
rList.clear();
|
|
// Ueber Components iterieren
|
|
Reference<XPropertySet> xComponentSet;
|
|
::rtl::OUString aPrefix;
|
|
|
|
// we know already how many objects should be appended,
|
|
// so why not allocate the space for them
|
|
rList.reserve( getCount() );
|
|
for( sal_Int32 nIndex=0; nIndex < getCount(); nIndex++ )
|
|
{
|
|
getByIndex( nIndex ) >>= xComponentSet;
|
|
AppendComponent(rList, xComponentSet, aPrefix, rxSubmitButton, MouseEvt);
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
void ODatabaseForm::Encode( ::rtl::OUString& rString ) const
|
|
{
|
|
::rtl::OUString aResult;
|
|
|
|
// Immer ANSI #58641
|
|
// rString.Convert(CHARSET_SYSTEM, CHARSET_ANSI);
|
|
|
|
|
|
// Zeilenendezeichen werden als CR dargestellt
|
|
UniString sConverter = rString;
|
|
sConverter.ConvertLineEnd( LINEEND_CR );
|
|
rString = sConverter;
|
|
|
|
|
|
// Jeden einzelnen Character ueberpruefen
|
|
sal_Int32 nStrLen = rString.getLength();
|
|
sal_Unicode nCharCode;
|
|
for( sal_Int32 nCurPos=0; nCurPos < nStrLen; ++nCurPos )
|
|
{
|
|
nCharCode = rString[nCurPos];
|
|
|
|
// Behandlung fuer chars, die kein alphanumerisches Zeichen sind
|
|
// und CharacterCodes > 127
|
|
if( (!isalnum(nCharCode) && nCharCode != (sal_Unicode)' ') || nCharCode > 127 )
|
|
{
|
|
switch( nCharCode )
|
|
{
|
|
case 13: // CR
|
|
aResult += ::rtl::OUString::createFromAscii("%0D%0A"); // Hex-Darstellung CR LF
|
|
break;
|
|
|
|
|
|
// Netscape Sonderbehandlung
|
|
case 42: // '*'
|
|
case 45: // '-'
|
|
case 46: // '.'
|
|
case 64: // '@'
|
|
case 95: // '_'
|
|
aResult += UniString(nCharCode);
|
|
break;
|
|
|
|
default:
|
|
{
|
|
// In Hex umrechnen
|
|
short nHi = ((sal_Int16)nCharCode) / 16;
|
|
short nLo = ((sal_Int16)nCharCode) - (nHi*16);
|
|
if( nHi > 9 ) nHi += (int)'A'-10; else nHi += (int)'0';
|
|
if( nLo > 9 ) nLo += (int)'A'-10; else nLo += (int)'0';
|
|
aResult += UniString('%');
|
|
aResult += UniString((sal_Unicode)nHi);
|
|
aResult += UniString((sal_Unicode)nLo);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
aResult += UniString(nCharCode);
|
|
}
|
|
|
|
|
|
// Spaces durch '+' ersetzen
|
|
aResult = aResult.replace(' ', '+');
|
|
|
|
rString = aResult;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
void ODatabaseForm::InsertTextPart( INetMIMEMessage& rParent, const ::rtl::OUString& rName,
|
|
const ::rtl::OUString& rData )
|
|
{
|
|
|
|
// Part als Message-Child erzeugen
|
|
INetMIMEMessage* pChild = new INetMIMEMessage();
|
|
|
|
|
|
// Header
|
|
::rtl::OUString aContentDisp = ::rtl::OUString::createFromAscii("form-data; name=\"");
|
|
aContentDisp += rName;
|
|
aContentDisp += UniString('\"');
|
|
pChild->SetContentDisposition( aContentDisp );
|
|
pChild->SetContentType( UniString::CreateFromAscii("text/plain") );
|
|
|
|
rtl_TextEncoding eSystemEncoding = gsl_getSystemTextEncoding();
|
|
const sal_Char* pBestMatchingEncoding = rtl_getBestMimeCharsetFromTextEncoding( eSystemEncoding );
|
|
UniString aBestMatchingEncoding = UniString::CreateFromAscii( pBestMatchingEncoding );
|
|
pChild->SetContentTransferEncoding(aBestMatchingEncoding);
|
|
|
|
// Body
|
|
SvMemoryStream* pStream = new SvMemoryStream;
|
|
pStream->WriteLine( ByteString( UniString(rData), rtl_getTextEncodingFromMimeCharset(pBestMatchingEncoding) ) );
|
|
pStream->Flush();
|
|
pStream->Seek( 0 );
|
|
pChild->SetDocumentLB( new SvLockBytes(pStream, sal_True) );
|
|
rParent.AttachChild( *pChild );
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
sal_Bool ODatabaseForm::InsertFilePart( INetMIMEMessage& rParent, const ::rtl::OUString& rName,
|
|
const ::rtl::OUString& rFileName )
|
|
{
|
|
UniString aFileName( rFileName );
|
|
UniString aContentType(UniString::CreateFromAscii(CONTENT_TYPE_STR_TEXT_PLAIN));
|
|
SvStream *pStream = 0;
|
|
|
|
if( aFileName.Len() )
|
|
{
|
|
// Bisher koennen wir nur File-URLs verarbeiten
|
|
INetURLObject aURL;
|
|
aURL.SetSmartProtocol(INET_PROT_FILE);
|
|
aURL.SetSmartURL(rFileName);
|
|
if( INET_PROT_FILE == aURL.GetProtocol() )
|
|
{
|
|
aFileName = INetURLObject::decode(aURL.PathToFileName(), '%', INetURLObject::DECODE_UNAMBIGUOUS);
|
|
DirEntry aDirEntry( aFileName );
|
|
if( aDirEntry.Exists() )
|
|
{
|
|
pStream = ::utl::UcbStreamHelper::CreateStream(aFileName, STREAM_READ);
|
|
if (!pStream || (pStream->GetError() != ERRCODE_NONE))
|
|
{
|
|
delete pStream;
|
|
pStream = 0;
|
|
}
|
|
}
|
|
INetContentType eContentType = INetContentTypes::GetContentType4Extension(
|
|
aDirEntry.GetExtension() );
|
|
if (eContentType != CONTENT_TYPE_UNKNOWN)
|
|
aContentType = INetContentTypes::GetContentType(eContentType);
|
|
}
|
|
}
|
|
|
|
// Wenn irgendetwas nicht geklappt hat, legen wir einen leeren
|
|
// MemoryStream an
|
|
if( !pStream )
|
|
pStream = new SvMemoryStream;
|
|
|
|
|
|
// Part als Message-Child erzeugen
|
|
INetMIMEMessage* pChild = new INetMIMEMessage;
|
|
|
|
|
|
// Header
|
|
::rtl::OUString aContentDisp = ::rtl::OUString::createFromAscii( "form-data; name=\"" );
|
|
aContentDisp += rName;
|
|
aContentDisp += UniString('\"');
|
|
aContentDisp += ::rtl::OUString::createFromAscii("; filename=\"");
|
|
aContentDisp += aFileName;
|
|
aContentDisp += UniString('\"');
|
|
pChild->SetContentDisposition( aContentDisp );
|
|
pChild->SetContentType( aContentType );
|
|
pChild->SetContentTransferEncoding( UniString(::rtl::OUString::createFromAscii("8bit")) );
|
|
|
|
|
|
// Body
|
|
pChild->SetDocumentLB( new SvLockBytes(pStream, sal_True) );
|
|
rParent.AttachChild( *pChild );
|
|
|
|
return sal_True;
|
|
}
|
|
|
|
//==============================================================================
|
|
// internals
|
|
//------------------------------------------------------------------------------
|
|
void ODatabaseForm::onError( const SQLErrorEvent& _rEvent )
|
|
{
|
|
m_aErrorListeners.notifyEach( &XSQLErrorListener::errorOccured, _rEvent );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void ODatabaseForm::onError( const SQLException& _rException, const ::rtl::OUString& _rContextDescription )
|
|
{
|
|
if ( !m_aErrorListeners.getLength() )
|
|
return;
|
|
|
|
SQLErrorEvent aEvent( *this, makeAny( prependErrorInfo( _rException, *this, _rContextDescription ) ) );
|
|
onError( aEvent );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void ODatabaseForm::updateParameterInfo()
|
|
{
|
|
m_aParameterManager.updateParameterInfo( m_aFilterManager );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
bool ODatabaseForm::hasValidParent() const
|
|
{
|
|
// do we have to fill the parameters again?
|
|
if (m_bSubForm)
|
|
{
|
|
Reference<XResultSet> xResultSet(m_xParent, UNO_QUERY);
|
|
if (!xResultSet.is())
|
|
{
|
|
DBG_ERROR("ODatabaseForm::hasValidParent() : no parent resultset !");
|
|
return false;
|
|
}
|
|
try
|
|
{
|
|
Reference< XPropertySet > xSet( m_xParent, UNO_QUERY );
|
|
Reference< XLoadable > xLoad( m_xParent, UNO_QUERY );
|
|
if ( xLoad->isLoaded()
|
|
&& ( xResultSet->isBeforeFirst()
|
|
|| xResultSet->isAfterLast()
|
|
|| getBOOL( xSet->getPropertyValue( PROPERTY_ISNEW ) )
|
|
)
|
|
)
|
|
// the parent form is loaded and on a "virtual" row -> not valid
|
|
return false;
|
|
}
|
|
catch(Exception&)
|
|
{
|
|
// parent could be forwardonly?
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
bool ODatabaseForm::fillParameters( ::osl::ResettableMutexGuard& _rClearForNotifies, const Reference< XInteractionHandler >& _rxCompletionHandler )
|
|
{
|
|
// do we have to fill the parameters again?
|
|
if ( !m_aParameterManager.isUpToDate() )
|
|
updateParameterInfo();
|
|
|
|
// is there a valid parent?
|
|
if ( m_bSubForm && !hasValidParent() )
|
|
return true;
|
|
|
|
// ensure we're connected
|
|
if ( !implEnsureConnection() )
|
|
return false;
|
|
|
|
if ( m_aParameterManager.isUpToDate() )
|
|
return m_aParameterManager.fillParameterValues( _rxCompletionHandler, _rClearForNotifies );
|
|
|
|
return true;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void ODatabaseForm::saveInsertOnlyState( )
|
|
{
|
|
OSL_ENSURE( !m_aIgnoreResult.hasValue(), "ODatabaseForm::saveInsertOnlyState: overriding old value!" );
|
|
m_aIgnoreResult = m_xAggregateSet->getPropertyValue( PROPERTY_INSERTONLY );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void ODatabaseForm::restoreInsertOnlyState( )
|
|
{
|
|
if ( m_aIgnoreResult.hasValue() )
|
|
{
|
|
m_xAggregateSet->setPropertyValue( PROPERTY_INSERTONLY, m_aIgnoreResult );
|
|
m_aIgnoreResult = Any();
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
sal_Bool ODatabaseForm::executeRowSet(::osl::ResettableMutexGuard& _rClearForNotifies, sal_Bool bMoveToFirst, const Reference< XInteractionHandler >& _rxCompletionHandler)
|
|
{
|
|
if (!m_xAggregateAsRowSet.is())
|
|
return sal_False;
|
|
|
|
if (!fillParameters(_rClearForNotifies, _rxCompletionHandler))
|
|
return sal_False;
|
|
|
|
restoreInsertOnlyState( );
|
|
|
|
// ensure the aggregated row set has the correct properties
|
|
sal_Int32 nConcurrency = ResultSetConcurrency::READ_ONLY;
|
|
|
|
// if we have a parent, who is not positioned on a valid row
|
|
// we can't be updatable!
|
|
if (m_bSubForm && !hasValidParent())
|
|
{
|
|
nConcurrency = ResultSetConcurrency::READ_ONLY;
|
|
|
|
// don't use any parameters if we don't have a valid parent
|
|
m_aParameterManager.setAllParametersNull();
|
|
|
|
// switch to "insert only" mode
|
|
saveInsertOnlyState( );
|
|
m_xAggregateSet->setPropertyValue( PROPERTY_INSERTONLY, makeAny( sal_True ) );
|
|
}
|
|
else if (m_bAllowInsert || m_bAllowUpdate || m_bAllowDelete)
|
|
nConcurrency = ResultSetConcurrency::UPDATABLE;
|
|
else
|
|
nConcurrency = ResultSetConcurrency::READ_ONLY;
|
|
|
|
m_xAggregateSet->setPropertyValue( PROPERTY_RESULTSET_CONCURRENCY, makeAny( (sal_Int32)nConcurrency ) );
|
|
m_xAggregateSet->setPropertyValue( PROPERTY_RESULTSET_TYPE, makeAny( (sal_Int32)ResultSetType::SCROLL_SENSITIVE ) );
|
|
|
|
sal_Bool bSuccess = sal_False;
|
|
try
|
|
{
|
|
m_xAggregateAsRowSet->execute();
|
|
bSuccess = sal_True;
|
|
}
|
|
catch( const RowSetVetoException& eVeto )
|
|
{
|
|
(void)eVeto;
|
|
}
|
|
catch(SQLException& eDb)
|
|
{
|
|
_rClearForNotifies.clear();
|
|
if (m_sCurrentErrorContext.getLength())
|
|
onError(eDb, m_sCurrentErrorContext);
|
|
else
|
|
onError(eDb, FRM_RES_STRING(RID_STR_READERROR));
|
|
_rClearForNotifies.reset();
|
|
|
|
restoreInsertOnlyState( );
|
|
}
|
|
|
|
if (bSuccess)
|
|
{
|
|
// adjust the privilege property
|
|
// m_nPrivileges;
|
|
m_xAggregateSet->getPropertyValue(PROPERTY_PRIVILEGES) >>= m_nPrivileges;
|
|
if (!m_bAllowInsert)
|
|
m_nPrivileges &= ~Privilege::INSERT;
|
|
if (!m_bAllowUpdate)
|
|
m_nPrivileges &= ~Privilege::UPDATE;
|
|
if (!m_bAllowDelete)
|
|
m_nPrivileges &= ~Privilege::DELETE;
|
|
|
|
if (bMoveToFirst)
|
|
{
|
|
// the row set is positioned _before_ the first row (per definitionem), so move the set ...
|
|
try
|
|
{
|
|
// if we have an insert only rowset we move to the insert row
|
|
next();
|
|
if (((m_nPrivileges & Privilege::INSERT) == Privilege::INSERT)
|
|
&& isAfterLast())
|
|
{
|
|
// move on the insert row of set
|
|
// resetting must be done later, after the load events have been posted
|
|
// see :moveToInsertRow and load , reload
|
|
Reference<XResultSetUpdate> xUpdate;
|
|
if (query_aggregation( m_xAggregate, xUpdate))
|
|
xUpdate->moveToInsertRow();
|
|
}
|
|
}
|
|
catch(SQLException& eDB)
|
|
{
|
|
_rClearForNotifies.clear();
|
|
if (m_sCurrentErrorContext.getLength())
|
|
onError(eDB, m_sCurrentErrorContext);
|
|
else
|
|
onError(eDB, FRM_RES_STRING(RID_STR_READERROR));
|
|
_rClearForNotifies.reset();
|
|
bSuccess = sal_False;
|
|
}
|
|
}
|
|
}
|
|
return bSuccess;
|
|
}
|
|
|
|
//------------------------------------------------------------------
|
|
void ODatabaseForm::disposing()
|
|
{
|
|
if (m_pAggregatePropertyMultiplexer)
|
|
m_pAggregatePropertyMultiplexer->dispose();
|
|
|
|
if (m_bLoaded)
|
|
unload();
|
|
|
|
// cancel the submit/reset-thread
|
|
{
|
|
::osl::MutexGuard aGuard( m_aMutex );
|
|
if (m_pThread)
|
|
{
|
|
m_pThread->release();
|
|
m_pThread = NULL;
|
|
}
|
|
}
|
|
|
|
EventObject aEvt(static_cast<XWeak*>(this));
|
|
m_aLoadListeners.disposeAndClear(aEvt);
|
|
m_aRowSetApproveListeners.disposeAndClear(aEvt);
|
|
m_aParameterManager.disposing( aEvt );
|
|
m_aResetListeners.disposing();
|
|
m_aSubmitListeners.disposeAndClear(aEvt);
|
|
m_aErrorListeners.disposeAndClear(aEvt);
|
|
|
|
m_aParameterManager.dispose(); // (to free any references it may have to me)
|
|
m_aFilterManager.dispose(); // (dito)
|
|
|
|
OFormComponents::disposing();
|
|
OPropertySetAggregationHelper::disposing();
|
|
|
|
// stop listening on the aggregate
|
|
if (m_xAggregateAsRowSet.is())
|
|
m_xAggregateAsRowSet->removeRowSetListener(this);
|
|
|
|
// dispose the active connection
|
|
Reference<XComponent> xAggregationComponent;
|
|
if (query_aggregation(m_xAggregate, xAggregationComponent))
|
|
xAggregationComponent->dispose();
|
|
|
|
m_aPropertyBagHelper.dispose();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
Reference< XConnection > ODatabaseForm::getConnection()
|
|
{
|
|
Reference< XConnection > xConn;
|
|
m_xAggregateSet->getPropertyValue( PROPERTY_ACTIVE_CONNECTION ) >>= xConn;
|
|
return xConn;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
::osl::Mutex& ODatabaseForm::getMutex()
|
|
{
|
|
return m_aMutex;
|
|
}
|
|
|
|
//==============================================================================
|
|
// property handling
|
|
//------------------------------------------------------------------------------
|
|
void ODatabaseForm::describeFixedAndAggregateProperties(
|
|
Sequence< Property >& _rProps,
|
|
Sequence< Property >& _rAggregateProps ) const
|
|
{
|
|
BEGIN_DESCRIBE_AGGREGATION_PROPERTIES(22, m_xAggregateSet)
|
|
// we want to "override" the privileges, since we have additional "AllowInsert" etc. properties
|
|
RemoveProperty( _rAggregateProps, PROPERTY_PRIVILEGES );
|
|
|
|
// InsertOnly is also to be overridden, since we sometimes change it ourself
|
|
RemoveProperty( _rAggregateProps, PROPERTY_INSERTONLY );
|
|
|
|
// we remove and re-declare the DataSourceName property, 'cause we want it to be constrained, and the
|
|
// original property of our aggregate isn't
|
|
RemoveProperty( _rAggregateProps, PROPERTY_DATASOURCE );
|
|
|
|
// for connection sharing, we need to override the ActiveConnection property, too
|
|
RemoveProperty( _rAggregateProps, PROPERTY_ACTIVE_CONNECTION );
|
|
|
|
// the Filter property is also overwritten, since we have some implicit filters
|
|
// (e.g. the ones which result from linking master fields to detail fields
|
|
// via column names instead of parameters)
|
|
RemoveProperty( _rAggregateProps, PROPERTY_FILTER );
|
|
RemoveProperty( _rAggregateProps, PROPERTY_APPLYFILTER );
|
|
|
|
DECL_IFACE_PROP4(ACTIVE_CONNECTION, XConnection, BOUND, TRANSIENT, MAYBEVOID, CONSTRAINED);
|
|
DECL_BOOL_PROP2 ( APPLYFILTER, BOUND, MAYBEDEFAULT );
|
|
DECL_PROP1 ( NAME, ::rtl::OUString, BOUND );
|
|
DECL_PROP1 ( MASTERFIELDS, Sequence< ::rtl::OUString >, BOUND );
|
|
DECL_PROP1 ( DETAILFIELDS, Sequence< ::rtl::OUString >, BOUND );
|
|
DECL_PROP2 ( DATASOURCE, ::rtl::OUString, BOUND, CONSTRAINED );
|
|
DECL_PROP3 ( CYCLE, TabulatorCycle, BOUND, MAYBEVOID, MAYBEDEFAULT );
|
|
DECL_PROP2 ( FILTER, ::rtl::OUString, BOUND, MAYBEDEFAULT );
|
|
DECL_BOOL_PROP2 ( INSERTONLY, BOUND, MAYBEDEFAULT );
|
|
DECL_PROP1 ( NAVIGATION, NavigationBarMode, BOUND );
|
|
DECL_BOOL_PROP1 ( ALLOWADDITIONS, BOUND );
|
|
DECL_BOOL_PROP1 ( ALLOWEDITS, BOUND );
|
|
DECL_BOOL_PROP1 ( ALLOWDELETIONS, BOUND );
|
|
DECL_PROP2 ( PRIVILEGES, sal_Int32, TRANSIENT, READONLY );
|
|
DECL_PROP1 ( TARGET_URL, ::rtl::OUString, BOUND );
|
|
DECL_PROP1 ( TARGET_FRAME, ::rtl::OUString, BOUND );
|
|
DECL_PROP1 ( SUBMIT_METHOD, FormSubmitMethod, BOUND );
|
|
DECL_PROP1 ( SUBMIT_ENCODING, FormSubmitEncoding, BOUND );
|
|
DECL_BOOL_PROP3 ( DYNAMIC_CONTROL_BORDER, BOUND, MAYBEVOID, MAYBEDEFAULT );
|
|
DECL_PROP3 ( CONTROL_BORDER_COLOR_FOCUS, sal_Int32, BOUND, MAYBEVOID, MAYBEDEFAULT );
|
|
DECL_PROP3 ( CONTROL_BORDER_COLOR_MOUSE, sal_Int32, BOUND, MAYBEVOID, MAYBEDEFAULT );
|
|
DECL_PROP3 ( CONTROL_BORDER_COLOR_INVALID, sal_Int32, BOUND, MAYBEVOID, MAYBEDEFAULT );
|
|
END_DESCRIBE_PROPERTIES();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
Reference< XMultiPropertySet > ODatabaseForm::getPropertiesInterface()
|
|
{
|
|
return Reference< XMultiPropertySet >( *this, UNO_QUERY );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
::cppu::IPropertyArrayHelper& ODatabaseForm::getInfoHelper()
|
|
{
|
|
return m_aPropertyBagHelper.getInfoHelper();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
Reference< XPropertySetInfo > ODatabaseForm::getPropertySetInfo() throw( RuntimeException )
|
|
{
|
|
return createPropertySetInfo( getInfoHelper() );
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::addProperty( const ::rtl::OUString& _rName, ::sal_Int16 _nAttributes, const Any& _rInitialValue ) throw (PropertyExistException, IllegalTypeException, IllegalArgumentException, RuntimeException)
|
|
{
|
|
m_aPropertyBagHelper.addProperty( _rName, _nAttributes, _rInitialValue );
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::removeProperty( const ::rtl::OUString& _rName ) throw (UnknownPropertyException, NotRemoveableException, RuntimeException)
|
|
{
|
|
m_aPropertyBagHelper.removeProperty( _rName );
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
Sequence< PropertyValue > SAL_CALL ODatabaseForm::getPropertyValues() throw (RuntimeException)
|
|
{
|
|
return m_aPropertyBagHelper.getPropertyValues();
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::setPropertyValues( const Sequence< PropertyValue >& _rProps ) throw (UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException)
|
|
{
|
|
m_aPropertyBagHelper.setPropertyValues( _rProps );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
Any SAL_CALL ODatabaseForm::getWarnings( ) throw (SQLException, RuntimeException)
|
|
{
|
|
return m_aWarnings.getWarnings();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::clearWarnings( ) throw (SQLException, RuntimeException)
|
|
{
|
|
m_aWarnings.clearWarnings();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
Reference< XCloneable > SAL_CALL ODatabaseForm::createClone( ) throw (RuntimeException)
|
|
{
|
|
ODatabaseForm* pClone = new ODatabaseForm( *this );
|
|
osl_incrementInterlockedCount( &pClone->m_refCount );
|
|
pClone->clonedFrom( *this );
|
|
osl_decrementInterlockedCount( &pClone->m_refCount );
|
|
return pClone;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void ODatabaseForm::fire( sal_Int32* pnHandles, const Any* pNewValues, const Any* pOldValues, sal_Int32 nCount, sal_Bool bVetoable )
|
|
{
|
|
// same as in getFastPropertyValue(INT32) : if we're resetting currently don't fire any changes of the
|
|
// IsModified property from FALSE to TRUE, as this is only temporary 'til the reset is done
|
|
if (m_nResetsPending > 0)
|
|
{
|
|
// look for the PROPERTY_ID_ISMODIFIED
|
|
sal_Int32 nPos = 0;
|
|
for (nPos=0; nPos<nCount; ++nPos)
|
|
if (pnHandles[nPos] == PROPERTY_ID_ISMODIFIED)
|
|
break;
|
|
|
|
if ((nPos < nCount) && (pNewValues[nPos].getValueType().getTypeClass() == TypeClass_BOOLEAN) && getBOOL(pNewValues[nPos]))
|
|
{ // yeah, we found it, and it changed to TRUE
|
|
if (nPos == 0)
|
|
{ // just cut the first element
|
|
++pnHandles;
|
|
++pNewValues;
|
|
++pOldValues;
|
|
--nCount;
|
|
}
|
|
else if (nPos == nCount - 1)
|
|
// just cut the last element
|
|
--nCount;
|
|
else
|
|
{ // split into two base class calls
|
|
OPropertySetAggregationHelper::fire(pnHandles, pNewValues, pOldValues, nPos, bVetoable);
|
|
++nPos;
|
|
OPropertySetAggregationHelper::fire(pnHandles + nPos, pNewValues + nPos, pOldValues + nPos, nCount - nPos, bVetoable);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
OPropertySetAggregationHelper::fire(pnHandles, pNewValues, pOldValues, nCount, bVetoable);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
Any SAL_CALL ODatabaseForm::getFastPropertyValue( sal_Int32 nHandle )
|
|
throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
|
|
{
|
|
if ((nHandle == PROPERTY_ID_ISMODIFIED) && (m_nResetsPending > 0))
|
|
return ::cppu::bool2any((sal_False));
|
|
// don't allow the aggregate which is currently being reset to return a (temporary) "yes"
|
|
else
|
|
return OPropertySetAggregationHelper::getFastPropertyValue(nHandle);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void ODatabaseForm::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const
|
|
{
|
|
switch (nHandle)
|
|
{
|
|
case PROPERTY_ID_INSERTONLY:
|
|
rValue <<= m_bInsertOnly;
|
|
break;
|
|
|
|
case PROPERTY_ID_FILTER:
|
|
rValue <<= m_aFilterManager.getFilterComponent( FilterManager::fcPublicFilter );
|
|
break;
|
|
|
|
case PROPERTY_ID_APPLYFILTER:
|
|
rValue <<= m_aFilterManager.isApplyPublicFilter();
|
|
break;
|
|
|
|
case PROPERTY_ID_DATASOURCE:
|
|
rValue = m_xAggregateSet->getPropertyValue( PROPERTY_DATASOURCE );
|
|
break;
|
|
|
|
case PROPERTY_ID_TARGET_URL:
|
|
rValue <<= m_aTargetURL;
|
|
break;
|
|
case PROPERTY_ID_TARGET_FRAME:
|
|
rValue <<= m_aTargetFrame;
|
|
break;
|
|
case PROPERTY_ID_SUBMIT_METHOD:
|
|
rValue <<= m_eSubmitMethod;
|
|
break;
|
|
case PROPERTY_ID_SUBMIT_ENCODING:
|
|
rValue <<= m_eSubmitEncoding;
|
|
break;
|
|
case PROPERTY_ID_NAME:
|
|
rValue <<= m_sName;
|
|
break;
|
|
case PROPERTY_ID_MASTERFIELDS:
|
|
rValue <<= m_aMasterFields;
|
|
break;
|
|
case PROPERTY_ID_DETAILFIELDS:
|
|
rValue <<= m_aDetailFields;
|
|
break;
|
|
case PROPERTY_ID_CYCLE:
|
|
rValue = m_aCycle;
|
|
break;
|
|
case PROPERTY_ID_NAVIGATION:
|
|
rValue <<= m_eNavigation;
|
|
break;
|
|
case PROPERTY_ID_ALLOWADDITIONS:
|
|
rValue <<= (sal_Bool)m_bAllowInsert;
|
|
break;
|
|
case PROPERTY_ID_ALLOWEDITS:
|
|
rValue <<= (sal_Bool)m_bAllowUpdate;
|
|
break;
|
|
case PROPERTY_ID_ALLOWDELETIONS:
|
|
rValue <<= (sal_Bool)m_bAllowDelete;
|
|
break;
|
|
case PROPERTY_ID_PRIVILEGES:
|
|
rValue <<= (sal_Int32)m_nPrivileges;
|
|
break;
|
|
case PROPERTY_ID_DYNAMIC_CONTROL_BORDER:
|
|
rValue = m_aDynamicControlBorder;
|
|
break;
|
|
case PROPERTY_ID_CONTROL_BORDER_COLOR_FOCUS:
|
|
rValue = m_aControlBorderColorFocus;
|
|
break;
|
|
case PROPERTY_ID_CONTROL_BORDER_COLOR_MOUSE:
|
|
rValue = m_aControlBorderColorMouse;
|
|
break;
|
|
case PROPERTY_ID_CONTROL_BORDER_COLOR_INVALID:
|
|
rValue = m_aControlBorderColorInvalid;
|
|
break;
|
|
default:
|
|
if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( nHandle ) )
|
|
m_aPropertyBagHelper.getDynamicFastPropertyValue( nHandle, rValue );
|
|
else
|
|
OPropertySetAggregationHelper::getFastPropertyValue( rValue, nHandle );
|
|
break;
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
sal_Bool ODatabaseForm::convertFastPropertyValue( Any& rConvertedValue, Any& rOldValue,
|
|
sal_Int32 nHandle, const Any& rValue ) throw( IllegalArgumentException )
|
|
{
|
|
sal_Bool bModified(sal_False);
|
|
switch (nHandle)
|
|
{
|
|
case PROPERTY_ID_INSERTONLY:
|
|
bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_bInsertOnly );
|
|
break;
|
|
|
|
case PROPERTY_ID_FILTER:
|
|
bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_aFilterManager.getFilterComponent( FilterManager::fcPublicFilter ) );
|
|
break;
|
|
|
|
case PROPERTY_ID_APPLYFILTER:
|
|
bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_aFilterManager.isApplyPublicFilter() );
|
|
break;
|
|
|
|
case PROPERTY_ID_DATASOURCE:
|
|
{
|
|
Any aAggregateProperty;
|
|
getFastPropertyValue(aAggregateProperty, PROPERTY_ID_DATASOURCE);
|
|
bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, aAggregateProperty, ::getCppuType(static_cast<const ::rtl::OUString*>(NULL)));
|
|
}
|
|
break;
|
|
case PROPERTY_ID_TARGET_URL:
|
|
bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aTargetURL);
|
|
break;
|
|
case PROPERTY_ID_TARGET_FRAME:
|
|
bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aTargetFrame);
|
|
break;
|
|
case PROPERTY_ID_SUBMIT_METHOD:
|
|
bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_eSubmitMethod);
|
|
break;
|
|
case PROPERTY_ID_SUBMIT_ENCODING:
|
|
bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_eSubmitEncoding);
|
|
break;
|
|
case PROPERTY_ID_NAME:
|
|
bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_sName);
|
|
break;
|
|
case PROPERTY_ID_MASTERFIELDS:
|
|
bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aMasterFields);
|
|
break;
|
|
case PROPERTY_ID_DETAILFIELDS:
|
|
bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aDetailFields);
|
|
break;
|
|
case PROPERTY_ID_CYCLE:
|
|
bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aCycle, ::getCppuType(static_cast<const TabulatorCycle*>(NULL)));
|
|
break;
|
|
case PROPERTY_ID_NAVIGATION:
|
|
bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_eNavigation);
|
|
break;
|
|
case PROPERTY_ID_ALLOWADDITIONS:
|
|
bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bAllowInsert);
|
|
break;
|
|
case PROPERTY_ID_ALLOWEDITS:
|
|
bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bAllowUpdate);
|
|
break;
|
|
case PROPERTY_ID_ALLOWDELETIONS:
|
|
bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bAllowDelete);
|
|
break;
|
|
case PROPERTY_ID_DYNAMIC_CONTROL_BORDER:
|
|
bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_aDynamicControlBorder, ::getBooleanCppuType() );
|
|
break;
|
|
case PROPERTY_ID_CONTROL_BORDER_COLOR_FOCUS:
|
|
bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_aControlBorderColorFocus, getCppuType( static_cast< sal_Int32* >( NULL ) ) );
|
|
break;
|
|
case PROPERTY_ID_CONTROL_BORDER_COLOR_MOUSE:
|
|
bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_aControlBorderColorMouse, getCppuType( static_cast< sal_Int32* >( NULL ) ) );
|
|
break;
|
|
case PROPERTY_ID_CONTROL_BORDER_COLOR_INVALID:
|
|
bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_aControlBorderColorInvalid, getCppuType( static_cast< sal_Int32* >( NULL ) ) );
|
|
break;
|
|
default:
|
|
if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle ( nHandle ) )
|
|
bModified = m_aPropertyBagHelper.convertDynamicFastPropertyValue( nHandle, rValue, rConvertedValue, rOldValue );
|
|
else
|
|
bModified = OPropertySetAggregationHelper::convertFastPropertyValue( rConvertedValue, rOldValue, nHandle, rValue );
|
|
break;
|
|
}
|
|
return bModified;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void ODatabaseForm::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw( Exception )
|
|
{
|
|
switch (nHandle)
|
|
{
|
|
case PROPERTY_ID_INSERTONLY:
|
|
rValue >>= m_bInsertOnly;
|
|
if ( m_aIgnoreResult.hasValue() )
|
|
m_aIgnoreResult <<= m_bInsertOnly;
|
|
else
|
|
m_xAggregateSet->setPropertyValue( PROPERTY_INSERTONLY, makeAny( m_bInsertOnly ) );
|
|
break;
|
|
|
|
case PROPERTY_ID_FILTER:
|
|
{
|
|
::rtl::OUString sNewFilter;
|
|
rValue >>= sNewFilter;
|
|
m_aFilterManager.setFilterComponent( FilterManager::fcPublicFilter, sNewFilter );
|
|
}
|
|
break;
|
|
|
|
case PROPERTY_ID_APPLYFILTER:
|
|
{
|
|
sal_Bool bApply = sal_True;
|
|
rValue >>= bApply;
|
|
m_aFilterManager.setApplyPublicFilter( bApply );
|
|
}
|
|
break;
|
|
|
|
case PROPERTY_ID_DATASOURCE:
|
|
{
|
|
Reference< XConnection > xSomeConnection;
|
|
if ( ::dbtools::isEmbeddedInDatabase( getParent(), xSomeConnection ) )
|
|
throw PropertyVetoException();
|
|
|
|
try
|
|
{
|
|
m_xAggregateSet->setPropertyValue(PROPERTY_DATASOURCE, rValue);
|
|
}
|
|
catch(Exception&) { }
|
|
}
|
|
break;
|
|
case PROPERTY_ID_TARGET_URL:
|
|
rValue >>= m_aTargetURL;
|
|
break;
|
|
case PROPERTY_ID_TARGET_FRAME:
|
|
rValue >>= m_aTargetFrame;
|
|
break;
|
|
case PROPERTY_ID_SUBMIT_METHOD:
|
|
rValue >>= m_eSubmitMethod;
|
|
break;
|
|
case PROPERTY_ID_SUBMIT_ENCODING:
|
|
rValue >>= m_eSubmitEncoding;
|
|
break;
|
|
case PROPERTY_ID_NAME:
|
|
rValue >>= m_sName;
|
|
break;
|
|
case PROPERTY_ID_MASTERFIELDS:
|
|
rValue >>= m_aMasterFields;
|
|
invlidateParameters();
|
|
break;
|
|
case PROPERTY_ID_DETAILFIELDS:
|
|
rValue >>= m_aDetailFields;
|
|
invlidateParameters();
|
|
break;
|
|
case PROPERTY_ID_CYCLE:
|
|
m_aCycle = rValue;
|
|
break;
|
|
case PROPERTY_ID_NAVIGATION:
|
|
rValue >>= m_eNavigation;
|
|
break;
|
|
case PROPERTY_ID_ALLOWADDITIONS:
|
|
m_bAllowInsert = getBOOL(rValue);
|
|
break;
|
|
case PROPERTY_ID_ALLOWEDITS:
|
|
m_bAllowUpdate = getBOOL(rValue);
|
|
break;
|
|
case PROPERTY_ID_ALLOWDELETIONS:
|
|
m_bAllowDelete = getBOOL(rValue);
|
|
break;
|
|
case PROPERTY_ID_DYNAMIC_CONTROL_BORDER:
|
|
m_aDynamicControlBorder = rValue;
|
|
break;
|
|
case PROPERTY_ID_CONTROL_BORDER_COLOR_FOCUS:
|
|
m_aControlBorderColorFocus = rValue;
|
|
break;
|
|
case PROPERTY_ID_CONTROL_BORDER_COLOR_MOUSE:
|
|
m_aControlBorderColorMouse = rValue;
|
|
break;
|
|
case PROPERTY_ID_CONTROL_BORDER_COLOR_INVALID:
|
|
m_aControlBorderColorInvalid = rValue;
|
|
break;
|
|
|
|
case PROPERTY_ID_ACTIVE_CONNECTION:
|
|
{
|
|
Reference< XConnection > xOuterConnection;
|
|
if ( ::dbtools::isEmbeddedInDatabase( getParent(), xOuterConnection ) )
|
|
{
|
|
if ( xOuterConnection != Reference< XConnection >( rValue, UNO_QUERY ) )
|
|
// somebody's trying to set a connection which is not equal the connection
|
|
// implied by the database we're embedded in
|
|
throw PropertyVetoException();
|
|
}
|
|
OPropertySetAggregationHelper::setFastPropertyValue_NoBroadcast( nHandle, rValue );
|
|
break;
|
|
}
|
|
|
|
default:
|
|
if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( nHandle ) )
|
|
m_aPropertyBagHelper.setDynamicFastPropertyValue( nHandle, rValue );
|
|
else
|
|
OPropertySetAggregationHelper::setFastPropertyValue_NoBroadcast( nHandle, rValue );
|
|
break;
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::forwardingPropertyValue( sal_Int32 _nHandle )
|
|
{
|
|
OSL_ENSURE( _nHandle == PROPERTY_ID_ACTIVE_CONNECTION, "ODatabaseForm::forwardingPropertyValue: unexpected property!" );
|
|
if ( _nHandle == PROPERTY_ID_ACTIVE_CONNECTION )
|
|
{
|
|
if ( m_bSharingConnection )
|
|
stopSharingConnection( );
|
|
m_bForwardingConnection = sal_True;
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::forwardedPropertyValue( sal_Int32 _nHandle, bool /*_bSuccess*/ )
|
|
{
|
|
OSL_ENSURE( _nHandle == PROPERTY_ID_ACTIVE_CONNECTION, "ODatabaseForm::forwardedPropertyValue: unexpected property!" );
|
|
if ( _nHandle == PROPERTY_ID_ACTIVE_CONNECTION )
|
|
{
|
|
m_bForwardingConnection = sal_False;
|
|
}
|
|
}
|
|
|
|
//==============================================================================
|
|
// com::sun::star::beans::XPropertyState
|
|
//------------------------------------------------------------------
|
|
PropertyState ODatabaseForm::getPropertyStateByHandle(sal_Int32 nHandle)
|
|
{
|
|
PropertyState eState;
|
|
switch (nHandle)
|
|
{
|
|
case PROPERTY_ID_NAVIGATION:
|
|
return (NavigationBarMode_CURRENT == m_eNavigation) ? PropertyState_DEFAULT_VALUE : PropertyState_DIRECT_VALUE;
|
|
|
|
case PROPERTY_ID_CYCLE:
|
|
eState = m_aCycle.hasValue() ? PropertyState_DIRECT_VALUE : PropertyState_DEFAULT_VALUE;
|
|
break;
|
|
|
|
case PROPERTY_ID_INSERTONLY:
|
|
eState = m_bInsertOnly ? PropertyState_DIRECT_VALUE : PropertyState_DEFAULT_VALUE;
|
|
break;
|
|
|
|
case PROPERTY_ID_FILTER:
|
|
if ( !m_aFilterManager.getFilterComponent( FilterManager::fcPublicFilter ).getLength() )
|
|
eState = PropertyState_DEFAULT_VALUE;
|
|
else
|
|
eState = PropertyState_DIRECT_VALUE;
|
|
break;
|
|
|
|
case PROPERTY_ID_APPLYFILTER:
|
|
eState = m_aFilterManager.isApplyPublicFilter() ? PropertyState_DEFAULT_VALUE : PropertyState_DIRECT_VALUE;
|
|
break;
|
|
|
|
case PROPERTY_ID_DYNAMIC_CONTROL_BORDER:
|
|
eState = m_aDynamicControlBorder.hasValue() ? PropertyState_DIRECT_VALUE : PropertyState_DEFAULT_VALUE;
|
|
break;
|
|
|
|
case PROPERTY_ID_CONTROL_BORDER_COLOR_FOCUS:
|
|
eState = m_aControlBorderColorFocus.hasValue() ? PropertyState_DIRECT_VALUE : PropertyState_DEFAULT_VALUE;
|
|
break;
|
|
|
|
case PROPERTY_ID_CONTROL_BORDER_COLOR_MOUSE:
|
|
eState = m_aControlBorderColorMouse.hasValue() ? PropertyState_DIRECT_VALUE : PropertyState_DEFAULT_VALUE;
|
|
break;
|
|
|
|
case PROPERTY_ID_CONTROL_BORDER_COLOR_INVALID:
|
|
eState = m_aControlBorderColorInvalid.hasValue() ? PropertyState_DIRECT_VALUE : PropertyState_DEFAULT_VALUE;
|
|
break;
|
|
|
|
default:
|
|
eState = OPropertySetAggregationHelper::getPropertyStateByHandle(nHandle);
|
|
}
|
|
return eState;
|
|
}
|
|
|
|
//------------------------------------------------------------------
|
|
void ODatabaseForm::setPropertyToDefaultByHandle(sal_Int32 nHandle)
|
|
{
|
|
switch (nHandle)
|
|
{
|
|
case PROPERTY_ID_INSERTONLY:
|
|
case PROPERTY_ID_FILTER:
|
|
case PROPERTY_ID_APPLYFILTER:
|
|
case PROPERTY_ID_NAVIGATION:
|
|
case PROPERTY_ID_CYCLE:
|
|
case PROPERTY_ID_DYNAMIC_CONTROL_BORDER:
|
|
case PROPERTY_ID_CONTROL_BORDER_COLOR_FOCUS:
|
|
case PROPERTY_ID_CONTROL_BORDER_COLOR_MOUSE:
|
|
case PROPERTY_ID_CONTROL_BORDER_COLOR_INVALID:
|
|
setFastPropertyValue( nHandle, getPropertyDefaultByHandle( nHandle ) );
|
|
break;
|
|
|
|
default:
|
|
OPropertySetAggregationHelper::setPropertyToDefaultByHandle(nHandle);
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------
|
|
Any ODatabaseForm::getPropertyDefaultByHandle( sal_Int32 nHandle ) const
|
|
{
|
|
Any aReturn;
|
|
switch (nHandle)
|
|
{
|
|
case PROPERTY_ID_INSERTONLY:
|
|
case PROPERTY_ID_DYNAMIC_CONTROL_BORDER:
|
|
aReturn <<= sal_False;
|
|
break;
|
|
|
|
case PROPERTY_ID_FILTER:
|
|
aReturn <<= ::rtl::OUString();
|
|
break;
|
|
|
|
case PROPERTY_ID_APPLYFILTER:
|
|
aReturn <<= sal_True;
|
|
break;
|
|
|
|
case PROPERTY_ID_NAVIGATION:
|
|
aReturn = makeAny(NavigationBarMode_CURRENT);
|
|
break;
|
|
|
|
case PROPERTY_ID_CYCLE:
|
|
case PROPERTY_ID_CONTROL_BORDER_COLOR_FOCUS:
|
|
case PROPERTY_ID_CONTROL_BORDER_COLOR_MOUSE:
|
|
case PROPERTY_ID_CONTROL_BORDER_COLOR_INVALID:
|
|
break;
|
|
|
|
default:
|
|
if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( nHandle ) )
|
|
m_aPropertyBagHelper.getDynamicPropertyDefaultByHandle( nHandle, aReturn );
|
|
else
|
|
aReturn = OPropertySetAggregationHelper::getPropertyDefaultByHandle( nHandle );
|
|
break;
|
|
}
|
|
return aReturn;
|
|
}
|
|
|
|
//==============================================================================
|
|
// com::sun::star::form::XReset
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::reset() throw( RuntimeException )
|
|
{
|
|
::osl::ResettableMutexGuard aGuard(m_aMutex);
|
|
|
|
if (isLoaded())
|
|
{
|
|
::osl::MutexGuard aResetGuard(m_aResetSafety);
|
|
++m_nResetsPending;
|
|
reset_impl(true);
|
|
return;
|
|
}
|
|
|
|
if ( !m_aResetListeners.empty() )
|
|
{
|
|
::osl::MutexGuard aResetGuard(m_aResetSafety);
|
|
++m_nResetsPending;
|
|
// create an own thread if we have (approve-)reset-listeners (so the listeners can't do that much damage
|
|
// to this thread which is probably the main one)
|
|
if (!m_pThread)
|
|
{
|
|
m_pThread = new OFormSubmitResetThread(this);
|
|
m_pThread->acquire();
|
|
m_pThread->create();
|
|
}
|
|
EventObject aEvt;
|
|
m_pThread->addEvent(&aEvt, sal_False);
|
|
}
|
|
else
|
|
{
|
|
// direct call without any approving by the listeners
|
|
aGuard.clear();
|
|
|
|
::osl::MutexGuard aResetGuard(m_aResetSafety);
|
|
++m_nResetsPending;
|
|
reset_impl(false);
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void ODatabaseForm::reset_impl(bool _bAproveByListeners)
|
|
{
|
|
if ( _bAproveByListeners )
|
|
if ( !m_aResetListeners.approveReset() )
|
|
return;
|
|
|
|
::osl::ResettableMutexGuard aResetGuard(m_aResetSafety);
|
|
// do we have a database connected form and stay on the insert row
|
|
sal_Bool bInsertRow = sal_False;
|
|
if (m_xAggregateSet.is())
|
|
bInsertRow = getBOOL(m_xAggregateSet->getPropertyValue(PROPERTY_ISNEW));
|
|
if (bInsertRow)
|
|
{
|
|
try
|
|
{
|
|
// Iterate through all columns and set the default value
|
|
Reference< XColumnsSupplier > xColsSuppl( m_xAggregateSet, UNO_QUERY );
|
|
Reference< XIndexAccess > xIndexCols( xColsSuppl->getColumns(), UNO_QUERY );
|
|
for (sal_Int32 i = 0; i < xIndexCols->getCount(); ++i)
|
|
{
|
|
Reference< XPropertySet > xColProps;
|
|
xIndexCols->getByIndex(i) >>= xColProps;
|
|
|
|
Reference< XColumnUpdate > xColUpdate( xColProps, UNO_QUERY );
|
|
if ( !xColUpdate.is() )
|
|
continue;
|
|
|
|
Reference< XPropertySetInfo > xPSI;
|
|
if ( xColProps.is() )
|
|
xPSI = xColProps->getPropertySetInfo( );
|
|
|
|
static const ::rtl::OUString PROPERTY_CONTROLDEFAULT( RTL_CONSTASCII_USTRINGPARAM( "ControlDefault" ) );
|
|
if ( xPSI.is() && xPSI->hasPropertyByName( PROPERTY_CONTROLDEFAULT ) )
|
|
{
|
|
Any aDefault = xColProps->getPropertyValue( PROPERTY_CONTROLDEFAULT );
|
|
|
|
sal_Bool bReadOnly = sal_False;
|
|
if ( xPSI->hasPropertyByName( PROPERTY_ISREADONLY ) )
|
|
xColProps->getPropertyValue( PROPERTY_ISREADONLY ) >>= bReadOnly;
|
|
|
|
if ( !bReadOnly )
|
|
{
|
|
try
|
|
{
|
|
if ( aDefault.hasValue() )
|
|
xColUpdate->updateObject( aDefault );
|
|
}
|
|
catch(Exception&)
|
|
{
|
|
DBG_UNHANDLED_EXCEPTION();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch(Exception&)
|
|
{
|
|
}
|
|
|
|
if (m_bSubForm)
|
|
{
|
|
Reference< XColumnsSupplier > xParentColSupp( m_xParent, UNO_QUERY );
|
|
Reference< XNameAccess > xParentCols;
|
|
if ( xParentColSupp.is() )
|
|
xParentCols = xParentColSupp->getColumns();
|
|
|
|
if ( xParentCols.is() && xParentCols->hasElements() && m_aMasterFields.getLength() )
|
|
{
|
|
try
|
|
{
|
|
// analyze our parameters
|
|
if ( !m_aParameterManager.isUpToDate() )
|
|
updateParameterInfo();
|
|
|
|
m_aParameterManager.resetParameterValues( );
|
|
}
|
|
catch(const Exception&)
|
|
{
|
|
OSL_ENSURE(sal_False, "ODatabaseForm::reset_impl: could not initialize the master-detail-driven parameters!");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
aResetGuard.clear();
|
|
// iterate through all components. don't use an XIndexAccess as this will cause massive
|
|
// problems with the count.
|
|
Reference<XEnumeration> xIter = createEnumeration();
|
|
while (xIter->hasMoreElements())
|
|
{
|
|
Reference<XReset> xReset;
|
|
xIter->nextElement() >>= xReset;
|
|
if (xReset.is())
|
|
{
|
|
// TODO : all reset-methods have to be thread-safe
|
|
xReset->reset();
|
|
}
|
|
}
|
|
|
|
aResetGuard.reset();
|
|
// ensure that the row isn't modified
|
|
// (do this _before_ the listeners are notified ! their reaction (maybe asynchronous) may depend
|
|
// on the modified state of the row
|
|
// 21.02.00 - 73265 - FS)
|
|
if (bInsertRow)
|
|
m_xAggregateSet->setPropertyValue(PROPERTY_ISMODIFIED, ::cppu::bool2any(sal_Bool(sal_False)));
|
|
|
|
aResetGuard.clear();
|
|
{
|
|
m_aResetListeners.resetted();
|
|
}
|
|
|
|
aResetGuard.reset();
|
|
// and again : ensure the row isn't modified
|
|
// we already did this after we (and maybe our dependents) resetted the values, but the listeners may have changed the row, too
|
|
if (bInsertRow)
|
|
m_xAggregateSet->setPropertyValue(PROPERTY_ISMODIFIED, ::cppu::bool2any((sal_False)));
|
|
|
|
--m_nResetsPending;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::addResetListener(const Reference<XResetListener>& _rListener) throw( RuntimeException )
|
|
{
|
|
m_aResetListeners.addTypedListener( _rListener );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::removeResetListener(const Reference<XResetListener>& _rListener) throw( RuntimeException )
|
|
{
|
|
m_aResetListeners.removeTypedListener( _rListener );
|
|
}
|
|
|
|
//==============================================================================
|
|
// com::sun::star::form::XSubmit
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::submit( const Reference<XControl>& Control,
|
|
const ::com::sun::star::awt::MouseEvent& MouseEvt ) throw( RuntimeException )
|
|
{
|
|
{
|
|
::osl::MutexGuard aGuard(m_aMutex);
|
|
// Sind Controls und eine Submit-URL vorhanden?
|
|
if( !getCount() || !m_aTargetURL.getLength() )
|
|
return;
|
|
}
|
|
|
|
::osl::ClearableMutexGuard aGuard(m_aMutex);
|
|
if (m_aSubmitListeners.getLength())
|
|
{
|
|
// create an own thread if we have (approve-)submit-listeners (so the listeners can't do that much damage
|
|
// to this thread which is probably the main one)
|
|
if (!m_pThread)
|
|
{
|
|
m_pThread = new OFormSubmitResetThread(this);
|
|
m_pThread->acquire();
|
|
m_pThread->create();
|
|
}
|
|
m_pThread->addEvent(&MouseEvt, Control, sal_True);
|
|
}
|
|
else
|
|
{
|
|
// direct call without any approving by the listeners
|
|
aGuard.clear();
|
|
submit_impl( Control, MouseEvt, true );
|
|
}
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
void lcl_dispatch(const Reference< XFrame >& xFrame,const Reference<XURLTransformer>& xTransformer,const ::rtl::OUString& aURLStr,const ::rtl::OUString& aReferer,const ::rtl::OUString& aTargetName
|
|
,const ::rtl::OUString& aData,rtl_TextEncoding _eEncoding)
|
|
{
|
|
URL aURL;
|
|
aURL.Complete = aURLStr;
|
|
xTransformer->parseStrict(aURL);
|
|
|
|
Reference< XDispatch > xDisp = Reference< XDispatchProvider > (xFrame,UNO_QUERY)->queryDispatch(aURL, aTargetName,
|
|
FrameSearchFlag::SELF | FrameSearchFlag::PARENT | FrameSearchFlag::CHILDREN |
|
|
FrameSearchFlag::SIBLINGS | FrameSearchFlag::CREATE | FrameSearchFlag::TASKS);
|
|
|
|
if (xDisp.is())
|
|
{
|
|
Sequence<PropertyValue> aArgs(2);
|
|
aArgs.getArray()[0].Name = ::rtl::OUString::createFromAscii("Referer");
|
|
aArgs.getArray()[0].Value <<= aReferer;
|
|
|
|
// build a sequence from the to-be-submitted string
|
|
ByteString a8BitData(aData.getStr(), (sal_uInt16)aData.getLength(), _eEncoding);
|
|
// always ANSI #58641
|
|
Sequence< sal_Int8 > aPostData((sal_Int8*)a8BitData.GetBuffer(), a8BitData.Len());
|
|
Reference< XInputStream > xPostData = new SequenceInputStream(aPostData);
|
|
|
|
aArgs.getArray()[1].Name = ::rtl::OUString::createFromAscii("PostData");
|
|
aArgs.getArray()[1].Value <<= xPostData;
|
|
|
|
xDisp->dispatch(aURL, aArgs);
|
|
} // if (xDisp.is())
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
void ODatabaseForm::submit_impl(const Reference<XControl>& Control, const ::com::sun::star::awt::MouseEvent& MouseEvt, bool _bAproveByListeners)
|
|
{
|
|
|
|
if (_bAproveByListeners)
|
|
{
|
|
::cppu::OInterfaceIteratorHelper aIter(m_aSubmitListeners);
|
|
EventObject aEvt(static_cast<XWeak*>(this));
|
|
sal_Bool bCanceled = sal_False;
|
|
while (aIter.hasMoreElements() && !bCanceled)
|
|
{
|
|
if (!((XSubmitListener*)aIter.next())->approveSubmit(aEvt))
|
|
bCanceled = sal_True;
|
|
}
|
|
|
|
if (bCanceled)
|
|
return;
|
|
}
|
|
|
|
FormSubmitEncoding eSubmitEncoding;
|
|
FormSubmitMethod eSubmitMethod;
|
|
::rtl::OUString aURLStr;
|
|
::rtl::OUString aReferer;
|
|
::rtl::OUString aTargetName;
|
|
Reference< XModel > xModel;
|
|
{
|
|
::vos::OGuard aGuard( Application::GetSolarMutex() );
|
|
// starform->Forms
|
|
|
|
Reference<XChild> xParent(m_xParent, UNO_QUERY);
|
|
|
|
if (xParent.is())
|
|
xModel = getXModel(xParent->getParent());
|
|
|
|
if (xModel.is())
|
|
aReferer = xModel->getURL();
|
|
|
|
// TargetItem
|
|
aTargetName = m_aTargetFrame;
|
|
|
|
eSubmitEncoding = m_eSubmitEncoding;
|
|
eSubmitMethod = m_eSubmitMethod;
|
|
aURLStr = m_aTargetURL;
|
|
}
|
|
|
|
if (!xModel.is())
|
|
return;
|
|
Reference< XFrame > xFrame = xModel->getCurrentController()->getFrame();
|
|
if (!xFrame.is())
|
|
return;
|
|
|
|
Reference<XURLTransformer>
|
|
xTransformer(m_xServiceFactory->createInstance(
|
|
::rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer")), UNO_QUERY);
|
|
DBG_ASSERT(xTransformer.is(), "ODatabaseForm::submit_impl : could not create an URL transformer !");
|
|
|
|
// URL-Encoding
|
|
if( eSubmitEncoding == FormSubmitEncoding_URL )
|
|
{
|
|
::rtl::OUString aData;
|
|
{
|
|
::vos::OGuard aGuard( Application::GetSolarMutex() );
|
|
aData = GetDataURLEncoded( Control, MouseEvt );
|
|
}
|
|
|
|
URL aURL;
|
|
// FormMethod GET
|
|
if( eSubmitMethod == FormSubmitMethod_GET )
|
|
{
|
|
INetURLObject aUrlObj( aURLStr, INetURLObject::WAS_ENCODED );
|
|
aUrlObj.SetParam( aData, INetURLObject::ENCODE_ALL );
|
|
aURL.Complete = aUrlObj.GetMainURL( INetURLObject::DECODE_UNAMBIGUOUS );
|
|
if (xTransformer.is())
|
|
xTransformer->parseStrict(aURL);
|
|
|
|
Reference< XDispatch > xDisp = Reference< XDispatchProvider > (xFrame,UNO_QUERY)->queryDispatch(aURL, aTargetName,
|
|
FrameSearchFlag::SELF | FrameSearchFlag::PARENT | FrameSearchFlag::CHILDREN |
|
|
FrameSearchFlag::SIBLINGS | FrameSearchFlag::CREATE | FrameSearchFlag::TASKS);
|
|
|
|
if (xDisp.is())
|
|
{
|
|
Sequence<PropertyValue> aArgs(1);
|
|
aArgs.getArray()->Name = ::rtl::OUString::createFromAscii("Referer");
|
|
aArgs.getArray()->Value <<= aReferer;
|
|
xDisp->dispatch(aURL, aArgs);
|
|
}
|
|
}
|
|
// FormMethod POST
|
|
else if( eSubmitMethod == FormSubmitMethod_POST )
|
|
{
|
|
lcl_dispatch(xFrame,xTransformer,aURLStr,aReferer,aTargetName,aData,RTL_TEXTENCODING_MS_1252);
|
|
}
|
|
}
|
|
else if( eSubmitEncoding == FormSubmitEncoding_MULTIPART )
|
|
{
|
|
URL aURL;
|
|
aURL.Complete = aURLStr;
|
|
xTransformer->parseStrict(aURL);
|
|
|
|
Reference< XDispatch > xDisp = Reference< XDispatchProvider > (xFrame,UNO_QUERY)->queryDispatch(aURL, aTargetName,
|
|
FrameSearchFlag::SELF | FrameSearchFlag::PARENT | FrameSearchFlag::CHILDREN |
|
|
FrameSearchFlag::SIBLINGS | FrameSearchFlag::CREATE | FrameSearchFlag::TASKS);
|
|
|
|
if (xDisp.is())
|
|
{
|
|
::rtl::OUString aContentType;
|
|
Sequence<sal_Int8> aData;
|
|
{
|
|
::vos::OGuard aGuard( Application::GetSolarMutex() );
|
|
aData = GetDataMultiPartEncoded(Control, MouseEvt, aContentType);
|
|
}
|
|
if (!aData.getLength())
|
|
return;
|
|
|
|
Sequence<PropertyValue> aArgs(3);
|
|
aArgs.getArray()[0].Name = ::rtl::OUString::createFromAscii("Referer");
|
|
aArgs.getArray()[0].Value <<= aReferer;
|
|
aArgs.getArray()[1].Name = ::rtl::OUString::createFromAscii("ContentType");
|
|
aArgs.getArray()[1].Value <<= aContentType;
|
|
|
|
// build a sequence from the to-be-submitted string
|
|
Reference< XInputStream > xPostData = new SequenceInputStream(aData);
|
|
|
|
aArgs.getArray()[2].Name = ::rtl::OUString::createFromAscii("PostData");
|
|
aArgs.getArray()[2].Value <<= xPostData;
|
|
|
|
xDisp->dispatch(aURL, aArgs);
|
|
}
|
|
}
|
|
else if( eSubmitEncoding == FormSubmitEncoding_TEXT )
|
|
{
|
|
::rtl::OUString aData;
|
|
{
|
|
::vos::OGuard aGuard( Application::GetSolarMutex() );
|
|
aData = GetDataTextEncoded( Reference<XControl> (), MouseEvt );
|
|
}
|
|
|
|
lcl_dispatch(xFrame,xTransformer,aURLStr,aReferer,aTargetName,aData,osl_getThreadTextEncoding());
|
|
}
|
|
else {
|
|
DBG_ERROR("ODatabaseForm::submit_Impl : wrong encoding !");
|
|
}
|
|
|
|
}
|
|
|
|
// XSubmit
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::addSubmitListener(const Reference<XSubmitListener>& _rListener) throw( RuntimeException )
|
|
{
|
|
m_aSubmitListeners.addInterface(_rListener);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::removeSubmitListener(const Reference<XSubmitListener>& _rListener) throw( RuntimeException )
|
|
{
|
|
m_aSubmitListeners.removeInterface(_rListener);
|
|
}
|
|
|
|
//==============================================================================
|
|
// com::sun::star::sdbc::XSQLErrorBroadcaster
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::addSQLErrorListener(const Reference<XSQLErrorListener>& _rListener) throw( RuntimeException )
|
|
{
|
|
m_aErrorListeners.addInterface(_rListener);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::removeSQLErrorListener(const Reference<XSQLErrorListener>& _rListener) throw( RuntimeException )
|
|
{
|
|
m_aErrorListeners.removeInterface(_rListener);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void ODatabaseForm::invlidateParameters()
|
|
{
|
|
::osl::MutexGuard aGuard(m_aMutex);
|
|
m_aParameterManager.clearAllParameterInformation();
|
|
}
|
|
|
|
//==============================================================================
|
|
// OChangeListener
|
|
//------------------------------------------------------------------------------
|
|
void ODatabaseForm::_propertyChanged(const PropertyChangeEvent& evt) throw( RuntimeException )
|
|
{
|
|
if ((0 == evt.PropertyName.compareToAscii(PROPERTY_ACTIVE_CONNECTION)) && !m_bForwardingConnection)
|
|
{
|
|
// the rowset changed its active connection itself (without interaction from our side), so
|
|
// we need to fire this event, too
|
|
sal_Int32 nHandle = PROPERTY_ID_ACTIVE_CONNECTION;
|
|
fire(&nHandle, &evt.NewValue, &evt.OldValue, 1, sal_False);
|
|
}
|
|
else // it was one of the statement relevant props
|
|
{
|
|
// if the statement has changed we have to delete the parameter info
|
|
invlidateParameters();
|
|
}
|
|
}
|
|
|
|
//==============================================================================
|
|
// smartXChild
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::setParent(const InterfaceRef& Parent) throw ( ::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException)
|
|
{
|
|
::osl::ResettableMutexGuard aGuard(m_aMutex);
|
|
|
|
Reference<XForm> xParentForm(getParent(), UNO_QUERY);
|
|
if (xParentForm.is())
|
|
{
|
|
try
|
|
{
|
|
Reference< XRowSetApproveBroadcaster > xParentApprBroadcast( xParentForm, UNO_QUERY_THROW );
|
|
xParentApprBroadcast->removeRowSetApproveListener( this );
|
|
|
|
Reference< XLoadable > xParentLoadable( xParentForm, UNO_QUERY_THROW );
|
|
xParentLoadable->removeLoadListener( this );
|
|
|
|
Reference< XPropertySet > xParentProperties( xParentForm, UNO_QUERY_THROW );
|
|
xParentProperties->removePropertyChangeListener( PROPERTY_ISNEW, this );
|
|
}
|
|
catch( const Exception& )
|
|
{
|
|
DBG_UNHANDLED_EXCEPTION();
|
|
}
|
|
}
|
|
|
|
OFormComponents::setParent(Parent);
|
|
|
|
xParentForm.set(getParent(), UNO_QUERY);
|
|
if ( xParentForm.is() )
|
|
{
|
|
try
|
|
{
|
|
Reference< XRowSetApproveBroadcaster > xParentApprBroadcast( xParentForm, UNO_QUERY_THROW );
|
|
xParentApprBroadcast->addRowSetApproveListener( this );
|
|
|
|
Reference< XLoadable > xParentLoadable( xParentForm, UNO_QUERY_THROW );
|
|
xParentLoadable->addLoadListener( this );
|
|
|
|
Reference< XPropertySet > xParentProperties( xParentForm, UNO_QUERY_THROW );
|
|
xParentProperties->addPropertyChangeListener( PROPERTY_ISNEW, this );
|
|
}
|
|
catch( const Exception& )
|
|
{
|
|
DBG_UNHANDLED_EXCEPTION();
|
|
}
|
|
}
|
|
|
|
Reference< XConnection > xOuterConnection;
|
|
sal_Bool bIsEmbedded = ::dbtools::isEmbeddedInDatabase( Parent, xOuterConnection );
|
|
|
|
// clear the guard before setting property values, because of the notifications
|
|
// which are triggered there
|
|
aGuard.clear();
|
|
if ( bIsEmbedded )
|
|
m_xAggregateSet->setPropertyValue( PROPERTY_DATASOURCE, makeAny( ::rtl::OUString() ) );
|
|
}
|
|
|
|
//==============================================================================
|
|
// smartXTabControllerModel
|
|
//------------------------------------------------------------------------------
|
|
sal_Bool SAL_CALL ODatabaseForm::getGroupControl() throw(com::sun::star::uno::RuntimeException)
|
|
{
|
|
::osl::ResettableMutexGuard aGuard(m_aMutex);
|
|
|
|
// Sollen Controls in einer TabOrder gruppe zusammengefasst werden?
|
|
if (m_aCycle.hasValue())
|
|
{
|
|
sal_Int32 nCycle = 0;
|
|
::cppu::enum2int(nCycle, m_aCycle);
|
|
return nCycle != TabulatorCycle_PAGE;
|
|
}
|
|
|
|
if (isLoaded() && getConnection().is())
|
|
return sal_True;
|
|
|
|
return sal_False;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::setControlModels(const Sequence<Reference<XControlModel> >& rControls) throw( RuntimeException )
|
|
{
|
|
::osl::ResettableMutexGuard aGuard(m_aMutex);
|
|
|
|
// TabIndex in der Reihenfolge der Sequence setzen
|
|
const Reference<XControlModel>* pControls = rControls.getConstArray();
|
|
sal_Int16 nTabIndex = 1;
|
|
sal_Int32 nCount = getCount();
|
|
sal_Int32 nNewCount = rControls.getLength();
|
|
|
|
// HiddenControls und Formulare werden nicht aufgefuehrt
|
|
if (nNewCount <= nCount)
|
|
{
|
|
Any aElement;
|
|
for (sal_Int32 i=0; i < nNewCount; ++i, ++pControls)
|
|
{
|
|
Reference<XFormComponent> xComp(*pControls, UNO_QUERY);
|
|
if (xComp.is())
|
|
{
|
|
// suchen der Componente in der Liste
|
|
for (sal_Int32 j = 0; j < nCount; ++j)
|
|
{
|
|
Reference<XFormComponent> xElement;
|
|
::cppu::extractInterface(xElement, getByIndex(j));
|
|
if (xComp == xElement)
|
|
{
|
|
Reference<XPropertySet> xSet(xComp, UNO_QUERY);
|
|
if (xSet.is() && hasProperty(PROPERTY_TABINDEX, xSet))
|
|
xSet->setPropertyValue( PROPERTY_TABINDEX, makeAny(nTabIndex++) );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
Sequence<Reference<XControlModel> > SAL_CALL ODatabaseForm::getControlModels() throw( RuntimeException )
|
|
{
|
|
::osl::MutexGuard aGuard(m_aMutex);
|
|
return m_pGroupManager->getControlModels();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::setGroup( const Sequence<Reference<XControlModel> >& _rGroup, const ::rtl::OUString& Name ) throw( RuntimeException )
|
|
{
|
|
::osl::MutexGuard aGuard(m_aMutex);
|
|
|
|
// Die Controls werden gruppiert, indem ihr Name dem Namen des ersten
|
|
// Controls der Sequenz angepasst wird
|
|
const Reference<XControlModel>* pControls = _rGroup.getConstArray();
|
|
Reference< XPropertySet > xSet;
|
|
::rtl::OUString sGroupName( Name );
|
|
|
|
for( sal_Int32 i=0; i<_rGroup.getLength(); ++i, ++pControls )
|
|
{
|
|
xSet = xSet.query( *pControls );
|
|
if ( !xSet.is() )
|
|
{
|
|
// can't throw an exception other than a RuntimeException (which would not be appropriate),
|
|
// so we ignore (and only assert) this
|
|
OSL_ENSURE( sal_False, "ODatabaseForm::setGroup: invalid arguments!" );
|
|
continue;
|
|
}
|
|
|
|
if (!sGroupName.getLength())
|
|
xSet->getPropertyValue(PROPERTY_NAME) >>= sGroupName;
|
|
else
|
|
xSet->setPropertyValue(PROPERTY_NAME, makeAny(sGroupName));
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
sal_Int32 SAL_CALL ODatabaseForm::getGroupCount() throw( RuntimeException )
|
|
{
|
|
::osl::MutexGuard aGuard(m_aMutex);
|
|
return m_pGroupManager->getGroupCount();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::getGroup( sal_Int32 nGroup, Sequence<Reference<XControlModel> >& _rGroup, ::rtl::OUString& _rName ) throw( RuntimeException )
|
|
{
|
|
::osl::MutexGuard aGuard(m_aMutex);
|
|
_rGroup.realloc(0);
|
|
_rName = ::rtl::OUString();
|
|
|
|
if ((nGroup < 0) || (nGroup >= m_pGroupManager->getGroupCount()))
|
|
return;
|
|
m_pGroupManager->getGroup( nGroup, _rGroup, _rName );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::getGroupByName(const ::rtl::OUString& Name, Sequence< Reference<XControlModel> >& _rGroup) throw( RuntimeException )
|
|
{
|
|
::osl::MutexGuard aGuard(m_aMutex);
|
|
_rGroup.realloc(0);
|
|
m_pGroupManager->getGroupByName( Name, _rGroup );
|
|
}
|
|
|
|
//==============================================================================
|
|
// com::sun::star::lang::XEventListener
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::disposing(const EventObject& Source) throw( RuntimeException )
|
|
{
|
|
// does the call come from the connection which we are sharing with our parent?
|
|
if ( isSharingConnection() )
|
|
{
|
|
Reference< XConnection > xConnSource( Source.Source, UNO_QUERY );
|
|
if ( xConnSource.is() )
|
|
{
|
|
#if OSL_DEBUG_LEVEL > 0
|
|
Reference< XConnection > xActiveConn;
|
|
m_xAggregateSet->getPropertyValue( PROPERTY_ACTIVE_CONNECTION ) >>= xActiveConn;
|
|
OSL_ENSURE( xActiveConn.get() == xConnSource.get(), "ODatabaseForm::disposing: where did this come from?" );
|
|
// there should be exactly one XConnection object we're listening at - our aggregate connection
|
|
#endif
|
|
disposingSharedConnection( xConnSource );
|
|
}
|
|
}
|
|
|
|
OInterfaceContainer::disposing(Source);
|
|
|
|
// does the disposing come from the aggregate ?
|
|
if (m_xAggregate.is())
|
|
{ // no -> forward it
|
|
com::sun::star::uno::Reference<com::sun::star::lang::XEventListener> xListener;
|
|
if (query_aggregation(m_xAggregate, xListener))
|
|
xListener->disposing(Source);
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void ODatabaseForm::impl_createLoadTimer()
|
|
{
|
|
OSL_PRECOND( m_pLoadTimer == NULL, "ODatabaseForm::impl_createLoadTimer: timer already exists!" );
|
|
m_pLoadTimer = new Timer();
|
|
m_pLoadTimer->SetTimeout(100);
|
|
m_pLoadTimer->SetTimeoutHdl(LINK(this,ODatabaseForm,OnTimeout));
|
|
}
|
|
|
|
//==============================================================================
|
|
// com::sun::star::form::XLoadListener
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::loaded(const EventObject& /*aEvent*/) throw( RuntimeException )
|
|
{
|
|
// now start the rowset listening to recover cursor events
|
|
load_impl(sal_True);
|
|
{
|
|
::osl::MutexGuard aGuard(m_aMutex);
|
|
Reference<XRowSet> xParentRowSet(m_xParent, UNO_QUERY);
|
|
if (xParentRowSet.is())
|
|
xParentRowSet->addRowSetListener(this);
|
|
|
|
impl_createLoadTimer();
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::unloading(const EventObject& /*aEvent*/) throw( RuntimeException )
|
|
{
|
|
{
|
|
// now stop the rowset listening if we are a subform
|
|
::osl::MutexGuard aGuard(m_aMutex);
|
|
DELETEZ(m_pLoadTimer);
|
|
|
|
Reference<XRowSet> xParentRowSet(m_xParent, UNO_QUERY);
|
|
if (xParentRowSet.is())
|
|
xParentRowSet->removeRowSetListener(this);
|
|
}
|
|
|
|
unload();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::unloaded(const EventObject& /*aEvent*/) throw( RuntimeException )
|
|
{
|
|
// nothing to do
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::reloading(const EventObject& /*aEvent*/) throw( RuntimeException )
|
|
{
|
|
// now stop the rowset listening if we are a subform
|
|
::osl::MutexGuard aGuard(m_aMutex);
|
|
Reference<XRowSet> xParentRowSet(m_xParent, UNO_QUERY);
|
|
if (xParentRowSet.is())
|
|
xParentRowSet->removeRowSetListener(this);
|
|
|
|
if (m_pLoadTimer && m_pLoadTimer->IsActive())
|
|
m_pLoadTimer->Stop();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::reloaded(const EventObject& /*aEvent*/) throw( RuntimeException )
|
|
{
|
|
reload_impl(sal_True);
|
|
{
|
|
::osl::MutexGuard aGuard(m_aMutex);
|
|
Reference<XRowSet> xParentRowSet(m_xParent, UNO_QUERY);
|
|
if (xParentRowSet.is())
|
|
xParentRowSet->addRowSetListener(this);
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
IMPL_LINK( ODatabaseForm, OnTimeout, void*, EMPTYARG )
|
|
{
|
|
reload_impl(sal_True);
|
|
return 1;
|
|
}
|
|
|
|
//==============================================================================
|
|
// com::sun::star::form::XLoadable
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::load() throw( RuntimeException )
|
|
{
|
|
load_impl(sal_False);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
sal_Bool ODatabaseForm::canShareConnection( const Reference< XPropertySet >& _rxParentProps )
|
|
{
|
|
// our own data source
|
|
::rtl::OUString sOwnDatasource;
|
|
m_xAggregateSet->getPropertyValue( PROPERTY_DATASOURCE ) >>= sOwnDatasource;
|
|
|
|
// our parents data source
|
|
::rtl::OUString sParentDataSource;
|
|
OSL_ENSURE( _rxParentProps.is() && _rxParentProps->getPropertySetInfo().is() && _rxParentProps->getPropertySetInfo()->hasPropertyByName( PROPERTY_DATASOURCE ),
|
|
"ODatabaseForm::doShareConnection: invalid parent form!" );
|
|
if ( _rxParentProps.is() )
|
|
_rxParentProps->getPropertyValue( PROPERTY_DATASOURCE ) >>= sParentDataSource;
|
|
|
|
sal_Bool bCanShareConnection = sal_False;
|
|
|
|
// both rowsets share are connected to the same data source
|
|
if ( sParentDataSource == sOwnDatasource )
|
|
{
|
|
if ( 0 != sParentDataSource.getLength() )
|
|
// and it's really a data source name (not empty)
|
|
bCanShareConnection = sal_True;
|
|
else
|
|
{ // the data source name is empty
|
|
// -> ook for the URL
|
|
::rtl::OUString sParentURL;
|
|
::rtl::OUString sMyURL;
|
|
_rxParentProps->getPropertyValue( PROPERTY_URL ) >>= sParentURL;
|
|
m_xAggregateSet->getPropertyValue( PROPERTY_URL ) >>= sMyURL;
|
|
|
|
bCanShareConnection = (sParentURL == sMyURL);
|
|
}
|
|
}
|
|
|
|
if ( bCanShareConnection )
|
|
{
|
|
// check for the user/password
|
|
|
|
// take the user property on the rowset (if any) into account
|
|
::rtl::OUString sParentUser, sParentPwd;
|
|
_rxParentProps->getPropertyValue( PROPERTY_USER ) >>= sParentUser;
|
|
_rxParentProps->getPropertyValue( PROPERTY_PASSWORD ) >>= sParentPwd;
|
|
|
|
::rtl::OUString sMyUser, sMyPwd;
|
|
m_xAggregateSet->getPropertyValue( PROPERTY_USER ) >>= sMyUser;
|
|
m_xAggregateSet->getPropertyValue( PROPERTY_PASSWORD ) >>= sMyPwd;
|
|
|
|
bCanShareConnection =
|
|
( sParentUser == sMyUser )
|
|
&& ( sParentPwd == sMyPwd );
|
|
}
|
|
|
|
return bCanShareConnection;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void ODatabaseForm::doShareConnection( const Reference< XPropertySet >& _rxParentProps )
|
|
{
|
|
// get the conneciton of the parent
|
|
Reference< XConnection > xParentConn;
|
|
_rxParentProps->getPropertyValue( PROPERTY_ACTIVE_CONNECTION ) >>= xParentConn;
|
|
OSL_ENSURE( xParentConn.is(), "ODatabaseForm::doShareConnection: we're a valid sub-form, but the parent has no connection?!" );
|
|
|
|
if ( xParentConn.is() )
|
|
{
|
|
// add as dispose listener to the connection
|
|
Reference< XComponent > xParentConnComp( xParentConn, UNO_QUERY );
|
|
OSL_ENSURE( xParentConnComp.is(), "ODatabaseForm::doShareConnection: invalid connection!" );
|
|
xParentConnComp->addEventListener( static_cast< XLoadListener* >( this ) );
|
|
|
|
// forward the connection to our own aggreagte
|
|
m_bForwardingConnection = sal_True;
|
|
m_xAggregateSet->setPropertyValue( PROPERTY_ACTIVE_CONNECTION, makeAny( xParentConn ) );
|
|
m_bForwardingConnection = sal_False;
|
|
|
|
m_bSharingConnection = sal_True;
|
|
}
|
|
else
|
|
m_bSharingConnection = sal_False;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void ODatabaseForm::disposingSharedConnection( const Reference< XConnection >& /*_rxConn*/ )
|
|
{
|
|
stopSharingConnection();
|
|
|
|
// TODO: we could think about whether or not to re-connect.
|
|
unload( );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void ODatabaseForm::stopSharingConnection( )
|
|
{
|
|
OSL_ENSURE( m_bSharingConnection, "ODatabaseForm::stopSharingConnection: invalid call!" );
|
|
|
|
if ( m_bSharingConnection )
|
|
{
|
|
// get the connection
|
|
Reference< XConnection > xSharedConn;
|
|
m_xAggregateSet->getPropertyValue( PROPERTY_ACTIVE_CONNECTION ) >>= xSharedConn;
|
|
OSL_ENSURE( xSharedConn.is(), "ODatabaseForm::stopSharingConnection: there's no conn!" );
|
|
|
|
// remove ourself as event listener
|
|
Reference< XComponent > xSharedConnComp( xSharedConn, UNO_QUERY );
|
|
if ( xSharedConnComp.is() )
|
|
xSharedConnComp->removeEventListener( static_cast< XLoadListener* >( this ) );
|
|
|
|
// no need to dispose the conn: we're not the owner, this is our parent
|
|
// (in addition, this method may be called if the connection is beeing disposed while we use it)
|
|
|
|
// reset the property
|
|
xSharedConn.clear();
|
|
m_bForwardingConnection = sal_True;
|
|
m_xAggregateSet->setPropertyValue( PROPERTY_ACTIVE_CONNECTION, makeAny( xSharedConn ) );
|
|
m_bForwardingConnection = sal_False;
|
|
|
|
// reset the flag
|
|
m_bSharingConnection = sal_False;
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
sal_Bool ODatabaseForm::implEnsureConnection()
|
|
{
|
|
try
|
|
{
|
|
if ( getConnection( ).is() )
|
|
// if our aggregate already has a connection, nothing needs to be done about it
|
|
return sal_True;
|
|
|
|
// see whether we're an embedded form
|
|
Reference< XConnection > xOuterConnection;
|
|
if ( ::dbtools::isEmbeddedInDatabase( getParent(), xOuterConnection ) )
|
|
{
|
|
m_xAggregateSet->setPropertyValue( PROPERTY_ACTIVE_CONNECTION, makeAny( xOuterConnection ) );
|
|
return xOuterConnection.is();
|
|
}
|
|
|
|
m_bSharingConnection = sal_False;
|
|
|
|
// if we're a sub form, we try to re-use the connection of our parent
|
|
if (m_bSubForm)
|
|
{
|
|
OSL_ENSURE( Reference< XForm >( getParent(), UNO_QUERY ).is(),
|
|
"ODatabaseForm::implEnsureConnection: m_bSubForm is TRUE, but the parent is no form?" );
|
|
|
|
Reference< XPropertySet > xParentProps( getParent(), UNO_QUERY );
|
|
|
|
// can we re-use (aka share) the connection of the parent?
|
|
if ( canShareConnection( xParentProps ) )
|
|
{
|
|
// yep -> do it
|
|
doShareConnection( xParentProps );
|
|
// success?
|
|
if ( m_bSharingConnection )
|
|
// yes -> outta here
|
|
return sal_True;
|
|
}
|
|
}
|
|
|
|
if (m_xAggregateSet.is())
|
|
{
|
|
Reference< XConnection > xConnection = connectRowset(
|
|
Reference<XRowSet> (m_xAggregate, UNO_QUERY),
|
|
m_xServiceFactory,
|
|
sal_True // set a calculated connection as ActiveConnection
|
|
);
|
|
return xConnection.is();
|
|
}
|
|
}
|
|
catch(SQLException& eDB)
|
|
{
|
|
onError(eDB, FRM_RES_STRING(RID_STR_CONNECTERROR));
|
|
}
|
|
catch( Exception )
|
|
{
|
|
DBG_ERROR( "ODatabaseForm::implEnsureConnection: caught an exception which I cannot handle!" );
|
|
}
|
|
|
|
return sal_False;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void ODatabaseForm::load_impl(sal_Bool bCausedByParentForm, sal_Bool bMoveToFirst, const Reference< XInteractionHandler >& _rxCompletionHandler ) throw( RuntimeException )
|
|
{
|
|
::osl::ResettableMutexGuard aGuard(m_aMutex);
|
|
|
|
// are we already loaded?
|
|
if (isLoaded())
|
|
return;
|
|
|
|
m_bSubForm = bCausedByParentForm;
|
|
|
|
// if we don't have a connection, we are not intended to be a database form or the aggregate was not able
|
|
// to establish a connection
|
|
sal_Bool bConnected = implEnsureConnection();
|
|
|
|
// we don't have to execute if we do not have a command to execute
|
|
sal_Bool bExecute = bConnected && m_xAggregateSet.is() && getString(m_xAggregateSet->getPropertyValue(PROPERTY_COMMAND)).getLength();
|
|
|
|
// a database form always uses caching
|
|
// we use starting fetchsize with at least 10 rows
|
|
if (bConnected)
|
|
m_xAggregateSet->setPropertyValue(PROPERTY_FETCHSIZE, makeAny((sal_Int32)10));
|
|
|
|
// if we're loaded as sub form we got a "rowSetChanged" from the parent rowset _before_ we got the "loaded"
|
|
// so we don't need to execute the statement again, this was already done
|
|
// (and there were no relevant changes between these two listener calls, the "load" of a form is quite an
|
|
// atomar operation.)
|
|
|
|
sal_Bool bSuccess = sal_False;
|
|
if (bExecute)
|
|
{
|
|
m_sCurrentErrorContext = FRM_RES_STRING(RID_ERR_LOADING_FORM);
|
|
bSuccess = executeRowSet(aGuard, bMoveToFirst, _rxCompletionHandler);
|
|
}
|
|
|
|
if (bSuccess)
|
|
{
|
|
m_bLoaded = sal_True;
|
|
aGuard.clear();
|
|
EventObject aEvt(static_cast<XWeak*>(this));
|
|
m_aLoadListeners.notifyEach( &XLoadListener::loaded, aEvt );
|
|
|
|
// if we are on the insert row, we have to reset all controls
|
|
// to set the default values
|
|
if (bExecute && getBOOL(m_xAggregateSet->getPropertyValue(PROPERTY_ISNEW)))
|
|
reset();
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::unload() throw( RuntimeException )
|
|
{
|
|
::osl::ResettableMutexGuard aGuard(m_aMutex);
|
|
if (!isLoaded())
|
|
return;
|
|
|
|
DELETEZ(m_pLoadTimer);
|
|
|
|
aGuard.clear();
|
|
EventObject aEvt(static_cast<XWeak*>(this));
|
|
m_aLoadListeners.notifyEach( &XLoadListener::unloading, aEvt );
|
|
|
|
if (m_xAggregateAsRowSet.is())
|
|
{
|
|
// we may have reset the InsertOnly property on the aggregate - restore it
|
|
restoreInsertOnlyState( );
|
|
|
|
// clear the parameters if there are any
|
|
invlidateParameters();
|
|
|
|
try
|
|
{
|
|
// close the aggregate
|
|
Reference<XCloseable> xCloseable;
|
|
query_aggregation( m_xAggregate, xCloseable);
|
|
aGuard.clear();
|
|
if (xCloseable.is())
|
|
xCloseable->close();
|
|
}
|
|
catch( const SQLException& e )
|
|
{
|
|
(void)e;
|
|
}
|
|
aGuard.reset();
|
|
}
|
|
|
|
m_bLoaded = sal_False;
|
|
|
|
// if the connection we used while we were loaded is only shared with our parent, we
|
|
// reset it
|
|
if ( isSharingConnection() )
|
|
stopSharingConnection();
|
|
|
|
aGuard.clear();
|
|
m_aLoadListeners.notifyEach( &XLoadListener::unloaded, aEvt );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::reload() throw( RuntimeException )
|
|
{
|
|
reload_impl(sal_True);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void ODatabaseForm::reload_impl(sal_Bool bMoveToFirst, const Reference< XInteractionHandler >& _rxCompletionHandler ) throw( RuntimeException )
|
|
{
|
|
::osl::ResettableMutexGuard aGuard(m_aMutex);
|
|
if (!isLoaded())
|
|
return;
|
|
|
|
DocumentModifyGuard aModifyGuard( *this );
|
|
// ensures the document is not marked as "modified" just because we change some control's content during
|
|
// reloading ...
|
|
|
|
EventObject aEvent(static_cast<XWeak*>(this));
|
|
{
|
|
// only if there is no approve listener we can post the event at this time
|
|
// otherwise see approveRowsetChange
|
|
// the aprrovement is done by the aggregate
|
|
if (!m_aRowSetApproveListeners.getLength())
|
|
{
|
|
::cppu::OInterfaceIteratorHelper aIter(m_aLoadListeners);
|
|
aGuard.clear();
|
|
|
|
while (aIter.hasMoreElements())
|
|
((XLoadListener*)aIter.next())->reloading(aEvent);
|
|
|
|
aGuard.reset();
|
|
}
|
|
}
|
|
|
|
sal_Bool bSuccess = sal_True;
|
|
try
|
|
{
|
|
m_sCurrentErrorContext = FRM_RES_STRING(RID_ERR_REFRESHING_FORM);
|
|
bSuccess = executeRowSet(aGuard, bMoveToFirst, _rxCompletionHandler);
|
|
}
|
|
catch( const SQLException& e )
|
|
{
|
|
DBG_ERROR("ODatabaseForm::reload_impl : shouldn't executeRowSet catch this exception?");
|
|
(void)e;
|
|
}
|
|
|
|
if (bSuccess)
|
|
{
|
|
::cppu::OInterfaceIteratorHelper aIter(m_aLoadListeners);
|
|
aGuard.clear();
|
|
while (aIter.hasMoreElements())
|
|
((XLoadListener*)aIter.next())->reloaded(aEvent);
|
|
|
|
// if we are on the insert row, we have to reset all controls
|
|
// to set the default values
|
|
if (getBOOL(m_xAggregateSet->getPropertyValue(PROPERTY_ISNEW)))
|
|
reset();
|
|
}
|
|
else
|
|
m_bLoaded = sal_False;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
sal_Bool SAL_CALL ODatabaseForm::isLoaded() throw( RuntimeException )
|
|
{
|
|
return m_bLoaded;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::addLoadListener(const Reference<XLoadListener>& aListener) throw( RuntimeException )
|
|
{
|
|
m_aLoadListeners.addInterface(aListener);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::removeLoadListener(const Reference<XLoadListener>& aListener) throw( RuntimeException )
|
|
{
|
|
m_aLoadListeners.removeInterface(aListener);
|
|
}
|
|
|
|
//==============================================================================
|
|
// com::sun::star::sdbc::XCloseable
|
|
//==============================================================================
|
|
void SAL_CALL ODatabaseForm::close() throw( SQLException, RuntimeException )
|
|
{
|
|
// unload will close the aggregate
|
|
unload();
|
|
}
|
|
|
|
//==============================================================================
|
|
// com::sun::star::sdbc::XRowSetListener
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::cursorMoved(const EventObject& /*event*/) throw( RuntimeException )
|
|
{
|
|
// reload the subform with the new parameters of the parent
|
|
// do this handling delayed to provide of execute too many SQL Statements
|
|
::osl::ResettableMutexGuard aGuard(m_aMutex);
|
|
|
|
DBG_ASSERT( m_pLoadTimer, "ODatabaseForm::cursorMoved: how can this happen?!" );
|
|
if ( !m_pLoadTimer )
|
|
impl_createLoadTimer();
|
|
|
|
if ( m_pLoadTimer->IsActive() )
|
|
m_pLoadTimer->Stop();
|
|
|
|
// and start the timer again
|
|
m_pLoadTimer->Start();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::rowChanged(const EventObject& /*event*/) throw( RuntimeException )
|
|
{
|
|
// ignore it
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::rowSetChanged(const EventObject& /*event*/) throw( RuntimeException )
|
|
{
|
|
// not interested in :
|
|
// if our parent is an ODatabaseForm, too, then after this rowSetChanged we'll get a "reloaded"
|
|
// or a "loaded" event.
|
|
// If somebody gave us another parent which is an XRowSet but doesn't handle an execute as
|
|
// "load" respectivly "reload" ... can't do anything ....
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
bool ODatabaseForm::impl_approveRowChange_throw( const EventObject& _rEvent, const bool _bAllowSQLException,
|
|
::osl::ClearableMutexGuard& _rGuard )
|
|
{
|
|
::cppu::OInterfaceIteratorHelper aIter( m_aRowSetApproveListeners );
|
|
_rGuard.clear();
|
|
while ( aIter.hasMoreElements() )
|
|
{
|
|
Reference< XRowSetApproveListener > xListener( static_cast< XRowSetApproveListener* >( aIter.next() ) );
|
|
if ( !xListener.is() )
|
|
continue;
|
|
|
|
try
|
|
{
|
|
if ( !xListener->approveRowSetChange( _rEvent ) )
|
|
return false;
|
|
}
|
|
catch ( const DisposedException& e )
|
|
{
|
|
if ( e.Context == xListener )
|
|
aIter.remove();
|
|
}
|
|
catch ( const RuntimeException& ) { throw; }
|
|
catch ( const SQLException& )
|
|
{
|
|
if ( _bAllowSQLException )
|
|
throw;
|
|
DBG_UNHANDLED_EXCEPTION();
|
|
}
|
|
catch ( const Exception& )
|
|
{
|
|
DBG_UNHANDLED_EXCEPTION();
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
sal_Bool SAL_CALL ODatabaseForm::approveCursorMove(const EventObject& event) throw( RuntimeException )
|
|
{
|
|
// is our aggregate calling?
|
|
if (event.Source == InterfaceRef(static_cast<XWeak*>(this)))
|
|
{
|
|
// Our aggregate doesn't have any ApproveRowSetListeners (expect ourself), as we re-routed the queryInterface
|
|
// for XRowSetApproveBroadcaster-interface.
|
|
// So we have to multiplex this approve request.
|
|
::cppu::OInterfaceIteratorHelper aIter( m_aRowSetApproveListeners );
|
|
while ( aIter.hasMoreElements() )
|
|
{
|
|
Reference< XRowSetApproveListener > xListener( static_cast< XRowSetApproveListener* >( aIter.next() ) );
|
|
if ( !xListener.is() )
|
|
continue;
|
|
|
|
try
|
|
{
|
|
if ( !xListener->approveCursorMove( event ) )
|
|
return sal_False;
|
|
}
|
|
catch ( const DisposedException& e )
|
|
{
|
|
if ( e.Context == xListener )
|
|
aIter.remove();
|
|
}
|
|
catch ( const RuntimeException& ) { throw; }
|
|
catch ( const Exception& )
|
|
{
|
|
DBG_UNHANDLED_EXCEPTION();
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
// this is a call from our parent ...
|
|
// a parent's cursor move will result in a re-execute of our own row-set, so we have to
|
|
// ask our own RowSetChangesListeners, too
|
|
::osl::ClearableMutexGuard aGuard( m_aMutex );
|
|
if ( !impl_approveRowChange_throw( event, false, aGuard ) )
|
|
return sal_False;
|
|
}
|
|
return sal_True;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
sal_Bool SAL_CALL ODatabaseForm::approveRowChange(const RowChangeEvent& event) throw( RuntimeException )
|
|
{
|
|
// is our aggregate calling?
|
|
if (event.Source == InterfaceRef(static_cast<XWeak*>(this)))
|
|
{
|
|
// Our aggregate doesn't have any ApproveRowSetListeners (expect ourself), as we re-routed the queryInterface
|
|
// for XRowSetApproveBroadcaster-interface.
|
|
// So we have to multiplex this approve request.
|
|
::cppu::OInterfaceIteratorHelper aIter( m_aRowSetApproveListeners );
|
|
while ( aIter.hasMoreElements() )
|
|
{
|
|
Reference< XRowSetApproveListener > xListener( static_cast< XRowSetApproveListener* >( aIter.next() ) );
|
|
if ( !xListener.is() )
|
|
continue;
|
|
|
|
try
|
|
{
|
|
if ( !xListener->approveRowChange( event ) )
|
|
return false;
|
|
}
|
|
catch ( const DisposedException& e )
|
|
{
|
|
if ( e.Context == xListener )
|
|
aIter.remove();
|
|
}
|
|
catch ( const RuntimeException& ) { throw; }
|
|
catch ( const Exception& )
|
|
{
|
|
DBG_UNHANDLED_EXCEPTION();
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
return sal_True;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
sal_Bool SAL_CALL ODatabaseForm::approveRowSetChange(const EventObject& event) throw( RuntimeException )
|
|
{
|
|
if (event.Source == InterfaceRef(static_cast<XWeak*>(this))) // ignore our aggregate as we handle this approve ourself
|
|
{
|
|
::osl::ClearableMutexGuard aGuard( m_aMutex );
|
|
bool bWasLoaded = isLoaded();
|
|
if ( !impl_approveRowChange_throw( event, false, aGuard ) )
|
|
return sal_False;
|
|
|
|
if ( bWasLoaded )
|
|
{
|
|
m_aLoadListeners.notifyEach( &XLoadListener::reloading, event );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// this is a call from our parent ...
|
|
// a parent's cursor move will result in a re-execute of our own row-set, so we have to
|
|
// ask our own RowSetChangesListeners, too
|
|
::osl::ClearableMutexGuard aGuard( m_aMutex );
|
|
if ( !impl_approveRowChange_throw( event, false, aGuard ) )
|
|
return sal_False;
|
|
}
|
|
return sal_True;
|
|
}
|
|
|
|
//==============================================================================
|
|
// com::sun::star::sdb::XRowSetApproveBroadcaster
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::addRowSetApproveListener(const Reference<XRowSetApproveListener>& _rListener) throw( RuntimeException )
|
|
{
|
|
::osl::ResettableMutexGuard aGuard(m_aMutex);
|
|
m_aRowSetApproveListeners.addInterface(_rListener);
|
|
|
|
// do we have to multiplex ?
|
|
if (m_aRowSetApproveListeners.getLength() == 1)
|
|
{
|
|
Reference<XRowSetApproveBroadcaster> xBroadcaster;
|
|
if (query_aggregation( m_xAggregate, xBroadcaster))
|
|
{
|
|
Reference<XRowSetApproveListener> xListener((XRowSetApproveListener*)this);
|
|
xBroadcaster->addRowSetApproveListener(xListener);
|
|
}
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::removeRowSetApproveListener(const Reference<XRowSetApproveListener>& _rListener) throw( RuntimeException )
|
|
{
|
|
::osl::ResettableMutexGuard aGuard(m_aMutex);
|
|
// do we have to remove the multiplex ?
|
|
m_aRowSetApproveListeners.removeInterface(_rListener);
|
|
if ( m_aRowSetApproveListeners.getLength() == 0 )
|
|
{
|
|
Reference<XRowSetApproveBroadcaster> xBroadcaster;
|
|
if (query_aggregation( m_xAggregate, xBroadcaster))
|
|
{
|
|
Reference<XRowSetApproveListener> xListener((XRowSetApproveListener*)this);
|
|
xBroadcaster->removeRowSetApproveListener(xListener);
|
|
}
|
|
}
|
|
}
|
|
|
|
//==============================================================================
|
|
// com::sun:star::form::XDatabaseParameterBroadcaster
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::addDatabaseParameterListener(const Reference<XDatabaseParameterListener>& _rListener) throw( RuntimeException )
|
|
{
|
|
m_aParameterManager.addParameterListener( _rListener );
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::removeDatabaseParameterListener(const Reference<XDatabaseParameterListener>& _rListener) throw( RuntimeException )
|
|
{
|
|
m_aParameterManager.removeParameterListener( _rListener );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::addParameterListener(const Reference<XDatabaseParameterListener>& _rListener) throw( RuntimeException )
|
|
{
|
|
ODatabaseForm::addDatabaseParameterListener( _rListener );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::removeParameterListener(const Reference<XDatabaseParameterListener>& _rListener) throw( RuntimeException )
|
|
{
|
|
ODatabaseForm::removeDatabaseParameterListener( _rListener );
|
|
}
|
|
|
|
//==============================================================================
|
|
// com::sun::star::sdb::XCompletedExecution
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::executeWithCompletion( const Reference< XInteractionHandler >& _rxHandler ) throw(SQLException, RuntimeException)
|
|
{
|
|
::osl::ClearableMutexGuard aGuard(m_aMutex);
|
|
// the difference between execute and load is, that we position on the first row in case of load
|
|
// after execute we remain before the first row
|
|
if (!isLoaded())
|
|
{
|
|
aGuard.clear();
|
|
load_impl(sal_False, sal_False, _rxHandler);
|
|
}
|
|
else
|
|
{
|
|
EventObject event(static_cast< XWeak* >(this));
|
|
if ( !impl_approveRowChange_throw( event, true, aGuard ) )
|
|
return;
|
|
|
|
// we're loaded and somebody want's to execute ourself -> this means a reload
|
|
reload_impl(sal_False, _rxHandler);
|
|
}
|
|
}
|
|
|
|
//==============================================================================
|
|
// com::sun::star::sdbc::XRowSet
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::execute() throw( SQLException, RuntimeException )
|
|
{
|
|
::osl::ResettableMutexGuard aGuard(m_aMutex);
|
|
// if somebody calls an execute and we're not loaded we reroute this call to our load method.
|
|
|
|
// the difference between execute and load is, that we position on the first row in case of load
|
|
// after execute we remain before the first row
|
|
if (!isLoaded())
|
|
{
|
|
aGuard.clear();
|
|
load_impl(sal_False, sal_False);
|
|
}
|
|
else
|
|
{
|
|
EventObject event(static_cast< XWeak* >(this));
|
|
if ( !impl_approveRowChange_throw( event, true, aGuard ) )
|
|
return;
|
|
|
|
// we're loaded and somebody want's to execute ourself -> this means a reload
|
|
reload_impl(sal_False);
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::addRowSetListener(const Reference<XRowSetListener>& _rListener) throw( RuntimeException )
|
|
{
|
|
if (m_xAggregateAsRowSet.is())
|
|
m_xAggregateAsRowSet->addRowSetListener(_rListener);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::removeRowSetListener(const Reference<XRowSetListener>& _rListener) throw( RuntimeException )
|
|
{
|
|
if (m_xAggregateAsRowSet.is())
|
|
m_xAggregateAsRowSet->removeRowSetListener(_rListener);
|
|
}
|
|
|
|
//==============================================================================
|
|
// com::sun::star::sdbc::XResultSet
|
|
//------------------------------------------------------------------------------
|
|
sal_Bool SAL_CALL ODatabaseForm::next() throw( SQLException, RuntimeException )
|
|
{
|
|
return m_xAggregateAsRowSet->next();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
sal_Bool SAL_CALL ODatabaseForm::isBeforeFirst() throw( SQLException, RuntimeException )
|
|
{
|
|
return m_xAggregateAsRowSet->isBeforeFirst();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
sal_Bool SAL_CALL ODatabaseForm::isAfterLast() throw( SQLException, RuntimeException )
|
|
{
|
|
return m_xAggregateAsRowSet->isAfterLast();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
sal_Bool SAL_CALL ODatabaseForm::isFirst() throw( SQLException, RuntimeException )
|
|
{
|
|
return m_xAggregateAsRowSet->isFirst();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
sal_Bool SAL_CALL ODatabaseForm::isLast() throw( SQLException, RuntimeException )
|
|
{
|
|
return m_xAggregateAsRowSet->isLast();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::beforeFirst() throw( SQLException, RuntimeException )
|
|
{
|
|
m_xAggregateAsRowSet->beforeFirst();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::afterLast() throw( SQLException, RuntimeException )
|
|
{
|
|
m_xAggregateAsRowSet->afterLast();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
sal_Bool SAL_CALL ODatabaseForm::first() throw( SQLException, RuntimeException )
|
|
{
|
|
return m_xAggregateAsRowSet->first();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
sal_Bool SAL_CALL ODatabaseForm::last() throw( SQLException, RuntimeException )
|
|
{
|
|
return m_xAggregateAsRowSet->last();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
sal_Int32 SAL_CALL ODatabaseForm::getRow() throw( SQLException, RuntimeException )
|
|
{
|
|
return m_xAggregateAsRowSet->getRow();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
sal_Bool SAL_CALL ODatabaseForm::absolute(sal_Int32 row) throw( SQLException, RuntimeException )
|
|
{
|
|
return m_xAggregateAsRowSet->absolute(row);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
sal_Bool SAL_CALL ODatabaseForm::relative(sal_Int32 rows) throw( SQLException, RuntimeException )
|
|
{
|
|
return m_xAggregateAsRowSet->relative(rows);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
sal_Bool SAL_CALL ODatabaseForm::previous() throw( SQLException, RuntimeException )
|
|
{
|
|
return m_xAggregateAsRowSet->previous();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::refreshRow() throw( SQLException, RuntimeException )
|
|
{
|
|
m_xAggregateAsRowSet->refreshRow();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
sal_Bool SAL_CALL ODatabaseForm::rowUpdated() throw( SQLException, RuntimeException )
|
|
{
|
|
return m_xAggregateAsRowSet->rowUpdated();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
sal_Bool SAL_CALL ODatabaseForm::rowInserted() throw( SQLException, RuntimeException )
|
|
{
|
|
return m_xAggregateAsRowSet->rowInserted();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
sal_Bool SAL_CALL ODatabaseForm::rowDeleted() throw( SQLException, RuntimeException )
|
|
{
|
|
return m_xAggregateAsRowSet->rowDeleted();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
InterfaceRef SAL_CALL ODatabaseForm::getStatement() throw( SQLException, RuntimeException )
|
|
{
|
|
return m_xAggregateAsRowSet->getStatement();
|
|
}
|
|
|
|
// com::sun::star::sdbc::XResultSetUpdate
|
|
// exceptions during insert update and delete will be forwarded to the errorlistener
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::insertRow() throw( SQLException, RuntimeException )
|
|
{
|
|
try
|
|
{
|
|
Reference<XResultSetUpdate> xUpdate;
|
|
if (query_aggregation( m_xAggregate, xUpdate))
|
|
xUpdate->insertRow();
|
|
}
|
|
catch( const RowSetVetoException& eVeto )
|
|
{
|
|
(void)eVeto;
|
|
throw;
|
|
}
|
|
catch(SQLException& eDb)
|
|
{
|
|
onError(eDb, FRM_RES_STRING(RID_STR_ERR_INSERTRECORD));
|
|
throw;
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::updateRow() throw( SQLException, RuntimeException )
|
|
{
|
|
try
|
|
{
|
|
Reference<XResultSetUpdate> xUpdate;
|
|
if (query_aggregation( m_xAggregate, xUpdate))
|
|
xUpdate->updateRow();
|
|
}
|
|
catch( const RowSetVetoException& eVeto )
|
|
{
|
|
(void)eVeto;
|
|
throw;
|
|
}
|
|
catch(SQLException& eDb)
|
|
{
|
|
onError(eDb, FRM_RES_STRING(RID_STR_ERR_UPDATERECORD));
|
|
throw;
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::deleteRow() throw( SQLException, RuntimeException )
|
|
{
|
|
try
|
|
{
|
|
Reference<XResultSetUpdate> xUpdate;
|
|
if (query_aggregation( m_xAggregate, xUpdate))
|
|
xUpdate->deleteRow();
|
|
}
|
|
catch( const RowSetVetoException& eVeto )
|
|
{
|
|
(void)eVeto;
|
|
throw;
|
|
}
|
|
catch(SQLException& eDb)
|
|
{
|
|
onError(eDb, FRM_RES_STRING(RID_STR_ERR_DELETERECORD));
|
|
throw;
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::cancelRowUpdates() throw( SQLException, RuntimeException )
|
|
{
|
|
try
|
|
{
|
|
Reference<XResultSetUpdate> xUpdate;
|
|
if (query_aggregation( m_xAggregate, xUpdate))
|
|
xUpdate->cancelRowUpdates();
|
|
}
|
|
catch( const RowSetVetoException& eVeto )
|
|
{
|
|
(void)eVeto;
|
|
throw;
|
|
}
|
|
catch(SQLException& eDb)
|
|
{
|
|
onError(eDb, FRM_RES_STRING(RID_STR_ERR_INSERTRECORD));
|
|
throw;
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::moveToInsertRow() throw( SQLException, RuntimeException )
|
|
{
|
|
Reference<XResultSetUpdate> xUpdate;
|
|
if (query_aggregation( m_xAggregate, xUpdate))
|
|
{
|
|
// _always_ move to the insert row
|
|
//
|
|
// Formerly, the following line was conditioned with a "not is new", means we did not move the aggregate
|
|
// to the insert row if it was already positioned there.
|
|
//
|
|
// This prevented the RowSet implementation from resetting it's column values. We, ourself, formerly
|
|
// did this reset of columns in reset_impl, where we set every column to the ControlDefault, or, if this
|
|
// was not present, to NULL. However, the problem with setting to NULL was #88888#, the problem with
|
|
// _not_ setting to NULL (which was the original fix for #88888#) was #97955#.
|
|
//
|
|
// So now we
|
|
// * move our aggregate to the insert row
|
|
// * in reset_impl
|
|
// - set the control defaults into the columns if not void
|
|
// - do _not_ set the columns to NULL if no control default is set
|
|
// This fixes both #88888# and #97955#
|
|
//
|
|
// Still, there is #72756#. During fixing this bug, DG introduced not calling the aggregate here. So
|
|
// in theory, we re-introduced #72756#. But the bug described therein does not happen anymore, as the
|
|
// preliminaries for it changed (no display of guessed values for new records with autoinc fields)
|
|
//
|
|
// BTW: the public Issuezilla bug for #97955# is #i2815#
|
|
//
|
|
// 16.04.2002 - 97955 - fs@openoffice.org
|
|
xUpdate->moveToInsertRow();
|
|
|
|
// then set the default values and the parameters given from the parent
|
|
reset();
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::moveToCurrentRow() throw( SQLException, RuntimeException )
|
|
{
|
|
Reference<XResultSetUpdate> xUpdate;
|
|
if (query_aggregation( m_xAggregate, xUpdate))
|
|
xUpdate->moveToCurrentRow();
|
|
}
|
|
|
|
// com::sun::star::sdbcx::XDeleteRows
|
|
//------------------------------------------------------------------------------
|
|
Sequence<sal_Int32> SAL_CALL ODatabaseForm::deleteRows(const Sequence<Any>& rows) throw( SQLException, RuntimeException )
|
|
{
|
|
try
|
|
{
|
|
Reference<XDeleteRows> xDelete;
|
|
if (query_aggregation( m_xAggregate, xDelete))
|
|
return xDelete->deleteRows(rows);
|
|
}
|
|
catch( const RowSetVetoException& eVeto )
|
|
{
|
|
(void)eVeto; // make compiler happy
|
|
throw;
|
|
}
|
|
catch(SQLException& eDb)
|
|
{
|
|
onError(eDb, FRM_RES_STRING(RID_STR_ERR_DELETERECORDS));
|
|
throw;
|
|
}
|
|
|
|
return Sequence< sal_Int32 >();
|
|
}
|
|
|
|
// com::sun::star::sdbc::XParameters
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::setNull(sal_Int32 parameterIndex, sal_Int32 sqlType) throw( SQLException, RuntimeException )
|
|
{
|
|
m_aParameterManager.setNull(parameterIndex, sqlType);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::setObjectNull(sal_Int32 parameterIndex, sal_Int32 sqlType, const ::rtl::OUString& typeName) throw( SQLException, RuntimeException )
|
|
{
|
|
m_aParameterManager.setObjectNull(parameterIndex, sqlType, typeName);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::setBoolean(sal_Int32 parameterIndex, sal_Bool x) throw( SQLException, RuntimeException )
|
|
{
|
|
m_aParameterManager.setBoolean(parameterIndex, x);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::setByte(sal_Int32 parameterIndex, sal_Int8 x) throw( SQLException, RuntimeException )
|
|
{
|
|
m_aParameterManager.setByte(parameterIndex, x);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::setShort(sal_Int32 parameterIndex, sal_Int16 x) throw( SQLException, RuntimeException )
|
|
{
|
|
m_aParameterManager.setShort(parameterIndex, x);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::setInt(sal_Int32 parameterIndex, sal_Int32 x) throw( SQLException, RuntimeException )
|
|
{
|
|
m_aParameterManager.setInt(parameterIndex, x);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::setLong(sal_Int32 parameterIndex, sal_Int64 x) throw( SQLException, RuntimeException )
|
|
{
|
|
m_aParameterManager.setLong(parameterIndex, x);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::setFloat(sal_Int32 parameterIndex, float x) throw( SQLException, RuntimeException )
|
|
{
|
|
m_aParameterManager.setFloat(parameterIndex, x);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::setDouble(sal_Int32 parameterIndex, double x) throw( SQLException, RuntimeException )
|
|
{
|
|
m_aParameterManager.setDouble(parameterIndex, x);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::setString(sal_Int32 parameterIndex, const ::rtl::OUString& x) throw( SQLException, RuntimeException )
|
|
{
|
|
m_aParameterManager.setString(parameterIndex, x);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::setBytes(sal_Int32 parameterIndex, const Sequence< sal_Int8 >& x) throw( SQLException, RuntimeException )
|
|
{
|
|
m_aParameterManager.setBytes(parameterIndex, x);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::setDate(sal_Int32 parameterIndex, const ::com::sun::star::util::Date& x) throw( SQLException, RuntimeException )
|
|
{
|
|
m_aParameterManager.setDate(parameterIndex, x);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::setTime(sal_Int32 parameterIndex, const ::com::sun::star::util::Time& x) throw( SQLException, RuntimeException )
|
|
{
|
|
m_aParameterManager.setTime(parameterIndex, x);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::setTimestamp(sal_Int32 parameterIndex, const ::com::sun::star::util::DateTime& x) throw( SQLException, RuntimeException )
|
|
{
|
|
m_aParameterManager.setTimestamp(parameterIndex, x);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::setBinaryStream(sal_Int32 parameterIndex, const Reference<XInputStream>& x, sal_Int32 length) throw( SQLException, RuntimeException )
|
|
{
|
|
m_aParameterManager.setBinaryStream(parameterIndex, x, length);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::setCharacterStream(sal_Int32 parameterIndex, const Reference<XInputStream>& x, sal_Int32 length) throw( SQLException, RuntimeException )
|
|
{
|
|
m_aParameterManager.setCharacterStream(parameterIndex, x, length);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::setObjectWithInfo(sal_Int32 parameterIndex, const Any& x, sal_Int32 targetSqlType, sal_Int32 scale) throw( SQLException, RuntimeException )
|
|
{
|
|
m_aParameterManager.setObjectWithInfo(parameterIndex, x, targetSqlType, scale);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::setObject(sal_Int32 parameterIndex, const Any& x) throw( SQLException, RuntimeException )
|
|
{
|
|
m_aParameterManager.setObject(parameterIndex, x);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::setRef(sal_Int32 parameterIndex, const Reference<XRef>& x) throw( SQLException, RuntimeException )
|
|
{
|
|
m_aParameterManager.setRef(parameterIndex, x);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::setBlob(sal_Int32 parameterIndex, const Reference<XBlob>& x) throw( SQLException, RuntimeException )
|
|
{
|
|
m_aParameterManager.setBlob(parameterIndex, x);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::setClob(sal_Int32 parameterIndex, const Reference<XClob>& x) throw( SQLException, RuntimeException )
|
|
{
|
|
m_aParameterManager.setClob(parameterIndex, x);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::setArray(sal_Int32 parameterIndex, const Reference<XArray>& x) throw( SQLException, RuntimeException )
|
|
{
|
|
m_aParameterManager.setArray(parameterIndex, x);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::clearParameters() throw( SQLException, RuntimeException )
|
|
{
|
|
m_aParameterManager.clearParameters();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::propertyChange( const PropertyChangeEvent& evt ) throw (RuntimeException)
|
|
{
|
|
if ( evt.Source == m_xParent )
|
|
{
|
|
if ( evt.PropertyName == PROPERTY_ISNEW )
|
|
{
|
|
sal_Bool bCurrentIsNew( sal_False );
|
|
OSL_VERIFY( evt.NewValue >>= bCurrentIsNew );
|
|
if ( !bCurrentIsNew )
|
|
reload_impl( sal_True );
|
|
}
|
|
return;
|
|
}
|
|
OFormComponents::propertyChange( evt );
|
|
}
|
|
|
|
// com::sun::star::lang::XServiceInfo
|
|
//------------------------------------------------------------------------------
|
|
::rtl::OUString SAL_CALL ODatabaseForm::getImplementationName_Static()
|
|
{
|
|
return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.forms.ODatabaseForm" ) );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
Sequence< ::rtl::OUString > SAL_CALL ODatabaseForm::getCompatibleServiceNames_Static()
|
|
{
|
|
Sequence< ::rtl::OUString > aServices( 1 );
|
|
::rtl::OUString* pServices = aServices.getArray();
|
|
|
|
*pServices++ = FRM_COMPONENT_FORM;
|
|
|
|
return aServices;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
Sequence< ::rtl::OUString > SAL_CALL ODatabaseForm::getCurrentServiceNames_Static()
|
|
{
|
|
Sequence< ::rtl::OUString > aServices( 5 );
|
|
::rtl::OUString* pServices = aServices.getArray();
|
|
|
|
*pServices++ = FRM_SUN_FORMCOMPONENT;
|
|
*pServices++ = ::rtl::OUString::createFromAscii("com.sun.star.form.FormComponents");
|
|
*pServices++ = FRM_SUN_COMPONENT_FORM;
|
|
*pServices++ = FRM_SUN_COMPONENT_HTMLFORM;
|
|
*pServices++ = FRM_SUN_COMPONENT_DATAFORM;
|
|
|
|
return aServices;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
Sequence< ::rtl::OUString > SAL_CALL ODatabaseForm::getSupportedServiceNames_Static()
|
|
{
|
|
return ::comphelper::concatSequences(
|
|
getCurrentServiceNames_Static(),
|
|
getCompatibleServiceNames_Static()
|
|
);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
::rtl::OUString SAL_CALL ODatabaseForm::getImplementationName() throw( RuntimeException )
|
|
{
|
|
return getImplementationName_Static();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
Sequence< ::rtl::OUString > SAL_CALL ODatabaseForm::getSupportedServiceNames() throw( RuntimeException )
|
|
{
|
|
// the services of our aggregate
|
|
Sequence< ::rtl::OUString > aServices;
|
|
Reference< XServiceInfo > xInfo;
|
|
if (query_aggregation(m_xAggregate, xInfo))
|
|
aServices = xInfo->getSupportedServiceNames();
|
|
|
|
// concat with out own services
|
|
return ::comphelper::concatSequences(
|
|
getCurrentServiceNames_Static(),
|
|
aServices
|
|
);
|
|
// use getCurrentXXX instead of getSupportedXXX, because at runtime, we do not want to have
|
|
// the compatible names
|
|
// This is maily to be consistent with the implementation before fixing #97083#, though the
|
|
// better solution _may_ be to return the compatible names at runtime, too
|
|
// 04.03.2002 - fs@openoffice.org
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
sal_Bool SAL_CALL ODatabaseForm::supportsService(const ::rtl::OUString& ServiceName) throw( RuntimeException )
|
|
{
|
|
Sequence< ::rtl::OUString > aSupported( getSupportedServiceNames() );
|
|
const ::rtl::OUString* pArray = aSupported.getConstArray();
|
|
for( sal_Int32 i = 0; i < aSupported.getLength(); ++i, ++pArray )
|
|
if( pArray->equals( ServiceName ) )
|
|
return sal_True;
|
|
return sal_False;
|
|
}
|
|
|
|
//==============================================================================
|
|
// com::sun::star::io::XPersistObject
|
|
//------------------------------------------------------------------------------
|
|
|
|
const sal_uInt16 CYCLE = 0x0001;
|
|
const sal_uInt16 DONTAPPLYFILTER = 0x0002;
|
|
|
|
//------------------------------------------------------------------------------
|
|
::rtl::OUString ODatabaseForm::getServiceName() throw( RuntimeException )
|
|
{
|
|
return FRM_COMPONENT_FORM; // old (non-sun) name for compatibility !
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::write(const Reference<XObjectOutputStream>& _rxOutStream) throw( IOException, RuntimeException )
|
|
{
|
|
DBG_ASSERT(m_xAggregateSet.is(), "ODatabaseForm::write : only to be called if the aggregate exists !");
|
|
|
|
// all children
|
|
OFormComponents::write(_rxOutStream);
|
|
|
|
// version
|
|
_rxOutStream->writeShort(0x0003);
|
|
|
|
// Name
|
|
_rxOutStream << m_sName;
|
|
|
|
::rtl::OUString sDataSource;
|
|
if (m_xAggregateSet.is())
|
|
m_xAggregateSet->getPropertyValue(PROPERTY_DATASOURCE) >>= sDataSource;
|
|
_rxOutStream << sDataSource;
|
|
|
|
// former CursorSource
|
|
::rtl::OUString sCommand;
|
|
if (m_xAggregateSet.is())
|
|
m_xAggregateSet->getPropertyValue(PROPERTY_COMMAND) >>= sCommand;
|
|
_rxOutStream << sCommand;
|
|
|
|
// former MasterFields
|
|
_rxOutStream << m_aMasterFields;
|
|
// former DetailFields
|
|
_rxOutStream << m_aDetailFields;
|
|
|
|
// former DataSelectionType
|
|
DataSelectionType eTranslated = DataSelectionType_TABLE;
|
|
if (m_xAggregateSet.is())
|
|
{
|
|
sal_Int32 nCommandType = 0;
|
|
m_xAggregateSet->getPropertyValue(PROPERTY_COMMANDTYPE) >>= nCommandType;
|
|
switch (nCommandType)
|
|
{
|
|
case CommandType::TABLE : eTranslated = DataSelectionType_TABLE; break;
|
|
case CommandType::QUERY : eTranslated = DataSelectionType_QUERY; break;
|
|
case CommandType::COMMAND:
|
|
{
|
|
sal_Bool bEscapeProcessing = getBOOL(m_xAggregateSet->getPropertyValue(PROPERTY_ESCAPE_PROCESSING));
|
|
eTranslated = bEscapeProcessing ? DataSelectionType_SQL : DataSelectionType_SQLPASSTHROUGH;
|
|
}
|
|
break;
|
|
default : DBG_ERROR("ODatabaseForm::write : wrong CommandType !");
|
|
}
|
|
}
|
|
_rxOutStream->writeShort((sal_Int16)eTranslated); // former DataSelectionType
|
|
|
|
// very old versions expect a CursorType here
|
|
_rxOutStream->writeShort(DatabaseCursorType_KEYSET);
|
|
|
|
_rxOutStream->writeBoolean(m_eNavigation != NavigationBarMode_NONE);
|
|
|
|
// former DataEntry
|
|
if (m_xAggregateSet.is())
|
|
_rxOutStream->writeBoolean(getBOOL(m_xAggregateSet->getPropertyValue(PROPERTY_INSERTONLY)));
|
|
else
|
|
_rxOutStream->writeBoolean(sal_False);
|
|
|
|
_rxOutStream->writeBoolean(m_bAllowInsert);
|
|
_rxOutStream->writeBoolean(m_bAllowUpdate);
|
|
_rxOutStream->writeBoolean(m_bAllowDelete);
|
|
|
|
// html form stuff
|
|
::rtl::OUString sTmp = INetURLObject::decode( m_aTargetURL, '%', INetURLObject::DECODE_UNAMBIGUOUS);
|
|
_rxOutStream << sTmp;
|
|
_rxOutStream->writeShort( (sal_Int16)m_eSubmitMethod );
|
|
_rxOutStream->writeShort( (sal_Int16)m_eSubmitEncoding );
|
|
_rxOutStream << m_aTargetFrame;
|
|
|
|
// version 2 didn't know some options and the "default" state
|
|
sal_Int32 nCycle = TabulatorCycle_RECORDS;
|
|
if (m_aCycle.hasValue())
|
|
{
|
|
::cppu::enum2int(nCycle, m_aCycle);
|
|
if (m_aCycle == TabulatorCycle_PAGE)
|
|
// unknown in earlier versions
|
|
nCycle = TabulatorCycle_RECORDS;
|
|
}
|
|
_rxOutStream->writeShort((sal_Int16) nCycle);
|
|
|
|
_rxOutStream->writeShort((sal_Int16)m_eNavigation);
|
|
|
|
::rtl::OUString sFilter;
|
|
::rtl::OUString sOrder;
|
|
if (m_xAggregateSet.is())
|
|
{
|
|
m_xAggregateSet->getPropertyValue(PROPERTY_FILTER) >>= sFilter;
|
|
m_xAggregateSet->getPropertyValue(PROPERTY_SORT) >>= sOrder;
|
|
}
|
|
_rxOutStream << sFilter;
|
|
_rxOutStream << sOrder;
|
|
|
|
|
|
// version 3
|
|
sal_uInt16 nAnyMask = 0;
|
|
if (m_aCycle.hasValue())
|
|
nAnyMask |= CYCLE;
|
|
|
|
if (m_xAggregateSet.is() && !getBOOL(m_xAggregateSet->getPropertyValue(PROPERTY_APPLYFILTER)))
|
|
nAnyMask |= DONTAPPLYFILTER;
|
|
|
|
_rxOutStream->writeShort(nAnyMask);
|
|
|
|
if (nAnyMask & CYCLE)
|
|
{
|
|
sal_Int32 nRealCycle = 0;
|
|
::cppu::enum2int(nRealCycle, m_aCycle);
|
|
_rxOutStream->writeShort((sal_Int16)nRealCycle);
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::read(const Reference<XObjectInputStream>& _rxInStream) throw( IOException, RuntimeException )
|
|
{
|
|
DBG_ASSERT(m_xAggregateSet.is(), "ODatabaseForm::read : only to be called if the aggregate exists !");
|
|
|
|
OFormComponents::read(_rxInStream);
|
|
|
|
// version
|
|
sal_uInt16 nVersion = _rxInStream->readShort();
|
|
|
|
_rxInStream >> m_sName;
|
|
|
|
::rtl::OUString sAggregateProp;
|
|
_rxInStream >> sAggregateProp;
|
|
if (m_xAggregateSet.is())
|
|
m_xAggregateSet->setPropertyValue(PROPERTY_DATASOURCE, makeAny(sAggregateProp));
|
|
_rxInStream >> sAggregateProp;
|
|
if (m_xAggregateSet.is())
|
|
m_xAggregateSet->setPropertyValue(PROPERTY_COMMAND, makeAny(sAggregateProp));
|
|
|
|
_rxInStream >> m_aMasterFields;
|
|
_rxInStream >> m_aDetailFields;
|
|
|
|
sal_Int16 nCursorSourceType = _rxInStream->readShort();
|
|
sal_Int32 nCommandType = 0;
|
|
switch ((DataSelectionType)nCursorSourceType)
|
|
{
|
|
case DataSelectionType_TABLE : nCommandType = CommandType::TABLE; break;
|
|
case DataSelectionType_QUERY : nCommandType = CommandType::QUERY; break;
|
|
case DataSelectionType_SQL:
|
|
case DataSelectionType_SQLPASSTHROUGH:
|
|
{
|
|
nCommandType = CommandType::COMMAND;
|
|
sal_Bool bEscapeProcessing = ((DataSelectionType)nCursorSourceType) != DataSelectionType_SQLPASSTHROUGH;
|
|
m_xAggregateSet->setPropertyValue(PROPERTY_ESCAPE_PROCESSING, makeAny((sal_Bool)bEscapeProcessing));
|
|
}
|
|
break;
|
|
default : DBG_ERROR("ODatabaseForm::read : wrong CommandType !");
|
|
}
|
|
if (m_xAggregateSet.is())
|
|
m_xAggregateSet->setPropertyValue(PROPERTY_COMMANDTYPE, makeAny(nCommandType));
|
|
|
|
// obsolete
|
|
_rxInStream->readShort();
|
|
|
|
// navigation mode was a boolean in version 1
|
|
// war in der version 1 ein sal_Bool
|
|
sal_Bool bNavigation = _rxInStream->readBoolean();
|
|
if (nVersion == 1)
|
|
m_eNavigation = bNavigation ? NavigationBarMode_CURRENT : NavigationBarMode_NONE;
|
|
|
|
sal_Bool bInsertOnly = _rxInStream->readBoolean();
|
|
if (m_xAggregateSet.is())
|
|
m_xAggregateSet->setPropertyValue(PROPERTY_INSERTONLY, makeAny(bInsertOnly));
|
|
|
|
m_bAllowInsert = _rxInStream->readBoolean();
|
|
m_bAllowUpdate = _rxInStream->readBoolean();
|
|
m_bAllowDelete = _rxInStream->readBoolean();
|
|
|
|
// html stuff
|
|
::rtl::OUString sTmp;
|
|
_rxInStream >> sTmp;
|
|
m_aTargetURL = INetURLObject::decode( sTmp, '%', INetURLObject::DECODE_UNAMBIGUOUS);
|
|
m_eSubmitMethod = (FormSubmitMethod)_rxInStream->readShort();
|
|
m_eSubmitEncoding = (FormSubmitEncoding)_rxInStream->readShort();
|
|
_rxInStream >> m_aTargetFrame;
|
|
|
|
if (nVersion > 1)
|
|
{
|
|
sal_Int32 nCycle = _rxInStream->readShort();
|
|
m_aCycle = ::cppu::int2enum(nCycle, ::getCppuType(static_cast<const TabulatorCycle*>(NULL)));
|
|
m_eNavigation = (NavigationBarMode)_rxInStream->readShort();
|
|
|
|
_rxInStream >> sAggregateProp;
|
|
setPropertyValue(PROPERTY_FILTER, makeAny(sAggregateProp));
|
|
|
|
_rxInStream >> sAggregateProp;
|
|
if (m_xAggregateSet.is())
|
|
m_xAggregateSet->setPropertyValue(PROPERTY_SORT, makeAny(sAggregateProp));
|
|
}
|
|
|
|
sal_uInt16 nAnyMask = 0;
|
|
if (nVersion > 2)
|
|
{
|
|
nAnyMask = _rxInStream->readShort();
|
|
if (nAnyMask & CYCLE)
|
|
{
|
|
sal_Int32 nCycle = _rxInStream->readShort();
|
|
m_aCycle = ::cppu::int2enum(nCycle, ::getCppuType(static_cast<const TabulatorCycle*>(NULL)));
|
|
}
|
|
else
|
|
m_aCycle.clear();
|
|
}
|
|
if (m_xAggregateSet.is())
|
|
m_xAggregateSet->setPropertyValue(PROPERTY_APPLYFILTER, makeAny((sal_Bool)((nAnyMask & DONTAPPLYFILTER) == 0)));
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void ODatabaseForm::implInserted( const ElementDescription* _pElement )
|
|
{
|
|
OFormComponents::implInserted( _pElement );
|
|
|
|
Reference< XSQLErrorBroadcaster > xBroadcaster( _pElement->xInterface, UNO_QUERY );
|
|
Reference< XForm > xForm ( _pElement->xInterface, UNO_QUERY );
|
|
|
|
if ( xBroadcaster.is() && !xForm.is() )
|
|
{ // the object is an error broadcaster, but no form itself -> add ourself as listener
|
|
xBroadcaster->addSQLErrorListener( this );
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void ODatabaseForm::implRemoved(const InterfaceRef& _rxObject)
|
|
{
|
|
OFormComponents::implRemoved( _rxObject );
|
|
|
|
Reference<XSQLErrorBroadcaster> xBroadcaster(_rxObject, UNO_QUERY);
|
|
Reference<XForm> xForm(_rxObject, UNO_QUERY);
|
|
if (xBroadcaster.is() && !xForm.is())
|
|
{ // the object is an error broadcaster, but no form itself -> remove ourself as listener
|
|
xBroadcaster->removeSQLErrorListener(this);
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::errorOccured(const SQLErrorEvent& _rEvent) throw( RuntimeException )
|
|
{
|
|
// give it to my own error listener
|
|
onError(_rEvent);
|
|
// TODO : think about extending the chain with an SQLContext object saying
|
|
// "this was an error of one of my children"
|
|
}
|
|
|
|
// com::sun::star::container::XNamed
|
|
//------------------------------------------------------------------------------
|
|
::rtl::OUString SAL_CALL ODatabaseForm::getName() throw( RuntimeException )
|
|
{
|
|
::rtl::OUString sReturn;
|
|
OPropertySetHelper::getFastPropertyValue(PROPERTY_ID_NAME) >>= sReturn;
|
|
return sReturn;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL ODatabaseForm::setName(const ::rtl::OUString& aName) throw( RuntimeException )
|
|
{
|
|
setFastPropertyValue(PROPERTY_ID_NAME, makeAny(aName));
|
|
}
|
|
|
|
//.........................................................................
|
|
} // namespace frm
|
|
//.........................................................................
|
|
|