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