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