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 #ifndef EXTENSIONS_SOURCE_PROPCTRLR_FORMCOMPONENTHANDLER_HXX 25 #define EXTENSIONS_SOURCE_PROPCTRLR_FORMCOMPONENTHANDLER_HXX 26 27 #include "propertyhandler.hxx" 28 #include "sqlcommanddesign.hxx" 29 #include "pcrcommon.hxx" 30 #include <comphelper/uno3.hxx> 31 #include <comphelper/proparrhlp.hxx> 32 #include <comphelper/propertycontainer.hxx> 33 /** === begin UNO includes === **/ 34 #include <com/sun/star/frame/XModel.hpp> 35 #include <com/sun/star/beans/XPropertyState.hpp> 36 #include <com/sun/star/sdbc/XRowSet.hpp> 37 #include <com/sun/star/awt/XControlContainer.hpp> 38 #include <com/sun/star/form/XForm.hpp> 39 /** === end UNO includes === **/ 40 #include <tools/fldunit.hxx> 41 #include <vcl/waitobj.hxx> 42 #include <connectivity/dbtools.hxx> 43 44 #include <set> 45 46 //........................................................................ 47 namespace pcr 48 { 49 //........................................................................ 50 51 //==================================================================== 52 //= ComponentClassification 53 //==================================================================== 54 enum ComponentClassification 55 { 56 eFormControl, 57 eDialogControl, 58 eUnknown 59 }; 60 61 //==================================================================== 62 //= FormComponentPropertyHandler 63 //==================================================================== 64 class FormComponentPropertyHandler; 65 typedef HandlerComponentBase< FormComponentPropertyHandler > FormComponentPropertyHandler_Base; 66 typedef ::comphelper::OPropertyArrayUsageHelper<FormComponentPropertyHandler> FormComponentPropertyHandler_PROP; 67 /** default ->XPropertyHandler for all form components. 68 */ 69 class FormComponentPropertyHandler : public FormComponentPropertyHandler_Base, 70 public ::comphelper::OPropertyContainer, 71 public FormComponentPropertyHandler_PROP 72 { 73 private: 74 /// access to property states 75 ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyState > m_xPropertyState; 76 /// the parent of our component 77 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > m_xObjectParent; 78 79 /// the database connection. Owned by us if and only if we created it ourself. 80 mutable ::dbtools::SharedConnection m_xRowSetConnection; 81 ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSet > m_xRowSet; 82 /** helper component encapsulating the handling for the QueryDesign component for 83 interactively designing an SQL command 84 */ 85 ::rtl::Reference< SQLCommandDesigner > m_xCommandDesigner; 86 ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XObjectInspectorUI > m_xBrowserUI; 87 88 /// the string indicating a "default" (VOID) value in list-like controls 89 ::rtl::OUString m_sDefaultValueString; 90 /// all properties to whose control's we added ->m_sDefaultValueString 91 ::std::set< ::rtl::OUString > m_aPropertiesWithDefListEntry; 92 /// type of our component 93 ComponentClassification m_eComponentClass; 94 /// is our component a (database) sub form? 95 bool m_bComponentIsSubForm : 1; 96 /// our component has a "ListSource" property 97 bool m_bHaveListSource : 1; 98 /// our component has a "Command" property 99 bool m_bHaveCommand : 1; 100 /// the class id of the component - if appliable 101 sal_Int16 m_nClassId; 102 103 public: 104 FormComponentPropertyHandler( 105 const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& _rxContext 106 ); 107 108 DECLARE_XINTERFACE( ) 109 110 // XPropertySet 111 virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) throw(::com::sun::star::uno::RuntimeException); 112 113 static ::rtl::OUString SAL_CALL getImplementationName_static( ) throw (::com::sun::star::uno::RuntimeException); 114 static ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames_static( ) throw (::com::sun::star::uno::RuntimeException); 115 116 protected: 117 ~FormComponentPropertyHandler(); 118 119 protected: 120 virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const; 121 virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); 122 // XPropertyHandler overridables 123 virtual ::com::sun::star::uno::Any SAL_CALL getPropertyValue( const ::rtl::OUString& _rPropertyName ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException); 124 virtual void SAL_CALL setPropertyValue( const ::rtl::OUString& _rPropertyName, const ::com::sun::star::uno::Any& _rValue ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException); 125 virtual ::com::sun::star::uno::Any SAL_CALL convertToPropertyValue( const ::rtl::OUString& _rPropertyName, const ::com::sun::star::uno::Any& _rControlValue ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException); 126 virtual ::com::sun::star::uno::Any SAL_CALL convertToControlValue( const ::rtl::OUString& _rPropertyName, const ::com::sun::star::uno::Any& _rPropertyValue, const ::com::sun::star::uno::Type& _rControlValueType ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException); 127 virtual ::com::sun::star::beans::PropertyState SAL_CALL getPropertyState( const ::rtl::OUString& _rPropertyName ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException); 128 virtual void SAL_CALL addPropertyChangeListener( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& _rxListener ) throw (::com::sun::star::uno::RuntimeException); 129 virtual void SAL_CALL removePropertyChangeListener( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& _rxListener ) throw (::com::sun::star::uno::RuntimeException); 130 virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupersededProperties() throw (::com::sun::star::uno::RuntimeException); 131 virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getActuatingProperties() throw (::com::sun::star::uno::RuntimeException); 132 virtual ::com::sun::star::inspection::LineDescriptor SAL_CALL describePropertyLine( const ::rtl::OUString& _rPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyControlFactory >& _rxControlFactory ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::NullPointerException, ::com::sun::star::uno::RuntimeException); 133 virtual ::com::sun::star::inspection::InteractiveSelectionResult 134 SAL_CALL onInteractivePropertySelection( const ::rtl::OUString& _rPropertyName, sal_Bool _bPrimary, ::com::sun::star::uno::Any& _rData, const ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XObjectInspectorUI >& _rxInspectorUI ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::NullPointerException, ::com::sun::star::uno::RuntimeException); 135 virtual void SAL_CALL actuatingPropertyChanged( const ::rtl::OUString& _rActuatingPropertyName, const ::com::sun::star::uno::Any& _rNewValue, const ::com::sun::star::uno::Any& _rOldValue, const ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XObjectInspectorUI >& _rxInspectorUI, sal_Bool _bFirstTimeInit ) throw (::com::sun::star::lang::NullPointerException, ::com::sun::star::uno::RuntimeException); 136 virtual sal_Bool SAL_CALL suspend( sal_Bool _bSuspend ) throw (::com::sun::star::uno::RuntimeException); 137 138 // XComponent 139 virtual void SAL_CALL disposing(); 140 141 // PropertyHandler 142 virtual ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property > 143 SAL_CALL doDescribeSupportedProperties() const; 144 virtual void onNewComponent(); 145 146 private: 147 /** initializes some (cached) meta data about the component 148 @throws RuntimeException 149 if a serious error occurs, for instance if the component does not provide an XPropertySetInfo instance 150 */ 151 void impl_initComponentMetaData_throw(); 152 153 /** classifies our component, in case it's a control model, by ClassId 154 155 Note that UNO dialog controls are also classified, though they don't have the ClassId property 156 */ 157 void impl_classifyControlModel_throw(); 158 159 /** const-version of ->getPropertyValue 160 */ 161 ::com::sun::star::uno::Any impl_getPropertyValue_throw( const ::rtl::OUString& _rPropertyName ) const; 162 163 // some property values are faked, and not used in the way they're provided by our component 164 void impl_normalizePropertyValue_nothrow( ::com::sun::star::uno::Any& _rValue, PropertyId _nPropId ) const; 165 166 /** determines whether we should exclude a given property from our "supported properties" 167 */ 168 bool impl_shouldExcludeProperty_nothrow( const ::com::sun::star::beans::Property& _rProperty ) const; 169 170 /** initializes the list of field names, if we're handling a control which supports the 171 DataField property 172 */ 173 void impl_initFieldList_nothrow( ::std::vector< ::rtl::OUString >& rFieldNames ) const; 174 175 /** obtaines the RowSet to which our component belongs 176 177 If the component is a RowSet itself, it's returned directly. Else, the parent 178 is examined for the XRowSet interface. If the parent is no XRowSet, then 179 a check is made whether our component is a grid control column, and if so, 180 the parent of the grid control is examied for the XRowSet interace. 181 182 Normally, at least one of those methods should succeed. 183 */ 184 ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSet > impl_getRowSet_throw( ) const; 185 186 /** nothrow-version of ->impl_getRowSet_throw 187 */ 188 ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSet > impl_getRowSet_nothrow( ) const; 189 190 /** connects the row set belonging to our introspected data aware form component, 191 and remembers the connection in ->m_xRowSetConnection. 192 193 If the row set already is connected, ->m_xRowSetConnection will be set, too, but 194 not take the ownership of the connection. 195 196 If ->m_xRowSetConnection is already set, nothing happens, so if you want to 197 force creation of a connection, you need to clear ->m_xRowSetConnection. 198 */ 199 bool impl_ensureRowsetConnection_nothrow() const; 200 201 /** clears ->m_xRowSetConnection 202 */ 203 void impl_clearRowsetConnection_nothrow(); 204 205 /** fills an ->LineDescriptor with information to represent a cursor source 206 of our form - that is, a table, a query, or an SQL statement. 207 208 As an example, if our form has currently a CommandType of TABLE, then the 209 value list in the LineDescriptor will contain a list of all tables 210 of the data source which the form is bound to. 211 212 @seealso impl_fillTableNames_throw 213 @seealso impl_fillQueryNames_throw 214 */ 215 void impl_describeCursorSource_nothrow( 216 ::com::sun::star::inspection::LineDescriptor& _out_rProperty, 217 const ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyControlFactory >& _rxControlFactory 218 ) const; 219 220 /** describes the UI for selecting a table name 221 222 @precond 223 m_xRowSetConnection is not <NULL/> 224 */ 225 void impl_fillTableNames_throw( ::std::vector< ::rtl::OUString >& _out_rNames ) const; 226 227 /** describes the UI for selecting a query name 228 229 @precond 230 m_xRowSetConnection is not <NULL/> 231 */ 232 void impl_fillQueryNames_throw( ::std::vector< ::rtl::OUString >& _out_rNames ) const; 233 234 /** describes the UI for selecting a query name 235 236 @precond 237 m_xRowSetConnection is not <NULL/> 238 */ 239 void impl_fillQueryNames_throw( const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& _xQueryNames 240 ,::std::vector< ::rtl::OUString >& _out_rNames 241 ,const ::rtl::OUString& _sName = ::rtl::OUString() ) const; 242 243 /** describes the UI for selecting a ListSource (for list-like form controls) 244 @precond 245 ->m_xRowSetConnection is not <NULL/> 246 @precond 247 ->m_xComponent is not <NULL/> 248 */ 249 void impl_describeListSourceUI_throw( 250 ::com::sun::star::inspection::LineDescriptor& _out_rDescriptor, 251 const ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyControlFactory >& _rxControlFactory 252 ) const; 253 254 /** displays a datbase-related error to the user 255 */ 256 void impl_displaySQLError_nothrow( const ::dbtools::SQLExceptionInfo& _rErrorDescriptor ) const; 257 258 /** let's the user chose a selection of entries from a string list, and stores this 259 selection in the given property 260 @return 261 <TRUE/> if and only if the user successfully changed the property 262 */ 263 bool impl_dialogListSelection_nothrow( const ::rtl::OUString& _rProperty, ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const; 264 265 /** executes a dialog for chosing a filter or sort criterion for a database form 266 @param _bFilter 267 <TRUE/> if the Filter property should be used, <FALSE/> if it's the Order 268 property 269 @param _out_rSelectedClause 270 the filter or order clause as chosen by the user 271 @precond 272 we're really inspecting a database form (well, a RowSet at least) 273 @return 274 <TRUE/> if and only if the user successfully chose a clause 275 */ 276 bool impl_dialogFilterOrSort_nothrow( bool _bFilter, ::rtl::OUString& _out_rSelectedClause, ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const; 277 278 /** executes a dialog which allows the user to chose the columns linking 279 a sub to a master form, and sets the respective MasterFields / SlaveFields 280 properties at the form. 281 @precond 282 we're inspecting (sub) database form 283 @return 284 <TRUE/> if and only if the user successfully eneter master and slave fields 285 */ 286 bool impl_dialogLinkedFormFields_nothrow( ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const; 287 288 /** executes a dialog which allows the user to modify the FormatKey 289 property of our component, by chosing a (number) format. 290 @precond 291 Our component actually has a FormatKey property. 292 @param _out_rNewValue 293 the new property value, if the user chose a new formatting 294 @return 295 <TRUE/> if and only if a new formatting has been chosen by the user. 296 In this case, ->_out_rNewValue is filled with the new property value 297 */ 298 bool impl_dialogFormatting_nothrow( ::com::sun::star::uno::Any& _out_rNewValue, ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const; 299 300 /** executes a dialog which allows to the user to change the ImageURL property 301 of our component by browsing for an image file. 302 @precond 303 our component actually has a ImageURL property 304 @param _out_rNewValue 305 the new property value, if the user chose a new image url 306 @return 307 <TRUE/> if and only if a new image URL has been chosen by the user. 308 In this case, ->_out_rNewValue is filled with the new property value 309 */ 310 bool impl_browseForImage_nothrow( ::com::sun::star::uno::Any& _out_rNewValue, ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const; 311 312 /** executes a dialog which allows the user to change the TargetURL property of 313 our component 314 @precond 315 our component actually has a TargetURL property 316 @param _out_rNewValue 317 the new property value, if the user chose a new TargetURL 318 @return 319 <TRUE/> if and only if a new TargetURL has been chosen by the user. 320 In this case, ->_out_rNewValue is filled with the new property value 321 */ 322 bool impl_browseForTargetURL_nothrow( ::com::sun::star::uno::Any& _out_rNewValue, ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const; 323 324 /** executes a dialog which allows the user to change the font, plus related properties, 325 of our component 326 @precond 327 our component actually has a Font property 328 @param _out_rNewValue 329 a value desribing the new font, as <code>Sequence< NamedValue ></code> 330 @return 331 <TRUE/> if and only if the user successfully changed the font of our component 332 */ 333 bool impl_executeFontDialog_nothrow( ::com::sun::star::uno::Any& _out_rNewValue, ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const; 334 335 /** allows the user browsing for a database document 336 @precond 337 our component actually has a DataSource property 338 @param _out_rNewValue 339 the new property value, if the user chose a new DataSource 340 @return 341 <TRUE/> if and only if a new DataSource has been chosen by the user. 342 In this case, ->_out_rNewValue is filled with the new property value 343 */ 344 bool impl_browseForDatabaseDocument_throw( ::com::sun::star::uno::Any& _out_rNewValue, ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const; 345 346 /** raises a dialog which allows the user to choose a color 347 @param _nColorPropertyId 348 the ID of the color property 349 @param _out_rNewValue 350 the chosen color value 351 @return 352 <TRUE/> if and only if a color was chosen by the user 353 */ 354 bool impl_dialogColorChooser_throw( sal_Int32 _nColorPropertyId, ::com::sun::star::uno::Any& _out_rNewValue, ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const; 355 356 /** raises a dialog which allows the user to choose a label control for our component 357 @param _out_rNewValue 358 the chosen label control, if any 359 @return 360 <TRUE/> if and only if a label control was chosen by the user 361 */ 362 bool impl_dialogChooseLabelControl_nothrow( ::com::sun::star::uno::Any& _out_rNewValue, ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const; 363 364 /** raises a dialog which lets the user chose the tab order of controls of a form 365 @precond 366 we have a view control container in which our controls live 367 @return 368 <TRUE/> if and only if the user successfully changed the tab order 369 @seealso impl_getContextControlContainer_nothrow 370 */ 371 bool impl_dialogChangeTabOrder_nothrow( ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const; 372 373 /** retrieves the context for controls, whose model(s) we're inspecting 374 375 If we're inspecting a control model, this is usually part of a set of controls 376 and control models, where the controls live in a certain context (a ->XControlContainer). 377 If we know this context, we can enable additional special functionality. 378 379 The ->XComponentContext in which we were created is examined for a value 380 named "ControlContext", and this value is returned. 381 */ 382 ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlContainer > 383 impl_getContextControlContainer_nothrow() const; 384 385 /** opens a query design window for interactively designing the SQL command of a 386 database form 387 @param _rxUIUpdate 388 access to the property browser UI 389 @param _nDesignForProperty 390 the ID for the property for which the designer is opened 391 @return 392 <TRUE/> if the window was successfully opened, or was previously open, 393 <FALSE/> otherwise 394 */ 395 bool impl_doDesignSQLCommand_nothrow( 396 const ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XObjectInspectorUI >& _rxInspectorUI, 397 PropertyId _nDesignForProperty 398 ); 399 400 /** updates a property (UI) whose state depends on more than one other property 401 402 ->actuatingPropertyChanged is called for certain properties in whose changes 403 we expressed interes (->getActuatingProperty). Now such a property change can 404 result in simple UI updates, for instance another property being enabled or disabled. 405 406 However, it can also result in a more complex change: The current (UI) state might 407 depend on the value of more than one other property. Those dependent properties (their 408 UI, more precisly) are updated in this method. 409 410 @param _nPropid 411 the ->PropertyId of the dependent property whose UI state is to be updated 412 413 @param _rxInspectorUI 414 provides access to the property browser UI. Must not be <NULL/>. 415 */ 416 void impl_updateDependentProperty_nothrow( PropertyId _nPropId, const ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XObjectInspectorUI >& _rxInspectorUI ) const; 417 418 /** determines whether the given form has a valid data source signature. 419 420 Valid here means that the DataSource property denotes an existing data source, and the 421 Command property is not empty. No check is made whether the value of the Command property 422 denotes an existent object, since this would be way too expensive. 423 424 @param _xFormProperties 425 the form to check. Must not be <NULL/>. 426 @param _bAllowEmptyDataSourceName 427 determine whether an empty data source name is allowed (<TRUE/>), and should not 428 lead to rejection 429 */ 430 static bool impl_hasValidDataSourceSignature_nothrow( 431 const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _xFormProperties, 432 bool _bAllowEmptyDataSourceName ); 433 434 /** returns the URL of our context document 435 @return 436 */ 437 ::rtl::OUString impl_getDocumentURL_nothrow() const; 438 439 private: 440 DECL_LINK( OnDesignerClosed, void* ); 441 442 private: 443 FormComponentPropertyHandler(); // never implemented 444 FormComponentPropertyHandler( const FormComponentPropertyHandler& ); // never implemented 445 FormComponentPropertyHandler& operator=( const FormComponentPropertyHandler& ); // never implemented 446 447 private: 448 using ::comphelper::OPropertyContainer::addPropertyChangeListener; 449 using ::comphelper::OPropertyContainer::removePropertyChangeListener; 450 }; 451 452 //==================================================================== 453 //= WaitCursor 454 //==================================================================== 455 /** wrapper around a ->WaitObject which can cope with a NULL window 456 */ 457 class WaitCursor 458 { 459 private: 460 ::std::auto_ptr< WaitObject > m_aWaitObject; 461 462 public: WaitCursor(Window * _pWindow)463 WaitCursor( Window* _pWindow ) 464 { 465 if ( _pWindow ) 466 m_aWaitObject.reset( new WaitObject( _pWindow ) ); 467 } 468 }; 469 470 //........................................................................ 471 } // namespace pcr 472 //........................................................................ 473 474 #endif // EXTENSIONS_SOURCE_PROPCTRLR_FORMCOMPONENTHANDLER_HXX 475 476