1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_forms.hxx" 30 31 #include "formoperations.hxx" 32 #include "frm_strings.hxx" 33 #include "frm_resource.hxx" 34 #include "frm_resource.hrc" 35 #include "frm_module.hxx" 36 37 /** === begin UNO includes === **/ 38 #include <com/sun/star/ucb/AlreadyInitializedException.hpp> 39 #include <com/sun/star/util/XModifyBroadcaster.hpp> 40 #include <com/sun/star/form/runtime/FormFeature.hpp> 41 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 42 #include <com/sun/star/lang/DisposedException.hpp> 43 #include <com/sun/star/awt/XControl.hpp> 44 #include <com/sun/star/form/XGrid.hpp> 45 #include <com/sun/star/form/XBoundControl.hpp> 46 #include <com/sun/star/form/XBoundComponent.hpp> 47 #include <com/sun/star/sdbcx/XRowLocate.hpp> 48 #include <com/sun/star/form/XConfirmDeleteListener.hpp> 49 #include <com/sun/star/sdb/RowChangeEvent.hpp> 50 #include <com/sun/star/sdb/RowChangeAction.hpp> 51 #include <com/sun/star/sdb/SQLFilterOperator.hpp> 52 #include <com/sun/star/sdbc/DataType.hpp> 53 #include <com/sun/star/form/XReset.hpp> 54 #include <com/sun/star/beans/XMultiPropertySet.hpp> 55 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp> 56 #include <com/sun/star/util/XRefreshable.hpp> 57 /** === end UNO includes === **/ 58 59 #include <connectivity/dbtools.hxx> 60 #include <connectivity/dbexception.hxx> 61 #include <vcl/svapp.hxx> 62 #include <vcl/stdtext.hxx> 63 #include <vcl/msgbox.hxx> 64 #include <vcl/waitobj.hxx> 65 #include <tools/diagnose_ex.h> 66 #include <comphelper/container.hxx> 67 #include <comphelper/property.hxx> 68 #include <comphelper/namedvaluecollection.hxx> 69 #include <cppuhelper/exc_hlp.hxx> 70 #include <vos/mutex.hxx> 71 72 //-------------------------------------------------------------------------- 73 extern "C" void SAL_CALL createRegistryInfo_FormOperations() 74 { 75 static ::frm::OMultiInstanceAutoRegistration< ::frm::FormOperations > aAutoRegistration; 76 } 77 78 //........................................................................ 79 namespace frm 80 { 81 //........................................................................ 82 83 using ::dbtools::SQLExceptionInfo; 84 /** === begin UNO using === **/ 85 using ::com::sun::star::uno::Reference; 86 using ::com::sun::star::uno::XComponentContext; 87 using ::com::sun::star::uno::RuntimeException; 88 using ::com::sun::star::uno::Sequence; 89 using ::com::sun::star::uno::Exception; 90 using ::com::sun::star::uno::Any; 91 using ::com::sun::star::uno::XInterface; 92 using ::com::sun::star::sdbc::XRowSet; 93 using ::com::sun::star::sdbc::XResultSetUpdate; 94 using ::com::sun::star::form::runtime::XFormController; 95 using ::com::sun::star::form::runtime::XFeatureInvalidation; 96 using ::com::sun::star::form::runtime::FeatureState; 97 using ::com::sun::star::lang::IllegalArgumentException; 98 using ::com::sun::star::sdbc::SQLException; 99 using namespace ::com::sun::star::sdbc; 100 using ::com::sun::star::form::XForm; 101 using ::com::sun::star::ucb::AlreadyInitializedException; 102 using ::com::sun::star::util::XModifyBroadcaster; 103 using ::com::sun::star::uno::UNO_QUERY; 104 using ::com::sun::star::lang::EventObject; 105 using ::com::sun::star::beans::PropertyChangeEvent; 106 using ::com::sun::star::lang::XMultiServiceFactory; 107 using ::com::sun::star::lang::DisposedException; 108 using ::com::sun::star::beans::XPropertySet; 109 using ::com::sun::star::awt::XControl; 110 using ::com::sun::star::form::XGrid; 111 using ::com::sun::star::container::XIndexAccess; 112 using ::com::sun::star::uno::UNO_QUERY_THROW; 113 using ::com::sun::star::form::XBoundControl; 114 using ::com::sun::star::form::XBoundComponent; 115 using ::com::sun::star::sdbcx::XRowLocate; 116 using ::com::sun::star::form::XConfirmDeleteListener; 117 using ::com::sun::star::sdb::RowChangeEvent; 118 using namespace ::com::sun::star::sdb; 119 using ::com::sun::star::form::XReset; 120 using ::com::sun::star::beans::XMultiPropertySet; 121 using ::com::sun::star::uno::makeAny; 122 using ::com::sun::star::lang::WrappedTargetException; 123 using ::com::sun::star::beans::PropertyValue; 124 using ::com::sun::star::ui::dialogs::XExecutableDialog; 125 using ::com::sun::star::beans::NamedValue; 126 127 using ::com::sun::star::util::XRefreshable; 128 using ::com::sun::star::awt::XControlModel; 129 /** === end UNO using === **/ 130 namespace FormFeature = ::com::sun::star::form::runtime::FormFeature; 131 namespace RowChangeAction = ::com::sun::star::sdb::RowChangeAction; 132 133 //==================================================================== 134 //= FormOperations 135 //==================================================================== 136 //-------------------------------------------------------------------- 137 FormOperations::FormOperations( const Reference< XMultiServiceFactory >& _rxContext ) 138 :FormOperations_Base( m_aMutex ) 139 ,m_aContext( _rxContext ) 140 ,m_bInitializedParser( false ) 141 ,m_bActiveControlModified( false ) 142 ,m_bConstructed( false ) 143 #ifdef DBG_UTIL 144 ,m_nMethodNestingLevel( false ) 145 #endif 146 { 147 } 148 149 //-------------------------------------------------------------------- 150 FormOperations::~FormOperations() 151 { 152 } 153 154 //-------------------------------------------------------------------- 155 ::rtl::OUString FormOperations::getImplementationName_Static( ) throw(RuntimeException) 156 { 157 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.forms.FormOperations" ) ); 158 } 159 160 //-------------------------------------------------------------------- 161 Sequence< ::rtl::OUString > FormOperations::getSupportedServiceNames_Static( ) throw(RuntimeException) 162 { 163 Sequence< ::rtl::OUString > aNames(1); 164 aNames[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.form.runtime.FormOperations" ) ); 165 return aNames; 166 } 167 168 //-------------------------------------------------------------------- 169 Reference< XInterface > SAL_CALL FormOperations::Create(const Reference< XMultiServiceFactory >& _rxFactory ) 170 { 171 return *new FormOperations( _rxFactory ); 172 } 173 174 //-------------------------------------------------------------------- 175 void SAL_CALL FormOperations::initialize( const Sequence< Any >& _arguments ) throw (Exception, RuntimeException) 176 { 177 if ( m_bConstructed ) 178 throw AlreadyInitializedException(); 179 180 if ( _arguments.getLength() == 1 ) 181 { 182 Reference< XFormController > xController; 183 Reference< XForm > xForm; 184 if ( _arguments[0] >>= xController ) 185 createWithFormController( xController ); 186 else if ( _arguments[0] >>= xForm ) 187 createWithForm( xForm ); 188 else 189 throw IllegalArgumentException( ::rtl::OUString(), *this, 1 ); 190 return; 191 } 192 193 throw IllegalArgumentException( ::rtl::OUString(), *this, 0 ); 194 } 195 196 //-------------------------------------------------------------------- 197 ::rtl::OUString SAL_CALL FormOperations::getImplementationName( ) throw (RuntimeException) 198 { 199 return getImplementationName_Static(); 200 } 201 202 //-------------------------------------------------------------------- 203 ::sal_Bool SAL_CALL FormOperations::supportsService( const ::rtl::OUString& _ServiceName ) throw (RuntimeException) 204 { 205 Sequence< ::rtl::OUString > aSupportedServiceNames( getSupportedServiceNames() ); 206 const ::rtl::OUString* pBegin = aSupportedServiceNames.getConstArray(); 207 const ::rtl::OUString* pEnd = aSupportedServiceNames.getConstArray() + aSupportedServiceNames.getLength(); 208 return ::std::find( pBegin, pEnd, _ServiceName ) != pEnd; 209 } 210 211 //-------------------------------------------------------------------- 212 Sequence< ::rtl::OUString > SAL_CALL FormOperations::getSupportedServiceNames( ) throw (RuntimeException) 213 { 214 return getSupportedServiceNames_Static(); 215 } 216 217 //-------------------------------------------------------------------- 218 Reference< XRowSet > SAL_CALL FormOperations::getCursor() throw (RuntimeException) 219 { 220 MethodGuard aGuard( *this ); 221 return m_xCursor; 222 } 223 224 //-------------------------------------------------------------------- 225 Reference< XResultSetUpdate > SAL_CALL FormOperations::getUpdateCursor() throw (RuntimeException) 226 { 227 MethodGuard aGuard( *this ); 228 return m_xUpdateCursor; 229 } 230 231 //-------------------------------------------------------------------- 232 Reference< XFormController > SAL_CALL FormOperations::getController() throw (RuntimeException) 233 { 234 MethodGuard aGuard( *this ); 235 return m_xController; 236 } 237 238 //-------------------------------------------------------------------- 239 Reference< XFeatureInvalidation > SAL_CALL FormOperations::getFeatureInvalidation() throw (RuntimeException) 240 { 241 MethodGuard aGuard( *this ); 242 return m_xFeatureInvalidation; 243 } 244 245 //-------------------------------------------------------------------- 246 void SAL_CALL FormOperations::setFeatureInvalidation( const Reference< XFeatureInvalidation > & _rxFeatureInvalidation ) throw (RuntimeException) 247 { 248 MethodGuard aGuard( *this ); 249 m_xFeatureInvalidation = _rxFeatureInvalidation; 250 } 251 252 //-------------------------------------------------------------------- 253 FeatureState SAL_CALL FormOperations::getState( ::sal_Int16 _nFeature ) throw (RuntimeException) 254 { 255 MethodGuard aGuard( *this ); 256 257 FeatureState aState; 258 aState.Enabled = sal_False; 259 260 try 261 { 262 // some checks for basic pre-requisites 263 if ( !m_xLoadableForm.is() 264 || !m_xLoadableForm->isLoaded() 265 || !m_xCursorProperties.is() 266 ) 267 { 268 return aState; 269 } 270 271 switch ( _nFeature ) 272 { 273 case FormFeature::MoveToFirst: 274 case FormFeature::MoveToPrevious: 275 aState.Enabled = impl_canMoveLeft_throw( ); 276 break; 277 278 case FormFeature::MoveToNext: 279 aState.Enabled = impl_canMoveRight_throw(); 280 break; 281 282 case FormFeature::MoveToLast: 283 aState.Enabled = impl_getRowCount_throw() && ( !m_xCursor->isLast() || impl_isInsertionRow_throw() ); 284 break; 285 286 case FormFeature::DeleteRecord: 287 // already deleted ? 288 if ( m_xCursor->rowDeleted() ) 289 aState.Enabled = sal_False; 290 else 291 { 292 // allowed to delete the row ? 293 aState.Enabled = !impl_isInsertionRow_throw() && ::dbtools::canDelete( m_xCursorProperties ); 294 } 295 break; 296 297 case FormFeature::MoveToInsertRow: 298 // if we are inserting we can move to the next row if the current record or control is modified 299 aState.Enabled = impl_isInsertionRow_throw() 300 ? impl_isModifiedRow_throw() || m_bActiveControlModified 301 : ::dbtools::canInsert( m_xCursorProperties ); 302 break; 303 304 case FormFeature::ReloadForm: 305 { 306 // there must be an active connection 307 Reference< XRowSet > xCursorRowSet( m_xCursor, UNO_QUERY ); 308 aState.Enabled = ::dbtools::getConnection( xCursorRowSet ).is(); 309 310 // and an active command 311 ::rtl::OUString sActiveCommand; 312 m_xCursorProperties->getPropertyValue( PROPERTY_ACTIVECOMMAND ) >>= sActiveCommand; 313 aState.Enabled &= sActiveCommand.getLength() > 0; 314 } 315 break; 316 317 case FormFeature::RefreshCurrentControl: 318 { 319 Reference< XRefreshable > xControlModelRefresh( impl_getCurrentControlModel_throw(), UNO_QUERY ); 320 aState.Enabled = xControlModelRefresh.is(); 321 } 322 break; 323 324 case FormFeature::SaveRecordChanges: 325 case FormFeature::UndoRecordChanges: 326 aState.Enabled = impl_isModifiedRow_throw() || m_bActiveControlModified; 327 break; 328 329 case FormFeature::RemoveFilterAndSort: 330 if ( impl_isParseable_throw() && impl_hasFilterOrOrder_throw() ) 331 aState.Enabled = !impl_isInsertOnlyForm_throw(); 332 break; 333 334 case FormFeature::SortAscending: 335 case FormFeature::SortDescending: 336 case FormFeature::AutoFilter: 337 if ( m_xController.is() && impl_isParseable_throw() ) 338 { 339 sal_Bool bIsDeleted = m_xCursor->rowDeleted(); 340 341 if ( !bIsDeleted && !impl_isInsertOnlyForm_throw() ) 342 { 343 Reference< XPropertySet > xBoundField = impl_getCurrentBoundField_nothrow( ); 344 if ( xBoundField.is() ) 345 xBoundField->getPropertyValue( PROPERTY_SEARCHABLE ) >>= aState.Enabled; 346 } 347 } 348 break; 349 350 case FormFeature::InteractiveSort: 351 case FormFeature::InteractiveFilter: 352 if ( impl_isParseable_throw() ) 353 aState.Enabled = !impl_isInsertOnlyForm_throw(); 354 break; 355 356 case FormFeature::ToggleApplyFilter: 357 { 358 ::rtl::OUString sFilter; 359 m_xCursorProperties->getPropertyValue( PROPERTY_FILTER ) >>= sFilter; 360 if ( sFilter.getLength() ) 361 { 362 aState.State = m_xCursorProperties->getPropertyValue( PROPERTY_APPLYFILTER ); 363 aState.Enabled = !impl_isInsertOnlyForm_throw(); 364 } 365 else 366 aState.State <<= (sal_Bool)sal_False; 367 } 368 break; 369 370 case FormFeature::MoveAbsolute: 371 { 372 sal_Int32 nPosition = m_xCursor->getRow(); 373 sal_Bool bIsNew = impl_isInsertionRow_throw(); 374 sal_Int32 nCount = impl_getRowCount_throw(); 375 sal_Bool bFinalCount = impl_isRowCountFinal_throw(); 376 377 if ( ( nPosition >= 0 ) || bIsNew ) 378 { 379 if ( bFinalCount ) 380 { 381 // special case: there are no records at all, and we 382 // can't insert records -> disabled 383 if ( !nCount && !::dbtools::canInsert( m_xCursorProperties ) ) 384 { 385 aState.Enabled = sal_False; 386 } 387 else 388 { 389 if ( bIsNew ) 390 nPosition = ++nCount; 391 aState.State <<= (sal_Int32)nPosition; 392 aState.Enabled = sal_True; 393 } 394 } 395 else 396 { 397 aState.State <<= (sal_Int32)nPosition; 398 aState.Enabled = sal_True; 399 } 400 } 401 } 402 break; 403 404 case FormFeature::TotalRecords: 405 { 406 sal_Bool bIsNew = impl_isInsertionRow_throw(); 407 sal_Int32 nCount = impl_getRowCount_throw(); 408 sal_Bool bFinalCount = impl_isRowCountFinal_throw(); 409 410 if ( bIsNew ) 411 ++nCount; 412 413 ::rtl::OUString sValue = ::rtl::OUString::valueOf( sal_Int32( nCount ) ); 414 if ( !bFinalCount ) 415 sValue += ::rtl::OUString::createFromAscii( " *" ); 416 417 aState.State <<= sValue; 418 aState.Enabled = sal_True; 419 } 420 break; 421 422 default: 423 OSL_ENSURE( sal_False, "FormOperations::getState: unknown feature id!" ); 424 break; 425 } 426 } 427 catch( const Exception& ) 428 { 429 OSL_ENSURE( sal_False, "FormOperations::getState: caught an exception!" ); 430 } 431 432 return aState; 433 } 434 435 //-------------------------------------------------------------------- 436 ::sal_Bool SAL_CALL FormOperations::isEnabled( ::sal_Int16 _nFeature ) throw (RuntimeException) 437 { 438 MethodGuard aGuard( *this ); 439 440 FeatureState aState( getState( _nFeature ) ); 441 return aState.Enabled; 442 } 443 444 //-------------------------------------------------------------------- 445 namespace 446 { 447 static bool lcl_needConfirmCommit( sal_Int32 _nFeature ) 448 { 449 return ( ( _nFeature == FormFeature::ReloadForm ) 450 || ( _nFeature == FormFeature::RemoveFilterAndSort ) 451 || ( _nFeature == FormFeature::ToggleApplyFilter ) 452 || ( _nFeature == FormFeature::SortAscending ) 453 || ( _nFeature == FormFeature::SortDescending ) 454 || ( _nFeature == FormFeature::AutoFilter ) 455 || ( _nFeature == FormFeature::InteractiveSort ) 456 || ( _nFeature == FormFeature::InteractiveFilter ) 457 ); 458 } 459 static bool lcl_requiresArguments( sal_Int32 _nFeature ) 460 { 461 return ( _nFeature == FormFeature::MoveAbsolute ); 462 } 463 static bool lcl_isExecutableFeature( sal_Int32 _nFeature ) 464 { 465 return ( _nFeature != FormFeature::TotalRecords ); 466 } 467 } 468 469 //-------------------------------------------------------------------- 470 void SAL_CALL FormOperations::execute( ::sal_Int16 _nFeature ) throw (RuntimeException, IllegalArgumentException, SQLException, WrappedTargetException) 471 { 472 ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); 473 MethodGuard aGuard( *this ); 474 475 if ( ( _nFeature != FormFeature::DeleteRecord ) && ( _nFeature != FormFeature::UndoRecordChanges ) ) 476 { 477 // if we have a controller, commit the current control 478 if ( m_xController.is() ) 479 if ( !impl_commitCurrentControl_throw() ) 480 return; 481 482 // commit the current record 483 bool bCommitCurrentRecord = true; 484 // (but before, let the user confirm if necessary) 485 if ( impl_isModifiedRow_throw() ) 486 { 487 if ( lcl_needConfirmCommit( _nFeature ) ) 488 { 489 // TODO: shouldn't this be done with an interaction handler? 490 QueryBox aQuery( NULL, WB_YES_NO_CANCEL | WB_DEF_YES, FRM_RES_STRING( RID_STR_QUERY_SAVE_MODIFIED_ROW ) ); 491 switch ( aQuery.Execute() ) 492 { 493 case RET_NO: bCommitCurrentRecord = false; break; 494 case RET_CANCEL: return; 495 } 496 } 497 } 498 499 if ( bCommitCurrentRecord && !impl_commitCurrentRecord_throw() ) 500 return; 501 } 502 503 try 504 { 505 switch ( _nFeature ) 506 { 507 case FormFeature::MoveToFirst: 508 m_xCursor->first(); 509 break; 510 511 case FormFeature::MoveToNext: 512 impl_moveRight_throw( ); 513 break; 514 515 case FormFeature::MoveToPrevious: 516 impl_moveLeft_throw( ); 517 break; 518 519 case FormFeature::MoveToLast: 520 { 521 /* 522 // TODO: re-implement this ..... 523 // run in an own thread if ... 524 // ... the data source is thread safe ... 525 sal_Bool bAllowOwnThread = sal_False; 526 if ( ::comphelper::hasProperty( PROPERTY_THREADSAFE, m_xCursorProperties ) ) 527 m_xCursorProperties->getPropertyValue( PROPERTY_THREADSAFE ) >>= bAllowOwnThread; 528 529 // ... the record count is unknown 530 sal_Bool bNeedOwnThread sal_False; 531 if ( ::comphelper::hasProperty( PROPERTY_ROWCOUNTFINAL, m_xCursorProperties ) ) 532 m_xCursorProperties->getPropertyValue( PROPERTY_ROWCOUNTFINAL ) >>= bNeedOwnThread; 533 534 if ( bNeedOwnThread && bAllowOwnThread ) 535 ; 536 else 537 */ 538 m_xCursor->last(); 539 } 540 break; 541 542 case FormFeature::ReloadForm: 543 if ( m_xLoadableForm.is() ) 544 { 545 WaitObject aWO( NULL ); 546 m_xLoadableForm->reload(); 547 548 // refresh all controls in the form (and sub forms) which can be refreshed 549 // #i90914# / 2008-07-02 / frank.schoenheit@sun.com 550 ::comphelper::IndexAccessIterator aIter( m_xLoadableForm ); 551 Reference< XInterface > xElement( aIter.Next() ); 552 while ( xElement.is() ) 553 { 554 Reference< XRefreshable > xRefresh( xElement, UNO_QUERY ); 555 if ( xRefresh.is() ) 556 xRefresh->refresh(); 557 xElement = aIter.Next(); 558 } 559 } 560 break; 561 562 case FormFeature::RefreshCurrentControl: 563 { 564 Reference< XRefreshable > xControlModelRefresh( impl_getCurrentControlModel_throw(), UNO_QUERY ); 565 OSL_ENSURE( xControlModelRefresh.is(), "FormOperations::execute: how did you reach this?" ); 566 if ( xControlModelRefresh.is() ) 567 xControlModelRefresh->refresh(); 568 } 569 break; 570 571 case FormFeature::DeleteRecord: 572 { 573 sal_uInt32 nCount = impl_getRowCount_throw(); 574 575 // next position 576 sal_Bool bLeft = m_xCursor->isLast() && ( nCount > 1 ); 577 sal_Bool bRight= !m_xCursor->isLast(); 578 sal_Bool bSuccess = sal_False; 579 try 580 { 581 // ask for confirmation 582 Reference< XConfirmDeleteListener > xConfirmDelete( m_xController, UNO_QUERY ); 583 584 if ( xConfirmDelete.is() ) 585 { 586 RowChangeEvent aEvent; 587 aEvent.Source = Reference< XInterface >( m_xCursor, UNO_QUERY ); 588 aEvent.Action = RowChangeAction::DELETE; 589 aEvent.Rows = 1; 590 bSuccess = xConfirmDelete->confirmDelete( aEvent ); 591 } 592 593 // delete it 594 if ( bSuccess ) 595 m_xUpdateCursor->deleteRow(); 596 } 597 catch( const Exception& ) 598 { 599 bSuccess = sal_False; 600 } 601 602 if ( bSuccess ) 603 { 604 if ( bLeft || bRight ) 605 m_xCursor->relative( bRight ? 1 : -1 ); 606 else 607 { 608 sal_Bool bCanInsert = ::dbtools::canInsert( m_xCursorProperties ); 609 // is it possible to insert another record? 610 if ( bCanInsert ) 611 m_xUpdateCursor->moveToInsertRow(); 612 else 613 // move record to update stati 614 m_xCursor->first(); 615 } 616 } 617 } 618 break; 619 620 case FormFeature::SaveRecordChanges: 621 case FormFeature::UndoRecordChanges: 622 { 623 sal_Bool bInserting = impl_isInsertionRow_throw(); 624 625 if ( FormFeature::UndoRecordChanges == _nFeature ) 626 { 627 if ( !bInserting ) 628 m_xUpdateCursor->cancelRowUpdates(); 629 630 // reset all controls for this form 631 impl_resetAllControls_nothrow( ); 632 633 if ( bInserting ) // back to insertion mode for this form 634 m_xUpdateCursor->moveToInsertRow(); 635 } 636 else 637 { 638 if ( bInserting ) 639 { 640 m_xUpdateCursor->insertRow(); 641 m_xCursor->last(); 642 } 643 else 644 m_xUpdateCursor->updateRow(); 645 } 646 } 647 break; 648 649 case FormFeature::MoveToInsertRow: 650 // move to the last row before moving to the insert row 651 // 21.01.2002 - 96480 - fs@openoffice.org 652 m_xCursor->last(); 653 m_xUpdateCursor->moveToInsertRow(); 654 break; 655 656 case FormFeature::RemoveFilterAndSort: 657 { 658 // simultaneously reset Filter and Order property 659 Reference< XMultiPropertySet > xProperties( m_xCursorProperties, UNO_QUERY ); 660 OSL_ENSURE( xProperties.is(), "FormOperations::execute: no multi property access!" ); 661 if ( xProperties.is() ) 662 { 663 Sequence< ::rtl::OUString > aNames( 2 ); 664 aNames[0] = PROPERTY_FILTER; 665 aNames[1] = PROPERTY_SORT; 666 667 Sequence< Any> aValues( 2 ); 668 aValues[0] <<= ::rtl::OUString(); 669 aValues[1] <<= ::rtl::OUString(); 670 671 WaitObject aWO( NULL ); 672 xProperties->setPropertyValues( aNames, aValues ); 673 674 if ( m_xLoadableForm.is() ) 675 m_xLoadableForm->reload(); 676 } 677 } 678 break; 679 680 case FormFeature::ToggleApplyFilter: 681 if ( impl_commitCurrentControl_throw() && impl_commitCurrentRecord_throw() ) 682 { 683 // simply toggle the value 684 sal_Bool bApplied = sal_False; 685 m_xCursorProperties->getPropertyValue( PROPERTY_APPLYFILTER ) >>= bApplied; 686 m_xCursorProperties->setPropertyValue( PROPERTY_APPLYFILTER, makeAny( (sal_Bool)!bApplied ) ); 687 688 // and reload 689 WaitObject aWO( NULL ); 690 m_xLoadableForm->reload(); 691 } 692 break; 693 694 case FormFeature::SortAscending: 695 impl_executeAutoSort_throw( true ); 696 break; 697 698 case FormFeature::SortDescending: 699 impl_executeAutoSort_throw( false ); 700 break; 701 702 case FormFeature::AutoFilter: 703 impl_executeAutoFilter_throw(); 704 break; 705 706 case FormFeature::InteractiveSort: 707 impl_executeFilterOrSort_throw( false ); 708 break; 709 710 case FormFeature::InteractiveFilter: 711 impl_executeFilterOrSort_throw( true ); 712 break; 713 714 default: 715 { 716 sal_uInt16 nErrorResourceId = RID_STR_FEATURE_UNKNOWN; 717 if ( lcl_requiresArguments( _nFeature ) ) 718 nErrorResourceId = RID_STR_FEATURE_REQUIRES_PARAMETERS; 719 else if ( !lcl_isExecutableFeature( _nFeature ) ) 720 nErrorResourceId = RID_STR_FEATURE_NOT_EXECUTABLE; 721 throw IllegalArgumentException( FRM_RES_STRING( nErrorResourceId ), *this, 1 ); 722 } 723 } // switch 724 } 725 catch( const RuntimeException& ) { throw; } 726 catch( const SQLException& ) { throw; } 727 catch( const IllegalArgumentException& ) { throw; } 728 catch( const Exception& ) 729 { 730 throw WrappedTargetException( ::rtl::OUString(), *const_cast< FormOperations* >( this ), ::cppu::getCaughtException() ); 731 } 732 733 impl_invalidateAllSupportedFeatures_nothrow( aGuard ); 734 } 735 736 //-------------------------------------------------------------------- 737 void SAL_CALL FormOperations::executeWithArguments( ::sal_Int16 _nFeature, const Sequence< NamedValue >& _rArguments ) throw (RuntimeException, IllegalArgumentException, SQLException, WrappedTargetException) 738 { 739 if ( !lcl_requiresArguments( _nFeature ) ) 740 { 741 execute( _nFeature ); 742 return; 743 } 744 745 ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); 746 MethodGuard aGuard( *this ); 747 748 // at the moment we have only one feature which supports execution parameters 749 if ( !lcl_isExecutableFeature( _nFeature ) ) 750 throw IllegalArgumentException( FRM_RES_STRING( RID_STR_FEATURE_NOT_EXECUTABLE ), *this, 1 ); 751 752 switch ( _nFeature ) 753 { 754 case FormFeature::MoveAbsolute: 755 { 756 sal_Int32 nPosition = -1; 757 758 ::comphelper::NamedValueCollection aArguments( _rArguments ); 759 aArguments.get_ensureType( "Position", nPosition ); 760 761 if ( nPosition < 1 ) 762 nPosition = 1; 763 764 try 765 { 766 // commit before doing anything else 767 if ( m_xController.is() && !impl_commitCurrentControl_throw() ) 768 return; 769 if ( !impl_commitCurrentRecord_throw() ) 770 return; 771 772 sal_Int32 nCount = impl_getRowCount_throw(); 773 sal_Bool bFinalCount = impl_isRowCountFinal_throw(); 774 775 if ( bFinalCount && ( (sal_Int32)nPosition > nCount ) ) 776 nPosition = nCount; 777 778 m_xCursor->absolute( nPosition ); 779 } 780 catch( const RuntimeException& ) { throw; } 781 catch( const SQLException& ) { throw; } 782 catch( const Exception& ) 783 { 784 throw WrappedTargetException( ::rtl::OUString(), *this, ::cppu::getCaughtException() ); 785 } 786 } 787 break; 788 default: 789 throw IllegalArgumentException( FRM_RES_STRING( RID_STR_FEATURE_UNKNOWN ), *this, 1 ); 790 } // switch 791 } 792 793 //-------------------------------------------------------------------- 794 ::sal_Bool SAL_CALL FormOperations::commitCurrentRecord( ::sal_Bool& _out_rRecordInserted ) throw (RuntimeException, SQLException) 795 { 796 MethodGuard aGuard( *this ); 797 _out_rRecordInserted = sal_False; 798 799 return impl_commitCurrentRecord_throw( &_out_rRecordInserted ); 800 } 801 802 //-------------------------------------------------------------------- 803 bool FormOperations::impl_commitCurrentRecord_throw( ::sal_Bool* _pRecordInserted ) const 804 { 805 DBG_ASSERT( m_nMethodNestingLevel, "FormOperations::impl_commitCurrentRecord_throw: to be called within a MethodGuard'ed section only!" ); 806 807 if ( !impl_hasCursor_nothrow() ) 808 return false; 809 810 // nothing to do if the record is not modified 811 sal_Bool bResult = !impl_isModifiedRow_throw(); 812 if ( !bResult ) 813 { 814 // insert respectively update the row 815 if ( impl_isInsertionRow_throw() ) 816 { 817 m_xUpdateCursor->insertRow(); 818 if ( _pRecordInserted ) 819 *_pRecordInserted = sal_True; 820 } 821 else 822 m_xUpdateCursor->updateRow(); 823 bResult = true; 824 } 825 return bResult; 826 } 827 828 //-------------------------------------------------------------------- 829 ::sal_Bool SAL_CALL FormOperations::commitCurrentControl() throw (RuntimeException, SQLException) 830 { 831 MethodGuard aGuard( *this ); 832 return impl_commitCurrentControl_throw(); 833 } 834 835 //-------------------------------------------------------------------- 836 bool FormOperations::impl_commitCurrentControl_throw() const 837 { 838 DBG_ASSERT( m_nMethodNestingLevel, "FormOperations::impl_commitCurrentRecord_throw: to be called within a MethodGuard'ed section only!" ); 839 OSL_PRECOND( m_xController.is(), "FormOperations::commitCurrentControl: no controller!" ); 840 if ( !m_xController.is() ) 841 return false; 842 843 bool bSuccess = false; 844 try 845 { 846 Reference< XControl > xCurrentControl( m_xController->getCurrentControl() ); 847 848 // check whether the control is locked 849 Reference< XBoundControl > xCheckLock( xCurrentControl, UNO_QUERY ); 850 sal_Bool bControlIsLocked = xCheckLock.is() && xCheckLock->getLock(); 851 852 // commit if necessary 853 bSuccess = true; 854 if ( xCurrentControl.is() && !bControlIsLocked ) 855 { 856 // both the control and it's model can be committable, so try both 857 Reference< XBoundComponent > xBound( xCurrentControl, UNO_QUERY ); 858 if ( !xBound.is() ) 859 xBound = xBound.query( xCurrentControl->getModel() ); 860 // and now really commit 861 if ( xBound.is() ) 862 bSuccess = xBound->commit(); 863 } 864 865 } 866 catch( const RuntimeException& ) { throw; } 867 catch( const SQLException& ) { throw; } 868 catch( const Exception& ) 869 { 870 DBG_UNHANDLED_EXCEPTION(); 871 bSuccess = false; 872 } 873 874 return bSuccess; 875 } 876 877 //-------------------------------------------------------------------- 878 ::sal_Bool SAL_CALL FormOperations::isInsertionRow() throw (RuntimeException, WrappedTargetException) 879 { 880 sal_Bool bIs = sal_False; 881 try 882 { 883 bIs = impl_isInsertionRow_throw(); 884 } 885 catch( const RuntimeException& ) { throw; } 886 catch( const Exception& ) 887 { 888 throw WrappedTargetException( ::rtl::OUString(), *this, ::cppu::getCaughtException() ); 889 } 890 return bIs; 891 } 892 893 //-------------------------------------------------------------------- 894 ::sal_Bool SAL_CALL FormOperations::isModifiedRow() throw (RuntimeException, WrappedTargetException) 895 { 896 sal_Bool bIs = sal_False; 897 try 898 { 899 bIs = impl_isModifiedRow_throw(); 900 } 901 catch( const RuntimeException& ) { throw; } 902 catch( const Exception& ) 903 { 904 throw WrappedTargetException( ::rtl::OUString(), *this, ::cppu::getCaughtException() ); 905 } 906 return bIs; 907 } 908 909 //-------------------------------------------------------------------- 910 void SAL_CALL FormOperations::cursorMoved( const EventObject& /*_Event*/ ) throw (RuntimeException) 911 { 912 MethodGuard aGuard( *this ); 913 m_bActiveControlModified = sal_False; 914 915 impl_invalidateAllSupportedFeatures_nothrow( aGuard ); 916 } 917 918 //-------------------------------------------------------------------- 919 void SAL_CALL FormOperations::rowChanged( const EventObject& /*_Event*/ ) throw (RuntimeException) 920 { 921 // not interested in 922 } 923 924 //-------------------------------------------------------------------- 925 void SAL_CALL FormOperations::rowSetChanged( const EventObject& /*_Event*/ ) throw (RuntimeException) 926 { 927 // not interested in 928 } 929 930 //-------------------------------------------------------------------- 931 void SAL_CALL FormOperations::modified( const EventObject& /*_Source*/ ) throw( RuntimeException ) 932 { 933 MethodGuard aGuard( *this ); 934 935 OSL_ENSURE( m_xCursor.is(), "FormOperations::modified: already disposed!" ); 936 if ( !m_bActiveControlModified ) 937 { 938 m_bActiveControlModified = sal_True; 939 impl_invalidateModifyDependentFeatures_nothrow( aGuard ); 940 } 941 } 942 943 //-------------------------------------------------------------------- 944 void SAL_CALL FormOperations::propertyChange( const PropertyChangeEvent& _rEvent ) throw (RuntimeException) 945 { 946 MethodGuard aGuard( *this ); 947 948 if ( m_xCursor.is() && ( m_xCursor == _rEvent.Source ) ) 949 { 950 sal_Bool bIs = sal_False; 951 if ( ( _rEvent.PropertyName == PROPERTY_ISMODIFIED ) 952 || ( _rEvent.PropertyName == PROPERTY_ISNEW ) 953 ) 954 { 955 if ( ( _rEvent.NewValue >>= bIs ) && !bIs ) 956 m_bActiveControlModified = sal_False; 957 } 958 impl_invalidateAllSupportedFeatures_nothrow( aGuard ); 959 } 960 961 if ( m_xParser.is() && ( m_xCursor == _rEvent.Source ) ) 962 { 963 try 964 { 965 ::rtl::OUString sNewValue; 966 _rEvent.NewValue >>= sNewValue; 967 if ( _rEvent.PropertyName == PROPERTY_ACTIVECOMMAND ) 968 { 969 m_xParser->setElementaryQuery( sNewValue ); 970 } 971 else if ( _rEvent.PropertyName == PROPERTY_FILTER ) 972 { 973 if ( m_xParser->getFilter() != sNewValue ) 974 m_xParser->setFilter( sNewValue ); 975 } 976 else if ( _rEvent.PropertyName == PROPERTY_SORT ) 977 { 978 _rEvent.NewValue >>= sNewValue; 979 if ( m_xParser->getOrder() != sNewValue ) 980 m_xParser->setOrder( sNewValue ); 981 } 982 } 983 catch( Exception& ) 984 { 985 OSL_ENSURE( sal_False, "FormOperations::propertyChange: caught an exception while updating the parser!" ); 986 } 987 impl_invalidateAllSupportedFeatures_nothrow( aGuard ); 988 } 989 } 990 991 //-------------------------------------------------------------------- 992 void SAL_CALL FormOperations::disposing( const EventObject& /*_Source*/ ) throw (RuntimeException) 993 { 994 // TODO: should we react on this? Or is this the responsibility of our owner to dispose us? 995 } 996 997 //-------------------------------------------------------------------- 998 void SAL_CALL FormOperations::disposing() 999 { 1000 ::osl::MutexGuard aGuard( m_aMutex ); 1001 1002 impl_disposeParser_nothrow(); 1003 1004 try 1005 { 1006 // revoke various listeners 1007 if ( m_xCursor.is() ) 1008 m_xCursor->removeRowSetListener( this ); 1009 1010 if ( m_xCursorProperties.is() ) 1011 { 1012 m_xCursorProperties->removePropertyChangeListener( PROPERTY_ISMODIFIED,this ); 1013 m_xCursorProperties->removePropertyChangeListener( PROPERTY_ISNEW, this ); 1014 } 1015 1016 Reference< XModifyBroadcaster > xBroadcaster( m_xController, UNO_QUERY ); 1017 if ( xBroadcaster.is() ) 1018 xBroadcaster->removeModifyListener( this ); 1019 } 1020 catch( const Exception& ) 1021 { 1022 DBG_UNHANDLED_EXCEPTION(); 1023 } 1024 1025 m_xController.clear(); 1026 m_xCursor.clear(); 1027 m_xUpdateCursor.clear(); 1028 m_xCursorProperties.clear(); 1029 m_xLoadableForm.clear(); 1030 m_xFeatureInvalidation.clear(); 1031 1032 m_bActiveControlModified = true; 1033 } 1034 1035 //-------------------------------------------------------------------- 1036 void FormOperations::impl_checkDisposed_throw() const 1037 { 1038 if ( impl_isDisposed_nothrow() ) 1039 throw DisposedException( ::rtl::OUString(), *const_cast< FormOperations* >( this ) ); 1040 } 1041 1042 //-------------------------------------------------------------------- 1043 void FormOperations::impl_initFromController_throw() 1044 { 1045 OSL_PRECOND( m_xController.is(), "FormOperations::impl_initFromController_throw: invalid controller!" ); 1046 m_xCursor = m_xCursor.query( m_xController->getModel() ); 1047 if ( !m_xCursor.is() ) 1048 throw IllegalArgumentException( ::rtl::OUString(), *this, 0 ); 1049 1050 impl_initFromForm_throw(); 1051 1052 Reference< XModifyBroadcaster > xBroadcaster( m_xController, UNO_QUERY ); 1053 if ( xBroadcaster.is() ) 1054 xBroadcaster->addModifyListener( this ); 1055 } 1056 1057 //-------------------------------------------------------------------- 1058 void FormOperations::impl_initFromForm_throw() 1059 { 1060 OSL_PRECOND( m_xCursor.is(), "FormOperations::impl_initFromForm_throw: invalid form!" ); 1061 m_xCursorProperties = m_xCursorProperties.query ( m_xCursor ); 1062 m_xUpdateCursor = m_xUpdateCursor.query ( m_xCursor ); 1063 m_xLoadableForm = m_xLoadableForm.query ( m_xCursor ); 1064 1065 if ( !m_xCursor.is() || !m_xCursorProperties.is() || !m_xLoadableForm.is() ) 1066 throw IllegalArgumentException( ::rtl::OUString(), *this, 0 ); 1067 1068 m_xCursor->addRowSetListener( this ); 1069 m_xCursorProperties->addPropertyChangeListener( PROPERTY_ISMODIFIED,this ); 1070 m_xCursorProperties->addPropertyChangeListener( PROPERTY_ISNEW, this ); 1071 } 1072 1073 //-------------------------------------------------------------------- 1074 void FormOperations::createWithFormController( const Reference< XFormController >& _rxController ) 1075 { 1076 m_xController = _rxController; 1077 if ( !m_xController.is() ) 1078 throw IllegalArgumentException( ::rtl::OUString(), *this, 0 ); 1079 1080 impl_initFromController_throw(); 1081 1082 m_bConstructed = true; 1083 } 1084 1085 //-------------------------------------------------------------------- 1086 void FormOperations::createWithForm( const Reference< XForm >& _rxForm ) 1087 { 1088 m_xCursor = m_xCursor.query( _rxForm ); 1089 if ( !m_xCursor.is() ) 1090 throw IllegalArgumentException( ::rtl::OUString(), *this, 0 ); 1091 1092 impl_initFromForm_throw(); 1093 1094 m_bConstructed = true; 1095 } 1096 1097 //------------------------------------------------------------------------------ 1098 void FormOperations::impl_invalidateAllSupportedFeatures_nothrow( MethodGuard& _rClearForCallback ) const 1099 { 1100 if ( !m_xFeatureInvalidation.is() ) 1101 // nobody's interested in ... 1102 return; 1103 1104 Reference< XFeatureInvalidation > xInvalidation = m_xFeatureInvalidation; 1105 _rClearForCallback.clear(); 1106 xInvalidation->invalidateAllFeatures(); 1107 } 1108 1109 //------------------------------------------------------------------------------ 1110 void FormOperations::impl_invalidateModifyDependentFeatures_nothrow( MethodGuard& _rClearForCallback ) const 1111 { 1112 if ( !m_xFeatureInvalidation.is() ) 1113 // nobody's interested in ... 1114 return; 1115 1116 static Sequence< sal_Int16 > s_aModifyDependentFeatures; 1117 if ( s_aModifyDependentFeatures.getLength() == 0 ) 1118 { 1119 sal_Int16 pModifyDependentFeatures[] = 1120 { 1121 FormFeature::MoveToNext, 1122 FormFeature::MoveToInsertRow, 1123 FormFeature::SaveRecordChanges, 1124 FormFeature::UndoRecordChanges 1125 }; 1126 size_t nFeatureCount = sizeof( pModifyDependentFeatures ) / sizeof( pModifyDependentFeatures[ 0 ] ); 1127 s_aModifyDependentFeatures = Sequence< sal_Int16 >( pModifyDependentFeatures, nFeatureCount ); 1128 } 1129 1130 Reference< XFeatureInvalidation > xInvalidation = m_xFeatureInvalidation; 1131 _rClearForCallback.clear(); 1132 1133 xInvalidation->invalidateFeatures( s_aModifyDependentFeatures ); 1134 } 1135 1136 //-------------------------------------------------------------------- 1137 void FormOperations::impl_ensureInitializedParser_nothrow() 1138 { 1139 OSL_PRECOND( m_xCursorProperties.is(), "FormOperations::impl_ensureInitializedParser_nothrow: we're disposed!" ); 1140 if ( m_bInitializedParser ) 1141 return; 1142 1143 try 1144 { 1145 sal_Bool bUseEscapeProcessing = sal_False; 1146 m_xCursorProperties->getPropertyValue( PROPERTY_ESCAPE_PROCESSING ) >>= bUseEscapeProcessing; 1147 if ( bUseEscapeProcessing ) 1148 { 1149 Reference< XMultiServiceFactory > xFactory( ::dbtools::getConnection( m_xCursor ), UNO_QUERY ); 1150 if ( xFactory.is() ) 1151 { 1152 m_xParser.set( xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdb.SingleSelectQueryComposer" ) ) ), UNO_QUERY ); 1153 OSL_ENSURE( m_xParser.is(), "FormOperations::impl_ensureInitializedParser_nothrow: factory did not create a parser for us!" ); 1154 } 1155 } 1156 1157 if ( m_xParser.is() ) 1158 { 1159 if ( m_xLoadableForm.is() && m_xLoadableForm->isLoaded() ) 1160 { 1161 ::rtl::OUString sStatement; 1162 ::rtl::OUString sFilter; 1163 ::rtl::OUString sSort; 1164 1165 m_xCursorProperties->getPropertyValue( PROPERTY_ACTIVECOMMAND ) >>= sStatement; 1166 m_xCursorProperties->getPropertyValue( PROPERTY_FILTER ) >>= sFilter; 1167 m_xCursorProperties->getPropertyValue( PROPERTY_SORT ) >>= sSort; 1168 1169 m_xParser->setElementaryQuery( sStatement ); 1170 m_xParser->setFilter ( sFilter ); 1171 m_xParser->setOrder ( sSort ); 1172 } 1173 1174 // start listening at the order/sort properties at the form, so 1175 // we can keep our parser in sync 1176 m_xCursorProperties->addPropertyChangeListener( PROPERTY_ACTIVECOMMAND, this ); 1177 m_xCursorProperties->addPropertyChangeListener( PROPERTY_FILTER, this ); 1178 m_xCursorProperties->addPropertyChangeListener( PROPERTY_SORT, this ); 1179 } 1180 } 1181 catch( const Exception& ) 1182 { 1183 OSL_ENSURE( sal_False, "FormOperations::impl_ensureInitializedParser_nothrow: caught an exception!" ); 1184 } 1185 1186 m_bInitializedParser = true; 1187 } 1188 1189 //-------------------------------------------------------------------- 1190 void FormOperations::impl_disposeParser_nothrow() 1191 { 1192 try 1193 { 1194 // if we have a parser (and a cursor), then we're listening at the cursor's 1195 // properties to keep the parser in sync with the cursor 1196 if ( m_xParser.is() && m_xCursorProperties.is() ) 1197 { 1198 m_xCursorProperties->removePropertyChangeListener( PROPERTY_FILTER, this ); 1199 m_xCursorProperties->removePropertyChangeListener( PROPERTY_ACTIVECOMMAND, this ); 1200 m_xCursorProperties->removePropertyChangeListener( PROPERTY_SORT, this ); 1201 } 1202 1203 Reference< XComponent > xParserComp( m_xParser, UNO_QUERY ); 1204 if ( xParserComp.is() ) 1205 xParserComp->dispose(); 1206 m_xParser.clear(); 1207 1208 m_bInitializedParser = false; 1209 } 1210 catch( const Exception& ) 1211 { 1212 OSL_ENSURE( sal_False, "FormOperations::impl_disposeParser_nothrow: caught an exception!" ); 1213 } 1214 } 1215 1216 //-------------------------------------------------------------------- 1217 bool FormOperations::impl_canMoveLeft_throw( ) const 1218 { 1219 if ( !impl_hasCursor_nothrow() ) 1220 return false; 1221 1222 return impl_getRowCount_throw() && ( !m_xCursor->isFirst() || impl_isInsertionRow_throw() ); 1223 } 1224 1225 //-------------------------------------------------------------------- 1226 bool FormOperations::impl_canMoveRight_throw( ) const 1227 { 1228 if ( !impl_hasCursor_nothrow() ) 1229 return false; 1230 1231 bool bIsNew = impl_isInsertionRow_throw(); 1232 1233 if ( impl_getRowCount_throw() && !m_xCursor->isLast() && !bIsNew ) 1234 return true; 1235 1236 if ( ::dbtools::canInsert( m_xCursorProperties ) ) 1237 if ( !bIsNew || impl_isModifiedRow_throw() ) 1238 return true; 1239 1240 if ( bIsNew && m_bActiveControlModified ) 1241 return true; 1242 1243 return false; 1244 } 1245 1246 //-------------------------------------------------------------------- 1247 namespace 1248 { 1249 template < typename TYPE > 1250 TYPE lcl_safeGetPropertyValue_throw( const Reference< XPropertySet >& _rxProperties, const ::rtl::OUString& _rPropertyName, TYPE _Default ) 1251 { 1252 TYPE value( _Default ); 1253 OSL_PRECOND( _rxProperties.is(), "FormOperations::<foo>: no cursor (already disposed?)!" ); 1254 if ( _rxProperties.is() ) 1255 OSL_VERIFY( _rxProperties->getPropertyValue( _rPropertyName ) >>= value ); 1256 return value; 1257 } 1258 } 1259 1260 //-------------------------------------------------------------------- 1261 bool FormOperations::impl_isInsertionRow_throw() const 1262 { 1263 return lcl_safeGetPropertyValue_throw( m_xCursorProperties, PROPERTY_ISNEW, false ); 1264 } 1265 1266 //-------------------------------------------------------------------- 1267 sal_Int32 FormOperations::impl_getRowCount_throw() const 1268 { 1269 return lcl_safeGetPropertyValue_throw( m_xCursorProperties, PROPERTY_ROWCOUNT, (sal_Int32)0 ); 1270 } 1271 //-------------------------------------------------------------------- 1272 bool FormOperations::impl_isRowCountFinal_throw() const 1273 { 1274 return lcl_safeGetPropertyValue_throw( m_xCursorProperties, PROPERTY_ROWCOUNTFINAL, false ); 1275 } 1276 1277 //-------------------------------------------------------------------- 1278 bool FormOperations::impl_isModifiedRow_throw() const 1279 { 1280 return lcl_safeGetPropertyValue_throw( m_xCursorProperties, PROPERTY_ISMODIFIED, false ); 1281 } 1282 1283 //-------------------------------------------------------------------- 1284 bool FormOperations::impl_isParseable_throw() const 1285 { 1286 const_cast< FormOperations* >( this )->impl_ensureInitializedParser_nothrow(); 1287 return m_xParser.is() && m_xParser->getQuery().getLength(); 1288 } 1289 1290 //-------------------------------------------------------------------- 1291 bool FormOperations::impl_hasFilterOrOrder_throw() const 1292 { 1293 return impl_isParseable_throw() && ( m_xParser->getFilter().getLength() || m_xParser->getOrder().getLength() ); 1294 } 1295 1296 //-------------------------------------------------------------------- 1297 bool FormOperations::impl_isInsertOnlyForm_throw() const 1298 { 1299 return lcl_safeGetPropertyValue_throw( m_xCursorProperties, PROPERTY_INSERTONLY, true ); 1300 } 1301 1302 //------------------------------------------------------------------------------ 1303 Reference< XControlModel > FormOperations::impl_getCurrentControlModel_throw() const 1304 { 1305 Reference< XControl > xControl( m_xController->getCurrentControl() ); 1306 1307 // special handling for grid controls 1308 Reference< XGrid > xGrid( xControl, UNO_QUERY ); 1309 Reference< XControlModel > xControlModel; 1310 1311 if ( xGrid.is() ) 1312 { 1313 Reference< XIndexAccess > xColumns( xControl->getModel(), UNO_QUERY_THROW ); 1314 sal_Int16 nCurrentPos = xGrid->getCurrentColumnPosition(); 1315 nCurrentPos = impl_gridView2ModelPos_nothrow( xColumns, nCurrentPos ); 1316 1317 if ( nCurrentPos != (sal_Int16)-1 ) 1318 xColumns->getByIndex( nCurrentPos ) >>= xControlModel; 1319 } 1320 else if ( xControl.is() ) 1321 { 1322 xControlModel = xControl->getModel(); 1323 } 1324 return xControlModel; 1325 } 1326 1327 //------------------------------------------------------------------------------ 1328 Reference< XPropertySet > FormOperations::impl_getCurrentBoundField_nothrow( ) const 1329 { 1330 OSL_PRECOND( m_xController.is(), "FormOperations::impl_getCurrentBoundField_nothrow: no controller -> no control!" ); 1331 if ( !m_xController.is() ) 1332 return NULL; 1333 1334 Reference< XPropertySet > xField; 1335 try 1336 { 1337 Reference< XPropertySet > xControlModel( impl_getCurrentControlModel_throw(), UNO_QUERY ); 1338 1339 if ( xControlModel.is() && ::comphelper::hasProperty( PROPERTY_BOUNDFIELD, xControlModel ) ) 1340 xControlModel->getPropertyValue( PROPERTY_BOUNDFIELD ) >>= xField; 1341 1342 } 1343 catch( const Exception& ) 1344 { 1345 DBG_UNHANDLED_EXCEPTION(); 1346 } 1347 1348 return xField; 1349 } 1350 1351 //------------------------------------------------------------------------------ 1352 sal_Int16 FormOperations::impl_gridView2ModelPos_nothrow( const Reference< XIndexAccess >& _rxColumns, sal_Int16 _nViewPos ) const 1353 { 1354 OSL_PRECOND( _rxColumns.is(), "FormOperations::impl_gridView2ModelPos_nothrow: invalid columns container!" ); 1355 try 1356 { 1357 // loop through all columns 1358 sal_Int16 col = 0; 1359 Reference< XPropertySet > xCol; 1360 bool bHidden( false ); 1361 for ( col = 0; col < _rxColumns->getCount(); ++col ) 1362 { 1363 _rxColumns->getByIndex( col ) >>= xCol; 1364 OSL_VERIFY( xCol->getPropertyValue( PROPERTY_HIDDEN ) >>= bHidden ); 1365 if ( bHidden ) 1366 continue; 1367 1368 // for every visible col : if nViewPos is greater zero, decrement it, else we 1369 // have found the model position 1370 if ( !_nViewPos ) 1371 break; 1372 else 1373 --_nViewPos; 1374 } 1375 if ( col < _rxColumns->getCount() ) 1376 return col; 1377 } 1378 catch( const Exception& ) 1379 { 1380 DBG_UNHANDLED_EXCEPTION(); 1381 } 1382 return (sal_Int16)-1; 1383 } 1384 1385 //------------------------------------------------------------------------------ 1386 bool FormOperations::impl_moveLeft_throw( ) const 1387 { 1388 OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_moveLeft_throw: no cursor!" ); 1389 if ( !impl_hasCursor_nothrow() ) 1390 return false; 1391 1392 sal_Bool bRecordInserted = sal_False; 1393 sal_Bool bSuccess = impl_commitCurrentRecord_throw( &bRecordInserted ); 1394 1395 if ( !bSuccess ) 1396 return false; 1397 1398 if ( bRecordInserted ) 1399 { 1400 // retrieve the bookmark of the new record and move to the record preceding this bookmark 1401 Reference< XRowLocate > xLocate( m_xCursor, UNO_QUERY ); 1402 OSL_ENSURE( xLocate.is(), "FormOperations::impl_moveLeft_throw: no XRowLocate!" ); 1403 if ( xLocate.is() ) 1404 xLocate->moveRelativeToBookmark( xLocate->getBookmark(), -1 ); 1405 } 1406 else 1407 { 1408 if ( impl_isInsertionRow_throw() ) 1409 { 1410 // we assume that the inserted record is now the last record in the 1411 // result set 1412 m_xCursor->last(); 1413 } 1414 else 1415 m_xCursor->previous(); 1416 } 1417 1418 return true; 1419 } 1420 1421 //-------------------------------------------------------------------- 1422 bool FormOperations::impl_moveRight_throw( ) const 1423 { 1424 OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_moveRight_throw: no cursor!" ); 1425 if ( !impl_hasCursor_nothrow() ) 1426 return false; 1427 1428 sal_Bool bRecordInserted = sal_False; 1429 sal_Bool bSuccess = impl_commitCurrentRecord_throw( &bRecordInserted ); 1430 1431 if ( !bSuccess ) 1432 return false; 1433 1434 if ( bRecordInserted ) 1435 { 1436 // go to insert row 1437 m_xUpdateCursor->moveToInsertRow(); 1438 } 1439 else 1440 { 1441 if ( m_xCursor->isLast() ) 1442 m_xUpdateCursor->moveToInsertRow(); 1443 else 1444 m_xCursor->next(); 1445 } 1446 1447 return true; 1448 } 1449 1450 //-------------------------------------------------------------------- 1451 void FormOperations::impl_resetAllControls_nothrow() const 1452 { 1453 Reference< XIndexAccess > xContainer( m_xCursor, UNO_QUERY ); 1454 if ( !xContainer.is() ) 1455 return; 1456 1457 try 1458 { 1459 Reference< XReset > xReset; 1460 sal_Int32 nCount( xContainer->getCount() ); 1461 for ( sal_Int32 i = 0; i < nCount; ++i ) 1462 { 1463 if ( xContainer->getByIndex( i ) >>= xReset ) 1464 { 1465 // no resets on sub forms 1466 Reference< XForm > xAsForm( xReset, UNO_QUERY ); 1467 if ( !xAsForm.is() ) 1468 xReset->reset(); 1469 } 1470 } 1471 } 1472 catch( const Exception& ) 1473 { 1474 DBG_UNHANDLED_EXCEPTION(); 1475 } 1476 } 1477 1478 //------------------------------------------------------------------------------ 1479 void FormOperations::impl_executeAutoSort_throw( bool _bUp ) const 1480 { 1481 OSL_PRECOND( m_xController.is(), "FormOperations::impl_executeAutoSort_throw: need a controller for this!" ); 1482 OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_executeAutoSort_throw: need a cursor for this!" ); 1483 OSL_PRECOND( impl_isParseable_throw(), "FormOperations::impl_executeAutoSort_throw: need a parseable statement for this!" ); 1484 if ( !m_xController.is() || !impl_hasCursor_nothrow() || !impl_isParseable_throw() ) 1485 return; 1486 1487 try 1488 { 1489 Reference< XControl > xControl = m_xController->getCurrentControl(); 1490 if ( !xControl.is() || !impl_commitCurrentControl_throw() || !impl_commitCurrentRecord_throw() ) 1491 return; 1492 1493 Reference< XPropertySet > xBoundField( impl_getCurrentBoundField_nothrow() ); 1494 if ( !xBoundField.is() ) 1495 return; 1496 1497 ::rtl::OUString sOriginalSort; 1498 m_xCursorProperties->getPropertyValue( PROPERTY_SORT ) >>= sOriginalSort; 1499 1500 // automatic sort by field is expected to always resets the previous sort order 1501 m_xParser->setOrder( ::rtl::OUString() ); 1502 1503 param_appendOrderByColumn aParam; 1504 aParam.xField = xBoundField; 1505 aParam.bUp = _bUp; 1506 impl_doActionInSQLContext_throw( 1507 (Action)&FormOperations::impl_appendOrderByColumn_throw, 1508 static_cast< const void* >( &aParam ), 1509 (sal_uInt16)RID_STR_COULD_NOT_SET_ORDER 1510 ); 1511 1512 WaitObject aWO( NULL ); 1513 try 1514 { 1515 m_xCursorProperties->setPropertyValue( PROPERTY_SORT, makeAny( m_xParser->getOrder() ) ); 1516 m_xLoadableForm->reload(); 1517 } 1518 catch( const Exception& ) 1519 { 1520 OSL_ENSURE( sal_False, "FormOperations::impl_executeAutoSort_throw: caught an exception while setting the parser properties!" ); 1521 } 1522 1523 1524 if ( !m_xLoadableForm->isLoaded() ) 1525 { // something went wrong -> restore the original state 1526 try 1527 { 1528 m_xParser->setOrder( sOriginalSort ); 1529 m_xCursorProperties->setPropertyValue( PROPERTY_SORT, makeAny( m_xParser->getOrder() ) ); 1530 m_xLoadableForm->reload(); 1531 } 1532 catch( const Exception& ) 1533 { 1534 OSL_ENSURE( sal_False, "FormOperations::impl_executeAutoSort_throw: could not reset the form to it's original state!" ); 1535 } 1536 1537 } 1538 } 1539 catch( const RuntimeException& ) { throw; } 1540 catch( const SQLException& ) { throw; } 1541 catch( const Exception& ) 1542 { 1543 throw WrappedTargetException( ::rtl::OUString(), *const_cast< FormOperations* >( this ), ::cppu::getCaughtException() ); 1544 } 1545 } 1546 1547 //------------------------------------------------------------------------------ 1548 void FormOperations::impl_executeAutoFilter_throw( ) const 1549 { 1550 OSL_PRECOND( m_xController.is(), "FormOperations::impl_executeAutoFilter_throw: need a controller for this!" ); 1551 OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_executeAutoFilter_throw: need a cursor for this!" ); 1552 OSL_PRECOND( impl_isParseable_throw(), "FormOperations::impl_executeAutoFilter_throw: need a parseable statement for this!" ); 1553 if ( !m_xController.is() || !impl_hasCursor_nothrow() || !impl_isParseable_throw() ) 1554 return; 1555 1556 try 1557 { 1558 Reference< XControl > xControl = m_xController->getCurrentControl(); 1559 if ( !xControl.is() || !impl_commitCurrentControl_throw() || !impl_commitCurrentRecord_throw() ) 1560 return; 1561 1562 Reference< XPropertySet > xBoundField( impl_getCurrentBoundField_nothrow() ); 1563 if ( !xBoundField.is() ) 1564 return; 1565 1566 ::rtl::OUString sOriginalFilter; 1567 m_xCursorProperties->getPropertyValue( PROPERTY_FILTER ) >>= sOriginalFilter; 1568 sal_Bool bApplied = sal_True; 1569 m_xCursorProperties->getPropertyValue( PROPERTY_APPLYFILTER ) >>= bApplied; 1570 1571 // if we have a filter, but it's not applied, then we have to overwrite it, else append one 1572 if ( !bApplied ) 1573 m_xParser->setFilter( ::rtl::OUString() ); 1574 1575 param_appendFilterByColumn aParam; 1576 aParam.xField = xBoundField; 1577 impl_doActionInSQLContext_throw( 1578 (Action)&FormOperations::impl_appendFilterByColumn_throw, 1579 static_cast< const void* >( &aParam ), 1580 (sal_uInt16)RID_STR_COULD_NOT_SET_FILTER 1581 ); 1582 1583 WaitObject aWO( NULL ); 1584 try 1585 { 1586 m_xCursorProperties->setPropertyValue( PROPERTY_FILTER, makeAny( m_xParser->getFilter() ) ); 1587 m_xCursorProperties->setPropertyValue( PROPERTY_APPLYFILTER, makeAny( (sal_Bool)sal_True ) ); 1588 1589 m_xLoadableForm->reload(); 1590 } 1591 catch( const Exception& ) 1592 { 1593 OSL_ENSURE( sal_False, "FormOperations::impl_executeAutoFilter_throw: caught an exception while setting the parser properties!" ); 1594 } 1595 1596 1597 if ( !m_xLoadableForm->isLoaded() ) 1598 { // something went wrong -> restore the original state 1599 try 1600 { 1601 m_xParser->setOrder( sOriginalFilter ); 1602 m_xCursorProperties->setPropertyValue( PROPERTY_APPLYFILTER, makeAny( (sal_Bool)bApplied ) ); 1603 m_xCursorProperties->setPropertyValue( PROPERTY_FILTER, makeAny( m_xParser->getFilter() ) ); 1604 m_xLoadableForm->reload(); 1605 } 1606 catch( const Exception& ) 1607 { 1608 OSL_ENSURE( sal_False, "FormOperations::impl_executeAutoFilter_throw: could not reset the form to it's original state!" ); 1609 } 1610 1611 } 1612 } 1613 catch( const RuntimeException& ) { throw; } 1614 catch( const SQLException& ) { throw; } 1615 catch( const Exception& ) 1616 { 1617 throw WrappedTargetException( ::rtl::OUString(), *const_cast< FormOperations* >( this ), ::cppu::getCaughtException() ); 1618 } 1619 } 1620 1621 //-------------------------------------------------------------------- 1622 void FormOperations::impl_executeFilterOrSort_throw( bool _bFilter ) const 1623 { 1624 OSL_PRECOND( m_xController.is(), "FormOperations::impl_executeFilterOrSort_throw: need a controller for this!" ); 1625 OSL_PRECOND( impl_hasCursor_nothrow(), "FormOperations::impl_executeFilterOrSort_throw: need a cursor for this!" ); 1626 OSL_PRECOND( impl_isParseable_throw(), "FormOperations::impl_executeFilterOrSort_throw: need a parseable statement for this!" ); 1627 if ( !m_xController.is() || !impl_hasCursor_nothrow() || !impl_isParseable_throw() ) 1628 return; 1629 1630 if ( !impl_commitCurrentControl_throw() || !impl_commitCurrentRecord_throw() ) 1631 return; 1632 try 1633 { 1634 PropertyValue aFirst; 1635 aFirst.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "QueryComposer" ) ); 1636 aFirst.Value <<= m_xParser; 1637 1638 PropertyValue aSecond; 1639 aSecond.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "RowSet" ) ); 1640 aSecond.Value <<= m_xCursorProperties; 1641 1642 Sequence<Any> aInit(2); 1643 aInit[0] <<= aFirst; 1644 aInit[1] <<= aSecond; 1645 1646 ::rtl::OUString sDialogServiceName; 1647 if ( _bFilter ) 1648 sDialogServiceName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdb.FilterDialog" ) ); 1649 else 1650 sDialogServiceName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdb.OrderDialog" ) ); 1651 1652 Reference< XExecutableDialog> xDialog; 1653 m_aContext.createComponentWithArguments( sDialogServiceName, aInit, xDialog ); 1654 1655 if ( !xDialog.is() ) 1656 { 1657 ShowServiceNotAvailableError( NULL, sDialogServiceName, sal_True ); 1658 return; 1659 } 1660 1661 if ( RET_OK == xDialog->execute() ) 1662 { 1663 WaitObject aWO( NULL ); 1664 if ( _bFilter ) 1665 m_xCursorProperties->setPropertyValue( PROPERTY_FILTER, makeAny( m_xParser->getFilter() ) ); 1666 else 1667 m_xCursorProperties->setPropertyValue( PROPERTY_SORT, makeAny( m_xParser->getOrder() ) ); 1668 m_xLoadableForm->reload(); 1669 } 1670 1671 } 1672 catch( const RuntimeException& ) { throw; } 1673 catch( const SQLException& ) { throw; } 1674 catch( const Exception& ) 1675 { 1676 throw WrappedTargetException( ::rtl::OUString(), *const_cast< FormOperations* >( this ), ::cppu::getCaughtException() ); 1677 } 1678 } 1679 1680 //------------------------------------------------------------------------------ 1681 void FormOperations::impl_appendOrderByColumn_throw( const void* _pActionParam ) const 1682 { 1683 const param_appendOrderByColumn* pParam = static_cast< const param_appendOrderByColumn* >( _pActionParam ); 1684 m_xParser->appendOrderByColumn( pParam->xField, pParam->bUp ); 1685 } 1686 1687 //------------------------------------------------------------------------------ 1688 void FormOperations::impl_appendFilterByColumn_throw( const void* _pActionParam ) const 1689 { 1690 const param_appendFilterByColumn* pParam = static_cast< const param_appendFilterByColumn* >( _pActionParam ); 1691 sal_Int32 nOp = SQLFilterOperator::EQUAL; 1692 if ( pParam->xField.is() ) 1693 { 1694 sal_Int32 nType = 0; 1695 pParam->xField->getPropertyValue(PROPERTY_FIELDTYPE) >>= nType; 1696 switch(nType) 1697 { 1698 case DataType::VARCHAR: 1699 case DataType::CHAR: 1700 case DataType::LONGVARCHAR: 1701 nOp = SQLFilterOperator::LIKE; 1702 break; 1703 default: 1704 nOp = SQLFilterOperator::EQUAL; 1705 } 1706 } 1707 m_xParser->appendFilterByColumn( pParam->xField, sal_True,nOp ); 1708 } 1709 1710 //------------------------------------------------------------------------------ 1711 void FormOperations::impl_doActionInSQLContext_throw( Action _pAction, const void* _pParam, sal_uInt16 _nErrorResourceId ) const 1712 { 1713 try 1714 { 1715 (this->*_pAction)( _pParam ); 1716 } 1717 catch( const SQLException& e ) 1718 { 1719 (void)e; 1720 if ( !_nErrorResourceId ) 1721 // no information to prepend 1722 throw; 1723 1724 SQLExceptionInfo aInfo( ::cppu::getCaughtException() ); 1725 ::rtl::OUString sAdditionalError( FRM_RES_STRING( _nErrorResourceId ) ); 1726 aInfo.prepend( sAdditionalError ); 1727 aInfo.doThrow(); 1728 } 1729 catch( const RuntimeException& ) { throw; } 1730 catch( const Exception& ) 1731 { 1732 ::rtl::OUString sAdditionalError( FRM_RES_STRING( _nErrorResourceId ) ); 1733 throw WrappedTargetException( sAdditionalError, *const_cast< FormOperations* >( this ), ::cppu::getCaughtException() ); 1734 } 1735 } 1736 1737 //........................................................................ 1738 } // namespace frm 1739 //........................................................................ 1740