Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "browserids.hxx"
21 : #include "commontypes.hxx"
22 : #include <dbaccess/dataview.hxx>
23 : #include "dbu_misc.hrc"
24 : #include "dbustrings.hrc"
25 : #include "moduledbu.hxx"
26 : #include <dbaccess/dbsubcomponentcontroller.hxx>
27 :
28 : #include <com/sun/star/frame/XUntitledNumbers.hpp>
29 : #include <com/sun/star/beans/PropertyAttribute.hpp>
30 : #include <com/sun/star/container/XChild.hpp>
31 : #include <com/sun/star/container/XNameAccess.hpp>
32 : #include <com/sun/star/sdb/XDocumentDataSource.hpp>
33 : #include <com/sun/star/sdb/XOfficeDatabaseDocument.hpp>
34 : #include <com/sun/star/sdbc/XDataSource.hpp>
35 : #include <com/sun/star/util/NumberFormatter.hpp>
36 : #include <com/sun/star/lang/IllegalArgumentException.hpp>
37 :
38 : #include <comphelper/processfactory.hxx>
39 : #include <comphelper/sequence.hxx>
40 : #include <comphelper/types.hxx>
41 : #include <connectivity/dbexception.hxx>
42 : #include <connectivity/dbtools.hxx>
43 : #include <cppuhelper/typeprovider.hxx>
44 : #include <rtl/ustrbuf.hxx>
45 : #include <toolkit/helper/vclunohelper.hxx>
46 : #include <tools/debug.hxx>
47 : #include <tools/diagnose_ex.h>
48 : #include <vcl/msgbox.hxx>
49 :
50 : namespace dbaui
51 : {
52 :
53 : using ::com::sun::star::uno::Any;
54 : using ::com::sun::star::uno::Reference;
55 : using ::com::sun::star::beans::XPropertySet;
56 : using ::com::sun::star::lang::XMultiServiceFactory;
57 : using ::com::sun::star::uno::RuntimeException;
58 : using ::com::sun::star::uno::Sequence;
59 : using ::com::sun::star::uno::Type;
60 : using ::com::sun::star::uno::XComponentContext;
61 : using ::com::sun::star::sdbc::XConnection;
62 : using ::com::sun::star::uno::UNO_QUERY;
63 : using ::com::sun::star::container::XChild;
64 : using ::com::sun::star::sdbc::XDataSource;
65 : using ::com::sun::star::util::NumberFormatter;
66 : using ::com::sun::star::util::XNumberFormatter;
67 : using ::com::sun::star::util::XNumberFormatsSupplier;
68 : using ::com::sun::star::frame::XFrame;
69 : using ::com::sun::star::uno::Exception;
70 : using ::com::sun::star::sdbc::SQLException;
71 : using ::com::sun::star::lang::EventObject;
72 : using ::com::sun::star::beans::PropertyValue;
73 : using ::com::sun::star::frame::XModel;
74 : using ::com::sun::star::sdb::XOfficeDatabaseDocument;
75 : using ::com::sun::star::awt::XWindow;
76 : using ::com::sun::star::sdbc::XDatabaseMetaData;
77 : using ::com::sun::star::sdb::XDocumentDataSource;
78 : using ::com::sun::star::document::XEmbeddedScripts;
79 : using ::com::sun::star::lang::IllegalArgumentException;
80 : using ::com::sun::star::uno::UNO_SET_THROW;
81 : using ::com::sun::star::uno::UNO_QUERY_THROW;
82 : using ::com::sun::star::frame::XUntitledNumbers;
83 : using ::com::sun::star::beans::PropertyVetoException;
84 :
85 0 : class DataSourceHolder
86 : {
87 : public:
88 0 : DataSourceHolder()
89 0 : {
90 0 : }
91 :
92 0 : DataSourceHolder( const Reference< XDataSource >& _rxDataSource )
93 0 : {
94 0 : m_xDataSource = _rxDataSource;
95 0 : Reference< XDocumentDataSource > xDocDS( m_xDataSource, UNO_QUERY );
96 0 : if ( xDocDS.is() )
97 0 : m_xDocument = xDocDS->getDatabaseDocument();
98 :
99 0 : m_xDataSourceProps.set( m_xDataSource, UNO_QUERY );
100 0 : }
101 :
102 0 : const Reference< XDataSource >& getDataSource() const { return m_xDataSource; }
103 0 : const Reference< XPropertySet >& getDataSourceProps() const { return m_xDataSourceProps; }
104 0 : const Reference< XOfficeDatabaseDocument > getDatabaseDocument() const { return m_xDocument; }
105 :
106 0 : bool is() const { return m_xDataSource.is(); }
107 :
108 0 : void clear()
109 : {
110 0 : m_xDataSource.clear();
111 0 : m_xDocument.clear();
112 0 : }
113 :
114 : private:
115 : Reference< XDataSource > m_xDataSource;
116 : Reference< XPropertySet > m_xDataSourceProps;
117 : Reference< XOfficeDatabaseDocument > m_xDocument;
118 : };
119 :
120 0 : struct DBSubComponentController_Impl
121 : {
122 : private:
123 : ::boost::optional< bool > m_aDocScriptSupport;
124 :
125 : public:
126 : OModuleClient m_aModuleClient;
127 : ::dbtools::SQLExceptionInfo m_aCurrentError;
128 :
129 : ::cppu::OInterfaceContainerHelper
130 : m_aModifyListeners;
131 :
132 : // <properties>
133 : SharedConnection m_xConnection;
134 : ::dbtools::DatabaseMetaData m_aSdbMetaData;
135 : // </properties>
136 : OUString m_sDataSourceName; // the data source we're working for
137 : DataSourceHolder m_aDataSource;
138 : Reference< XModel > m_xDocument;
139 : Reference< XNumberFormatter > m_xFormatter; // a number formatter working with the connection's NumberFormatsSupplier
140 : sal_Int32 m_nDocStartNumber;
141 : bool m_bSuspended; // is true when the controller was already suspended
142 : bool m_bEditable; // is the control readonly or not
143 : bool m_bModified; // is the data modified
144 : bool m_bNotAttached;
145 :
146 0 : DBSubComponentController_Impl( ::osl::Mutex& i_rMutex )
147 : :m_aDocScriptSupport()
148 : ,m_aModifyListeners( i_rMutex )
149 : ,m_nDocStartNumber(0)
150 : ,m_bSuspended( false )
151 : ,m_bEditable(true)
152 : ,m_bModified(false)
153 0 : ,m_bNotAttached(true)
154 : {
155 0 : }
156 :
157 0 : bool documentHasScriptSupport() const
158 : {
159 : OSL_PRECOND( !!m_aDocScriptSupport,
160 : "DBSubComponentController_Impl::documentHasScriptSupport: not completely initialized, yet - don't know!?" );
161 0 : return !!m_aDocScriptSupport && *m_aDocScriptSupport;
162 : }
163 :
164 0 : void setDocumentScriptSupport( const bool _bSupport )
165 : {
166 : OSL_PRECOND( !m_aDocScriptSupport,
167 : "DBSubComponentController_Impl::setDocumentScriptSupport: already initialized!" );
168 0 : m_aDocScriptSupport = ::boost::optional< bool >( _bSupport );
169 0 : }
170 : };
171 :
172 : // DBSubComponentController
173 0 : DBSubComponentController::DBSubComponentController(const Reference< XComponentContext >& _rxORB)
174 : :DBSubComponentController_Base( _rxORB )
175 0 : ,m_pImpl( new DBSubComponentController_Impl( getMutex() ) )
176 : {
177 0 : }
178 :
179 0 : DBSubComponentController::~DBSubComponentController()
180 : {
181 0 : }
182 :
183 0 : void DBSubComponentController::impl_initialize()
184 : {
185 0 : OGenericUnoController::impl_initialize();
186 :
187 0 : const ::comphelper::NamedValueCollection& rArguments( getInitParams() );
188 :
189 0 : Reference< XConnection > xConnection;
190 0 : xConnection = rArguments.getOrDefault( (OUString)PROPERTY_ACTIVE_CONNECTION, xConnection );
191 :
192 0 : if ( !xConnection.is() )
193 0 : ::dbtools::isEmbeddedInDatabase( getModel(), xConnection );
194 :
195 0 : if ( xConnection.is() )
196 0 : initializeConnection( xConnection );
197 :
198 0 : bool bShowError = true;
199 0 : if ( !isConnected() )
200 : {
201 0 : reconnect( false );
202 0 : bShowError = false;
203 : }
204 0 : if ( !isConnected() )
205 : {
206 0 : if ( bShowError )
207 0 : connectionLostMessage();
208 0 : throw IllegalArgumentException();
209 0 : }
210 0 : }
211 :
212 0 : Any SAL_CALL DBSubComponentController::queryInterface(const Type& _rType) throw (RuntimeException, std::exception)
213 : {
214 0 : if ( _rType.equals( cppu::UnoType<XScriptInvocationContext>::get() ) )
215 : {
216 0 : if ( m_pImpl->documentHasScriptSupport() )
217 0 : return makeAny( Reference< XScriptInvocationContext >( this ) );
218 0 : return Any();
219 : }
220 :
221 0 : return DBSubComponentController_Base::queryInterface( _rType );
222 : }
223 :
224 0 : Sequence< Type > SAL_CALL DBSubComponentController::getTypes( ) throw (RuntimeException, std::exception)
225 : {
226 0 : Sequence< Type > aTypes( DBSubComponentController_Base::getTypes() );
227 0 : if ( !m_pImpl->documentHasScriptSupport() )
228 : {
229 0 : Sequence< Type > aStrippedTypes( aTypes.getLength() - 1 );
230 : ::std::remove_copy_if(
231 : aTypes.getConstArray(),
232 0 : aTypes.getConstArray() + aTypes.getLength(),
233 : aStrippedTypes.getArray(),
234 0 : ::std::bind2nd( ::std::equal_to< Type >(), cppu::UnoType<XScriptInvocationContext>::get() )
235 0 : );
236 0 : aTypes = aStrippedTypes;
237 : }
238 0 : return aTypes;
239 : }
240 :
241 0 : void DBSubComponentController::initializeConnection( const Reference< XConnection >& _rxForeignConn )
242 : {
243 : DBG_ASSERT( !isConnected(), "DBSubComponentController::initializeConnection: not to be called when already connected!" );
244 : // usually this gets called from within initialize of derived classes ...
245 0 : if ( isConnected() )
246 0 : disconnect();
247 :
248 0 : m_pImpl->m_xConnection.reset( _rxForeignConn, SharedConnection::NoTakeOwnership );
249 0 : m_pImpl->m_aSdbMetaData.reset( m_pImpl->m_xConnection );
250 0 : startConnectionListening( m_pImpl->m_xConnection );
251 :
252 : // get the data source the connection belongs to
253 : try
254 : {
255 : // determine our data source
256 : OSL_PRECOND( !m_pImpl->m_aDataSource.is(), "DBSubComponentController::initializeConnection: already a data source in this phase?" );
257 : {
258 0 : Reference< XChild > xConnAsChild( m_pImpl->m_xConnection, UNO_QUERY );
259 0 : Reference< XDataSource > xDS;
260 0 : if ( xConnAsChild.is() )
261 0 : xDS = Reference< XDataSource >( xConnAsChild->getParent(), UNO_QUERY );
262 :
263 : // (take the indirection through XDataSource to ensure we have a correct object ....)
264 0 : m_pImpl->m_aDataSource = xDS;
265 : }
266 : OSL_POSTCOND( m_pImpl->m_aDataSource.is(), "DBSubComponentController::initializeConnection: unable to obtain the data source object!" );
267 :
268 0 : if ( m_pImpl->m_bNotAttached )
269 : {
270 0 : Reference< XUntitledNumbers > xUntitledProvider( getDatabaseDocument(), UNO_QUERY );
271 0 : m_pImpl->m_nDocStartNumber = 1;
272 0 : if ( xUntitledProvider.is() )
273 0 : m_pImpl->m_nDocStartNumber = xUntitledProvider->leaseNumber( static_cast< XWeak* >( this ) );
274 : }
275 :
276 : // determine the availability of script support in our document. Our own XScriptInvocationContext
277 : // interface depends on this
278 0 : m_pImpl->setDocumentScriptSupport( Reference< XEmbeddedScripts >( getDatabaseDocument(), UNO_QUERY ).is() );
279 :
280 : // get a number formatter
281 0 : Reference< XPropertySet > xDataSourceProps( m_pImpl->m_aDataSource.getDataSourceProps(), UNO_SET_THROW );
282 0 : xDataSourceProps->getPropertyValue( PROPERTY_NAME ) >>= m_pImpl->m_sDataSourceName;
283 : DBG_ASSERT( !m_pImpl->m_sDataSourceName.isEmpty(), "DBSubComponentController::initializeConnection: invalid data source name!" );
284 0 : Reference< XNumberFormatsSupplier> xSupplier = ::dbtools::getNumberFormats(m_pImpl->m_xConnection);
285 0 : if(xSupplier.is())
286 : {
287 0 : m_pImpl->m_xFormatter = Reference< XNumberFormatter >(
288 0 : NumberFormatter::create(getORB()), UNO_QUERY_THROW);
289 0 : m_pImpl->m_xFormatter->attachNumberFormatsSupplier(xSupplier);
290 : }
291 0 : OSL_ENSURE(m_pImpl->m_xFormatter.is(),"No NumberFormatter!");
292 : }
293 0 : catch( const Exception& )
294 : {
295 : DBG_UNHANDLED_EXCEPTION();
296 : }
297 0 : }
298 :
299 0 : void DBSubComponentController::reconnect( bool _bUI )
300 : {
301 : OSL_ENSURE(!m_pImpl->m_bSuspended, "Cannot reconnect while suspended!");
302 :
303 0 : stopConnectionListening( m_pImpl->m_xConnection );
304 0 : m_pImpl->m_aSdbMetaData.reset( NULL );
305 0 : m_pImpl->m_xConnection.clear();
306 :
307 : // reconnect
308 0 : bool bReConnect = true;
309 0 : if ( _bUI )
310 : {
311 0 : QueryBox aQuery( getView(), ModuleRes(QUERY_CONNECTION_LOST) );
312 0 : bReConnect = ( RET_YES == aQuery.Execute() );
313 : }
314 :
315 : // now really reconnect ...
316 0 : if ( bReConnect )
317 : {
318 0 : m_pImpl->m_xConnection.reset( connect( m_pImpl->m_aDataSource.getDataSource(), NULL ), SharedConnection::TakeOwnership );
319 0 : m_pImpl->m_aSdbMetaData.reset( m_pImpl->m_xConnection );
320 : }
321 :
322 : // invalidate all slots
323 0 : InvalidateAll();
324 0 : }
325 :
326 0 : void DBSubComponentController::disconnect()
327 : {
328 0 : stopConnectionListening(m_pImpl->m_xConnection);
329 0 : m_pImpl->m_aSdbMetaData.reset( NULL );
330 0 : m_pImpl->m_xConnection.clear();
331 :
332 0 : InvalidateAll();
333 0 : }
334 :
335 0 : void DBSubComponentController::losingConnection()
336 : {
337 : // our connection was disposed so we need a new one
338 0 : reconnect( true );
339 0 : InvalidateAll();
340 0 : }
341 :
342 0 : void SAL_CALL DBSubComponentController::disposing()
343 : {
344 0 : DBSubComponentController_Base::disposing();
345 :
346 0 : disconnect();
347 :
348 0 : attachFrame( Reference < XFrame >() );
349 :
350 0 : m_pImpl->m_aDataSource.clear();
351 0 : }
352 :
353 0 : void SAL_CALL DBSubComponentController::disposing(const EventObject& _rSource) throw( RuntimeException, std::exception )
354 : {
355 0 : if ( _rSource.Source == getConnection() )
356 : {
357 0 : if ( !m_pImpl->m_bSuspended // when already suspended then we don't have to reconnect
358 0 : && !getBroadcastHelper().bInDispose
359 0 : && !getBroadcastHelper().bDisposed
360 0 : && isConnected()
361 : )
362 : {
363 0 : losingConnection();
364 : }
365 : else
366 : {
367 0 : m_pImpl->m_xConnection.reset( m_pImpl->m_xConnection, SharedConnection::NoTakeOwnership );
368 : // this prevents the "disposeComponent" call in disconnect
369 0 : disconnect();
370 : }
371 : }
372 : else
373 0 : DBSubComponentController_Base::disposing( _rSource );
374 0 : }
375 :
376 0 : void DBSubComponentController::appendError( const OUString& _rErrorMessage, const ::dbtools::StandardSQLState _eSQLState,
377 : const sal_Int32 _nErrorCode )
378 : {
379 0 : m_pImpl->m_aCurrentError.append( ::dbtools::SQLExceptionInfo::SQL_EXCEPTION, _rErrorMessage, getStandardSQLState( _eSQLState ),
380 0 : _nErrorCode );
381 0 : }
382 0 : void DBSubComponentController::clearError()
383 : {
384 0 : m_pImpl->m_aCurrentError = ::dbtools::SQLExceptionInfo();
385 0 : }
386 :
387 0 : bool DBSubComponentController::hasError() const
388 : {
389 0 : return m_pImpl->m_aCurrentError.isValid();
390 : }
391 :
392 0 : const ::dbtools::SQLExceptionInfo& DBSubComponentController::getError() const
393 : {
394 0 : return m_pImpl->m_aCurrentError;
395 : }
396 :
397 0 : void DBSubComponentController::displayError()
398 : {
399 0 : showError( m_pImpl->m_aCurrentError );
400 0 : }
401 :
402 0 : sal_Bool SAL_CALL DBSubComponentController::suspend(sal_Bool bSuspend) throw( RuntimeException, std::exception )
403 : {
404 0 : m_pImpl->m_bSuspended = bSuspend;
405 0 : if ( !bSuspend && !isConnected() )
406 0 : reconnect(true);
407 :
408 0 : return sal_True;
409 : }
410 :
411 0 : sal_Bool SAL_CALL DBSubComponentController::attachModel( const Reference< XModel > & _rxModel) throw( RuntimeException, std::exception )
412 : {
413 0 : if ( !_rxModel.is() )
414 0 : return sal_False;
415 0 : if ( !DBSubComponentController_Base::attachModel( _rxModel ) )
416 0 : return sal_False;
417 :
418 0 : m_pImpl->m_bNotAttached = false;
419 0 : if ( m_pImpl->m_nDocStartNumber == 1 )
420 0 : releaseNumberForComponent();
421 :
422 0 : Reference< XUntitledNumbers > xUntitledProvider( _rxModel, UNO_QUERY );
423 0 : m_pImpl->m_nDocStartNumber = 1;
424 0 : if ( xUntitledProvider.is() )
425 0 : m_pImpl->m_nDocStartNumber = xUntitledProvider->leaseNumber( static_cast< XWeak* >( this ) );
426 :
427 0 : return sal_True;
428 : }
429 :
430 0 : void DBSubComponentController::Execute(sal_uInt16 _nId, const Sequence< PropertyValue >& _rArgs)
431 : {
432 0 : if ( _nId == ID_BROWSER_CLOSE )
433 : {
434 0 : closeTask();
435 0 : return;
436 : }
437 :
438 0 : DBSubComponentController_Base::Execute( _nId, _rArgs );
439 0 : InvalidateFeature( _nId );
440 : }
441 :
442 0 : OUString DBSubComponentController::getDataSourceName() const
443 : {
444 0 : OUString sName;
445 0 : Reference< XPropertySet > xDataSourceProps( m_pImpl->m_aDataSource.getDataSourceProps() );
446 0 : if ( xDataSourceProps.is() )
447 0 : xDataSourceProps->getPropertyValue(PROPERTY_NAME) >>= sName;
448 0 : return sName;
449 : }
450 0 : void DBSubComponentController::connectionLostMessage() const
451 : {
452 0 : OUString aMessage(ModuleRes(RID_STR_CONNECTION_LOST));
453 0 : Reference< XWindow > xWindow = getTopMostContainerWindow();
454 0 : Window* pWin = NULL;
455 0 : if ( xWindow.is() )
456 0 : pWin = VCLUnoHelper::GetWindow(xWindow);
457 0 : if ( !pWin )
458 0 : pWin = getView()->Window::GetParent();
459 :
460 0 : InfoBox(pWin, aMessage).Execute();
461 0 : }
462 0 : const Reference< XConnection >& DBSubComponentController::getConnection() const
463 : {
464 0 : return m_pImpl->m_xConnection;
465 : }
466 :
467 0 : bool DBSubComponentController::isReadOnly() const
468 : {
469 0 : return !m_pImpl->m_bEditable;
470 : }
471 :
472 0 : bool DBSubComponentController::isEditable() const
473 : {
474 0 : return m_pImpl->m_bEditable;
475 : }
476 :
477 0 : void DBSubComponentController::setEditable(bool _bEditable)
478 : {
479 0 : m_pImpl->m_bEditable = _bEditable;
480 0 : }
481 :
482 0 : const ::dbtools::DatabaseMetaData& DBSubComponentController::getSdbMetaData() const
483 : {
484 0 : return m_pImpl->m_aSdbMetaData;
485 : }
486 :
487 0 : bool DBSubComponentController::isConnected() const
488 : {
489 0 : return m_pImpl->m_xConnection.is();
490 : }
491 :
492 0 : Reference< XDatabaseMetaData > DBSubComponentController::getMetaData( ) const
493 : {
494 0 : Reference< XDatabaseMetaData > xMeta;
495 : try
496 : {
497 0 : if ( isConnected() )
498 0 : xMeta.set( m_pImpl->m_xConnection->getMetaData(), UNO_SET_THROW );
499 : }
500 0 : catch( const Exception& )
501 : {
502 : DBG_UNHANDLED_EXCEPTION();
503 : }
504 0 : return xMeta;
505 : }
506 :
507 0 : const Reference< XPropertySet >& DBSubComponentController::getDataSource() const
508 : {
509 0 : return m_pImpl->m_aDataSource.getDataSourceProps();
510 : }
511 :
512 0 : bool DBSubComponentController::haveDataSource() const
513 : {
514 0 : return m_pImpl->m_aDataSource.is();
515 : }
516 :
517 0 : Reference< XModel > DBSubComponentController::getDatabaseDocument() const
518 : {
519 0 : return Reference< XModel >( m_pImpl->m_aDataSource.getDatabaseDocument(), UNO_QUERY );
520 : }
521 :
522 0 : Reference< XNumberFormatter > DBSubComponentController::getNumberFormatter() const
523 : {
524 0 : return m_pImpl->m_xFormatter;
525 : }
526 :
527 0 : Reference< XModel > DBSubComponentController::getPrivateModel() const
528 : {
529 0 : return getDatabaseDocument();
530 : }
531 : // XTitle
532 0 : OUString SAL_CALL DBSubComponentController::getTitle()
533 : throw (RuntimeException, std::exception)
534 : {
535 0 : ::osl::MutexGuard aGuard( getMutex() );
536 0 : if ( m_bExternalTitle )
537 0 : return impl_getTitleHelper_throw()->getTitle ();
538 :
539 0 : OUStringBuffer sTitle;
540 0 : Reference< XTitle > xTitle(getPrivateModel(),UNO_QUERY);
541 0 : if ( xTitle.is() )
542 : {
543 0 : sTitle.append( xTitle->getTitle() );
544 0 : sTitle.appendAscii(" : ");
545 : }
546 0 : sTitle.append( getPrivateTitle() );
547 0 : return sTitle.makeStringAndClear();
548 : }
549 :
550 0 : sal_Int32 DBSubComponentController::getCurrentStartNumber() const
551 : {
552 0 : return m_pImpl->m_nDocStartNumber;
553 : }
554 :
555 0 : Reference< XEmbeddedScripts > SAL_CALL DBSubComponentController::getScriptContainer() throw (RuntimeException, std::exception)
556 : {
557 0 : ::osl::MutexGuard aGuard( getMutex() );
558 0 : if ( !m_pImpl->documentHasScriptSupport() )
559 0 : return NULL;
560 :
561 0 : return Reference< XEmbeddedScripts >( getDatabaseDocument(), UNO_QUERY_THROW );
562 : }
563 :
564 0 : void SAL_CALL DBSubComponentController::addModifyListener( const Reference< XModifyListener >& i_Listener ) throw (RuntimeException, std::exception)
565 : {
566 0 : ::osl::MutexGuard aGuard( getMutex() );
567 0 : m_pImpl->m_aModifyListeners.addInterface( i_Listener );
568 0 : }
569 :
570 0 : void SAL_CALL DBSubComponentController::removeModifyListener( const Reference< XModifyListener >& i_Listener ) throw (RuntimeException, std::exception)
571 : {
572 0 : ::osl::MutexGuard aGuard( getMutex() );
573 0 : m_pImpl->m_aModifyListeners.removeInterface( i_Listener );
574 0 : }
575 :
576 0 : sal_Bool SAL_CALL DBSubComponentController::isModified( ) throw (RuntimeException, std::exception)
577 : {
578 0 : ::osl::MutexGuard aGuard( getMutex() );
579 0 : return impl_isModified();
580 : }
581 :
582 0 : void SAL_CALL DBSubComponentController::setModified( sal_Bool i_bModified ) throw (PropertyVetoException, RuntimeException, std::exception)
583 : {
584 0 : ::osl::ClearableMutexGuard aGuard( getMutex() );
585 :
586 0 : if ( (m_pImpl->m_bModified ? 1 : 0) == i_bModified )
587 0 : return;
588 :
589 0 : m_pImpl->m_bModified = i_bModified;
590 0 : impl_onModifyChanged();
591 :
592 0 : EventObject aEvent( *this );
593 0 : aGuard.clear();
594 0 : m_pImpl->m_aModifyListeners.notifyEach( &XModifyListener::modified, aEvent );
595 : }
596 :
597 0 : bool DBSubComponentController::impl_isModified() const
598 : {
599 0 : return m_pImpl->m_bModified;
600 : }
601 :
602 0 : void DBSubComponentController::impl_onModifyChanged()
603 : {
604 0 : InvalidateFeature( ID_BROWSER_SAVEDOC );
605 0 : if ( isFeatureSupported( ID_BROWSER_SAVEASDOC ) )
606 0 : InvalidateFeature( ID_BROWSER_SAVEASDOC );
607 0 : }
608 :
609 : } // namespace dbaui
610 :
611 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|