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_dbaccess.hxx" 30 31 #ifndef _SBA_EXTCTRLR_HXX 32 #include "exsrcbrw.hxx" 33 #endif 34 #ifndef _COM_SUN_STAR_FORM_FORMCOMPONENTTYPE_HPP_ 35 #include <com/sun/star/form/FormComponentType.hpp> 36 #endif 37 #ifndef _COM_SUN_STAR_UTIL_XURLTRANSFORMER_HPP_ 38 #include <com/sun/star/util/XURLTransformer.hpp> 39 #endif 40 #ifndef _COM_SUN_STAR_FORM_XGRIDCOLUMNFACTORY_HPP_ 41 #include <com/sun/star/form/XGridColumnFactory.hpp> 42 #endif 43 #ifndef _COM_SUN_STAR_FORM_XLOADABLE_HPP_ 44 #include <com/sun/star/form/XLoadable.hpp> 45 #endif 46 #ifndef _COM_SUN_STAR_FRAME_FRAMESEARCHFLAG_HPP_ 47 #include <com/sun/star/frame/FrameSearchFlag.hpp> 48 #endif 49 #ifndef _SBA_FORMADAPTER_HXX 50 #include "formadapter.hxx" 51 #endif 52 #ifndef _COMPHELPER_PROCESSFACTORY_HXX_ 53 #include <comphelper/processfactory.hxx> 54 #endif 55 #ifndef DBACCESS_SHARED_DBUSTRINGS_HRC 56 #include "dbustrings.hrc" 57 #endif 58 #ifndef _DBU_REGHELPER_HXX_ 59 #include "dbu_reghelper.hxx" 60 #endif 61 #ifndef TOOLS_DIAGNOSE_EX_H 62 #include <tools/diagnose_ex.h> 63 #endif 64 65 using namespace ::com::sun::star::uno; 66 using namespace ::com::sun::star::sdb; 67 using namespace ::com::sun::star::sdbc; 68 using namespace ::com::sun::star::sdbcx; 69 using namespace ::com::sun::star::beans; 70 using namespace ::com::sun::star::container; 71 using namespace ::com::sun::star::lang; 72 using namespace ::com::sun::star::form; 73 using namespace ::com::sun::star::frame; 74 using namespace dbaui; 75 76 //============================================================================== 77 //= SbaExternalSourceBrowser 78 //============================================================================== 79 extern "C" void SAL_CALL createRegistryInfo_OFormGridView() 80 { 81 static OMultiInstanceAutoRegistration< SbaExternalSourceBrowser > aAutoRegistration; 82 } 83 //------------------------------------------------------------------------------ 84 Any SAL_CALL SbaExternalSourceBrowser::queryInterface(const Type& _rType) throw (RuntimeException) 85 { 86 Any aRet = SbaXDataBrowserController::queryInterface(_rType); 87 if(!aRet.hasValue()) 88 aRet = ::cppu::queryInterface(_rType, 89 (::com::sun::star::util::XModifyBroadcaster*)this, 90 (::com::sun::star::form::XLoadListener*)this); 91 92 return aRet; 93 } 94 DBG_NAME(SbaExternalSourceBrowser) 95 //------------------------------------------------------------------------------ 96 SbaExternalSourceBrowser::SbaExternalSourceBrowser(const Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rM) 97 :SbaXDataBrowserController(_rM) 98 ,m_aModifyListeners(getMutex()) 99 ,m_pDataSourceImpl(NULL) 100 ,m_bInQueryDispatch( sal_False ) 101 { 102 DBG_CTOR(SbaExternalSourceBrowser,NULL); 103 104 } 105 106 //------------------------------------------------------------------------------ 107 SbaExternalSourceBrowser::~SbaExternalSourceBrowser() 108 { 109 110 DBG_DTOR(SbaExternalSourceBrowser,NULL); 111 } 112 113 //------------------------------------------------------------------------- 114 ::comphelper::StringSequence SAL_CALL SbaExternalSourceBrowser::getSupportedServiceNames() throw(RuntimeException) 115 { 116 return getSupportedServiceNames_Static(); 117 } 118 // ------------------------------------------------------------------------- 119 ::rtl::OUString SbaExternalSourceBrowser::getImplementationName_Static() throw(RuntimeException) 120 { 121 return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.comp.dbu.OFormGridView")); 122 } 123 //------------------------------------------------------------------------- 124 ::comphelper::StringSequence SbaExternalSourceBrowser::getSupportedServiceNames_Static() throw(RuntimeException) 125 { 126 ::comphelper::StringSequence aSupported(1); 127 aSupported.getArray()[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sdb.FormGridView")); 128 return aSupported; 129 } 130 //------------------------------------------------------------------------- 131 Reference< XInterface > SAL_CALL SbaExternalSourceBrowser::Create(const Reference<XMultiServiceFactory >& _rxFactory) 132 { 133 return *(new SbaExternalSourceBrowser(_rxFactory)); 134 } 135 //------------------------------------------------------------------------- 136 ::rtl::OUString SAL_CALL SbaExternalSourceBrowser::getImplementationName() throw(RuntimeException) 137 { 138 return getImplementationName_Static(); 139 } 140 //------------------------------------------------------------------------------ 141 Reference< XRowSet > SbaExternalSourceBrowser::CreateForm() 142 { 143 m_pDataSourceImpl = new SbaXFormAdapter(); 144 return m_pDataSourceImpl; 145 } 146 147 //------------------------------------------------------------------------------ 148 sal_Bool SbaExternalSourceBrowser::InitializeForm(const Reference< XPropertySet > & /*i_formProperties*/) 149 { 150 return sal_True; 151 } 152 153 //------------------------------------------------------------------ 154 sal_Bool SbaExternalSourceBrowser::LoadForm() 155 { 156 // as we don't have a main form (yet), we have nothing to do 157 // we don't call FormLoaded, because this expects a working data source 158 return sal_True; 159 } 160 161 162 //------------------------------------------------------------------ 163 void SbaExternalSourceBrowser::modified(const ::com::sun::star::lang::EventObject& aEvent) throw( RuntimeException ) 164 { 165 SbaXDataBrowserController::modified(aEvent); 166 167 // multiplex this event to all my listeners 168 ::com::sun::star::lang::EventObject aEvt(*this); 169 ::cppu::OInterfaceIteratorHelper aIt(m_aModifyListeners); 170 while (aIt.hasMoreElements()) 171 ((::com::sun::star::util::XModifyListener*)aIt.next())->modified(aEvt); 172 } 173 174 //------------------------------------------------------------------ 175 void SAL_CALL SbaExternalSourceBrowser::dispatch(const ::com::sun::star::util::URL& aURL, const Sequence< ::com::sun::star::beans::PropertyValue>& aArgs) throw(::com::sun::star::uno::RuntimeException) 176 { 177 const ::com::sun::star::beans::PropertyValue* pArguments = aArgs.getConstArray(); 178 if (aURL.Complete.equals(::rtl::OUString::createFromAscii(".uno:FormSlots/AddGridColumn"))) 179 { 180 // search the argument describing the column to create 181 ::rtl::OUString sControlType; 182 sal_Int32 nControlPos = -1; 183 Sequence< ::com::sun::star::beans::PropertyValue> aControlProps; 184 sal_uInt16 i; 185 for ( i = 0; i < aArgs.getLength(); ++i, ++pArguments ) 186 { 187 if (pArguments->Name.equals(::rtl::OUString::createFromAscii("ColumnType"))) 188 { 189 sal_Bool bCorrectType = pArguments->Value.getValueType().equals(::getCppuType((const ::rtl::OUString*)0)); 190 OSL_ENSURE(bCorrectType, "invalid type for argument \"ColumnType\" !"); 191 if (bCorrectType) 192 sControlType = ::comphelper::getString(pArguments->Value); 193 } 194 else if (pArguments->Name.equals(::rtl::OUString::createFromAscii("ColumnPosition"))) 195 { 196 sal_Bool bCorrectType = pArguments->Value.getValueType().equals(::getCppuType((const sal_Int16*)0)); 197 OSL_ENSURE(bCorrectType, "invalid type for argument \"ColumnPosition\" !"); 198 if (bCorrectType) 199 nControlPos = ::comphelper::getINT16(pArguments->Value); 200 } 201 else if (pArguments->Name.equals(::rtl::OUString::createFromAscii("ColumnProperties"))) 202 { 203 sal_Bool bCorrectType = pArguments->Value.getValueType().equals(::getCppuType((const Sequence< ::com::sun::star::beans::PropertyValue>*)0)); 204 OSL_ENSURE(bCorrectType, "invalid type for argument \"ColumnProperties\" !"); 205 if (bCorrectType) 206 aControlProps = *(Sequence< ::com::sun::star::beans::PropertyValue>*)pArguments->Value.getValue(); 207 } 208 else 209 OSL_ENSURE(sal_False, ((ByteString("SbaExternalSourceBrowser::dispatch(AddGridColumn) : unknown argument (") += ByteString((const sal_Unicode*)pArguments->Name, gsl_getSystemTextEncoding()).GetBuffer()) += ") !").GetBuffer()); 210 } 211 if (!sControlType.getLength()) 212 { 213 OSL_ENSURE(sal_False, "SbaExternalSourceBrowser::dispatch(AddGridColumn) : missing argument (ColumnType) !"); 214 sControlType = ::rtl::OUString::createFromAscii("TextField"); 215 } 216 OSL_ENSURE(aControlProps.getLength(), "SbaExternalSourceBrowser::dispatch(AddGridColumn) : missing argument (ColumnProperties) !"); 217 218 // create the col 219 Reference< ::com::sun::star::form::XGridColumnFactory > xColFactory(getControlModel(), UNO_QUERY); 220 Reference< ::com::sun::star::beans::XPropertySet > xNewCol = xColFactory->createColumn(sControlType); 221 Reference< XPropertySetInfo > xNewColProperties; 222 if (xNewCol.is()) 223 xNewColProperties = xNewCol->getPropertySetInfo(); 224 // set it's properties 225 if (xNewColProperties.is()) 226 { 227 const ::com::sun::star::beans::PropertyValue* pControlProps = aControlProps.getConstArray(); 228 for (i=0; i<aControlProps.getLength(); ++i, ++pControlProps) 229 { 230 try 231 { 232 if (xNewColProperties->hasPropertyByName(pControlProps->Name)) 233 xNewCol->setPropertyValue(pControlProps->Name, pControlProps->Value); 234 } 235 catch(Exception&) 236 { 237 OSL_ENSURE(sal_False, 238 ( ByteString("SbaExternalSourceBrowser::dispatch : could not set a column property (") 239 += ByteString(pControlProps->Name.getStr(), (sal_uInt16)pControlProps->Name.getLength(), RTL_TEXTENCODING_ASCII_US) 240 += ByteString(")!")).GetBuffer()); 241 } 242 } 243 } 244 245 // correct the position 246 Reference< ::com::sun::star::container::XIndexContainer > xColContainer(getControlModel(), UNO_QUERY); 247 248 if (nControlPos > xColContainer->getCount()) 249 nControlPos = xColContainer->getCount(); 250 if (nControlPos < 0) 251 nControlPos = 0; 252 253 // append the column 254 xColContainer->insertByIndex(nControlPos, makeAny(xNewCol)); 255 } 256 else if (aURL.Complete.equals(::rtl::OUString::createFromAscii(".uno:FormSlots/ClearView"))) 257 { 258 ClearView(); 259 } 260 else if (aURL.Complete.equals(::rtl::OUString::createFromAscii(".uno:FormSlots/AttachToForm"))) 261 { 262 if (!m_pDataSourceImpl) 263 return; 264 265 Reference< XRowSet > xMasterForm; 266 // search the arguments for he master form 267 for (sal_uInt16 i=0; i<aArgs.getLength(); ++i, ++pArguments) 268 { 269 if ((pArguments->Name.equals(::rtl::OUString::createFromAscii("MasterForm"))) && (pArguments->Value.getValueTypeClass() == TypeClass_INTERFACE)) 270 { 271 xMasterForm = Reference< XRowSet > (*(Reference< XInterface > *)pArguments->Value.getValue(), UNO_QUERY); 272 break; 273 } 274 } 275 if (!xMasterForm.is()) 276 { 277 OSL_ENSURE(sal_False, "SbaExternalSourceBrowser::dispatch(FormSlots/AttachToForm) : please specify a form to attach to as argument !"); 278 return; 279 } 280 281 Attach(xMasterForm); 282 } 283 else 284 SbaXDataBrowserController::dispatch(aURL, aArgs); 285 } 286 287 //------------------------------------------------------------------ 288 Reference< ::com::sun::star::frame::XDispatch > SAL_CALL SbaExternalSourceBrowser::queryDispatch(const ::com::sun::star::util::URL& aURL, const ::rtl::OUString& aTargetFrameName, sal_Int32 nSearchFlags) throw( RuntimeException ) 289 { 290 Reference< ::com::sun::star::frame::XDispatch > xReturn; 291 if (m_bInQueryDispatch) 292 return xReturn; 293 294 m_bInQueryDispatch = sal_True; 295 296 if ( (aURL.Complete.equals(::rtl::OUString::createFromAscii(".uno:FormSlots/AttachToForm"))) 297 // attach a new external form 298 || (aURL.Complete.equals(::rtl::OUString::createFromAscii(".uno:FormSlots/AddGridColumn"))) 299 // add a column to the grid 300 || (aURL.Complete.equals(::rtl::OUString::createFromAscii(".uno:FormSlots/ClearView"))) 301 // clear the grid 302 ) 303 xReturn = (::com::sun::star::frame::XDispatch*)this; 304 305 if ( !xReturn.is() 306 && ( (aURL.Complete.equals(::rtl::OUString::createFromAscii(".uno:FormSlots/moveToFirst"))) 307 || (aURL.Complete.equals(::rtl::OUString::createFromAscii(".uno:FormSlots/moveToPrev"))) 308 || (aURL.Complete.equals(::rtl::OUString::createFromAscii(".uno:FormSlots/moveToNext"))) 309 || (aURL.Complete.equals(::rtl::OUString::createFromAscii(".uno:FormSlots/moveToLast"))) 310 || (aURL.Complete.equals(::rtl::OUString::createFromAscii(".uno:FormSlots/moveToNew"))) 311 || (aURL.Complete.equals(::rtl::OUString::createFromAscii(".uno:FormSlots/undoRecord"))) 312 ) 313 ) 314 { 315 OSL_ENSURE(aURL.Mark.getLength() == 0, "SbaExternalSourceBrowser::queryDispatch : the ::com::sun::star::util::URL shouldn't have a mark !"); 316 ::com::sun::star::util::URL aNewUrl = aURL; 317 318 // split the ::com::sun::star::util::URL 319 OSL_ENSURE( m_xUrlTransformer.is(), "SbaExternalSourceBrowser::queryDispatch : could not create an URLTransformer !" ); 320 if ( m_xUrlTransformer.is() ) 321 m_xUrlTransformer->parseStrict( aNewUrl ); 322 323 // set a new mark 324 aNewUrl.Mark = ::rtl::OUString::createFromAscii("DB/FormGridView"); 325 // this controller is instantiated when somebody dispatches the ".component:DB/FormGridView" in any 326 // frame, so we use "FormGridView" as mark that a dispatch request came from this view 327 328 if (m_xUrlTransformer.is()) 329 m_xUrlTransformer->assemble(aNewUrl); 330 331 Reference< XDispatchProvider > xFrameDispatcher( getFrame(), UNO_QUERY ); 332 if (xFrameDispatcher.is()) 333 xReturn = xFrameDispatcher->queryDispatch(aNewUrl, aTargetFrameName, FrameSearchFlag::PARENT); 334 335 } 336 337 if (!xReturn.is()) 338 xReturn = SbaXDataBrowserController::queryDispatch(aURL, aTargetFrameName, nSearchFlags); 339 340 m_bInQueryDispatch = sal_False; 341 return xReturn; 342 } 343 344 //------------------------------------------------------------------ 345 void SAL_CALL SbaExternalSourceBrowser::disposing() 346 { 347 // say our modify listeners goodbye 348 ::com::sun::star::lang::EventObject aEvt; 349 aEvt.Source = (XWeak*) this; 350 m_aModifyListeners.disposeAndClear(aEvt); 351 352 stopListening(); 353 354 SbaXDataBrowserController::disposing(); 355 } 356 357 //------------------------------------------------------------------ 358 void SAL_CALL SbaExternalSourceBrowser::addModifyListener(const Reference< ::com::sun::star::util::XModifyListener > & aListener) throw( RuntimeException ) 359 { 360 m_aModifyListeners.addInterface(aListener); 361 } 362 363 //------------------------------------------------------------------ 364 void SAL_CALL SbaExternalSourceBrowser::removeModifyListener(const Reference< ::com::sun::star::util::XModifyListener > & aListener) throw( RuntimeException ) 365 { 366 m_aModifyListeners.removeInterface(aListener); 367 } 368 369 //------------------------------------------------------------------ 370 void SAL_CALL SbaExternalSourceBrowser::unloading(const ::com::sun::star::lang::EventObject& aEvent) throw( RuntimeException ) 371 { 372 if (m_pDataSourceImpl && (m_pDataSourceImpl->getAttachedForm() == aEvent.Source)) 373 { 374 ClearView(); 375 } 376 377 SbaXDataBrowserController::unloading(aEvent); 378 } 379 380 //------------------------------------------------------------------ 381 void SbaExternalSourceBrowser::Attach(const Reference< XRowSet > & xMaster) 382 { 383 Any aOldPos; 384 sal_Bool bWasInsertRow = sal_False; 385 sal_Bool bBeforeFirst = sal_True; 386 sal_Bool bAfterLast = sal_True; 387 Reference< XResultSet > xResultSet(xMaster, UNO_QUERY); 388 Reference< XRowLocate > xCursor(xMaster, UNO_QUERY); 389 Reference< XPropertySet > xMasterProps(xMaster, UNO_QUERY); 390 391 try 392 { 393 // switch the control to design mode 394 if (getBrowserView() && getBrowserView()->getGridControl().is()) 395 getBrowserView()->getGridControl()->setDesignMode(sal_True); 396 397 // the grid will move the form's cursor to the first record, but we want the form to remain unchanged 398 // restore the old position 399 if (xCursor.is() && xResultSet.is()) 400 { 401 bBeforeFirst = xResultSet->isBeforeFirst(); 402 bAfterLast = xResultSet->isAfterLast(); 403 if(!bBeforeFirst && !bAfterLast) 404 aOldPos = xCursor->getBookmark(); 405 } 406 407 if (xMasterProps.is()) 408 xMasterProps->getPropertyValue(PROPERTY_ISNEW) >>= bWasInsertRow; 409 } 410 catch( const Exception& ) 411 { 412 DBG_UNHANDLED_EXCEPTION(); 413 } 414 415 onStartLoading( Reference< XLoadable >( xMaster, UNO_QUERY ) ); 416 417 stopListening(); 418 m_pDataSourceImpl->AttachForm(xMaster); 419 startListening(); 420 421 if (xMaster.is()) 422 { 423 // at this point we have to reset the formatter for the new form 424 initFormatter(); 425 // assume that the master form is already loaded 426 #if OSL_DEBUG_LEVEL > 0 427 { 428 Reference< XLoadable > xLoadable( xMaster, UNO_QUERY ); 429 OSL_ENSURE( xLoadable.is() && xLoadable->isLoaded(), "SbaExternalSourceBrowser::Attach: master is not loaded!" ); 430 } 431 #endif 432 433 LoadFinished(sal_True); 434 435 Reference< XResultSetUpdate > xUpdate(xMaster, UNO_QUERY); 436 try 437 { 438 if (bWasInsertRow && xUpdate.is()) 439 xUpdate->moveToInsertRow(); 440 else if (xCursor.is() && aOldPos.hasValue()) 441 xCursor->moveToBookmark(aOldPos); 442 else if(bBeforeFirst && xResultSet.is()) 443 xResultSet->beforeFirst(); 444 else if(bAfterLast && xResultSet.is()) 445 xResultSet->afterLast(); 446 } 447 catch(Exception&) 448 { 449 OSL_ENSURE(sal_False, "SbaExternalSourceBrowser::Attach : couldn't restore the cursor position !"); 450 } 451 452 } 453 } 454 455 //------------------------------------------------------------------ 456 void SbaExternalSourceBrowser::ClearView() 457 { 458 // set a new (empty) datasource 459 Attach(Reference< XRowSet > ()); 460 461 462 // clear all cols in the grid 463 Reference< ::com::sun::star::container::XIndexContainer > xColContainer(getControlModel(), UNO_QUERY); 464 while (xColContainer->getCount() > 0) 465 xColContainer->removeByIndex(0); 466 } 467 468 //------------------------------------------------------------------ 469 void SAL_CALL SbaExternalSourceBrowser::disposing(const ::com::sun::star::lang::EventObject& Source) throw( RuntimeException ) 470 { 471 if (m_pDataSourceImpl && (m_pDataSourceImpl->getAttachedForm() == Source.Source)) 472 { 473 ClearView(); 474 } 475 476 SbaXDataBrowserController::disposing(Source); 477 } 478 479 //------------------------------------------------------------------ 480 void SbaExternalSourceBrowser::startListening() 481 { 482 if (m_pDataSourceImpl && m_pDataSourceImpl->getAttachedForm().is()) 483 { 484 Reference< ::com::sun::star::form::XLoadable > xLoadable(m_pDataSourceImpl->getAttachedForm(), UNO_QUERY); 485 xLoadable->addLoadListener((::com::sun::star::form::XLoadListener*)this); 486 } 487 } 488 489 //------------------------------------------------------------------ 490 void SbaExternalSourceBrowser::stopListening() 491 { 492 if (m_pDataSourceImpl && m_pDataSourceImpl->getAttachedForm().is()) 493 { 494 Reference< ::com::sun::star::form::XLoadable > xLoadable(m_pDataSourceImpl->getAttachedForm(), UNO_QUERY); 495 xLoadable->removeLoadListener((::com::sun::star::form::XLoadListener*)this); 496 } 497 } 498 499 //================================================================== 500 //================================================================== 501