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