LibreOffice Module svx (master)  1
fmshimp.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <sal/config.h>
21 
22 #include <o3tl/safeint.hxx>
23 #include <sal/macros.h>
24 #include <sal/log.hxx>
25 #include <fmobj.hxx>
26 #include <fmpgeimp.hxx>
27 #include <svx/fmtools.hxx>
28 #include <fmprop.hxx>
29 #include <fmservs.hxx>
30 #include <fmshimp.hxx>
31 #include <fmtextcontrolshell.hxx>
32 #include <fmundo.hxx>
33 #include <fmurl.hxx>
34 #include <fmvwimp.hxx>
35 #include <gridcols.hxx>
36 #include <svx/svditer.hxx>
37 #include <svx/dialmgr.hxx>
38 #include <svx/strings.hrc>
39 #include <svx/fmglob.hxx>
40 #include <svx/fmmodel.hxx>
41 #include <svx/fmpage.hxx>
42 #include <svx/fmshell.hxx>
43 #include <svx/fmview.hxx>
44 #include <svx/obj3d.hxx>
45 #include <svx/sdrpagewindow.hxx>
46 #include <svx/svdpagv.hxx>
47 #include <svx/svxdlg.hxx>
48 #include <svx/svxids.hrc>
49 #include <bitmaps.hlst>
50 #include <formnavi.hrc>
51 
52 #include <com/sun/star/awt/XWindow2.hpp>
53 #include <com/sun/star/awt/XCheckBox.hpp>
54 #include <com/sun/star/awt/XListBox.hpp>
55 #include <com/sun/star/awt/XTextComponent.hpp>
56 #include <com/sun/star/beans/theIntrospection.hpp>
57 #include <com/sun/star/beans/PropertyAttribute.hpp>
58 #include <com/sun/star/beans/XPropertyState.hpp>
59 #include <com/sun/star/container/XContainer.hpp>
60 #include <com/sun/star/container/XIndexAccess.hpp>
61 #include <com/sun/star/container/XNamed.hpp>
62 #include <com/sun/star/form/ListSourceType.hpp>
63 #include <com/sun/star/form/TabOrderDialog.hpp>
64 #include <com/sun/star/form/XGrid.hpp>
65 #include <com/sun/star/form/XGridPeer.hpp>
66 #include <com/sun/star/form/XLoadable.hpp>
67 #include <com/sun/star/form/XReset.hpp>
68 #include <com/sun/star/form/binding/XBindableValue.hpp>
69 #include <com/sun/star/form/binding/XListEntrySink.hpp>
70 #include <com/sun/star/frame/FrameSearchFlag.hpp>
71 #include <com/sun/star/lang/XServiceInfo.hpp>
72 #include <com/sun/star/script/XEventAttacherManager.hpp>
73 #include <com/sun/star/sdbc/SQLException.hpp>
74 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
75 #include <com/sun/star/util/XModeSelector.hpp>
76 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
77 #include <com/sun/star/view/XSelectionSupplier.hpp>
78 
81 #include <comphelper/property.hxx>
82 #include <comphelper/sequence.hxx>
84 #include <comphelper/string.hxx>
85 #include <comphelper/types.hxx>
86 #include <connectivity/dbtools.hxx>
87 #include <sfx2/dispatch.hxx>
88 #include <sfx2/frame.hxx>
89 #include <sfx2/objsh.hxx>
90 #include <sfx2/viewfrm.hxx>
91 #include <sfx2/viewsh.hxx>
93 #include <tools/debug.hxx>
94 #include <tools/diagnose_ex.h>
95 #include <vcl/image.hxx>
96 #include <vcl/weld.hxx>
97 #include <vcl/settings.hxx>
98 #include <vcl/svapp.hxx>
99 
100 #include <algorithm>
101 #include <map>
102 #include <memory>
103 #include <vector>
104 
105 // is used for Invalidate -> maintain it as well
106 const sal_uInt16 DatabaseSlotMap[] =
107 {
108  SID_FM_RECORD_FIRST,
109  SID_FM_RECORD_NEXT,
110  SID_FM_RECORD_PREV,
111  SID_FM_RECORD_LAST,
112  SID_FM_RECORD_NEW,
113  SID_FM_RECORD_DELETE,
114  SID_FM_RECORD_ABSOLUTE,
115  SID_FM_RECORD_TOTAL,
116  SID_FM_RECORD_SAVE,
117  SID_FM_RECORD_UNDO,
118  SID_FM_REMOVE_FILTER_SORT,
119  SID_FM_SORTUP,
120  SID_FM_SORTDOWN,
121  SID_FM_ORDERCRIT,
122  SID_FM_AUTOFILTER,
123  SID_FM_FORM_FILTERED,
124  SID_FM_REFRESH,
125  SID_FM_REFRESH_FORM_CONTROL,
126  SID_FM_SEARCH,
127  SID_FM_FILTER_START,
128  SID_FM_VIEW_AS_GRID,
129  0
130 };
131 
132 // is used for Invalidate -> maintain it as well
133 // sort ascending !!!!!!
134 const sal_Int16 DlgSlotMap[] = // slots of the controller
135 {
136  SID_FM_CTL_PROPERTIES,
137  SID_FM_PROPERTIES,
138  SID_FM_TAB_DIALOG,
139  SID_FM_ADD_FIELD,
140  SID_FM_SHOW_FMEXPLORER,
141  SID_FM_FIELDS_CONTROL,
142  SID_FM_SHOW_PROPERTIES,
143  SID_FM_PROPERTY_CONTROL,
144  SID_FM_FMEXPLORER_CONTROL,
145  SID_FM_SHOW_DATANAVIGATOR,
146  SID_FM_DATANAVIGATOR_CONTROL,
147  0
148 };
149 
150 const sal_Int16 SelObjectSlotMap[] = // slots depending on the SelObject
151 {
152  SID_FM_CONVERTTO_EDIT,
153  SID_FM_CONVERTTO_BUTTON,
154  SID_FM_CONVERTTO_FIXEDTEXT,
155  SID_FM_CONVERTTO_LISTBOX,
156  SID_FM_CONVERTTO_CHECKBOX,
157  SID_FM_CONVERTTO_RADIOBUTTON,
158  SID_FM_CONVERTTO_GROUPBOX,
159  SID_FM_CONVERTTO_COMBOBOX,
160  SID_FM_CONVERTTO_IMAGEBUTTON,
161  SID_FM_CONVERTTO_FILECONTROL,
162  SID_FM_CONVERTTO_DATE,
163  SID_FM_CONVERTTO_TIME,
164  SID_FM_CONVERTTO_NUMERIC,
165  SID_FM_CONVERTTO_CURRENCY,
166  SID_FM_CONVERTTO_PATTERN,
167  SID_FM_CONVERTTO_IMAGECONTROL,
168  SID_FM_CONVERTTO_FORMATTED,
169  SID_FM_CONVERTTO_SCROLLBAR,
170  SID_FM_CONVERTTO_SPINBUTTON,
171  SID_FM_CONVERTTO_NAVIGATIONBAR,
172 
173  SID_FM_FMEXPLORER_CONTROL,
174  SID_FM_DATANAVIGATOR_CONTROL,
175 
176  0
177 };
178 
179 // the following arrays must be consistent, i.e., corresponding entries should
180 // be at the same relative position within their respective arrays
181 static const char* aConvertSlots[] =
182 {
183  "ConvertToEdit",
184  "ConvertToButton",
185  "ConvertToFixed",
186  "ConvertToList",
187  "ConvertToCheckBox",
188  "ConvertToRadio",
189  "ConvertToGroup",
190  "ConvertToCombo",
191  "ConvertToImageBtn",
192  "ConvertToFileControl",
193  "ConvertToDate",
194  "ConvertToTime",
195  "ConvertToNumeric",
196  "ConvertToCurrency",
197  "ConvertToPattern",
198  "ConvertToImageControl",
199  "ConvertToFormatted",
200  "ConvertToScrollBar",
201  "ConvertToSpinButton",
202  "ConvertToNavigationBar"
203 };
204 
205 const OUStringLiteral aImgIds[] =
206 {
207  RID_SVXBMP_EDITBOX,
208  RID_SVXBMP_BUTTON,
209  RID_SVXBMP_FIXEDTEXT,
210  RID_SVXBMP_LISTBOX,
211  RID_SVXBMP_CHECKBOX,
212  RID_SVXBMP_RADIOBUTTON,
213  RID_SVXBMP_GROUPBOX,
214  RID_SVXBMP_COMBOBOX,
215  RID_SVXBMP_IMAGEBUTTON,
216  RID_SVXBMP_FILECONTROL,
217  RID_SVXBMP_DATEFIELD,
218  RID_SVXBMP_TIMEFIELD,
219  RID_SVXBMP_NUMERICFIELD,
220  RID_SVXBMP_CURRENCYFIELD,
221  RID_SVXBMP_PATTERNFIELD,
222  RID_SVXBMP_IMAGECONTROL,
223  RID_SVXBMP_FORMATTEDFIELD,
224  RID_SVXBMP_SCROLLBAR,
225  RID_SVXBMP_SPINBUTTON,
226  RID_SVXBMP_NAVIGATIONBAR
227 };
228 
229 const sal_Int16 nObjectTypes[] =
230 {
231  OBJ_FM_EDIT,
251 };
252 
253 using namespace ::com::sun::star;
254 using namespace ::com::sun::star::ui;
255 using namespace ::com::sun::star::uno;
256 using namespace ::com::sun::star::sdb;
257 using namespace ::com::sun::star::sdbc;
258 using namespace ::com::sun::star::sdbcx;
259 using namespace ::com::sun::star::beans;
260 using namespace ::com::sun::star::container;
261 using namespace ::com::sun::star::form;
262 using namespace ::com::sun::star::form::binding;
263 using namespace ::com::sun::star::form::runtime;
264 using namespace ::com::sun::star::awt;
265 using namespace ::com::sun::star::view;
266 using namespace ::com::sun::star::util;
267 using namespace ::com::sun::star::script;
268 using namespace ::svxform;
269 using namespace ::svx;
270 using namespace ::dbtools;
271 
272 
273 //= helper
274 
275 namespace
276 {
277 
278  void collectInterfacesFromMarkList( const SdrMarkList& _rMarkList, InterfaceBag& /* [out] */ _rInterfaces )
279  {
280  _rInterfaces.clear();
281 
282  const size_t nMarkCount = _rMarkList.GetMarkCount();
283  for ( size_t i = 0; i < nMarkCount; ++i)
284  {
285  SdrObject* pCurrent = _rMarkList.GetMark( i )->GetMarkedSdrObj();
286 
287  std::unique_ptr<SdrObjListIter> pGroupIterator;
288  if ( pCurrent->IsGroupObject() )
289  {
290  pGroupIterator.reset(new SdrObjListIter( pCurrent->GetSubList() ));
291  pCurrent = pGroupIterator->IsMore() ? pGroupIterator->Next() : nullptr;
292  }
293 
294  while ( pCurrent )
295  {
296  FmFormObj* pAsFormObject = FmFormObj::GetFormObject( pCurrent );
297  // note this will de-reference virtual objects, if necessary/possible
298  if ( pAsFormObject )
299  {
300  Reference< XInterface > xControlModel( pAsFormObject->GetUnoControlModel(), UNO_QUERY );
301  // the UNO_QUERY is important for normalization
302  if ( xControlModel.is() )
303  _rInterfaces.insert( xControlModel );
304  }
305 
306  // next element
307  pCurrent = pGroupIterator && pGroupIterator->IsMore() ? pGroupIterator->Next() : nullptr;
308  }
309  }
310  }
311 
312 
313  sal_Int32 GridView2ModelPos(const Reference< XIndexAccess>& rColumns, sal_Int16 nViewPos)
314  {
315  try
316  {
317  if (rColumns.is())
318  {
319  // loop through all columns
320  sal_Int32 i;
321  Reference< XPropertySet> xCur;
322  for (i=0; i<rColumns->getCount(); ++i)
323  {
324  rColumns->getByIndex(i) >>= xCur;
325  if (!::comphelper::getBOOL(xCur->getPropertyValue(FM_PROP_HIDDEN)))
326  {
327  // for every visible col : if nViewPos is greater zero, decrement it, else we
328  // have found the model position
329  if (!nViewPos)
330  break;
331  else
332  --nViewPos;
333  }
334  }
335  if (i<rColumns->getCount())
336  return i;
337  }
338  }
339  catch(const Exception&)
340  {
342  }
343  return -1;
344  }
345 
346 
347  void TransferEventScripts(const Reference< XControlModel>& xModel, const Reference< XControl>& xControl,
348  const Sequence< ScriptEventDescriptor>& rTransferIfAvailable)
349  {
350  // first check if we have a XEventAttacherManager for the model
351  Reference< XChild> xModelChild(xModel, UNO_QUERY);
352  if (!xModelChild.is())
353  return; // nothing to do
354 
355  Reference< XEventAttacherManager> xEventManager(xModelChild->getParent(), UNO_QUERY);
356  if (!xEventManager.is())
357  return; // nothing to do
358 
359  if (!rTransferIfAvailable.hasElements())
360  return; // nothing to do
361 
362  // check for the index of the model within its parent
363  Reference< XIndexAccess> xParentIndex(xModelChild->getParent(), UNO_QUERY);
364  if (!xParentIndex.is())
365  return; // nothing to do
366  sal_Int32 nIndex = getElementPos(xParentIndex, xModel);
367  if (nIndex<0 || nIndex>=xParentIndex->getCount())
368  return; // nothing to do
369 
370  // then we need information about the listeners supported by the control and the model
371  Sequence< Type> aModelListeners;
372  Sequence< Type> aControlListeners;
373 
374  Reference< XIntrospection> xIntrospection = theIntrospection::get(::comphelper::getProcessComponentContext());
375 
376  if (xModel.is())
377  {
378  Any aModel(makeAny(xModel));
379  aModelListeners = xIntrospection->inspect(aModel)->getSupportedListeners();
380  }
381 
382  if (xControl.is())
383  {
384  Any aControl(makeAny(xControl));
385  aControlListeners = xIntrospection->inspect(aControl)->getSupportedListeners();
386  }
387 
388  sal_Int32 nMaxNewLen = aModelListeners.getLength() + aControlListeners.getLength();
389  if (!nMaxNewLen)
390  return; // the model and the listener don't support any listeners (or we were unable to retrieve these infos)
391 
392  Sequence< ScriptEventDescriptor> aTransferable(nMaxNewLen);
393  ScriptEventDescriptor* pTransferable = aTransferable.getArray();
394 
395  for (const ScriptEventDescriptor& rCurrent : rTransferIfAvailable)
396  {
397  // search the model/control idl classes for the event described by pCurrent
398  for (const Sequence< Type>* pCurrentArray : { &aModelListeners, &aControlListeners })
399  {
400  for (const Type& rCurrentListener : *pCurrentArray)
401  {
402  OUString aListener = rCurrentListener.getTypeName();
403  if (!aListener.isEmpty())
404  aListener = aListener.copy(aListener.lastIndexOf('.')+1);
405 
406  if (aListener == rCurrent.ListenerType)
407  // the current ScriptEventDescriptor doesn't match the current listeners class
408  continue;
409 
410  // now check the methods
411  Sequence< OUString> aMethodsNames = ::comphelper::getEventMethodsForType(rCurrentListener);
412 
413  if (comphelper::findValue(aMethodsNames, rCurrent.EventMethod) != -1)
414  {
415  // we can transfer the script event : the model (control) supports it
416  *pTransferable = rCurrent;
417  ++pTransferable;
418  break;
419  }
420  }
421  }
422  }
423 
424  sal_Int32 nRealNewLen = pTransferable - aTransferable.getArray();
425  aTransferable.realloc(nRealNewLen);
426 
427  xEventManager->registerScriptEvents(nIndex, aTransferable);
428  }
429 
430 
431  OUString getServiceNameByControlType(sal_Int16 nType)
432  {
433  switch (nType)
434  {
435  case OBJ_FM_EDIT : return FM_COMPONENT_TEXTFIELD;
438  case OBJ_FM_LISTBOX : return FM_COMPONENT_LISTBOX;
457  }
458  return OUString();
459  }
460 
461 }
462 
463 
464 // check if the control has one of the interfaces we can use for searching
465 // *_pCurrentText will be filled with the current text of the control (as used when searching this control)
466 bool IsSearchableControl( const css::uno::Reference< css::uno::XInterface>& _rxControl,
467  OUString* _pCurrentText )
468 {
469  if ( !_rxControl.is() )
470  return false;
471 
472  Reference< XTextComponent > xAsText( _rxControl, UNO_QUERY );
473  if ( xAsText.is() )
474  {
475  if ( _pCurrentText )
476  *_pCurrentText = xAsText->getText();
477  return true;
478  }
479 
480  Reference< XListBox > xListBox( _rxControl, UNO_QUERY );
481  if ( xListBox.is() )
482  {
483  if ( _pCurrentText )
484  *_pCurrentText = xListBox->getSelectedItem();
485  return true;
486  }
487 
488  Reference< XCheckBox > xCheckBox( _rxControl, UNO_QUERY );
489  if ( xCheckBox.is() )
490  {
491  if ( _pCurrentText )
492  {
493  switch ( static_cast<::TriState>(xCheckBox->getState()) )
494  {
495  case TRISTATE_FALSE: *_pCurrentText = "0"; break;
496  case TRISTATE_TRUE: *_pCurrentText = "1"; break;
497  default: _pCurrentText->clear(); break;
498  }
499  }
500  return true;
501  }
502 
503  return false;
504 }
505 
506 
508 {
509  if (_rContainer == m_xStartingPoint)
510  // would be quite stupid to step over the root...
511  return true;
512 
513  return Reference< XControlModel>(_rContainer, UNO_QUERY).is();
514 }
515 
516 
518 {
519  if (!_rElement.is())
520  // NULL element
521  return false;
522 
523  if (Reference< XForm>(_rElement, UNO_QUERY).is() || Reference< XGrid>(_rElement, UNO_QUERY).is())
524  // a forms or a grid
525  return false;
526 
527  Reference< XPropertySet> xSet(_rElement, UNO_QUERY);
528  if (!xSet.is() || !::comphelper::hasProperty(FM_PROP_BOUNDFIELD, xSet))
529  // no "BoundField" property
530  return false;
531 
532  Any aVal( xSet->getPropertyValue(FM_PROP_BOUNDFIELD) );
533  if (aVal.getValueTypeClass() != TypeClass_INTERFACE)
534  // void or invalid property value
535  return false;
536 
537  return aVal.hasValue();
538 }
539 
540 
541 static bool isControlList(const SdrMarkList& rMarkList)
542 {
543  // the list contains only controls and at least one control
544  const size_t nMarkCount = rMarkList.GetMarkCount();
545  bool bControlList = nMarkCount != 0;
546 
547  bool bHadAnyLeafs = false;
548 
549  for (size_t i = 0; i < nMarkCount && bControlList; ++i)
550  {
551  SdrObject *pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
552  E3dObject* pAs3DObject = dynamic_cast< E3dObject* >( pObj);
553  // E3dObject's do not contain any 2D-objects (by definition)
554  // we need this extra check here : an E3dObject->IsGroupObject says "YES", but an SdrObjListIter working
555  // with an E3dObject doesn't give me any Nodes (E3dObject has a sub list, but no members in that list,
556  // cause there implementation differs from the one of "normal" SdrObject's. Unfortunally SdrObject::IsGroupObject
557  // doesn't check the element count of the sub list, which is simply a bug in IsGroupObject we can't fix at the moment).
558  // So at the end of this function bControlList would have the same value it was initialized with above : sal_True
559  // And this would be wrong :)
560  // 03.02.00 - 72529 - FS
561  if (!pAs3DObject)
562  {
563  if (pObj->IsGroupObject())
564  {
565  SdrObjListIter aIter(pObj->GetSubList());
566  while (aIter.IsMore() && bControlList)
567  {
568  bControlList = SdrInventor::FmForm == aIter.Next()->GetObjInventor();
569  bHadAnyLeafs = true;
570  }
571  }
572  else
573  {
574  bHadAnyLeafs = true;
575  bControlList = SdrInventor::FmForm == pObj->GetObjInventor();
576  }
577  }
578  }
579 
580  return bControlList && bHadAnyLeafs;
581 }
582 
583 
584 static Reference< XForm > GetForm(const Reference< XInterface>& _rxElement)
585 {
586  Reference< XForm > xForm( _rxElement, UNO_QUERY );
587  if ( xForm.is() )
588  return xForm;
589 
590  Reference< XChild > xChild( _rxElement, UNO_QUERY );
591  if ( xChild.is() )
592  return GetForm( xChild->getParent() );
593 
594  return Reference< XForm >();
595 }
596 
598  :FmXFormShell_BD_BASE( _rMutex )
599 {
600 }
601 
602 FmXFormShell::FmXFormShell( FmFormShell& _rShell, SfxViewFrame* _pViewFrame )
604  ,FmXFormShell_CFGBASE("Office.Common/Misc", ConfigItemMode::NONE)
605  ,m_eNavigate( NavigationBarMode_NONE )
606  ,m_nInvalidationEvent( nullptr )
607  ,m_nActivationEvent( nullptr )
608  ,m_pShell( &_rShell )
609  ,m_pTextShell( new svx::FmTextControlShell( _pViewFrame ) )
610  ,m_aActiveControllerFeatures( this )
611  ,m_aNavControllerFeatures( this )
612  ,m_eDocumentType( eUnknownDocumentType )
613  ,m_nLockSlotInvalidation( 0 )
614  ,m_bHadPropertyBrowserInDesignMode( false )
615  ,m_bTrackProperties( true )
616  ,m_bUseWizards( true )
617  ,m_bDatabaseBar( false )
618  ,m_bInActivate( false )
619  ,m_bSetFocus( false )
620  ,m_bFilterMode( false )
621  ,m_bChangingDesignMode( false )
622  ,m_bPreparedClose( false )
623  ,m_bFirstActivation( true )
624 {
625  m_aMarkTimer.SetTimeout(100);
626  m_aMarkTimer.SetInvokeHandler(LINK(this, FmXFormShell, OnTimeOut_Lock));
627  m_aMarkTimer.SetDebugName("svx::FmXFormShell m_aMarkTimer");
628 
629  m_xAttachedFrame = _pViewFrame->GetFrame().GetFrameInterface();
630 
631  // to prevent deletion of this we acquire our refcounter once
632  osl_atomic_increment(&m_refCount);
633 
634  // correct the refcounter
635  osl_atomic_decrement(&m_refCount);
636 
637  // cache the current configuration settings we're interested in
638  implAdjustConfigCache_Lock();
639  // and register for changes on this settings
640  Sequence< OUString > aNames { "FormControlPilotsEnabled" };
641  EnableNotification(aNames);
642 }
643 
644 
645 FmXFormShell::~FmXFormShell()
646 {
647 }
648 
649 
650 Reference< css::frame::XModel > FmXFormShell::getContextDocument_Lock() const
651 {
652  Reference< css::frame::XModel > xModel;
653 
654  // determine the type of document we live in
655  try
656  {
657  Reference< css::frame::XController > xController;
658  if ( m_xAttachedFrame.is() )
659  xController = m_xAttachedFrame->getController();
660  if ( xController.is() )
661  xModel = xController->getModel();
662  }
663  catch( const Exception& )
664  {
666  }
667  return xModel;
668 }
669 
670 
671 bool FmXFormShell::isEnhancedForm_Lock() const
672 {
673  return getDocumentType_Lock() == eEnhancedForm;
674 }
675 
676 
677 bool FmXFormShell::impl_checkDisposed_Lock() const
678 {
680  if ( !m_pShell )
681  {
682  OSL_FAIL( "FmXFormShell::impl_checkDisposed: already disposed!" );
683  return true;
684  }
685  return false;
686 }
687 
688 
689 ::svxform::DocumentType FmXFormShell::getDocumentType_Lock() const
690 {
691  if ( m_eDocumentType != eUnknownDocumentType )
692  return m_eDocumentType;
693 
694  // determine the type of document we live in
695  Reference<css::frame::XModel> xModel = getContextDocument_Lock();
696  if ( xModel.is() )
697  m_eDocumentType = DocumentClassification::classifyDocument( xModel );
698  else
699  {
700  OSL_FAIL( "FmXFormShell::getDocumentType: can't determine the document type!" );
701  m_eDocumentType = eTextDocument;
702  // fallback, just to have a defined state
703  }
704 
705  return m_eDocumentType;
706 }
707 
708 
709 bool FmXFormShell::IsReadonlyDoc_Lock() const
710 {
711  if (impl_checkDisposed_Lock())
712  return true;
713 
714  FmFormModel* pModel = m_pShell->GetFormModel();
715  if ( pModel && pModel->GetObjectShell() )
716  return pModel->GetObjectShell()->IsReadOnly() || pModel->GetObjectShell()->IsReadOnlyUI();
717  return true;
718 }
719 
720 // EventListener
721 
722 void SAL_CALL FmXFormShell::disposing(const lang::EventObject& e)
723 {
724  SolarMutexGuard g;
725 
726  if (m_xActiveController == e.Source)
727  {
728  // the controller will release, then release everything
729  stopListening_Lock();
730  m_xActiveForm = nullptr;
731  m_xActiveController = nullptr;
732  m_xNavigationController = nullptr;
733 
734  m_aActiveControllerFeatures.dispose();
735  m_aNavControllerFeatures.dispose();
736 
737  if ( m_pShell )
738  m_pShell->GetViewShell()->GetViewFrame()->GetBindings().InvalidateShell(*m_pShell);
739  }
740 
741  if (e.Source == m_xExternalViewController)
742  {
743  Reference< runtime::XFormController > xFormController( m_xExternalViewController, UNO_QUERY );
744  OSL_ENSURE( xFormController.is(), "FmXFormShell::disposing: invalid external view controller!" );
745  if (xFormController.is())
746  xFormController->removeActivateListener(static_cast<XFormControllerListener*>(this));
747 
748  if (m_xExternalViewController.is())
749  m_xExternalViewController->removeEventListener(static_cast<XEventListener*>(static_cast<XPropertyChangeListener*>(this)));
750 
751  m_xExternalViewController = nullptr;
752  m_xExternalDisplayedForm = nullptr;
753  m_xExtViewTriggerController = nullptr;
754 
755  InvalidateSlot_Lock( SID_FM_VIEW_AS_GRID, false );
756  }
757 }
758 
759 
760 void SAL_CALL FmXFormShell::propertyChange(const PropertyChangeEvent& evt)
761 {
762  SolarMutexGuard g;
763 
764  if (impl_checkDisposed_Lock())
765  return;
766 
767  if (evt.PropertyName == FM_PROP_ROWCOUNT)
768  {
769  // The update following this forces a re-painting of the corresponding
770  // slots. But if I am not in the MainThread of the application (because,
771  // for example, a cursor is counting data sets at the moment and always
772  // gives me this PropertyChanges), this can clash with normal paints in
773  // the MainThread of the application. (Such paints happen, for example,
774  // if one simply places another application over the office and switches
775  // back again).
776  // Therefore the use of the SolarMutex, which safeguards that.
778  if (rSolarSafety.tryToAcquire())
779  {
780  m_pShell->GetViewShell()->GetViewFrame()->GetBindings().Invalidate(SID_FM_RECORD_TOTAL, true);
781  m_pShell->GetViewShell()->GetViewFrame()->GetBindings().Update(SID_FM_RECORD_TOTAL);
782  rSolarSafety.release();
783  }
784  else
785  {
786  // with the following the slot is invalidated asynchron
787  LockSlotInvalidation_Lock(true);
788  InvalidateSlot_Lock(SID_FM_RECORD_TOTAL, false);
789  LockSlotInvalidation_Lock(false);
790  }
791  }
792 
793  // this may be called from a non-main-thread so invalidate the shell asynchronously
794  LockSlotInvalidation_Lock(true);
795  InvalidateSlot_Lock(0, false); // special meaning : invalidate m_pShell
796  LockSlotInvalidation_Lock(false);
797 }
798 
799 
800 void FmXFormShell::invalidateFeatures( const ::std::vector< sal_Int32 >& _rFeatures )
801 {
802  SolarMutexGuard g;
803 
804  if (impl_checkDisposed_Lock())
805  return;
806 
807  OSL_ENSURE( !_rFeatures.empty(), "FmXFormShell::invalidateFeatures: invalid arguments!" );
808 
809  if ( m_pShell->GetViewShell() && m_pShell->GetViewShell()->GetViewFrame() )
810  {
811  // unfortunately, SFX requires sal_uInt16
812  ::std::vector< sal_uInt16 > aSlotIds( _rFeatures.begin(), _rFeatures.end() );
813 
814  // furthermore, SFX wants a terminating 0
815  aSlotIds.push_back( 0 );
816 
817  // and, last but not least, SFX wants the ids to be sorted
818  ::std::sort( aSlotIds.begin(), aSlotIds.end() - 1 );
819 
820  sal_uInt16 *pSlotIds = aSlotIds.data();
821  m_pShell->GetViewShell()->GetViewFrame()->GetBindings().Invalidate( pSlotIds );
822  }
823 }
824 
825 
826 void SAL_CALL FmXFormShell::formActivated(const lang::EventObject& rEvent)
827 {
828  SolarMutexGuard g;
829 
830  if (impl_checkDisposed_Lock())
831  return;
832 
833  Reference< runtime::XFormController > xController( rEvent.Source, UNO_QUERY_THROW );
834  m_pTextShell->formActivated( xController );
835  setActiveController_Lock(xController);
836 }
837 
838 
839 void SAL_CALL FmXFormShell::formDeactivated(const lang::EventObject& rEvent)
840 {
841  SolarMutexGuard g;
842 
843  if (impl_checkDisposed_Lock())
844  return;
845 
846  Reference< runtime::XFormController > xController( rEvent.Source, UNO_QUERY_THROW );
847  m_pTextShell->formDeactivated( xController );
848 }
849 
850 
851 void FmXFormShell::disposing()
852 {
853  SolarMutexGuard g;
854 
855  FmXFormShell_BASE::disposing();
856 
857  if ( m_pShell && !m_pShell->IsDesignMode() )
858  setActiveController_Lock(nullptr, true);
859  // do NOT save the content of the old form (the second parameter tells this)
860  // if we're here, then we expect that PrepareClose has been called, and thus the user
861  // got a chance to commit or reject any changes. So in case we're here and there
862  // are still uncommitted changes, the user explicitly wanted this.
863 
864  m_pTextShell->dispose();
865 
866  m_xAttachedFrame = nullptr;
867 
868  CloseExternalFormViewer_Lock();
869 
870  while ( !m_aLoadingPages.empty() )
871  {
872  Application::RemoveUserEvent( m_aLoadingPages.front().nEventId );
873  m_aLoadingPages.pop();
874  }
875 
876  {
877  if (m_nInvalidationEvent)
878  {
879  Application::RemoveUserEvent(m_nInvalidationEvent);
880  m_nInvalidationEvent = nullptr;
881  }
882  if ( m_nActivationEvent )
883  {
884  Application::RemoveUserEvent( m_nActivationEvent );
885  m_nActivationEvent = nullptr;
886  }
887  }
888 
889  {
890  DBG_ASSERT(!m_nInvalidationEvent, "FmXFormShell::~FmXFormShell : still have an invalidation event !");
891  // should have been deleted while being disposed
892 
893  m_aMarkTimer.Stop();
894  }
895 
896  DisableNotification();
897 
898  RemoveElement_Lock(m_xForms);
899  m_xForms.clear();
900 
901  impl_switchActiveControllerListening_Lock(false);
902  m_xActiveController = nullptr;
903  m_xActiveForm = nullptr;
904 
905  m_pShell = nullptr;
906  m_xNavigationController = nullptr;
907  m_xCurrentForm = nullptr;
908  m_xLastGridFound = nullptr;
909  m_xAttachedFrame = nullptr;
910  m_xExternalViewController = nullptr;
911  m_xExtViewTriggerController = nullptr;
912  m_xExternalDisplayedForm = nullptr;
913 
914  InterfaceBag aEmpty;
915  m_aCurrentSelection.swap( aEmpty );
916 
917  m_aActiveControllerFeatures.dispose();
918  m_aNavControllerFeatures.dispose();
919 }
920 
921 
922 void FmXFormShell::UpdateSlot_Lock(sal_Int16 _nId)
923 {
924  if (impl_checkDisposed_Lock())
925  return;
926 
927  if ( m_nLockSlotInvalidation )
928  {
929  OSL_FAIL( "FmXFormShell::UpdateSlot: cannot update if invalidation is currently locked!" );
930  InvalidateSlot_Lock(_nId, false);
931  }
932  else
933  {
934  OSL_ENSURE( _nId, "FmXFormShell::UpdateSlot: can't update the complete shell!" );
935  m_pShell->GetViewShell()->GetViewFrame()->GetBindings().Invalidate( _nId, true, true );
936  m_pShell->GetViewShell()->GetViewFrame()->GetBindings().Update( _nId );
937  }
938 }
939 
940 
941 void FmXFormShell::InvalidateSlot_Lock(sal_Int16 nId, bool bWithId)
942 {
943  if (impl_checkDisposed_Lock())
944  return;
945 
946  if (m_nLockSlotInvalidation)
947  {
948  sal_uInt8 nFlags = ( bWithId ? 0x01 : 0 );
949  m_arrInvalidSlots.emplace_back(nId, nFlags );
950  }
951  else
952  if (nId)
953  m_pShell->GetViewShell()->GetViewFrame()->GetBindings().Invalidate(nId, true, bWithId);
954  else
955  m_pShell->GetViewShell()->GetViewFrame()->GetBindings().InvalidateShell(*m_pShell);
956 }
957 
958 
959 void FmXFormShell::LockSlotInvalidation_Lock(bool bLock)
960 {
961  if (impl_checkDisposed_Lock())
962  return;
963 
964  DBG_ASSERT(bLock || m_nLockSlotInvalidation>0, "FmXFormShell::LockSlotInvalidation : invalid call !");
965 
966  if (bLock)
967  ++m_nLockSlotInvalidation;
968  else if (!--m_nLockSlotInvalidation)
969  {
970  // (asynchronously) invalidate everything accumulated during the locked phase
971  if (!m_nInvalidationEvent)
972  m_nInvalidationEvent = Application::PostUserEvent(LINK(this, FmXFormShell, OnInvalidateSlots_Lock));
973  }
974 }
975 
976 
977 IMPL_LINK_NOARG(FmXFormShell, OnInvalidateSlots_Lock, void*,void)
978 {
979  if (impl_checkDisposed_Lock())
980  return;
981 
982  m_nInvalidationEvent = nullptr;
983 
984  for (const auto& rInvalidSlot : m_arrInvalidSlots)
985  {
986  if (rInvalidSlot.id)
987  m_pShell->GetViewShell()->GetViewFrame()->GetBindings().Invalidate(rInvalidSlot.id, true, (rInvalidSlot.flags & 0x01));
988  else
989  m_pShell->GetViewShell()->GetViewFrame()->GetBindings().InvalidateShell(*m_pShell);
990  }
991  m_arrInvalidSlots.clear();
992 }
993 
994 
995 void FmXFormShell::ForceUpdateSelection_Lock()
996 {
997  if (impl_checkDisposed_Lock())
998  return;
999 
1000  if (IsSelectionUpdatePending_Lock())
1001  {
1002  m_aMarkTimer.Stop();
1003 
1004  // optionally turn off the invalidation of slots which is implicitly done by SetSelection
1005  LockSlotInvalidation_Lock(true);
1006 
1007  SetSelection_Lock(m_pShell->GetFormView()->GetMarkedObjectList());
1008 
1009  LockSlotInvalidation_Lock(false);
1010  }
1011 }
1012 
1013 void FmXFormShell::GetConversionMenu_Lock(weld::Menu& rNewMenu)
1014 {
1015  for (size_t i = 0; i < SAL_N_ELEMENTS(aConvertSlots); ++i)
1016  {
1017  // the corresponding image at it
1018  rNewMenu.append(OUString::createFromAscii(aConvertSlots[i]), SvxResId(RID_SVXSW_CONVERTMENU[i]), aImgIds[i]);
1019  }
1020 }
1021 
1022 OString FmXFormShell::SlotToIdent(sal_uInt16 nSlot)
1023 {
1025 
1026  for (size_t i = 0; i < SAL_N_ELEMENTS(aConvertSlots); ++i)
1027  {
1028  if (nSlot == SelObjectSlotMap[i])
1029  return aConvertSlots[i];
1030  }
1031 
1032  return OString();
1033 }
1034 
1035 bool FmXFormShell::isControlConversionSlot(const OString& rIdent)
1036 {
1037  for (const auto& rConvertSlot : aConvertSlots)
1038  if (rIdent == rConvertSlot)
1039  return true;
1040  return false;
1041 }
1042 
1043 void FmXFormShell::executeControlConversionSlot_Lock(const OString &rIdent)
1044 {
1045  OSL_PRECOND( canConvertCurrentSelectionToControl_Lock(rIdent), "FmXFormShell::executeControlConversionSlot: illegal call!" );
1046  InterfaceBag::const_iterator aSelectedElement = m_aCurrentSelection.begin();
1047  if ( aSelectedElement == m_aCurrentSelection.end() )
1048  return;
1049 
1050  executeControlConversionSlot_Lock(Reference<XFormComponent>(*aSelectedElement, UNO_QUERY), rIdent);
1051 }
1052 
1053 bool FmXFormShell::executeControlConversionSlot_Lock(const Reference<XFormComponent>& _rxObject, const OString& rIdent)
1054 {
1055  if (impl_checkDisposed_Lock())
1056  return false;
1057 
1058  OSL_ENSURE( _rxObject.is(), "FmXFormShell::executeControlConversionSlot: invalid object!" );
1059  if ( !_rxObject.is() )
1060  return false;
1061 
1062  SdrPage* pPage = m_pShell->GetCurPage();
1063  FmFormPage* pFormPage = dynamic_cast< FmFormPage* >( pPage );
1064  OSL_ENSURE( pFormPage, "FmXFormShell::executeControlConversionSlot: no current (form) page!" );
1065  if ( !pFormPage )
1066  return false;
1067 
1068  OSL_ENSURE( isSolelySelected_Lock(_rxObject),
1069  "FmXFormShell::executeControlConversionSlot: hmm ... shouldn't this parameter be redundant?" );
1070 
1071  for (size_t lookupSlot = 0; lookupSlot < SAL_N_ELEMENTS(aConvertSlots); ++lookupSlot)
1072  {
1073  if (rIdent == aConvertSlots[lookupSlot])
1074  {
1075  Reference< XInterface > xNormalizedObject( _rxObject, UNO_QUERY );
1076 
1077  FmFormObj* pFormObject = nullptr;
1078  SdrObjListIter aPageIter( pFormPage );
1079  while ( aPageIter.IsMore() )
1080  {
1081  SdrObject* pCurrent = aPageIter.Next();
1082  pFormObject = FmFormObj::GetFormObject( pCurrent );
1083  if ( !pFormObject )
1084  continue;
1085 
1086  Reference< XInterface > xCurrentNormalized( pFormObject->GetUnoControlModel(), UNO_QUERY );
1087  if ( xCurrentNormalized.get() == xNormalizedObject.get() )
1088  break;
1089 
1090  pFormObject = nullptr;
1091  }
1092 
1093  if ( !pFormObject )
1094  return false;
1095 
1096  OUString sNewName( getServiceNameByControlType( nObjectTypes[ lookupSlot ] ) );
1098  Reference< XControlModel> xNewModel( xContext->getServiceManager()->createInstanceWithContext(sNewName, xContext), UNO_QUERY );
1099  if (!xNewModel.is())
1100  return false;
1101 
1102  Reference< XControlModel> xOldModel( pFormObject->GetUnoControlModel() );
1103 
1104  // transfer properties
1105  Reference< XPropertySet> xOldSet(xOldModel, UNO_QUERY);
1106  Reference< XPropertySet> xNewSet(xNewModel, UNO_QUERY);
1107 
1108 
1109  lang::Locale aNewLanguage = Application::GetSettings().GetUILanguageTag().getLocale();
1110  TransferFormComponentProperties(xOldSet, xNewSet, aNewLanguage);
1111 
1112  Sequence< css::script::ScriptEventDescriptor> aOldScripts;
1113  Reference< XChild> xChild(xOldModel, UNO_QUERY);
1114  if (xChild.is())
1115  {
1116  Reference< XIndexAccess> xParent(xChild->getParent(), UNO_QUERY);
1117 
1118  // remember old script events
1119  Reference< css::script::XEventAttacherManager> xEvManager(xChild->getParent(), UNO_QUERY);
1120  if (xParent.is() && xEvManager.is())
1121  {
1122  sal_Int32 nIndex = getElementPos(xParent, xOldModel);
1123  if (nIndex>=0 && nIndex<xParent->getCount())
1124  aOldScripts = xEvManager->getScriptEvents(nIndex);
1125  }
1126 
1127  // replace the model within the parent container
1128  Reference< XIndexContainer> xIndexParent(xChild->getParent(), UNO_QUERY);
1129  if (xIndexParent.is())
1130  {
1131  // the form container works with FormComponents
1132  Reference< XFormComponent> xComponent(xNewModel, UNO_QUERY);
1133  DBG_ASSERT(xComponent.is(), "FmXFormShell::executeControlConversionSlot: the new model is no form component !");
1134  Any aNewModel(makeAny(xComponent));
1135  try
1136  {
1137 
1138  sal_Int32 nIndex = getElementPos(xParent, xOldModel);
1139  if (nIndex>=0 && nIndex<xParent->getCount())
1140  xIndexParent->replaceByIndex(nIndex, aNewModel);
1141  else
1142  {
1143  OSL_FAIL("FmXFormShell::executeControlConversionSlot: could not replace the model !");
1144  Reference< css::lang::XComponent> xNewComponent(xNewModel, UNO_QUERY);
1145  if (xNewComponent.is())
1146  xNewComponent->dispose();
1147  return false;
1148  }
1149  }
1150  catch(Exception&)
1151  {
1152  OSL_FAIL("FmXFormShell::executeControlConversionSlot: could not replace the model !");
1153  Reference< css::lang::XComponent> xNewComponent(xNewModel, UNO_QUERY);
1154  if (xNewComponent.is())
1155  xNewComponent->dispose();
1156  return false;
1157  }
1158 
1159  }
1160  }
1161 
1162  // special handling for the LabelControl-property : can only be set when the model is placed
1163  // within the forms hierarchy
1165  {
1166  try
1167  {
1168  xNewSet->setPropertyValue(FM_PROP_CONTROLLABEL, xOldSet->getPropertyValue(FM_PROP_CONTROLLABEL));
1169  }
1170  catch(Exception&)
1171  {
1172  }
1173 
1174  }
1175 
1176  // set new model
1177  pFormObject->SetChanged();
1178  pFormObject->SetUnoControlModel(xNewModel);
1179 
1180  // transfer script events
1181  // (do this _after_ SetUnoControlModel as we need the new (implicitly created) control)
1182  if (aOldScripts.hasElements())
1183  {
1184  // find the control for the model
1185  Reference<XControlContainer> xControlContainer(getControlContainerForView_Lock());
1186 
1187  Sequence< Reference< XControl> > aControls( xControlContainer->getControls() );
1188 
1189  Reference< XControl> xControl;
1190  auto pControl = std::find_if(aControls.begin(), aControls.end(),
1191  [&xNewModel](const Reference< XControl>& rControl) { return rControl->getModel() == xNewModel; });
1192  if (pControl != aControls.end())
1193  xControl = *pControl;
1194  TransferEventScripts(xNewModel, xControl, aOldScripts);
1195  }
1196 
1197  // transfer value bindings, if possible
1198  {
1199  Reference< XBindableValue > xOldBindable( xOldModel, UNO_QUERY );
1200  Reference< XBindableValue > xNewBindable( xNewModel, UNO_QUERY );
1201  if ( xOldBindable.is() )
1202  {
1203  try
1204  {
1205  if ( xNewBindable.is() )
1206  xNewBindable->setValueBinding( xOldBindable->getValueBinding() );
1207  xOldBindable->setValueBinding( nullptr );
1208  }
1209  catch(const Exception&)
1210  {
1211  DBG_UNHANDLED_EXCEPTION("svx");
1212  }
1213  }
1214  }
1215  // same for list entry sources
1216  {
1217  Reference< XListEntrySink > xOldSink( xOldModel, UNO_QUERY );
1218  Reference< XListEntrySink > xNewSink( xNewModel, UNO_QUERY );
1219  if ( xOldSink.is() )
1220  {
1221  try
1222  {
1223  if ( xNewSink.is() )
1224  xNewSink->setListEntrySource( xOldSink->getListEntrySource() );
1225  xOldSink->setListEntrySource( nullptr );
1226  }
1227  catch(const Exception&)
1228  {
1229  DBG_UNHANDLED_EXCEPTION("svx");
1230  }
1231  }
1232  }
1233 
1234  // create an undo action
1235  FmFormModel* pModel = m_pShell->GetFormModel();
1236  DBG_ASSERT(pModel != nullptr, "FmXFormShell::executeControlConversionSlot: my shell has no model !");
1237  if (pModel && pModel->IsUndoEnabled() )
1238  {
1239  pModel->AddUndo(std::make_unique<FmUndoModelReplaceAction>(*pModel, pFormObject, xOldModel));
1240  }
1241  else
1242  {
1244  }
1245 
1246  return true;
1247  }
1248  }
1249  return false;
1250 }
1251 
1252 bool FmXFormShell::canConvertCurrentSelectionToControl_Lock(const OString& rIdent)
1253 {
1254  if ( m_aCurrentSelection.empty() )
1255  return false;
1256 
1257  InterfaceBag::const_iterator aCheck = m_aCurrentSelection.begin();
1258  Reference< lang::XServiceInfo > xElementInfo( *aCheck, UNO_QUERY );
1259  if ( !xElementInfo.is() )
1260  // no service info -> cannot determine this
1261  return false;
1262 
1263  if ( ++aCheck != m_aCurrentSelection.end() )
1264  // more than one element
1265  return false;
1266 
1267  if ( Reference< XForm >::query( xElementInfo ).is() )
1268  // it's a form
1269  return false;
1270 
1271  sal_Int16 nObjectType = getControlTypeByObject( xElementInfo );
1272 
1273  if ( ( OBJ_FM_HIDDEN == nObjectType )
1274  || ( OBJ_FM_CONTROL == nObjectType )
1275  || ( OBJ_FM_GRID == nObjectType )
1276  )
1277  return false; // those types cannot be converted
1278 
1280  "FmXFormShell::canConvertCurrentSelectionToControl: aConvertSlots & nObjectTypes must have the same size !");
1281 
1282  for (size_t i = 0; i < SAL_N_ELEMENTS(aConvertSlots); ++i)
1283  if (rIdent == aConvertSlots[i])
1284  return nObjectTypes[i] != nObjectType;
1285 
1286  return true; // all other slots: assume "yes"
1287 }
1288 
1289 void FmXFormShell::checkControlConversionSlotsForCurrentSelection_Lock(weld::Menu& rMenu)
1290 {
1291  for (int i = 0, nCount = rMenu.n_children(); i < nCount; ++i)
1292  {
1293  // the context is already of a type that corresponds to the entry -> disable
1294  OString sIdent(aConvertSlots[i]);
1295  rMenu.set_sensitive(sIdent, canConvertCurrentSelectionToControl_Lock(sIdent));
1296  }
1297 }
1298 
1299 void FmXFormShell::LoopGrids_Lock(LoopGridsSync nSync, LoopGridsFlags nFlags)
1300 {
1301  if (impl_checkDisposed_Lock())
1302  return;
1303 
1304  Reference< XIndexContainer> xControlModels(m_xActiveForm, UNO_QUERY);
1305  if (xControlModels.is())
1306  {
1307  for (sal_Int32 i=0; i<xControlModels->getCount(); ++i)
1308  {
1309  Reference< XPropertySet> xModelSet;
1310  xControlModels->getByIndex(i) >>= xModelSet;
1311  if (!xModelSet.is())
1312  continue;
1313 
1314  if (!::comphelper::hasProperty(FM_PROP_CLASSID, xModelSet))
1315  continue;
1316  sal_Int16 nClassId = ::comphelper::getINT16(xModelSet->getPropertyValue(FM_PROP_CLASSID));
1317  if (FormComponentType::GRIDCONTROL != nClassId)
1318  continue;
1319 
1320  if (!::comphelper::hasProperty(FM_PROP_CURSORCOLOR, xModelSet) || !::comphelper::hasProperty(FM_PROP_ALWAYSSHOWCURSOR, xModelSet) || !::comphelper::hasProperty(FM_PROP_DISPLAYSYNCHRON, xModelSet))
1321  continue;
1322 
1323  switch (nSync)
1324  {
1326  {
1327  xModelSet->setPropertyValue(FM_PROP_DISPLAYSYNCHRON, Any(false));
1328  }
1329  break;
1331  {
1332  Any aOldVal( xModelSet->getPropertyValue(FM_PROP_DISPLAYSYNCHRON) );
1333  xModelSet->setPropertyValue(FM_PROP_DISPLAYSYNCHRON, Any(true));
1334  xModelSet->setPropertyValue(FM_PROP_DISPLAYSYNCHRON, aOldVal);
1335  }
1336  break;
1338  {
1339  xModelSet->setPropertyValue(FM_PROP_DISPLAYSYNCHRON, Any(true));
1340  }
1341  break;
1342  }
1343 
1344  if (nFlags & LoopGridsFlags::DISABLE_ROCTRLR)
1345  {
1346  xModelSet->setPropertyValue(FM_PROP_ALWAYSSHOWCURSOR, Any(false));
1347  Reference< XPropertyState> xModelPropState(xModelSet, UNO_QUERY);
1348  if (xModelPropState.is())
1349  xModelPropState->setPropertyToDefault(FM_PROP_CURSORCOLOR);
1350  else
1351  xModelSet->setPropertyValue(FM_PROP_CURSORCOLOR, Any()); // this should be the default
1352  }
1353  }
1354  }
1355 }
1356 
1357 
1358 Reference< XControlContainer > FmXFormShell::getControlContainerForView_Lock() const
1359 {
1360  if (impl_checkDisposed_Lock())
1361  return nullptr;
1362 
1363  SdrPageView* pPageView = nullptr;
1364  if ( m_pShell && m_pShell->GetFormView() )
1365  pPageView = m_pShell->GetFormView()->GetSdrPageView();
1366 
1367  Reference< XControlContainer> xControlContainer;
1368  if ( pPageView )
1369  xControlContainer = pPageView->GetPageWindow(0)->GetControlContainer();
1370 
1371  return xControlContainer;
1372 }
1373 
1374 
1375 void FmXFormShell::ExecuteTabOrderDialog_Lock(const Reference<XTabControllerModel>& _rxForForm)
1376 {
1377  if (impl_checkDisposed_Lock())
1378  return;
1379 
1380  OSL_PRECOND( _rxForForm.is(), "FmXFormShell::ExecuteTabOrderDialog: invalid tabbing model!" );
1381  if ( !_rxForForm.is() )
1382  return;
1383 
1384  try
1385  {
1386  Reference< XWindow > xParentWindow;
1387  if ( m_pShell->GetViewShell() && m_pShell->GetViewShell()->GetViewFrame() )
1388  xParentWindow = VCLUnoHelper::GetInterface ( &m_pShell->GetViewShell()->GetViewFrame()->GetWindow() );
1389 
1390  Reference< dialogs::XExecutableDialog > xDialog = form::TabOrderDialog::createWithModel(
1392  _rxForForm, getControlContainerForView_Lock(), xParentWindow
1393  );
1394 
1395  xDialog->execute();
1396  }
1397  catch( const Exception& )
1398  {
1399  TOOLS_WARN_EXCEPTION( "svx", "FmXFormShell::ExecuteTabOrderDialog" );
1400  }
1401 }
1402 
1403 
1404 void FmXFormShell::ExecuteSearch_Lock()
1405 {
1406  if (impl_checkDisposed_Lock())
1407  return;
1408 
1409  // a collection of all (logical) forms
1410  FmFormArray aEmpty;
1411  m_aSearchForms.swap( aEmpty );
1412  ::std::vector< OUString > aContextNames;
1413  impl_collectFormSearchContexts_nothrow_Lock(
1414  m_pShell->GetCurPage()->GetForms(), OUString(),
1415  m_aSearchForms, aContextNames);
1416 
1417  if ( m_aSearchForms.size() != aContextNames.size() )
1418  {
1419  SAL_WARN ( "svx.form", "FmXFormShell::ExecuteSearch: nonsense!" );
1420  return;
1421  }
1422 
1423  // filter out the forms which do not contain valid controls at all
1424  {
1425  FmFormArray aValidForms;
1426  ::std::vector< OUString > aValidContexts;
1427  FmFormArray::const_iterator form = m_aSearchForms.begin();
1428  ::std::vector< OUString >::const_iterator contextName = aContextNames.begin();
1429  for ( ; form != m_aSearchForms.end(); ++form, ++contextName )
1430  {
1431  FmSearchContext aTestContext;
1432  aTestContext.nContext = static_cast< sal_Int16 >( form - m_aSearchForms.begin() );
1433  sal_uInt32 nValidControls = OnSearchContextRequest_Lock(aTestContext);
1434  if ( nValidControls > 0 )
1435  {
1436  aValidForms.push_back( *form );
1437  aValidContexts.push_back( *contextName );
1438  }
1439  }
1440 
1441  m_aSearchForms.swap( aValidForms );
1442  aContextNames.swap( aValidContexts );
1443  }
1444 
1445  if (m_aSearchForms.empty() )
1446  {
1447  // there are no controls that meet all the conditions for a search
1448  std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(nullptr,
1449  VclMessageType::Warning, VclButtonsType::Ok,
1450  SvxResId(RID_STR_NODATACONTROLS)));
1451  xBox->run();
1452  return;
1453  }
1454 
1455  // now I need another 'initial context'
1456  sal_Int16 nInitialContext = 0;
1457  Reference<XForm> xActiveForm(getActiveForm_Lock());
1458  for ( size_t i=0; i<m_aSearchForms.size(); ++i )
1459  {
1460  if (m_aSearchForms.at(i) == xActiveForm)
1461  {
1462  nInitialContext = static_cast<sal_Int16>(i);
1463  break;
1464  }
1465  }
1466 
1467  // If the dialog should initially offer the text of the active control,
1468  // this must have an XTextComponent interface. An addition, this makes
1469  // sense only if the current field is also bound to a table (or whatever) field.
1470  OUString strActiveField;
1471  OUString strInitialText;
1472  // ... this I get from my FormController
1473  DBG_ASSERT(m_xActiveController.is(), "FmXFormShell::ExecuteSearch : no active controller !");
1474  Reference< XControl> xActiveControl( m_xActiveController->getCurrentControl());
1475  if (xActiveControl.is())
1476  {
1477  // the control can tell me its model ...
1478  Reference< XControlModel> xActiveModel( xActiveControl->getModel());
1479  DBG_ASSERT(xActiveModel.is(), "FmXFormShell::ExecuteSearch : active control has no model !");
1480 
1481  // I ask the model for the ControlSource property ...
1482  Reference< XPropertySet> xProperties(xActiveControl->getModel(), UNO_QUERY);
1483  if (::comphelper::hasProperty(FM_PROP_CONTROLSOURCE, xProperties) && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD, xProperties))
1484  {
1485  Reference< XPropertySet> xField;
1486  xProperties->getPropertyValue(FM_PROP_BOUNDFIELD) >>= xField;
1487  if (xField.is()) // (only when the thing is really bound)
1488  {
1489  // and the control itself for a TextComponent interface (so that I can pick up the text there)
1490  Reference< XTextComponent> xText(xActiveControl, UNO_QUERY);
1491  if (xText.is())
1492  {
1493  strActiveField = getLabelName(xProperties);
1494  strInitialText = xText->getText();
1495  }
1496  }
1497  }
1498  else
1499  {
1500  // the control itself has no ControlSource, but maybe it is a GridControl
1501  Reference< XGrid> xGrid(xActiveControl, UNO_QUERY);
1502  if (xGrid.is())
1503  {
1504  // for strActiveField I need the ControlSource of the column,
1505  // for that the columns container, for that the GridPeer
1506  Reference< XGridPeer> xGridPeer(xActiveControl->getPeer(), UNO_QUERY);
1507  Reference< XIndexAccess> xColumns;
1508  if (xGridPeer.is())
1509  xColumns = xGridPeer->getColumns();
1510 
1511  sal_Int16 nViewCol = xGrid->getCurrentColumnPosition();
1512  sal_Int32 nModelCol = GridView2ModelPos(xColumns, nViewCol);
1513  Reference< XPropertySet> xCurrentCol;
1514  if(xColumns.is())
1515  xColumns->getByIndex(nModelCol) >>= xCurrentCol;
1516  if (xCurrentCol.is())
1517  strActiveField = ::comphelper::getString(xCurrentCol->getPropertyValue(FM_PROP_LABEL));
1518 
1519  // the text of the current column
1520  Reference< XIndexAccess> xColControls(xGridPeer, UNO_QUERY);
1521  Reference< XInterface> xCurControl;
1522  xColControls->getByIndex(nViewCol) >>= xCurControl;
1523  OUString sInitialText;
1524  if (IsSearchableControl(xCurControl, &sInitialText))
1525  strInitialText = sInitialText;
1526  }
1527  }
1528  }
1529 
1530  // taking care of possible GridControls that I know
1531  LoopGrids_Lock(LoopGridsSync::DISABLE_SYNC);
1532 
1533  // Now I am ready for the dialogue.
1534  // When the potential deadlocks caused by the use of the solar mutex in
1535  // MTs VCLX... classes are eventually cleared, an SM_USETHREAD should be
1536  // placed here, because the search in a separate thread is nevertheless
1537  // somewhat more fluid. Should be, however, somehow made dependent of the
1538  // underlying cursor. DAO for example is not thread-safe.
1541  pFact->CreateFmSearchDialog(
1542  m_pShell->GetViewShell()->GetViewFrame()->GetWindow().GetFrameWeld(),
1543  strInitialText, aContextNames, nInitialContext,
1544  LINK(this, FmXFormShell, OnSearchContextRequest_Lock) ));
1545  pDialog->SetActiveField( strActiveField );
1546  pDialog->SetFoundHandler(LINK(this, FmXFormShell, OnFoundData_Lock));
1547  pDialog->SetCanceledNotFoundHdl(LINK(this, FmXFormShell, OnCanceledNotFound_Lock));
1548  pDialog->Execute();
1549  pDialog.disposeAndClear();
1550 
1551  // restore GridControls again
1552  LoopGrids_Lock(LoopGridsSync::ENABLE_SYNC, LoopGridsFlags::DISABLE_ROCTRLR);
1553 
1554  m_pShell->GetFormView()->UnMarkAll(m_pShell->GetFormView()->GetSdrPageView());
1555  // because I marked controls in OnFoundData (if I was there)
1556 }
1557 
1558 
1559 bool FmXFormShell::GetY2KState_Lock(sal_uInt16& n)
1560 {
1561  if (impl_checkDisposed_Lock())
1562  return false;
1563 
1564  if (m_pShell->IsDesignMode())
1565  // in the design mode (without active controls) the main document is to take care of it
1566  return false;
1567 
1568  Reference<XForm> xForm(getActiveForm_Lock());
1569  if (!xForm.is())
1570  // no current form (in particular no current control) -> the main document is to take care
1571  return false;
1572 
1573  Reference< XRowSet> xDB(xForm, UNO_QUERY);
1574  DBG_ASSERT(xDB.is(), "FmXFormShell::GetY2KState : current form has no dbform-interface !");
1575 
1576  Reference< XNumberFormatsSupplier> xSupplier( getNumberFormats(getConnection(xDB)));
1577  if (xSupplier.is())
1578  {
1579  Reference< XPropertySet> xSet(xSupplier->getNumberFormatSettings());
1580  if (xSet.is())
1581  {
1582  try
1583  {
1584  Any aVal( xSet->getPropertyValue("TwoDigitDateStart") );
1585  aVal >>= n;
1586  return true;
1587  }
1588  catch(Exception&)
1589  {
1590  }
1591 
1592  }
1593  }
1594  return false;
1595 }
1596 
1597 
1598 void FmXFormShell::SetY2KState_Lock(sal_uInt16 n)
1599 {
1600  if (impl_checkDisposed_Lock())
1601  return;
1602 
1603  Reference<XForm> xActiveForm(getActiveForm_Lock());
1604  Reference< XRowSet > xActiveRowSet( xActiveForm, UNO_QUERY );
1605  if ( xActiveRowSet.is() )
1606  {
1607  Reference< XNumberFormatsSupplier > xSupplier( getNumberFormats( getConnection( xActiveRowSet ) ) );
1608  if (xSupplier.is())
1609  {
1610  Reference< XPropertySet> xSet(xSupplier->getNumberFormatSettings());
1611  if (xSet.is())
1612  {
1613  try
1614  {
1615  xSet->setPropertyValue("TwoDigitDateStart", makeAny<sal_uInt16>(n));
1616  }
1617  catch(Exception&)
1618  {
1619  OSL_FAIL("FmXFormShell::SetY2KState: Exception occurred!");
1620  }
1621 
1622  }
1623  return;
1624  }
1625  }
1626 
1627  // no active form found -> iterate through all current forms
1628  Reference< XIndexAccess> xCurrentForms( m_xForms);
1629  if (!xCurrentForms.is())
1630  { // in the alive mode, my forms are not set, but the ones on the page are
1631  if (m_pShell->GetCurPage())
1632  xCurrentForms = m_pShell->GetCurPage()->GetForms( false );
1633  }
1634  if (!xCurrentForms.is())
1635  return;
1636 
1637  ::comphelper::IndexAccessIterator aIter(xCurrentForms);
1638  Reference< XInterface> xCurrentElement( aIter.Next());
1639  while (xCurrentElement.is())
1640  {
1641  // is the current element a DatabaseForm?
1642  Reference< XRowSet> xElementAsRowSet( xCurrentElement, UNO_QUERY );
1643  if ( xElementAsRowSet.is() )
1644  {
1645  Reference< XNumberFormatsSupplier > xSupplier( getNumberFormats( getConnection( xElementAsRowSet ) ) );
1646  if (!xSupplier.is())
1647  continue;
1648 
1649  Reference< XPropertySet> xSet(xSupplier->getNumberFormatSettings());
1650  if (xSet.is())
1651  {
1652  try
1653  {
1654  xSet->setPropertyValue("TwoDigitDateStart", makeAny<sal_uInt16>(n));
1655  }
1656  catch(Exception&)
1657  {
1658  OSL_FAIL("FmXFormShell::SetY2KState: Exception occurred!");
1659  }
1660 
1661  }
1662  }
1663  xCurrentElement = aIter.Next();
1664  }
1665 }
1666 
1667 
1668 void FmXFormShell::CloseExternalFormViewer_Lock()
1669 {
1670  if (impl_checkDisposed_Lock())
1671  return;
1672 
1673  if (!m_xExternalViewController.is())
1674  return;
1675 
1676  Reference< css::frame::XFrame> xExternalViewFrame( m_xExternalViewController->getFrame());
1677  Reference< css::frame::XDispatchProvider> xCommLink(xExternalViewFrame, UNO_QUERY);
1678  if (!xCommLink.is())
1679  return;
1680 
1681  xExternalViewFrame->setComponent(nullptr,nullptr);
1682  ::comphelper::disposeComponent(xExternalViewFrame);
1683  m_xExternalViewController = nullptr;
1684  m_xExtViewTriggerController = nullptr;
1685  m_xExternalDisplayedForm = nullptr;
1686 }
1687 
1688 
1689 Reference<XResultSet> FmXFormShell::getInternalForm_Lock(const Reference<XResultSet>& _xForm) const
1690 {
1691  if (impl_checkDisposed_Lock())
1692  return nullptr;
1693 
1694  Reference< runtime::XFormController> xExternalCtrlr(m_xExternalViewController, UNO_QUERY);
1695  if (xExternalCtrlr.is() && (_xForm == xExternalCtrlr->getModel()))
1696  {
1697  DBG_ASSERT(m_xExternalDisplayedForm.is(), "FmXFormShell::getInternalForm : invalid external form !");
1698  return m_xExternalDisplayedForm;
1699  }
1700  return _xForm;
1701 }
1702 
1703 
1704 Reference<XForm> FmXFormShell::getInternalForm_Lock(const Reference<XForm>& _xForm) const
1705 {
1706  if (impl_checkDisposed_Lock())
1707  return nullptr;
1708 
1709  Reference< runtime::XFormController > xExternalCtrlr(m_xExternalViewController, UNO_QUERY);
1710  if (xExternalCtrlr.is() && (_xForm == xExternalCtrlr->getModel()))
1711  {
1712  DBG_ASSERT(m_xExternalDisplayedForm.is(), "FmXFormShell::getInternalForm : invalid external form !");
1713  return Reference< XForm>(m_xExternalDisplayedForm, UNO_QUERY);
1714  }
1715  return _xForm;
1716 }
1717 
1718 
1719 namespace
1720 {
1721  bool lcl_isNavigationRelevant( sal_Int32 _nWhich )
1722  {
1723  return ( _nWhich == SID_FM_RECORD_FIRST )
1724  || ( _nWhich == SID_FM_RECORD_PREV )
1725  || ( _nWhich == SID_FM_RECORD_NEXT )
1726  || ( _nWhich == SID_FM_RECORD_LAST )
1727  || ( _nWhich == SID_FM_RECORD_NEW );
1728  }
1729 }
1730 
1731 
1732 bool FmXFormShell::IsFormSlotEnabled( sal_Int32 _nSlot, FeatureState* _pCompleteState )
1733 {
1734  const svx::ControllerFeatures& rController =
1735  lcl_isNavigationRelevant( _nSlot )
1736  ? getNavControllerFeatures_Lock()
1737  : getActiveControllerFeatures_Lock();
1738 
1739  if ( !_pCompleteState )
1740  return rController->isEnabled( _nSlot );
1741 
1742  rController->getState( _nSlot, *_pCompleteState );
1743  return _pCompleteState->Enabled;
1744 }
1745 
1746 
1747 void FmXFormShell::ExecuteFormSlot_Lock( sal_Int32 _nSlot )
1748 {
1749  const svx::ControllerFeatures& rController =
1750  lcl_isNavigationRelevant( _nSlot )
1751  ? getNavControllerFeatures_Lock()
1752  : getActiveControllerFeatures_Lock();
1753 
1754  rController->execute( _nSlot );
1755 
1756  if ( _nSlot == SID_FM_RECORD_UNDO )
1757  {
1758  // if we're doing an UNDO, *and* if the affected form is the form which we also display
1759  // as external view, then we need to reset the controls of the external form, too
1760  if (getInternalForm_Lock(getActiveForm_Lock()) == m_xExternalDisplayedForm)
1761  {
1762  Reference< XIndexAccess > xContainer( m_xExternalDisplayedForm, UNO_QUERY );
1763  if ( xContainer.is() )
1764  {
1765  Reference< XReset > xReset;
1766  for ( sal_Int32 i = 0; i < xContainer->getCount(); ++i )
1767  {
1768  if ( ( xContainer->getByIndex( i ) >>= xReset ) && xReset.is() )
1769  {
1770  // no resets on sub forms
1771  Reference< XForm > xAsForm( xReset, UNO_QUERY );
1772  if ( !xAsForm.is() )
1773  xReset->reset();
1774  }
1775  }
1776  }
1777  }
1778  }
1779 }
1780 
1781 
1782 void FmXFormShell::impl_switchActiveControllerListening_Lock(const bool _bListen)
1783 {
1784  if ( !m_xActiveController.is() )
1785  return;
1786 
1787  if ( _bListen )
1788  m_xActiveController->addEventListener( static_cast<XFormControllerListener*>(this) );
1789  else
1790  m_xActiveController->removeEventListener( static_cast<XFormControllerListener*>(this) );
1791 }
1792 
1793 
1794 void FmXFormShell::setActiveController_Lock(const Reference<runtime::XFormController>& xController, bool _bNoSaveOldContent)
1795 {
1796  if (impl_checkDisposed_Lock())
1797  return;
1798 
1799  if (m_bChangingDesignMode)
1800  return;
1801  DBG_ASSERT(!m_pShell->IsDesignMode(), "only to be used in alive mode");
1802 
1803  // if the routine has been called a second time,
1804  // the focus should no longer be transferred
1805  if (m_bInActivate)
1806  {
1807  m_bSetFocus = xController != m_xActiveController;
1808  return;
1809  }
1810 
1811  if (xController == m_xActiveController)
1812  return;
1813 
1814  // switch all nav dispatchers belonging to the form of the current nav controller to 'non active'
1815  Reference< XResultSet> xNavigationForm;
1816  if (m_xNavigationController.is())
1817  xNavigationForm.set(m_xNavigationController->getModel(), UNO_QUERY);
1818 
1819  m_bInActivate = true;
1820 
1821  // check if the 2 controllers serve different forms
1822  Reference< XResultSet> xOldForm;
1823  if (m_xActiveController.is())
1824  xOldForm.set(m_xActiveController->getModel(), UNO_QUERY);
1825  Reference< XResultSet> xNewForm;
1826  if (xController.is())
1827  xNewForm = Reference< XResultSet>(xController->getModel(), UNO_QUERY);
1828  xOldForm = getInternalForm_Lock(xOldForm);
1829  xNewForm = getInternalForm_Lock(xNewForm);
1830 
1831  bool bDifferentForm = ( xOldForm.get() != xNewForm.get() );
1832  bool bNeedSave = bDifferentForm && !_bNoSaveOldContent;
1833  // we save the content of the old form if we move to a new form, and saving old content is allowed
1834 
1835  if ( m_xActiveController.is() && bNeedSave )
1836  {
1837  // save content on change of the controller; a commit has already been executed
1838  if ( m_aActiveControllerFeatures->commitCurrentControl() )
1839  {
1840  m_bSetFocus = true;
1841  if ( m_aActiveControllerFeatures->isModifiedRow() )
1842  {
1843  bool bIsNew = m_aActiveControllerFeatures->isInsertionRow();
1844  bool bResult = m_aActiveControllerFeatures->commitCurrentRecord();
1845  if ( !bResult && m_bSetFocus )
1846  {
1847  // if we couldn't save the current record, set the focus back to the
1848  // current control
1849  Reference< XWindow > xWindow( m_xActiveController->getCurrentControl(), UNO_QUERY );
1850  if ( xWindow.is() )
1851  xWindow->setFocus();
1852  m_bInActivate = false;
1853  return;
1854  }
1855  else if ( bResult && bIsNew )
1856  {
1857  Reference< XResultSet > xCursor( m_aActiveControllerFeatures->getCursor().get() );
1858  if ( xCursor.is() )
1859  {
1860  DO_SAFE( xCursor->last(); );
1861  }
1862  }
1863  }
1864  }
1865  }
1866 
1867  stopListening_Lock();
1868 
1869  impl_switchActiveControllerListening_Lock(false);
1870 
1871  m_aActiveControllerFeatures.dispose();
1872  m_xActiveController = xController;
1873  if ( m_xActiveController.is() )
1874  m_aActiveControllerFeatures.assign( m_xActiveController );
1875 
1876  impl_switchActiveControllerListening_Lock(true);
1877 
1878  if ( m_xActiveController.is() )
1879  m_xActiveForm = getInternalForm_Lock(Reference<XForm>(m_xActiveController->getModel(), UNO_QUERY));
1880  else
1881  m_xActiveForm = nullptr;
1882 
1883  startListening_Lock();
1884 
1885  // activate all dispatchers belonging to form of the new navigation controller
1886  xNavigationForm = nullptr;
1887  if (m_xNavigationController.is())
1888  xNavigationForm.set(m_xNavigationController->getModel(), UNO_QUERY);
1889 
1890  m_bInActivate = false;
1891 
1892  m_pShell->UIFeatureChanged();
1893  m_pShell->GetViewShell()->GetViewFrame()->GetBindings().InvalidateShell(*m_pShell);
1894 
1895  InvalidateSlot_Lock(SID_FM_FILTER_NAVIGATOR_CONTROL, true);
1896 }
1897 
1898 
1899 void FmXFormShell::getCurrentSelection_Lock(InterfaceBag& /* [out] */ _rSelection) const
1900 {
1901  _rSelection = m_aCurrentSelection;
1902 }
1903 
1904 
1905 bool FmXFormShell::setCurrentSelectionFromMark_Lock(const SdrMarkList& _rMarkList)
1906 {
1907  m_aLastKnownMarkedControls.clear();
1908 
1909  if ( ( _rMarkList.GetMarkCount() > 0 ) && isControlList( _rMarkList ) )
1910  collectInterfacesFromMarkList( _rMarkList, m_aLastKnownMarkedControls );
1911 
1912  return setCurrentSelection_Lock(m_aLastKnownMarkedControls);
1913 }
1914 
1915 
1916 bool FmXFormShell::selectLastMarkedControls_Lock()
1917 {
1918  return setCurrentSelection_Lock(m_aLastKnownMarkedControls);
1919 }
1920 
1921 
1922 bool FmXFormShell::setCurrentSelection_Lock( const InterfaceBag& _rSelection )
1923 {
1924  if (impl_checkDisposed_Lock())
1925  return false;
1926 
1927  DBG_ASSERT( m_pShell->IsDesignMode(), "FmXFormShell::setCurrentSelection: only to be used in design mode!" );
1928 
1929  if ( _rSelection.empty() && m_aCurrentSelection.empty() )
1930  // nothing to do
1931  return false;
1932 
1933  if ( _rSelection.size() == m_aCurrentSelection.size() )
1934  {
1935  InterfaceBag::const_iterator aNew = _rSelection.begin();
1936  InterfaceBag::const_iterator aOld = m_aCurrentSelection.begin();
1937  for ( ; aNew != _rSelection.end(); ++aNew, ++aOld )
1938  {
1939  OSL_ENSURE( Reference< XInterface >( *aNew, UNO_QUERY ).get() == aNew->get(), "FmXFormShell::setCurrentSelection: new interface not normalized!" );
1940  OSL_ENSURE( Reference< XInterface >( *aOld, UNO_QUERY ).get() == aOld->get(), "FmXFormShell::setCurrentSelection: old interface not normalized!" );
1941 
1942  if ( aNew->get() != aOld->get() )
1943  break;
1944  }
1945 
1946  if ( aNew == _rSelection.end() )
1947  // both bags equal
1948  return false;
1949  }
1950 
1951  // the following is some strange code to ensure that when you have two grid controls in a document,
1952  // only one of them can have a selected column.
1953  // TODO: this should happen elsewhere, but not here - shouldn't it?
1954  if ( !m_aCurrentSelection.empty() )
1955  {
1956  Reference< XChild > xCur; if ( m_aCurrentSelection.size() == 1 ) xCur.set(*m_aCurrentSelection.begin(), css::uno::UNO_QUERY);
1957  Reference< XChild > xNew; if ( _rSelection.size() == 1 ) xNew.set(*_rSelection.begin(), css::uno::UNO_QUERY);
1958 
1959  // is there nothing to be selected, or the parents differ, and the parent of the current object
1960  // is a selection supplier, then deselect
1961  if ( xCur.is() && ( !xNew.is() || ( xCur->getParent() != xNew->getParent() ) ) )
1962  {
1963  Reference< XSelectionSupplier > xSel( xCur->getParent(), UNO_QUERY );
1964  if ( xSel.is() )
1965  xSel->select( Any() );
1966  }
1967  }
1968 
1969  m_aCurrentSelection = _rSelection;
1970 
1971  // determine the form which all the selected objects belong to, if any
1972  Reference< XForm > xNewCurrentForm;
1973  for (const auto& rpSelection : m_aCurrentSelection)
1974  {
1975  Reference< XForm > xThisRoundsForm( GetForm( rpSelection ) );
1976  OSL_ENSURE( xThisRoundsForm.is(), "FmXFormShell::setCurrentSelection: *everything* should belong to a form!" );
1977 
1978  if ( !xNewCurrentForm.is() )
1979  { // the first form we encountered
1980  xNewCurrentForm = xThisRoundsForm;
1981  }
1982  else if ( xNewCurrentForm != xThisRoundsForm )
1983  { // different forms -> no "current form" at all
1984  xNewCurrentForm.clear();
1985  break;
1986  }
1987  }
1988 
1989  if ( !m_aCurrentSelection.empty() )
1990  impl_updateCurrentForm_Lock(xNewCurrentForm);
1991 
1992  // ensure some slots are updated
1993  for (sal_Int16 i : SelObjectSlotMap)
1994  InvalidateSlot_Lock(i, false);
1995 
1996  return true;
1997 }
1998 
1999 
2000 bool FmXFormShell::isSolelySelected_Lock(const Reference<XInterface>& _rxObject)
2001 {
2002  return ( m_aCurrentSelection.size() == 1 ) && ( *m_aCurrentSelection.begin() == _rxObject );
2003 }
2004 
2005 
2006 void FmXFormShell::forgetCurrentForm_Lock()
2007 {
2008  if ( !m_xCurrentForm.is() )
2009  return;
2010 
2011  // reset ...
2012  impl_updateCurrentForm_Lock(nullptr);
2013 
2014  // ... and try finding a new current form
2015  // #i88186# / 2008-04-12 / frank.schoenheit@sun.com
2016  impl_defaultCurrentForm_nothrow_Lock();
2017 }
2018 
2019 
2020 void FmXFormShell::impl_updateCurrentForm_Lock(const Reference<XForm>& _rxNewCurForm)
2021 {
2022  if (impl_checkDisposed_Lock())
2023  return;
2024 
2025  m_xCurrentForm = _rxNewCurForm;
2026 
2027  // propagate to the FormPage(Impl)
2028  FmFormPage* pPage = m_pShell->GetCurPage();
2029  if ( pPage )
2030  pPage->GetImpl().setCurForm( m_xCurrentForm );
2031 
2032  // ensure the UI which depends on the current form is up-to-date
2033  for (sal_Int16 i : DlgSlotMap)
2034  InvalidateSlot_Lock(i, false);
2035 }
2036 
2037 
2038 void FmXFormShell::startListening_Lock()
2039 {
2040  if (impl_checkDisposed_Lock())
2041  return;
2042 
2043  Reference< XRowSet> xDatabaseForm(m_xActiveForm, UNO_QUERY);
2044  if (xDatabaseForm.is() && getConnection(xDatabaseForm).is())
2045  {
2046  Reference< XPropertySet> xActiveFormSet(m_xActiveForm, UNO_QUERY);
2047  if (xActiveFormSet.is())
2048  {
2049  // if there is a data source, then build the listener
2050  // TODO: this is strange - shouldn't this depend on a isLoaded instead of
2051  // a "has command value"? Finally, the command value only means that it was
2052  // intended to be loaded, not that it actually *is* loaded
2053  OUString aSource = ::comphelper::getString(xActiveFormSet->getPropertyValue(FM_PROP_COMMAND));
2054  if (!aSource.isEmpty())
2055  {
2056  m_bDatabaseBar = true;
2057 
2058  xActiveFormSet->getPropertyValue(FM_PROP_NAVIGATION) >>= m_eNavigate;
2059 
2060  switch (m_eNavigate)
2061  {
2062  case NavigationBarMode_PARENT:
2063  {
2064  // search for the controller via which navigation is possible
2065  Reference< XChild> xChild = m_xActiveController;
2066  Reference< runtime::XFormController > xParent;
2067  while (xChild.is())
2068  {
2069  xChild.set(xChild->getParent(), UNO_QUERY);
2070  xParent.set(xChild, UNO_QUERY);
2071  Reference< XPropertySet> xParentSet;
2072  if (xParent.is())
2073  xParentSet.set(xParent->getModel(), UNO_QUERY);
2074  if (xParentSet.is())
2075  {
2076  xParentSet->getPropertyValue(FM_PROP_NAVIGATION) >>= m_eNavigate;
2077  if (m_eNavigate == NavigationBarMode_CURRENT)
2078  break;
2079  }
2080  }
2081  m_xNavigationController = xParent;
2082  }
2083  break;
2084 
2085  case NavigationBarMode_CURRENT:
2086  m_xNavigationController = m_xActiveController;
2087  break;
2088 
2089  default:
2090  m_xNavigationController = nullptr;
2091  m_bDatabaseBar = false;
2092  }
2093 
2094  m_aNavControllerFeatures.dispose();
2095  if ( m_xNavigationController.is() && ( m_xNavigationController != m_xActiveController ) )
2096  m_aNavControllerFeatures.assign( m_xNavigationController );
2097 
2098  // because of RecordCount, listen at the controller which controls the navigation
2099  Reference< XPropertySet> xNavigationSet;
2100  if (m_xNavigationController.is())
2101  {
2102  xNavigationSet.set(m_xNavigationController->getModel(), UNO_QUERY);
2103  if (xNavigationSet.is())
2104  xNavigationSet->addPropertyChangeListener(FM_PROP_ROWCOUNT,this);
2105  }
2106  return;
2107  }
2108  }
2109  }
2110 
2111  m_eNavigate = NavigationBarMode_NONE;
2112  m_bDatabaseBar = false;
2113  m_xNavigationController = nullptr;
2114 }
2115 
2116 
2117 void FmXFormShell::stopListening_Lock()
2118 {
2119  if (impl_checkDisposed_Lock())
2120  return;
2121 
2122  Reference< XRowSet> xDatabaseForm(m_xActiveForm, UNO_QUERY);
2123  if ( xDatabaseForm.is() )
2124  {
2125  if (m_xNavigationController.is())
2126  {
2127  Reference< XPropertySet> xSet(m_xNavigationController->getModel(), UNO_QUERY);
2128  if (xSet.is())
2129  xSet->removePropertyChangeListener(FM_PROP_ROWCOUNT, this);
2130 
2131  }
2132  }
2133 
2134  m_bDatabaseBar = false;
2135  m_eNavigate = NavigationBarMode_NONE;
2136  m_xNavigationController = nullptr;
2137 }
2138 
2139 
2140 void FmXFormShell::ShowSelectionProperties_Lock(bool bShow)
2141 {
2142  if (impl_checkDisposed_Lock())
2143  return;
2144 
2145  // if the window is already visible, only update the state
2146  bool bHasChild = m_pShell->GetViewShell()->GetViewFrame()->HasChildWindow( SID_FM_SHOW_PROPERTIES );
2147  if ( bHasChild && bShow )
2148  UpdateSlot_Lock(SID_FM_PROPERTY_CONTROL);
2149 
2150  // else toggle state
2151  else
2152  m_pShell->GetViewShell()->GetViewFrame()->ToggleChildWindow(SID_FM_SHOW_PROPERTIES);
2153 
2154  InvalidateSlot_Lock(SID_FM_PROPERTIES, false);
2155  InvalidateSlot_Lock(SID_FM_CTL_PROPERTIES, false);
2156 }
2157 
2158 
2159 IMPL_LINK(FmXFormShell, OnFoundData_Lock, FmFoundRecordInformation&, rfriWhere, void)
2160 {
2161  if (impl_checkDisposed_Lock())
2162  return;
2163 
2164  DBG_ASSERT((rfriWhere.nContext >= 0) && (rfriWhere.nContext < static_cast<sal_Int16>(m_aSearchForms.size())),
2165  "FmXFormShell::OnFoundData : invalid context!");
2166  Reference< XForm> xForm( m_aSearchForms.at(rfriWhere.nContext));
2167  DBG_ASSERT(xForm.is(), "FmXFormShell::OnFoundData : invalid form!");
2168 
2169  Reference< XRowLocate> xCursor(xForm, UNO_QUERY);
2170  if (!xCursor.is())
2171  return; // what should I do there?
2172 
2173  // to the record
2174  try
2175  {
2176  xCursor->moveToBookmark(rfriWhere.aPosition);
2177  }
2178  catch(const SQLException&)
2179  {
2180  OSL_FAIL("Can position on bookmark!");
2181  }
2182 
2183  LoopGrids_Lock(LoopGridsSync::FORCE_SYNC);
2184 
2185  // and to the field (for that, I collected the XVclComponent interfaces before the start of the search)
2186  SAL_WARN_IF(o3tl::make_unsigned(rfriWhere.nFieldPos) >=
2187  m_arrSearchedControls.size(),
2188  "svx.form", "FmXFormShell::OnFoundData : invalid index!");
2189  SdrObject* pObject = m_arrSearchedControls.at(rfriWhere.nFieldPos);
2190 
2191  m_pShell->GetFormView()->UnMarkAll(m_pShell->GetFormView()->GetSdrPageView());
2192  m_pShell->GetFormView()->MarkObj(pObject, m_pShell->GetFormView()->GetSdrPageView());
2193 
2194  FmFormObj* pFormObject = FmFormObj::GetFormObject( pObject );
2195  Reference< XControlModel > xControlModel( pFormObject ? pFormObject->GetUnoControlModel() : Reference< XControlModel >() );
2196  DBG_ASSERT( xControlModel.is(), "FmXFormShell::OnFoundData: invalid control!" );
2197  if ( !xControlModel.is() )
2198  return;
2199 
2200  // disable the permanent cursor for the last grid we found a record
2201  if (m_xLastGridFound.is() && (m_xLastGridFound != xControlModel))
2202  {
2203  Reference< XPropertySet> xOldSet(m_xLastGridFound, UNO_QUERY);
2204  xOldSet->setPropertyValue(FM_PROP_ALWAYSSHOWCURSOR, makeAny( false ) );
2205  Reference< XPropertyState> xOldSetState(xOldSet, UNO_QUERY);
2206  if (xOldSetState.is())
2207  xOldSetState->setPropertyToDefault(FM_PROP_CURSORCOLOR);
2208  else
2209  xOldSet->setPropertyValue(FM_PROP_CURSORCOLOR, Any());
2210  }
2211 
2212  // if the field is in a GridControl, I have to additionally go into the corresponding column there
2213  sal_Int32 nGridColumn = m_arrRelativeGridColumn[rfriWhere.nFieldPos];
2214  if (nGridColumn != -1)
2215  { // unfortunately, I have to first get the control again
2216  Reference<XControl> xControl(pFormObject ? impl_getControl_Lock(xControlModel, *pFormObject) : Reference<XControl>());
2217  Reference< XGrid> xGrid(xControl, UNO_QUERY);
2218  DBG_ASSERT(xGrid.is(), "FmXFormShell::OnFoundData : invalid control!");
2219  // if one of the asserts fires, I probably did something wrong on building of m_arrSearchedControls
2220 
2221  // enable a permanent cursor for the grid so we can see the found text
2222  Reference< XPropertySet> xModelSet(xControlModel, UNO_QUERY);
2223  DBG_ASSERT(xModelSet.is(), "FmXFormShell::OnFoundData : invalid control model (no property set) !");
2224  xModelSet->setPropertyValue( FM_PROP_ALWAYSSHOWCURSOR, makeAny( true ) );
2225  xModelSet->setPropertyValue( FM_PROP_CURSORCOLOR, makeAny( COL_LIGHTRED ) );
2226  m_xLastGridFound = xControlModel;
2227 
2228  if ( xGrid.is() )
2229  xGrid->setCurrentColumnPosition(static_cast<sal_Int16>(nGridColumn));
2230  }
2231 
2232  // As the cursor has been repositioned, I have (in positioned) invalidated
2233  // my form bar slots. But that does not take effect here unfortunately, as
2234  // generally the (modal) search dialog is of course at the top ... So, force ...
2235  sal_uInt16 nPos = 0;
2236  while (DatabaseSlotMap[nPos])
2237  m_pShell->GetViewShell()->GetViewFrame()->GetBindings().Update(DatabaseSlotMap[nPos++]);
2238  // unfortunately the update goes against the invalidate with only individual slots
2239 }
2240 
2241 
2242 IMPL_LINK(FmXFormShell, OnCanceledNotFound_Lock, FmFoundRecordInformation&, rfriWhere, void)
2243 {
2244  if (impl_checkDisposed_Lock())
2245  return;
2246 
2247  DBG_ASSERT((rfriWhere.nContext >= 0) && (rfriWhere.nContext < static_cast<sal_Int16>(m_aSearchForms.size())),
2248  "FmXFormShell::OnCanceledNotFound : invalid context!");
2249  Reference< XForm> xForm( m_aSearchForms.at(rfriWhere.nContext));
2250  DBG_ASSERT(xForm.is(), "FmXFormShell::OnCanceledNotFound : invalid form!");
2251 
2252  Reference< XRowLocate> xCursor(xForm, UNO_QUERY);
2253  if (!xCursor.is())
2254  return; // what should I do there?
2255 
2256  // to the record
2257  try
2258  {
2259  xCursor->moveToBookmark(rfriWhere.aPosition);
2260  }
2261  catch(const SQLException&)
2262  {
2263  OSL_FAIL("Can position on bookmark!");
2264  }
2265 
2266 
2267  m_pShell->GetFormView()->UnMarkAll(m_pShell->GetFormView()->GetSdrPageView());
2268 }
2269 
2270 
2271 IMPL_LINK(FmXFormShell, OnSearchContextRequest_Lock, FmSearchContext&, rfmscContextInfo, sal_uInt32)
2272 {
2273  if (impl_checkDisposed_Lock())
2274  return 0;
2275 
2276  DBG_ASSERT(rfmscContextInfo.nContext < static_cast<sal_Int16>(m_aSearchForms.size()), "FmXFormShell::OnSearchContextRequest : invalid parameter !");
2277  Reference< XForm> xForm( m_aSearchForms.at(rfmscContextInfo.nContext));
2278  DBG_ASSERT(xForm.is(), "FmXFormShell::OnSearchContextRequest : unexpected : invalid context !");
2279 
2280  Reference< XResultSet> xIter(xForm, UNO_QUERY);
2281  DBG_ASSERT(xIter.is(), "FmXFormShell::OnSearchContextRequest : unexpected : context has no iterator !");
2282 
2283 
2284  // assemble the list of fields to involve (that is, the ControlSources of all fields that have such a property)
2285  OUString strFieldList, sFieldDisplayNames;
2286  m_arrSearchedControls.clear();
2287  m_arrRelativeGridColumn.clear();
2288 
2289  // small problem: To mark found fields, I need SdrObjects. To determine which controls
2290  // to include in the search, I need Controls (that is, XControl interfaces). So I have
2291  // to iterate over one of them and get the other in some way. Unfortunately, there is
2292  // no direct connection between the two worlds (except from a GetUnoControl to a
2293  // SdrUnoObject, but this requires an OutputDevice I can not do anything with.
2294  // However I can get to the Model from the Control and also from the SdrObject, and in
2295  // this way the assignment SdrObject<->Control is possible with a double loop.
2296  // The alternative to this (ugly but certainly not entirely fixable) solution would be
2297  // to renounce the caching of the SdrObjects, which would lead to significant extra
2298  // work in OnFoundData (since there I'd have to get the SdrObject first thing every
2299  // time). But since OnFoundData is usually called more often than ExecuteSearch, I'll
2300  // do that here.
2301 
2302  Reference< XNameAccess> xValidFormFields;
2303  Reference< XColumnsSupplier> xSupplyCols(xIter, UNO_QUERY);
2304  DBG_ASSERT(xSupplyCols.is(), "FmXFormShell::OnSearchContextRequest : invalid cursor : no columns supplier !");
2305  if (xSupplyCols.is())
2306  xValidFormFields = xSupplyCols->getColumns();
2307  DBG_ASSERT(xValidFormFields.is(), "FmXFormShell::OnSearchContextRequest : form has no fields !");
2308 
2309  // current Page/Controller
2310  FmFormPage* pCurrentPage = m_pShell->GetCurPage();
2311  assert(pCurrentPage && "FmXFormShell::OnSearchContextRequest : no page !");
2312  // Search all SdrControls of this page...
2313  OUString sControlSource, aName;
2314 
2315  SdrObjListIter aPageIter( pCurrentPage );
2316  while ( aPageIter.IsMore() )
2317  {
2318  SdrObject* pCurrent = aPageIter.Next();
2319  FmFormObj* pFormObject = FmFormObj::GetFormObject( pCurrent );
2320  // note that in case pCurrent is a virtual object, pFormObject points to the referenced object
2321 
2322  if ( !pFormObject )
2323  continue;
2324 
2325  // the current object's model, in different tastes
2326  Reference< XControlModel> xControlModel( pFormObject->GetUnoControlModel() );
2327  Reference< XFormComponent > xCurrentFormComponent( xControlModel, UNO_QUERY );
2328  DBG_ASSERT( xCurrentFormComponent.is(), "FmXFormShell::OnSearchContextRequest: invalid objects!" );
2329  if ( !xCurrentFormComponent.is() )
2330  continue;
2331 
2332  // does the component belong to the form which we're interested in?
2333  if ( xCurrentFormComponent->getParent() != xForm )
2334  continue;
2335 
2336  // ... ask for the ControlSource property
2337  SearchableControlIterator iter( xCurrentFormComponent );
2338  Reference< XControl> xControl;
2339  // the control that has model xControlModel
2340  // (the following while can be passed through several times, without the Control
2341  // being modified, so I don't have to search every time from scratch)
2342 
2343  Reference< XInterface > xSearchable( iter.Next() );
2344  while ( xSearchable.is() )
2345  {
2346  sControlSource = iter.getCurrentValue();
2347  if ( sControlSource.isEmpty() )
2348  {
2349  // the current element has no ControlSource, so it is a GridControl (that
2350  // is the only thing that still permits the SearchableControlIteratore)
2351  xControl = impl_getControl_Lock(xControlModel, *pFormObject);
2352  DBG_ASSERT(xControl.is(), "FmXFormShell::OnSearchContextRequest : didn't ::std::find a control with requested model !");
2353 
2354  Reference< XGridPeer> xGridPeer;
2355  if ( xControl.is() )
2356  xGridPeer.set( xControl->getPeer(), UNO_QUERY );
2357  do
2358  {
2359  if (!xGridPeer.is())
2360  break;
2361 
2362  Reference< XIndexAccess> xPeerContainer(xGridPeer, UNO_QUERY);
2363  if (!xPeerContainer.is())
2364  break;
2365 
2366  Reference< XIndexAccess> xModelColumns = xGridPeer->getColumns();
2367  DBG_ASSERT(xModelColumns.is(), "FmXFormShell::OnSearchContextRequest : there is a grid control without columns !");
2368  // the case 'no columns' should be indicated with an empty container, I think ...
2369  DBG_ASSERT(xModelColumns->getCount() >= xPeerContainer->getCount(), "FmXFormShell::OnSearchContextRequest : impossible : have more view than model columns !");
2370 
2371  Reference< XInterface> xCurrentColumn;
2372  for (sal_Int32 nViewPos=0; nViewPos<xPeerContainer->getCount(); ++nViewPos)
2373  {
2374  xPeerContainer->getByIndex(nViewPos) >>= xCurrentColumn;
2375  if (!xCurrentColumn.is())
2376  continue;
2377 
2378  // can we use this column control for searching ?
2379  if (!IsSearchableControl(xCurrentColumn))
2380  continue;
2381 
2382  sal_Int32 nModelPos = GridView2ModelPos(xModelColumns, nViewPos);
2383  Reference< XPropertySet> xCurrentColModel;
2384  xModelColumns->getByIndex(nModelPos) >>= xCurrentColModel;
2385  aName = ::comphelper::getString(xCurrentColModel->getPropertyValue(FM_PROP_CONTROLSOURCE));
2386  // the cursor has a field matching the control source ?
2387  if (xValidFormFields->hasByName(aName))
2388  {
2389  strFieldList += aName + ";";
2390 
2391  sFieldDisplayNames +=
2392  ::comphelper::getString(xCurrentColModel->getPropertyValue(FM_PROP_LABEL)) +
2393  ";";
2394 
2395  rfmscContextInfo.arrFields.push_back(xCurrentColumn);
2396 
2397  // and the SdrOject to the Field
2398  m_arrSearchedControls.push_back(pCurrent);
2399  // the number of the column
2400  m_arrRelativeGridColumn.push_back(nViewPos);
2401  }
2402  }
2403  } while (false);
2404  }
2405  else
2406  {
2407  if (!sControlSource.isEmpty() && xValidFormFields->hasByName(sControlSource))
2408  {
2409  // now I need the Control to SdrObject
2410  if (!xControl.is())
2411  {
2412  xControl = impl_getControl_Lock(xControlModel, *pFormObject);
2413  DBG_ASSERT(xControl.is(), "FmXFormShell::OnSearchContextRequest : didn't ::std::find a control with requested model !");
2414  }
2415 
2416  if (IsSearchableControl(xControl))
2417  {
2418  // all tests passed -> take along in the list
2419  strFieldList += sControlSource + ";";
2420 
2421  // the label which should appear for the control :
2422  sFieldDisplayNames +=
2423  getLabelName(Reference< XPropertySet>(xControlModel, UNO_QUERY)) +
2424  ";";
2425 
2426  // mark the SdrObject (accelerates the treatment in OnFoundData)
2427  m_arrSearchedControls.push_back(pCurrent);
2428 
2429  // the number of the column (here a dummy, since it is only interesting for GridControls)
2430  m_arrRelativeGridColumn.push_back(-1);
2431 
2432  // and for the formatted search...
2433  rfmscContextInfo.arrFields.emplace_back( xControl, UNO_QUERY );
2434  }
2435  }
2436  }
2437 
2438  xSearchable = iter.Next();
2439  }
2440  }
2441 
2442  strFieldList = comphelper::string::stripEnd(strFieldList, ';');
2443  sFieldDisplayNames = comphelper::string::stripEnd(sFieldDisplayNames, ';');
2444 
2445  if (rfmscContextInfo.arrFields.empty())
2446  {
2447  rfmscContextInfo.arrFields.clear();
2448  rfmscContextInfo.xCursor = nullptr;
2449  rfmscContextInfo.strUsedFields.clear();
2450  return 0;
2451  }
2452 
2453  rfmscContextInfo.xCursor = xIter;
2454  rfmscContextInfo.strUsedFields = strFieldList;
2455  rfmscContextInfo.sFieldDisplayNames = sFieldDisplayNames;
2456 
2457  // 66463 - 31.05.99 - FS
2458  // when the cursor is a non-STANDARD RecordMode, set it back
2459  Reference< XPropertySet> xCursorSet(rfmscContextInfo.xCursor, UNO_QUERY);
2460  Reference< XResultSetUpdate> xUpdateCursor(rfmscContextInfo.xCursor, UNO_QUERY);
2461  if (xUpdateCursor.is() && xCursorSet.is())
2462  {
2463  if (::comphelper::getBOOL(xCursorSet->getPropertyValue(FM_PROP_ISNEW)))
2464  xUpdateCursor->moveToCurrentRow();
2465  else if (::comphelper::getBOOL(xCursorSet->getPropertyValue(FM_PROP_ISMODIFIED)))
2466  xUpdateCursor->cancelRowUpdates();
2467  }
2468 
2469  return rfmscContextInfo.arrFields.size();
2470 }
2471 
2472  // XContainerListener
2473 
2474 void SAL_CALL FmXFormShell::elementInserted(const ContainerEvent& evt)
2475 {
2476  SolarMutexGuard g;
2477 
2478  if (impl_checkDisposed_Lock())
2479  return;
2480 
2481  // new object to listen to
2482  Reference< XInterface> xTemp;
2483  evt.Element >>= xTemp;
2484  AddElement_Lock(xTemp);
2485 
2486  m_pShell->DetermineForms(true);
2487 }
2488 
2489 
2490 void SAL_CALL FmXFormShell::elementReplaced(const ContainerEvent& evt)
2491 {
2492  SolarMutexGuard g;
2493 
2494  if (impl_checkDisposed_Lock() )
2495  return;
2496 
2497  Reference< XInterface> xTemp;
2498  evt.ReplacedElement >>= xTemp;
2499  RemoveElement_Lock(xTemp);
2500  evt.Element >>= xTemp;
2501  AddElement_Lock(xTemp);
2502 }
2503 
2504 
2505 void SAL_CALL FmXFormShell::elementRemoved(const ContainerEvent& evt)
2506 {
2507  SolarMutexGuard g;
2508 
2509  if (impl_checkDisposed_Lock())
2510  return;
2511 
2512  Reference< XInterface> xTemp;
2513  evt.Element >>= xTemp;
2514  RemoveElement_Lock(xTemp);
2515 
2516  m_pShell->DetermineForms(true);
2517 }
2518 
2519 
2520 void FmXFormShell::UpdateForms_Lock(bool _bInvalidate)
2521 {
2522  if (impl_checkDisposed_Lock())
2523  return;
2524 
2525  Reference< XIndexAccess > xForms;
2526 
2527  FmFormPage* pPage = m_pShell->GetCurPage();
2528  if ( pPage && m_pShell->m_bDesignMode )
2529  xForms = pPage->GetForms( false );
2530 
2531  if ( m_xForms != xForms )
2532  {
2533  RemoveElement_Lock( m_xForms );
2534  m_xForms = xForms;
2535  AddElement_Lock(m_xForms);
2536  }
2537 
2538  SolarMutexGuard g;
2539  m_pShell->DetermineForms( _bInvalidate );
2540 }
2541 
2542 
2543 void FmXFormShell::AddElement_Lock(const Reference<XInterface>& _xElement)
2544 {
2545  if (impl_checkDisposed_Lock())
2546  return;
2547  impl_AddElement_nothrow(_xElement);
2548 }
2549 
2550 void FmXFormShell::impl_AddElement_nothrow(const Reference< XInterface>& Element)
2551 {
2552  // listen at the container
2553  const Reference< XIndexContainer> xContainer(Element, UNO_QUERY);
2554  if (xContainer.is())
2555  {
2556  const sal_uInt32 nCount = xContainer->getCount();
2557  Reference< XInterface> xElement;
2558  for (sal_uInt32 i = 0; i < nCount; ++i)
2559  {
2560  xElement.set(xContainer->getByIndex(i),UNO_QUERY);
2561  impl_AddElement_nothrow(xElement);
2562  }
2563 
2564  const Reference< XContainer> xCont(Element, UNO_QUERY);
2565  if (xCont.is())
2566  xCont->addContainerListener(this);
2567  }
2568 
2569  const Reference< css::view::XSelectionSupplier> xSelSupplier(Element, UNO_QUERY);
2570  if (xSelSupplier.is())
2571  xSelSupplier->addSelectionChangeListener(this);
2572 }
2573 
2574 
2575 void FmXFormShell::RemoveElement_Lock(const Reference<XInterface>& Element)
2576 {
2577  if (impl_checkDisposed_Lock())
2578  return;
2579  impl_RemoveElement_nothrow_Lock(Element);
2580 }
2581 
2582 void FmXFormShell::impl_RemoveElement_nothrow_Lock(const Reference<XInterface>& Element)
2583 {
2584  const Reference< css::view::XSelectionSupplier> xSelSupplier(Element, UNO_QUERY);
2585  if (xSelSupplier.is())
2586  xSelSupplier->removeSelectionChangeListener(this);
2587 
2588  // remove connection to children
2589  const Reference< XIndexContainer> xContainer(Element, UNO_QUERY);
2590  if (xContainer.is())
2591  {
2592  const Reference< XContainer> xCont(Element, UNO_QUERY);
2593  if (xCont.is())
2594  xCont->removeContainerListener(this);
2595 
2596  const sal_uInt32 nCount = xContainer->getCount();
2597  Reference< XInterface> xElement;
2598  for (sal_uInt32 i = 0; i < nCount; i++)
2599  {
2600  xElement.set(xContainer->getByIndex(i),UNO_QUERY);
2601  impl_RemoveElement_nothrow_Lock(xElement);
2602  }
2603  }
2604 
2605  InterfaceBag::iterator wasSelectedPos = m_aCurrentSelection.find( Element );
2606  if ( wasSelectedPos != m_aCurrentSelection.end() )
2607  m_aCurrentSelection.erase( wasSelectedPos );
2608 }
2609 
2610 
2611 void SAL_CALL FmXFormShell::selectionChanged(const lang::EventObject& rEvent)
2612 {
2613  SolarMutexGuard g;
2614 
2615  if (impl_checkDisposed_Lock())
2616  return;
2617 
2618  Reference< XSelectionSupplier > xSupplier( rEvent.Source, UNO_QUERY );
2619  Reference< XInterface > xSelObj( xSupplier->getSelection(), UNO_QUERY );
2620  // a selection was removed, this can only be done by the shell
2621  if ( !xSelObj.is() )
2622  return;
2623 
2624  EnableTrackProperties_Lock(false);
2625 
2626  bool bMarkChanged = m_pShell->GetFormView()->checkUnMarkAll(rEvent.Source);
2627 
2629  aNewSelection.insert( Reference<XInterface>( xSelObj, UNO_QUERY ) );
2630 
2631  if (setCurrentSelection_Lock(aNewSelection) && IsPropBrwOpen_Lock())
2632  ShowSelectionProperties_Lock(true);
2633 
2634  EnableTrackProperties_Lock(true);
2635 
2636  if ( bMarkChanged )
2637  m_pShell->NotifyMarkListChanged( m_pShell->GetFormView() );
2638 }
2639 
2640 
2641 IMPL_LINK_NOARG(FmXFormShell, OnTimeOut_Lock, Timer*, void)
2642 {
2643  if (impl_checkDisposed_Lock())
2644  return;
2645 
2646  if (m_pShell->IsDesignMode() && m_pShell->GetFormView())
2647  SetSelection_Lock(m_pShell->GetFormView()->GetMarkedObjectList());
2648 }
2649 
2650 
2651 void FmXFormShell::SetSelectionDelayed_Lock()
2652 {
2653  if (impl_checkDisposed_Lock())
2654  return;
2655 
2656  if (m_pShell->IsDesignMode() && IsTrackPropertiesEnabled_Lock() && !m_aMarkTimer.IsActive())
2657  m_aMarkTimer.Start();
2658 }
2659 
2660 
2661 void FmXFormShell::SetSelection_Lock(const SdrMarkList& rMarkList)
2662 {
2663  if (impl_checkDisposed_Lock())
2664  return;
2665 
2666  DetermineSelection_Lock(rMarkList);
2667  m_pShell->NotifyMarkListChanged(m_pShell->GetFormView());
2668 }
2669 
2670 
2671 void FmXFormShell::DetermineSelection_Lock(const SdrMarkList& rMarkList)
2672 {
2673  if (setCurrentSelectionFromMark_Lock(rMarkList) && IsPropBrwOpen_Lock())
2674  ShowSelectionProperties_Lock(true);
2675 }
2676 
2677 
2678 bool FmXFormShell::IsPropBrwOpen_Lock() const
2679 {
2680  if (impl_checkDisposed_Lock())
2681  return false;
2682 
2683  return m_pShell->GetViewShell() && m_pShell->GetViewShell()->GetViewFrame()
2684  && m_pShell->GetViewShell()->GetViewFrame()->HasChildWindow(SID_FM_SHOW_PROPERTIES);
2685 }
2686 
2687 
2689 {
2690 private:
2693 
2694 public:
2696  :m_rShell( _rShell )
2697  ,m_bEnabled( false )
2698  {
2699  if (m_rShell.IsTrackPropertiesEnabled_Lock())
2700  {
2701  m_rShell.EnableTrackProperties_Lock(false);
2702  m_bEnabled = true;
2703  }
2704  }
2705 
2707  {
2708  if ( m_bEnabled ) // note that ( false != m_bEnabled ) implies ( NULL != m_pShell )
2709  m_rShell.EnableTrackProperties_Lock(true);
2710  }
2711 };
2712 
2713 
2714 void FmXFormShell::SetDesignMode_Lock(bool bDesign)
2715 {
2716  if (impl_checkDisposed_Lock())
2717  return;
2718 
2719  DBG_ASSERT(m_pShell->GetFormView(), "FmXFormShell::SetDesignMode : invalid call (have no shell or no view) !");
2720  m_bChangingDesignMode = true;
2721 
2722  // 67506 - 15.07.99 - FS
2723  // if we're switching off the design mode we have to force the property browser to be closed
2724  // so it can commit it's changes _before_ we load the forms
2725  if (!bDesign)
2726  {
2727  m_bHadPropertyBrowserInDesignMode = m_pShell->GetViewShell()->GetViewFrame()->HasChildWindow(SID_FM_SHOW_PROPERTIES);
2728  if (m_bHadPropertyBrowserInDesignMode)
2729  m_pShell->GetViewShell()->GetViewFrame()->ToggleChildWindow(SID_FM_SHOW_PROPERTIES);
2730  }
2731 
2732  FmFormView* pFormView = m_pShell->GetFormView();
2733  if (bDesign)
2734  {
2735  // we are currently filtering, so stop filtering
2736  if (m_bFilterMode)
2737  stopFiltering_Lock(false);
2738 
2739  // unsubscribe from the objects of my MarkList
2740  pFormView->GetImpl()->stopMarkListWatching();
2741  }
2742  else
2743  {
2744  m_aMarkTimer.Stop();
2745 
2746  SuspendPropertyTracking aSuspend( *this );
2747  pFormView->GetImpl()->saveMarkList();
2748  }
2749 
2750  if (bDesign && m_xExternalViewController.is())
2751  CloseExternalFormViewer_Lock();
2752 
2753  pFormView->ChangeDesignMode(bDesign);
2754 
2755  // notify listeners
2756  FmDesignModeChangedHint aChangedHint( bDesign );
2757  m_pShell->Broadcast(aChangedHint);
2758 
2759  m_pShell->m_bDesignMode = bDesign;
2760  UpdateForms_Lock(false);
2761 
2762  m_pTextShell->designModeChanged();
2763 
2764  if (bDesign)
2765  {
2766  SdrMarkList aList;
2767  {
2768  // during changing the mark list, don't track the selected objects in the property browser
2769  SuspendPropertyTracking aSuspend( *this );
2770  // restore the marks
2771  pFormView->GetImpl()->restoreMarkList( aList );
2772  }
2773 
2774  // synchronize with the restored mark list
2775  if ( aList.GetMarkCount() )
2776  SetSelection_Lock(aList);
2777  }
2778  else
2779  {
2780  // subscribe to the model of the view (so that I'm informed when someone deletes
2781  // during the alive mode controls that I had saved in the saveMarklist (60343)
2782  pFormView->GetImpl()->startMarkListWatching();
2783  }
2784 
2785  m_pShell->UIFeatureChanged();
2786 
2787  // 67506 - 15.07.99 - FS
2788  if (bDesign && m_bHadPropertyBrowserInDesignMode)
2789  {
2790  // The UIFeatureChanged performs an update (a check of the available features) asynchronously.
2791  // So we can't call ShowSelectionProperties directly as the according feature isn't enabled yet.
2792  // That's why we use an asynchron execution on the dispatcher.
2793  // (And that's why this has to be done AFTER the UIFeatureChanged.)
2794  m_pShell->GetViewShell()->GetViewFrame()->GetDispatcher()->Execute( SID_FM_SHOW_PROPERTY_BROWSER, SfxCallMode::ASYNCHRON );
2795  }
2796  m_bChangingDesignMode = false;
2797 }
2798 
2799 
2800 Reference< XControl> FmXFormShell::impl_getControl_Lock(const Reference<XControlModel>& i_rxModel, const FmFormObj& i_rKnownFormObj)
2801 {
2802  if (impl_checkDisposed_Lock())
2803  return nullptr;
2804 
2805  Reference< XControl > xControl;
2806  try
2807  {
2808  Reference< XControlContainer> xControlContainer(getControlContainerForView_Lock(), UNO_SET_THROW);
2809 
2810  const Sequence< Reference< XControl > > seqControls( xControlContainer->getControls() );
2811  // ... that I can then search
2812  for (Reference< XControl > const & control : seqControls)
2813  {
2814  xControl.set( control, UNO_SET_THROW );
2815  Reference< XControlModel > xCurrentModel( xControl->getModel() );
2816  if ( xCurrentModel == i_rxModel )
2817  break;
2818  xControl.clear();
2819  }
2820 
2821  if ( !xControl.is() )
2822  {
2823  // fallback (some controls might not have been created, yet, since they were never visible so far)
2824  Reference< XControl > xContainerControl( xControlContainer, UNO_QUERY_THROW );
2825  const vcl::Window* pContainerWindow = VCLUnoHelper::GetWindow( xContainerControl->getPeer() );
2826  ENSURE_OR_THROW( pContainerWindow, "unexpected control container implementation" );
2827 
2828  const SdrView* pSdrView = m_pShell ? m_pShell->GetFormView() : nullptr;
2829  ENSURE_OR_THROW( pSdrView, "no current view" );
2830 
2831  xControl.set( i_rKnownFormObj.GetUnoControl( *pSdrView, *pContainerWindow ), UNO_SET_THROW );
2832  }
2833  }
2834  catch( const Exception& )
2835  {
2836  DBG_UNHANDLED_EXCEPTION("svx");
2837  }
2838 
2839  OSL_ENSURE( xControl.is(), "FmXFormShell::impl_getControl: no control found!" );
2840  return xControl;
2841 }
2842 
2843 // note: _out_rForms is a member so needs lock
2844 void FmXFormShell::impl_collectFormSearchContexts_nothrow_Lock( const Reference<XInterface>& _rxStartingPoint,
2845  const OUString& _rCurrentLevelPrefix, FmFormArray& _out_rForms, ::std::vector< OUString >& _out_rNames )
2846 {
2847  try
2848  {
2849  Reference< XIndexAccess> xContainer( _rxStartingPoint, UNO_QUERY );
2850  if ( !xContainer.is() )
2851  return;
2852 
2853  sal_Int32 nCount( xContainer->getCount() );
2854  if ( nCount == 0 )
2855  return;
2856 
2857  OUString sCurrentFormName;
2858  OUStringBuffer aNextLevelPrefix;
2859  for ( sal_Int32 i=0; i<nCount; ++i )
2860  {
2861  // is the current child a form?
2862  Reference< XForm > xCurrentAsForm( xContainer->getByIndex(i), UNO_QUERY );
2863  if ( !xCurrentAsForm.is() )
2864  continue;
2865 
2866  Reference< XNamed > xNamed( xCurrentAsForm, UNO_QUERY_THROW );
2867  sCurrentFormName = xNamed->getName();
2868 
2869  // the name of the current form
2870  OUStringBuffer sCompleteCurrentName( sCurrentFormName );
2871  if ( !_rCurrentLevelPrefix.isEmpty() )
2872  {
2873  sCompleteCurrentName.append( " (" );
2874  sCompleteCurrentName.append ( _rCurrentLevelPrefix );
2875  sCompleteCurrentName.append( ")" );
2876  }
2877 
2878  // the prefix for the next level
2879  aNextLevelPrefix = _rCurrentLevelPrefix;
2880  if ( !_rCurrentLevelPrefix.isEmpty() )
2881  aNextLevelPrefix.append( '/' );
2882  aNextLevelPrefix.append( sCurrentFormName );
2883 
2884  // remember both the form and its "display name"
2885  _out_rForms.push_back( xCurrentAsForm );
2886  _out_rNames.push_back( sCompleteCurrentName.makeStringAndClear() );
2887 
2888  // and descend
2889  impl_collectFormSearchContexts_nothrow_Lock(
2890  xCurrentAsForm, aNextLevelPrefix.makeStringAndClear(),
2891  _out_rForms, _out_rNames);
2892  }
2893  }
2894  catch( const Exception& )
2895  {
2896  DBG_UNHANDLED_EXCEPTION("svx");
2897  }
2898 }
2899 
2900 
2901 void FmXFormShell::startFiltering_Lock()
2902 {
2903  if (impl_checkDisposed_Lock())
2904  return;
2905 
2906  // setting all forms in filter mode
2907  FmXFormView* pXView = m_pShell->GetFormView()->GetImpl();
2908 
2909  // if the active controller is our external one we have to use the trigger controller
2910  Reference< XControlContainer> xContainer;
2911  if (getActiveController_Lock() == m_xExternalViewController)
2912  {
2913  DBG_ASSERT(m_xExtViewTriggerController.is(), "FmXFormShell::startFiltering : inconsistent : active external controller, but no one triggered this !");
2914  xContainer = m_xExtViewTriggerController->getContainer();
2915  }
2916  else
2917  xContainer = getActiveController_Lock()->getContainer();
2918 
2919  PFormViewPageWindowAdapter pAdapter = pXView->findWindow( xContainer );
2920  if ( pAdapter.is() )
2921  {
2922  const ::std::vector< Reference< runtime::XFormController> >& rControllerList = pAdapter->GetList();
2923  for (const auto& rpController : rControllerList)
2924  {
2925  Reference< XModeSelector> xModeSelector(rpController, UNO_QUERY);
2926  if (xModeSelector.is())
2927  xModeSelector->setMode( "FilterMode" );
2928  }
2929  }
2930 
2931  m_bFilterMode = true;
2932 
2933  m_pShell->UIFeatureChanged();
2934  SfxViewFrame* pViewFrame = m_pShell->GetViewShell()->GetViewFrame();
2935  pViewFrame->GetBindings().InvalidateShell( *m_pShell );
2936 
2937  if ( pViewFrame->KnowsChildWindow( SID_FM_FILTER_NAVIGATOR )
2938  && !pViewFrame->HasChildWindow( SID_FM_FILTER_NAVIGATOR )
2939  )
2940  {
2941  pViewFrame->ToggleChildWindow( SID_FM_FILTER_NAVIGATOR );
2942  }
2943 }
2944 
2945 
2946 static void saveFilter(const Reference< runtime::XFormController >& _rxController)
2947 {
2948  Reference< XPropertySet> xFormAsSet(_rxController->getModel(), UNO_QUERY);
2949  Reference< XPropertySet> xControllerAsSet(_rxController, UNO_QUERY);
2950 
2951  // call the subcontroller
2952  Reference< runtime::XFormController > xController;
2953  for (sal_Int32 i = 0, nCount = _rxController->getCount(); i < nCount; ++i)
2954  {
2955  _rxController->getByIndex(i) >>= xController;
2956  saveFilter(xController);
2957  }
2958 
2959  try
2960  {
2961 
2962  xFormAsSet->setPropertyValue(FM_PROP_FILTER, xControllerAsSet->getPropertyValue(FM_PROP_FILTER));
2963  xFormAsSet->setPropertyValue(FM_PROP_APPLYFILTER, makeAny( true ) );
2964  }
2965  catch (const Exception& )
2966  {
2967  DBG_UNHANDLED_EXCEPTION("svx");
2968  }
2969 
2970 }
2971 
2972 
2973 void FmXFormShell::stopFiltering_Lock(bool bSave)
2974 {
2975  if (impl_checkDisposed_Lock())
2976  return;
2977 
2978  m_bFilterMode = false;
2979 
2980  FmXFormView* pXView = m_pShell->GetFormView()->GetImpl();
2981 
2982  // if the active controller is our external one we have to use the trigger controller
2983  Reference< XControlContainer> xContainer;
2984  if (getActiveController_Lock() == m_xExternalViewController)
2985  {
2986  DBG_ASSERT(m_xExtViewTriggerController.is(), "FmXFormShell::stopFiltering : inconsistent : active external controller, but no one triggered this !");
2987  xContainer = m_xExtViewTriggerController->getContainer();
2988  }
2989  else
2990  xContainer = getActiveController_Lock()->getContainer();
2991 
2992  PFormViewPageWindowAdapter pAdapter = pXView->findWindow(xContainer);
2993  if ( pAdapter.is() )
2994  {
2995  const ::std::vector< Reference< runtime::XFormController > >& rControllerList = pAdapter->GetList();
2996  ::std::vector < OUString > aOriginalFilters;
2997  ::std::vector < bool > aOriginalApplyFlags;
2998 
2999  if (bSave)
3000  {
3001  for (const auto& rpController : rControllerList)
3002  {
3003  // remember the current filter settings in case we're going to reload the forms below (which may fail)
3004  try
3005  {
3006  Reference< XPropertySet > xFormAsSet(rpController->getModel(), UNO_QUERY);
3007  aOriginalFilters.push_back(::comphelper::getString(xFormAsSet->getPropertyValue(FM_PROP_FILTER)));
3008  aOriginalApplyFlags.push_back(::comphelper::getBOOL(xFormAsSet->getPropertyValue(FM_PROP_APPLYFILTER)));
3009  }
3010  catch(Exception&)
3011  {
3012  OSL_FAIL("FmXFormShell::stopFiltering : could not get the original filter !");
3013  // put dummies into the arrays so the they have the right size
3014 
3015  if (aOriginalFilters.size() == aOriginalApplyFlags.size())
3016  // the first getPropertyValue failed -> use two dummies
3017  aOriginalFilters.emplace_back( );
3018  aOriginalApplyFlags.push_back( false );
3019  }
3020  saveFilter(rpController);
3021  }
3022  }
3023  for (const auto& rController : rControllerList)
3024  {
3025 
3026  Reference< XModeSelector> xModeSelector(rController, UNO_QUERY);
3027  if (xModeSelector.is())
3028  xModeSelector->setMode( "DataMode" );
3029  }
3030  if (bSave) // execute the filter
3031  {
3032  const ::std::vector< Reference< runtime::XFormController > > & rControllers = pAdapter->GetList();
3033  for (::std::vector< Reference< runtime::XFormController > > ::const_iterator j = rControllers.begin();
3034  j != rControllers.end(); ++j)
3035  {
3036  Reference< XLoadable> xReload((*j)->getModel(), UNO_QUERY);
3037  if (!xReload.is())
3038  continue;
3039  Reference< XPropertySet > xFormSet(xReload, UNO_QUERY);
3040 
3041  try
3042  {
3043  xReload->reload();
3044  }
3045  catch(Exception&)
3046  {
3047  OSL_FAIL("FmXFormShell::stopFiltering: Exception occurred!");
3048  }
3049 
3050  if (!isRowSetAlive(xFormSet))
3051  { // something went wrong -> restore the original state
3052  OUString sOriginalFilter = aOriginalFilters[ j - rControllers.begin() ];
3053  bool bOriginalApplyFlag = aOriginalApplyFlags[ j - rControllers.begin() ];
3054  try
3055  {
3056  xFormSet->setPropertyValue(FM_PROP_FILTER, makeAny(sOriginalFilter));
3057  xFormSet->setPropertyValue(FM_PROP_APPLYFILTER, makeAny(bOriginalApplyFlag));
3058  xReload->reload();
3059  }
3060  catch(const Exception&)
3061  {
3062  DBG_UNHANDLED_EXCEPTION("svx");
3063  }
3064  }
3065  }
3066  }
3067  }
3068 
3069  m_pShell->UIFeatureChanged();
3070  m_pShell->GetViewShell()->GetViewFrame()->GetBindings().InvalidateShell(*m_pShell);
3071 }
3072 
3073 
3074 void FmXFormShell::CreateExternalView_Lock()
3075 {
3076  if (impl_checkDisposed_Lock())
3077  return;
3078 
3079  DBG_ASSERT(m_xAttachedFrame.is(), "FmXFormShell::CreateExternalView : no frame !");
3080 
3081  // the frame the external view is displayed in
3082  bool bAlreadyExistent = m_xExternalViewController.is();
3083  Reference< css::frame::XFrame> xExternalViewFrame;
3084  OUString sFrameName("_beamer");
3085 
3086  Reference<runtime::XFormController> xCurrentNavController(getNavController_Lock());
3087  // the creation of the "partwindow" may cause a deactivate of the document which will result in our nav controller to be set to NULL
3088 
3089  // _first_ check if we have any valid fields we can use for the grid view
3090  // FS - 21.10.99 - 69219
3091  {
3092  FmXBoundFormFieldIterator aModelIterator(xCurrentNavController->getModel());
3093  bool bHaveUsableControls = false;
3094  for (;;)
3095  {
3096  Reference< XPropertySet> xCurrentModelSet(aModelIterator.Next(), UNO_QUERY);
3097  if (!xCurrentModelSet.is())
3098  break;
3099  // the FmXBoundFormFieldIterator only supplies controls with a valid control source
3100  // so we just have to check the field type
3101  sal_Int16 nClassId = ::comphelper::getINT16(xCurrentModelSet->getPropertyValue(FM_PROP_CLASSID));
3102  switch (nClassId)
3103  {
3104  case FormComponentType::IMAGECONTROL:
3105  case FormComponentType::CONTROL:
3106  continue;
3107  }
3108  bHaveUsableControls = true;
3109  break;
3110  }
3111 
3112  if (!bHaveUsableControls)
3113  {
3114  std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(nullptr,
3115  VclMessageType::Warning, VclButtonsType::Ok,
3116  SvxResId(RID_STR_NOCONTROLS_FOR_EXTERNALDISPLAY)));
3117  xBox->run();
3118  return;
3119  }
3120  }
3121 
3122  // load the component for external form views
3123  if (!bAlreadyExistent)
3124  {
3125  URL aWantToDispatch;
3126  aWantToDispatch.Complete = FMURL_COMPONENT_FORMGRIDVIEW;
3127 
3128  Reference< css::frame::XDispatchProvider> xProv(m_xAttachedFrame, UNO_QUERY);
3129  Reference< css::frame::XDispatch> xDisp;
3130  if (xProv.is())
3131  xDisp = xProv->queryDispatch(aWantToDispatch, sFrameName,
3132  css::frame::FrameSearchFlag::CHILDREN | css::frame::FrameSearchFlag::CREATE);
3133  if (xDisp.is())
3134  {
3135  xDisp->dispatch(aWantToDispatch, Sequence< PropertyValue>());
3136  }
3137 
3138  // with this the component should be loaded, now search the frame where it resides in
3139  xExternalViewFrame = m_xAttachedFrame->findFrame(sFrameName, css::frame::FrameSearchFlag::CHILDREN);
3140  if (xExternalViewFrame.is())
3141  {
3142  m_xExternalViewController = xExternalViewFrame->getController();
3143  if (m_xExternalViewController.is())
3144  m_xExternalViewController->addEventListener(static_cast<XEventListener*>(static_cast<XPropertyChangeListener*>(this)));
3145  }
3146  }
3147  else
3148  {
3149  xExternalViewFrame = m_xExternalViewController->getFrame();
3150  Reference< css::frame::XDispatchProvider> xCommLink(xExternalViewFrame, UNO_QUERY);
3151 
3152  // if we display the active form we interpret the slot as "remove it"
3153  Reference< XForm> xCurrentModel(xCurrentNavController->getModel(), UNO_QUERY);
3154  if ((xCurrentModel == m_xExternalDisplayedForm) || (getInternalForm_Lock(xCurrentModel) == m_xExternalDisplayedForm))
3155  {
3156  if (m_xExternalViewController == getActiveController_Lock())
3157  {
3158  Reference< runtime::XFormController > xAsFormController( m_xExternalViewController, UNO_QUERY );
3159  ControllerFeatures aHelper( xAsFormController );
3160  (void)aHelper->commitCurrentControl();
3161  }
3162 
3163  Reference< runtime::XFormController > xNewController(m_xExtViewTriggerController);
3164  CloseExternalFormViewer_Lock();
3165  setActiveController_Lock(xNewController);
3166  return;
3167  }
3168 
3169  URL aClearURL;
3170  aClearURL.Complete = FMURL_GRIDVIEW_CLEARVIEW;
3171 
3172  Reference< css::frame::XDispatch> xClear( xCommLink->queryDispatch(aClearURL, OUString(), 0));
3173  if (xClear.is())
3174  xClear->dispatch(aClearURL, Sequence< PropertyValue>());
3175  }
3176 
3177  // TODO: We need an interceptor at the xSupplier, which forwards all queryDispatch requests to the FormController
3178  // instance for which this "external view" was triggered
3179 
3180  // get the dispatch interface of the frame so we can communicate (interceptable) with the controller
3181  Reference< css::frame::XDispatchProvider> xCommLink(xExternalViewFrame, UNO_QUERY);
3182 
3183  if (m_xExternalViewController.is())
3184  {
3185  DBG_ASSERT(xCommLink.is(), "FmXFormShell::CreateExternalView : the component doesn't have the necessary interfaces !");
3186  // collect the dispatchers we will need
3187  URL aAddColumnURL;
3188  aAddColumnURL.Complete = FMURL_GRIDVIEW_ADDCOLUMN;
3189  Reference< css::frame::XDispatch> xAddColumnDispatch( xCommLink->queryDispatch(aAddColumnURL, OUString(), 0));
3190  URL aAttachURL;
3191  aAttachURL.Complete = FMURL_GRIDVIEW_ATTACHTOFORM;
3192  Reference< css::frame::XDispatch> xAttachDispatch( xCommLink->queryDispatch(aAttachURL, OUString(), 0));
3193 
3194  if (xAddColumnDispatch.is() && xAttachDispatch.is())
3195  {
3196  DBG_ASSERT(xCurrentNavController.is(), "FmXFormShell::CreateExternalView : invalid call : have no nav controller !");
3197  // first : dispatch the descriptions for the columns to add
3198  sal_Int16 nAddedColumns = 0;
3199 
3200  // for radio buttons we need some special structures
3201  typedef std::map< OUString, Sequence< OUString> > MapUString2UstringSeq;
3202  typedef std::map< OUString, OUString > FmMapUString2UString;
3203  typedef std::map< OUString, sal_Int16 > FmMapUString2Int16;
3204 
3205  MapUString2UstringSeq aRadioValueLists;
3206  MapUString2UstringSeq aRadioListSources;
3207  FmMapUString2UString aRadioControlSources;
3208  FmMapUString2Int16 aRadioPositions;
3209 
3210  FmXBoundFormFieldIterator aModelIterator(xCurrentNavController->getModel());
3211  OUString sColumnType,aGroupName,sControlSource;
3212  Sequence< Property> aProps;
3213  for (;;)
3214  {
3215  Reference< XPropertySet> xCurrentModelSet(aModelIterator.Next(), UNO_QUERY);
3216  if (!xCurrentModelSet.is())
3217  break;
3218  OSL_ENSURE(xCurrentModelSet.is(),"xCurrentModelSet is null!");
3219  // create a description of the column to be created
3220  // first : determine it's type
3221 
3222  sal_Int16 nClassId = ::comphelper::getINT16(xCurrentModelSet->getPropertyValue(FM_PROP_CLASSID));
3223  switch (nClassId)
3224  {
3225  case FormComponentType::RADIOBUTTON:
3226  {
3227  // get the label of the button (this is the access key for our structures)
3228  aGroupName = getLabelName(xCurrentModelSet);
3229 
3230  // add the reference value of the radio button to the list source sequence
3231  Sequence< OUString>& aThisGroupLabels = aRadioListSources[aGroupName];
3232  sal_Int32 nNewSizeL = aThisGroupLabels.getLength() + 1;
3233  aThisGroupLabels.realloc(nNewSizeL);
3234  aThisGroupLabels.getArray()[nNewSizeL - 1] = ::comphelper::getString(xCurrentModelSet->getPropertyValue(FM_PROP_REFVALUE));
3235 
3236  // add the label to the value list sequence
3237  Sequence< OUString>& aThisGroupControlSources = aRadioValueLists[aGroupName];
3238  sal_Int32 nNewSizeC = aThisGroupControlSources.getLength() + 1;
3239  aThisGroupControlSources.realloc(nNewSizeC);
3240  aThisGroupControlSources.getArray()[nNewSizeC - 1] = ::comphelper::getString(xCurrentModelSet->getPropertyValue(FM_PROP_LABEL));
3241 
3242  // remember the controls source of the radio group
3243  sControlSource = ::comphelper::getString(xCurrentModelSet->getPropertyValue(FM_PROP_CONTROLSOURCE));
3244  if (aRadioControlSources.find(aGroupName) == aRadioControlSources.end())
3245  aRadioControlSources[aGroupName] = sControlSource;
3246 #ifdef DBG_UTIL
3247  else
3248  DBG_ASSERT(aRadioControlSources[aGroupName] == sControlSource,
3249  "FmXFormShell::CreateExternalView : inconsistent radio buttons detected !");
3250  // (radio buttons with the same name should have the same control source)
3251 #endif
3252  // remember the position within the columns
3253  if (aRadioPositions.find(aGroupName) == aRadioPositions.end())
3254  aRadioPositions[aGroupName] = nAddedColumns;
3255 
3256  // any further handling is done below
3257  }
3258  continue;
3259 
3260  case FormComponentType::IMAGECONTROL:
3261  case FormComponentType::CONTROL:
3262  // no grid columns for these types (though they have a control source)
3263  continue;
3264  case FormComponentType::CHECKBOX:
3265  sColumnType = FM_COL_CHECKBOX; break;
3266  case FormComponentType::LISTBOX:
3267  sColumnType = FM_COL_LISTBOX; break;
3268  case FormComponentType::COMBOBOX:
3269  sColumnType = FM_COL_COMBOBOX; break;
3270  case FormComponentType::DATEFIELD:
3271  sColumnType = FM_COL_DATEFIELD; break;
3272  case FormComponentType::TIMEFIELD:
3273  sColumnType = FM_COL_TIMEFIELD; break;
3274  case FormComponentType::NUMERICFIELD:
3275  sColumnType = FM_COL_NUMERICFIELD; break;
3276  case FormComponentType::CURRENCYFIELD:
3277  sColumnType = FM_COL_CURRENCYFIELD; break;
3278  case FormComponentType::PATTERNFIELD:
3279  sColumnType = FM_COL_PATTERNFIELD; break;
3280 
3281  case FormComponentType::TEXTFIELD:
3282  {
3283  sColumnType = FM_COL_TEXTFIELD;
3284  // we know at least two different controls which are TextFields : the basic edit field and the formatted
3285  // field. we distinguish them by their service name
3286  Reference< lang::XServiceInfo> xInfo(xCurrentModelSet, UNO_QUERY);
3287  if (xInfo.is())
3288  {
3289  sal_Int16 nObjectType = getControlTypeByObject(xInfo);
3290  if (OBJ_FM_FORMATTEDFIELD == nObjectType)
3291  sColumnType = FM_COL_FORMATTEDFIELD;
3292  }
3293  }
3294  break;
3295  default:
3296  sColumnType = FM_COL_TEXTFIELD; break;
3297  }
3298 
3299  const sal_Int16 nDispatchArgs = 3;
3300  Sequence< PropertyValue> aDispatchArgs(nDispatchArgs);
3301  PropertyValue* pDispatchArgs = aDispatchArgs.getArray();
3302 
3303  // properties describing "meta data" about the column
3304  // the type
3305  pDispatchArgs->Name = FMARG_ADDCOL_COLUMNTYPE;
3306  pDispatchArgs->Value <<= sColumnType;
3307  ++pDispatchArgs;
3308 
3309  // the pos : append the col
3310  pDispatchArgs->Name = FMARG_ADDCOL_COLUMNPOS;
3311  pDispatchArgs->Value <<= nAddedColumns;
3312  ++pDispatchArgs;
3313 
3314  // the properties to forward to the new column
3315  Sequence< PropertyValue> aColumnProps(1);
3316  PropertyValue* pColumnProps = aColumnProps.getArray();
3317 
3318  // the label
3319  pColumnProps->Name = FM_PROP_LABEL;
3320  pColumnProps->Value <<= getLabelName(xCurrentModelSet);
3321  ++pColumnProps;
3322 
3323  // for all other props : transfer them
3324  Reference< XPropertySetInfo> xControlModelInfo( xCurrentModelSet->getPropertySetInfo());
3325  DBG_ASSERT(xControlModelInfo.is(), "FmXFormShell::CreateExternalView : the control model has no property info ! This will crash !");
3326  aProps = xControlModelInfo->getProperties();
3327 
3328  // realloc the control description sequence
3329  sal_Int32 nExistentDescs = pColumnProps - aColumnProps.getArray();
3330  aColumnProps.realloc(nExistentDescs + aProps.getLength());
3331  pColumnProps = aColumnProps.getArray() + nExistentDescs;
3332 
3333  for (const Property& rProp : std::as_const(aProps))
3334  {
3335  if (rProp.Name == FM_PROP_LABEL)
3336  // already set
3337  continue;
3338  if (rProp.Name == FM_PROP_DEFAULTCONTROL)
3339  // allow the column's own "default control"
3340  continue;
3341  if (rProp.Attributes & PropertyAttribute::READONLY)
3342  // assume that properties which are readonly for the control are ro for the column to be created, too
3343  continue;
3344 
3345  pColumnProps->Name = rProp.Name;
3346  pColumnProps->Value = xCurrentModelSet->getPropertyValue(rProp.Name);
3347  ++pColumnProps;
3348  }
3349  aColumnProps.realloc(pColumnProps - aColumnProps.getArray());
3350 
3351  // columns props are a dispatch argument
3352  pDispatchArgs->Name = "ColumnProperties"; // TODO : fmurl.*
3353  pDispatchArgs->Value <<= aColumnProps;
3354  ++pDispatchArgs;
3355  DBG_ASSERT(nDispatchArgs == (pDispatchArgs - aDispatchArgs.getConstArray()),
3356  "FmXFormShell::CreateExternalView : forgot to adjust nDispatchArgs ?");
3357 
3358  // dispatch the "add column"
3359  xAddColumnDispatch->dispatch(aAddColumnURL, aDispatchArgs);
3360  ++nAddedColumns;
3361  }
3362 
3363  // now for the radio button handling
3364  sal_Int16 nOffset(0);
3365  // properties describing the "direct" column properties
3366  const sal_Int16 nListBoxDescription = 6;
3367  Sequence< PropertyValue> aListBoxDescription(nListBoxDescription);
3368  for (const auto& rCtrlSource : aRadioControlSources)
3369  {
3370  PropertyValue* pListBoxDescription = aListBoxDescription.getArray();
3371  // label
3372  pListBoxDescription->Name = FM_PROP_LABEL;
3373  pListBoxDescription->Value <<= rCtrlSource.first;
3374  ++pListBoxDescription;
3375 
3376  // control source
3377  pListBoxDescription->Name = FM_PROP_CONTROLSOURCE;
3378  pListBoxDescription->Value <<= rCtrlSource.second;
3379  ++pListBoxDescription;
3380 
3381  // bound column
3382  pListBoxDescription->Name = FM_PROP_BOUNDCOLUMN;
3383  pListBoxDescription->Value <<= sal_Int16(1);
3384  ++pListBoxDescription;
3385 
3386  // content type
3387  pListBoxDescription->Name = FM_PROP_LISTSOURCETYPE;
3388  pListBoxDescription->Value <<= ListSourceType_VALUELIST;
3389  ++pListBoxDescription;
3390 
3391  // list source
3392  MapUString2UstringSeq::const_iterator aCurrentListSource = aRadioListSources.find(rCtrlSource.first);
3393  DBG_ASSERT(aCurrentListSource != aRadioListSources.end(),
3394  "FmXFormShell::CreateExternalView : inconsistent radio descriptions !");
3395  pListBoxDescription->Name = FM_PROP_LISTSOURCE;
3396  pListBoxDescription->Value <<= (*aCurrentListSource).second;
3397  ++pListBoxDescription;
3398 
3399  // value list
3400  MapUString2UstringSeq::const_iterator aCurrentValueList = aRadioValueLists.find(rCtrlSource.first);
3401  DBG_ASSERT(aCurrentValueList != aRadioValueLists.end(),
3402  "FmXFormShell::CreateExternalView : inconsistent radio descriptions !");
3403  pListBoxDescription->Name = FM_PROP_STRINGITEMLIST;
3404  pListBoxDescription->Value <<= (*aCurrentValueList).second;
3405  ++pListBoxDescription;
3406 
3407  DBG_ASSERT(nListBoxDescription == (pListBoxDescription - aListBoxDescription.getConstArray()),
3408  "FmXFormShell::CreateExternalView : forgot to adjust nListBoxDescription ?");
3409 
3410  // properties describing the column "meta data"
3411  const sal_Int16 nDispatchArgs = 3;
3412  Sequence< PropertyValue> aDispatchArgs(nDispatchArgs);
3413  PropertyValue* pDispatchArgs = aDispatchArgs.getArray();
3414 
3415  // column type : listbox
3416  pDispatchArgs->Name = FMARG_ADDCOL_COLUMNTYPE;
3417  pDispatchArgs->Value <<= OUString(FM_COL_LISTBOX);
3418 // pDispatchArgs->Value <<= (OUString)FM_COL_LISTBOX;
3419  ++pDispatchArgs;
3420 
3421  // column position
3422  pDispatchArgs->Name = FMARG_ADDCOL_COLUMNPOS;
3423  FmMapUString2Int16::const_iterator aOffset = aRadioPositions.find(rCtrlSource.first);
3424  DBG_ASSERT(aOffset != aRadioPositions.end(),
3425  "FmXFormShell::CreateExternalView : inconsistent radio descriptions !");
3426  sal_Int16 nPosition = (*aOffset).second;
3427  nPosition = nPosition + nOffset;
3428  // we already inserted nOffset additional columns...
3429  pDispatchArgs->Value <<= nPosition;
3430  ++pDispatchArgs;
3431 
3432  // the
3433  pDispatchArgs->Name = "ColumnProperties"; // TODO : fmurl.*
3434  pDispatchArgs->Value <<= aListBoxDescription;
3435  ++pDispatchArgs;
3436  DBG_ASSERT(nDispatchArgs == (pDispatchArgs - aDispatchArgs.getConstArray()),
3437  "FmXFormShell::CreateExternalView : forgot to adjust nDispatchArgs ?");
3438 
3439  // dispatch the "add column"
3440  xAddColumnDispatch->dispatch(aAddColumnURL, aDispatchArgs);
3441  ++nAddedColumns;
3442  ++nOffset;
3443  }
3444 
3445 
3446  DBG_ASSERT(nAddedColumns > 0, "FmXFormShell::CreateExternalView : no controls (inconsistent) !");
3447  // we should have checked if we have any usable controls (see above).
3448 
3449  // "load" the "form" of the external view
3450  PropertyValue aArg;
3451  aArg.Name = FMARG_ATTACHTO_MASTERFORM;
3452  Reference< XResultSet> xForm(xCurrentNavController->getModel(), UNO_QUERY);
3453  aArg.Value <<= xForm;
3454 
3455  m_xExternalDisplayedForm = xForm;
3456  // do this before dispatching the "attach" command, as the attach may result in a call to our queryDispatch (for the FormSlots)
3457  // which needs the m_xExternalDisplayedForm
3458 
3459  xAttachDispatch->dispatch(aAttachURL, Sequence< PropertyValue>(&aArg, 1));
3460 
3461  m_xExtViewTriggerController = xCurrentNavController;
3462 
3463  // we want to know modifications done in the external view
3464  // if the external controller is a XFormController we can use all our default handlings for it
3465  Reference< runtime::XFormController > xFormController( m_xExternalViewController, UNO_QUERY );
3466  OSL_ENSURE( xFormController.is(), "FmXFormShell::CreateExternalView:: invalid external view controller!" );
3467  if (xFormController.is())
3468  xFormController->addActivateListener(static_cast<XFormControllerListener*>(this));
3469  }
3470  }
3471 #ifdef DBG_UTIL
3472  else
3473  {
3474  OSL_FAIL("FmXFormShell::CreateExternalView : could not create the external form view !");
3475  }
3476 #endif
3477  InvalidateSlot_Lock(SID_FM_VIEW_AS_GRID, false);
3478 }
3479 
3480 
3481 void FmXFormShell::implAdjustConfigCache_Lock()
3482 {
3483  // get (cache) the wizard usage flag
3484  Sequence< OUString > aNames { "FormControlPilotsEnabled" };
3485  Sequence< Any > aFlags = GetProperties(aNames);
3486  if (1 == aFlags.getLength())
3487  m_bUseWizards = ::cppu::any2bool(aFlags[0]);
3488 }
3489 
3490 
3491 void FmXFormShell::Notify( const css::uno::Sequence< OUString >& _rPropertyNames)
3492 {
3494  if (impl_checkDisposed_Lock())
3495  return;
3496 
3497  for (const OUString& rName : _rPropertyNames)
3498  if (rName == "FormControlPilotsEnabled")
3499  {
3500  implAdjustConfigCache_Lock();
3501  InvalidateSlot_Lock(SID_FM_USE_WIZARDS, true);
3502  }
3503 }
3504 
3505 void FmXFormShell::ImplCommit()
3506 {
3507 }
3508 
3509 
3510 void FmXFormShell::SetWizardUsing_Lock(bool _bUseThem)
3511 {
3512  m_bUseWizards = _bUseThem;
3513 
3514  Sequence< OUString > aNames { "FormControlPilotsEnabled" };
3515  Sequence< Any > aValues(1);
3516  aValues[0] <<= m_bUseWizards;
3517  PutProperties(aNames, aValues);
3518 }
3519 
3520 
3521 void FmXFormShell::viewDeactivated_Lock(FmFormView& _rCurrentView, bool _bDeactivateController)
3522 {
3523 
3524  if ( _rCurrentView.GetImpl() && !_rCurrentView.IsDesignMode() )
3525  {
3526  _rCurrentView.GetImpl()->Deactivate( _bDeactivateController );
3527  }
3528 
3529  // if we have an async load operation pending for the 0-th page for this view,
3530  // we need to cancel this
3531  if (FmFormPage* pPage = _rCurrentView.GetCurPage())
3532  {
3533  // move all events from our queue to a new one, omit the events for the deactivated
3534  // page
3535  ::std::queue< FmLoadAction > aNewEvents;
3536  while ( !m_aLoadingPages.empty() )
3537  {
3538  FmLoadAction aAction = m_aLoadingPages.front();
3539  m_aLoadingPages.pop();
3540  if ( pPage != aAction.pPage )
3541  {
3542  aNewEvents.push( aAction );
3543  }
3544  else
3545  {
3547  }
3548  }
3549  m_aLoadingPages = aNewEvents;
3550 
3551  // remove callbacks at the page
3553  }
3554  UpdateForms_Lock(true);
3555 }
3556 
3557 
3558 IMPL_LINK_NOARG( FmXFormShell, OnFirstTimeActivation_Lock, void*, void )
3559 {
3560  if (impl_checkDisposed_Lock())
3561  return;
3562 
3563  m_nActivationEvent = nullptr;
3564  SfxObjectShell* pDocument = m_pShell->GetObjectShell();
3565 
3566  if ( pDocument && !pDocument->HasName() )
3567  {
3568  if (isEnhancedForm_Lock())
3569  {
3570  // show the data navigator
3571  if ( !m_pShell->GetViewShell()->GetViewFrame()->HasChildWindow( SID_FM_SHOW_DATANAVIGATOR ) )
3572  m_pShell->GetViewShell()->GetViewFrame()->ToggleChildWindow( SID_FM_SHOW_DATANAVIGATOR );
3573  }
3574  }
3575 }
3576 
3577 
3578 IMPL_LINK_NOARG( FmXFormShell, OnFormsCreated_Lock, FmFormPageImpl&, void )
3579 {
3580  UpdateForms_Lock(true);
3581 }
3582 
3583 
3584 void FmXFormShell::viewActivated_Lock(FmFormView& _rCurrentView, bool _bSyncAction)
3585 {
3586  FmFormPage* pPage = _rCurrentView.GetCurPage();
3587 
3588  // activate our view if we are activated ourself
3589  // FS - 30.06.99 - 67308
3590  if ( _rCurrentView.GetImpl() && !_rCurrentView.IsDesignMode() )
3591  {
3592  // load forms for the page the current view belongs to
3593  if ( pPage )
3594  {
3595  if ( !pPage->GetImpl().hasEverBeenActivated() )
3596  loadForms_Lock(pPage, LoadFormsFlags::Load
3597  | (_bSyncAction ? LoadFormsFlags::Sync
3599  pPage->GetImpl().setHasBeenActivated( );
3600  }
3601 
3602  // first-time initializations for the views
3603  if ( !_rCurrentView.GetImpl()->hasEverBeenActivated( ) )
3604  {
3605  _rCurrentView.GetImpl()->onFirstViewActivation( dynamic_cast<FmFormModel*>( _rCurrentView.GetModel() ) );
3606  _rCurrentView.GetImpl()->setHasBeenActivated( );
3607  }
3608 
3609  // activate the current view
3610  _rCurrentView.GetImpl()->Activate( _bSyncAction );
3611  }
3612 
3613  // set callbacks at the page
3614  if ( pPage )
3615  {
3616  pPage->GetImpl().SetFormsCreationHdl(LINK(this, FmXFormShell, OnFormsCreated_Lock));
3617  }
3618 
3619  UpdateForms_Lock(true);
3620 
3621  if ( m_bFirstActivation )
3622  {
3623  m_nActivationEvent = Application::PostUserEvent(LINK(this, FmXFormShell, OnFirstTimeActivation_Lock));
3624  m_bFirstActivation = false;
3625  }
3626 
3627  // find a default "current form", if there is none, yet
3628  // #i88186# / 2008-04-12 / frank.schoenheit@sun.com
3629  impl_defaultCurrentForm_nothrow_Lock();
3630 }
3631 
3632 
3633 void FmXFormShell::impl_defaultCurrentForm_nothrow_Lock()
3634 {
3635  if (impl_checkDisposed_Lock())
3636  return;
3637 
3638  if ( m_xCurrentForm.is() )
3639  // no action required
3640  return;
3641 
3642  FmFormView* pFormView = m_pShell->GetFormView();
3643  FmFormPage* pPage = pFormView ? pFormView->GetCurPage() : nullptr;
3644  if ( !pPage )
3645  return;
3646 
3647  try
3648  {
3649  Reference< XIndexAccess > xForms = pPage->GetForms( false );
3650  if ( !xForms.is() || !xForms->hasElements() )
3651  return;
3652 
3653  Reference< XForm > xNewCurrentForm( xForms->getByIndex(0), UNO_QUERY_THROW );
3654  impl_updateCurrentForm_Lock(xNewCurrentForm);
3655  }
3656  catch( const Exception& )
3657  {
3658  DBG_UNHANDLED_EXCEPTION("svx");
3659  }
3660 }
3661 
3662 
3663 void FmXFormShell::smartControlReset( const Reference< XIndexAccess >& _rxModels )
3664 {
3665  if (!_rxModels.is())
3666  {
3667  OSL_FAIL("FmXFormShell::smartControlReset: invalid container!");
3668  return;
3669  }
3670 
3671  static const OUString sClassIdPropertyName = FM_PROP_CLASSID;
3672  static const OUString sBoundFieldPropertyName = FM_PROP_BOUNDFIELD;
3673  sal_Int32 nCount = _rxModels->getCount();
3674  Reference< XPropertySet > xCurrent;
3675  Reference< XPropertySetInfo > xCurrentInfo;
3676  Reference< XPropertySet > xBoundField;
3677 
3678  for (sal_Int32 i=0; i<nCount; ++i)
3679  {
3680  _rxModels->getByIndex(i) >>= xCurrent;
3681  if (xCurrent.is())
3682  xCurrentInfo = xCurrent->getPropertySetInfo();
3683  else
3684  xCurrentInfo.clear();
3685  if (!xCurrentInfo.is())
3686  continue;
3687 
3688  if (xCurrentInfo->hasPropertyByName(sClassIdPropertyName))
3689  { // it's a control model
3690 
3691  // check if this control is bound to a living database field
3692  if (xCurrentInfo->hasPropertyByName(sBoundFieldPropertyName))
3693  xCurrent->getPropertyValue(sBoundFieldPropertyName) >>= xBoundField;
3694  else
3695  xBoundField.clear();
3696 
3697  // reset only if it's *not* bound
3698  bool bReset = !xBoundField.is();
3699 
3700  // and additionally, check if it has an external value binding
3701  Reference< XBindableValue > xBindable( xCurrent, UNO_QUERY );
3702  if ( xBindable.is() && xBindable->getValueBinding().is() )
3703  bReset = false;
3704 
3705  if ( bReset )
3706  {
3707  Reference< XReset > xControlReset( xCurrent, UNO_QUERY );
3708  if ( xControlReset.is() )
3709  xControlReset->reset();
3710  }
3711  }
3712  else
3713  {
3714  Reference< XIndexAccess > xContainer(xCurrent, UNO_QUERY);
3715  if (xContainer.is())
3716  smartControlReset(xContainer);
3717  }
3718  }
3719 }
3720 
3721 
3722 IMPL_LINK_NOARG( FmXFormShell, OnLoadForms_Lock, void*, void )
3723 {
3724  FmLoadAction aAction = m_aLoadingPages.front();
3725  m_aLoadingPages.pop();
3726 
3727  loadForms_Lock(aAction.pPage, aAction.nFlags & ~LoadFormsFlags::Async);
3728 }
3729 
3730 
3731 namespace
3732 {
3733  bool lcl_isLoadable( const Reference< XInterface >& _rxLoadable )
3734  {
3735  // determines whether a form should be loaded or not
3736  // if there is no datasource or connection there is no reason to load a form
3737  Reference< XPropertySet > xSet( _rxLoadable, UNO_QUERY );
3738  if ( !xSet.is() )
3739  return false;
3740  try
3741  {
3742  Reference< XConnection > xConn;
3743  if ( isEmbeddedInDatabase( _rxLoadable.get(), xConn ) )
3744  return true;
3745 
3746  // is there already an active connection
3747  xSet->getPropertyValue(FM_PROP_ACTIVE_CONNECTION) >>= xConn;
3748  if ( xConn.is() )
3749  return true;
3750 
3751  OUString sPropertyValue;
3752  OSL_VERIFY( xSet->getPropertyValue( FM_PROP_DATASOURCE ) >>= sPropertyValue );
3753  if ( !sPropertyValue.isEmpty() )
3754  return true;
3755 
3756  OSL_VERIFY( xSet->getPropertyValue( FM_PROP_URL ) >>= sPropertyValue );
3757  if ( !sPropertyValue.isEmpty() )
3758  return true;
3759  }
3760  catch(const Exception&)
3761  {
3762  DBG_UNHANDLED_EXCEPTION("svx");
3763  }
3764  return false;
3765  }
3766 }
3767 
3768 
3769 void FmXFormShell::loadForms_Lock(FmFormPage* _pPage, const LoadFormsFlags _nBehaviour /* LoadFormsFlags::Load | LoadFormsFlags::Sync */)
3770 {
3771  DBG_ASSERT( ( _nBehaviour & ( LoadFormsFlags::Async | LoadFormsFlags::Unload ) ) != ( LoadFormsFlags::Async | LoadFormsFlags::Unload ),
3772  "FmXFormShell::loadForms: async loading not supported - this will heavily fail!" );
3773 
3774  if ( _nBehaviour & LoadFormsFlags::Async )
3775  {
3776  m_aLoadingPages.push( FmLoadAction(
3777  _pPage,
3778  _nBehaviour,
3779  Application::PostUserEvent(LINK(this, FmXFormShell, OnLoadForms_Lock), _pPage)
3780  ) );
3781  return;
3782  }
3783 
3784  DBG_ASSERT( _pPage, "FmXFormShell::loadForms: invalid page!" );
3785  if ( _pPage )
3786  {
3787  // lock the undo env so the forms can change non-transient properties while loading
3788  // (without this my doc's modified flag would be set)
3789  FmFormModel& rFmFormModel(dynamic_cast< FmFormModel& >(_pPage->getSdrModelFromSdrPage()));
3790  rFmFormModel.GetUndoEnv().Lock();
3791 
3792  // load all forms
3793  Reference< XIndexAccess > xForms = _pPage->GetForms( false );
3794 
3795  if ( xForms.is() )
3796  {
3797  Reference< XLoadable > xForm;
3798  for ( sal_Int32 j = 0, nCount = xForms->getCount(); j < nCount; ++j )
3799  {
3800  xForms->getByIndex( j ) >>= xForm;
3801  bool bFormWasLoaded = false;
3802  // a database form must be loaded for
3803  try
3804  {
3805  if ( !( _nBehaviour & LoadFormsFlags::Unload ) )
3806  {
3807  if ( lcl_isLoadable( xForm ) && !xForm->isLoaded() )
3808  xForm->load();
3809  }
3810  else
3811  {
3812  if ( xForm->isLoaded() )
3813  {
3814  bFormWasLoaded = true;
3815  xForm->unload();
3816  }
3817  }
3818  }
3819  catch( const Exception& )
3820  {
3821  DBG_UNHANDLED_EXCEPTION("svx");
3822  }
3823 
3824  // reset the form if it was loaded
3825  if ( bFormWasLoaded )
3826  {
3827  Reference< XIndexAccess > xContainer( xForm, UNO_QUERY );
3828  DBG_ASSERT( xContainer.is(), "FmXFormShell::loadForms: the form is no container!" );
3829  if ( xContainer.is() )
3830  smartControlReset( xContainer );
3831  }
3832  }
3833  }
3834 
3835  // unlock the environment
3836  rFmFormModel.GetUndoEnv().UnLock();
3837  }
3838 }
3839 
3840 
3841 void FmXFormShell::ExecuteTextAttribute_Lock(SfxRequest& _rReq)
3842 {
3844  m_pTextShell->ExecuteTextAttribute( _rReq );
3845 }
3846 
3847 
3848 void FmXFormShell::GetTextAttributeState_Lock(SfxItemSet& _rSet)
3849 {
3851  m_pTextShell->GetTextAttributeState( _rSet );
3852 }
3853 
3854 
3855 bool FmXFormShell::IsActiveControl_Lock(bool _bCountRichTextOnly ) const
3856 {
3858  return m_pTextShell->IsActiveControl( _bCountRichTextOnly );
3859 }
3860 
3861 
3862 void FmXFormShell::ForgetActiveControl_Lock()
3863 {
3865  m_pTextShell->ForgetActiveControl();
3866 }
3867 
3868 
3869 void FmXFormShell::SetControlActivationHandler_Lock(const Link<LinkParamNone*,void>& _rHdl)
3870 {
3872  m_pTextShell->SetControlActivationHandler( _rHdl );
3873 }
3874 
3875 void FmXFormShell::handleShowPropertiesRequest_Lock()
3876 {
3877  if (onlyControlsAreMarked_Lock())
3878  ShowSelectionProperties_Lock( true );
3879 }
3880 
3881 
3882 void FmXFormShell::handleMouseButtonDown_Lock(const SdrViewEvent& _rViewEvent)
3883 {
3884  // catch simple double clicks
3885  if ( ( _rViewEvent.nMouseClicks == 2 ) && ( _rViewEvent.nMouseCode == MOUSE_LEFT ) )
3886  {
3887  if ( _rViewEvent.eHit == SdrHitKind::MarkedObject )
3888  {
3889  if (onlyControlsAreMarked_Lock())
3890  ShowSelectionProperties_Lock( true );
3891  }
3892  }
3893 }
3894 
3895 
3896 bool FmXFormShell::HasControlFocus_Lock() const
3897 {
3898  bool bHasControlFocus = false;
3899 
3900  try
3901  {
3902  Reference<runtime::XFormController> xController(getActiveController_Lock());
3903  Reference< XControl > xCurrentControl;
3904  if ( xController.is() )
3905  xCurrentControl.set( xController->getCurrentControl() );
3906  if ( xCurrentControl.is() )
3907  {
3908  Reference< XWindow2 > xPeerWindow( xCurrentControl->getPeer(), UNO_QUERY_THROW );
3909  bHasControlFocus = xPeerWindow->hasFocus();
3910  }
3911  }
3912  catch( const Exception& )
3913  {
3914  DBG_UNHANDLED_EXCEPTION("svx");
3915  }
3916 
3917  return bHasControlFocus;
3918 }
3919 
3920 
3922  :IndexAccessIterator(xStartingPoint)
3923 {
3924 }
3925 
3926 
3928 {
3929  // if the thing has a ControlSource and a BoundField property
3930  Reference< XPropertySet> xProperties(xElement, UNO_QUERY);
3932  {
3933  // and the BoundField is valid
3934  Reference< XPropertySet> xField;
3935  xProperties->getPropertyValue(FM_PROP_BOUNDFIELD) >>= xField;
3936  if (xField.is())
3937  {
3938  // we take it
3939  m_sCurrentValue = ::comphelper::getString(xProperties->getPropertyValue(FM_PROP_CONTROLSOURCE));
3940  return true;
3941  }
3942  }
3943 
3944  // if it is a grid control
3945  if (::comphelper::hasProperty(FM_PROP_CLASSID, xProperties))
3946  {
3947  Any aClassId( xProperties->getPropertyValue(FM_PROP_CLASSID) );
3948  if (::comphelper::getINT16(aClassId) == FormComponentType::GRIDCONTROL)
3949  {
3950  m_sCurrentValue.clear();
3951  return true;
3952  }
3953  }
3954 
3955  return false;
3956 }
3957 
3958 
3960 {
3961  return true;
3962 }
3963 
3964 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void stopMarkListWatching()
Definition: fmvwimp.cxx:1723
OString stripEnd(const OString &rIn, char c)
#define FMARG_ADDCOL_COLUMNPOS
Definition: fmurl.hxx:49
::std::set< css::uno::Reference< css::uno::XInterface > > InterfaceBag
Definition: fmtools.hxx:171
Type
void saveMarkList()
Definition: fmvwimp.cxx:1751
#define FMURL_GRIDVIEW_ATTACHTOFORM
Definition: fmurl.hxx:46
sal_Int32 nIndex
SearchableControlIterator(css::uno::Reference< css::uno::XInterface > const &xStartingPoint)
Definition: fmshimp.cxx:3921
const OUString & getCurrentValue() const
Definition: fmshimp.hxx:547
virtual void set_sensitive(const OString &rIdent, bool bSensitive)=0
size_t GetMarkCount() const
Definition: svdmark.hxx:180
#define FM_PROP_LISTSOURCETYPE
Definition: fmprop.hxx:67
static comphelper::SolarMutex & GetSolarMutex()
easier access to a FormControllerHelper instance
osl::Mutex m_aMutex
#define FM_COMPONENT_GRIDCONTROL
Definition: fmservs.hxx:39
::cppu::WeakComponentImplHelper< css::beans::XPropertyChangeListener, css::container::XContainerListener, css::view::XSelectionChangeListener, css::form::XFormControllerListener > FmXFormShell_BD_BASE
Definition: fmshimp.hxx:120
#define FM_PROP_DISPLAYSYNCHRON
Definition: fmprop.hxx:113
bool isEnabled(sal_Int32 _nSlotId) const
const LanguageTag & GetUILanguageTag() const
sal_Int16 getControlTypeByObject(const Reference< css::lang::XServiceInfo > &_rxObject)
Definition: fmtools.cxx:297
sal_Int32 findValue(const css::uno::Sequence< T1 > &_rList, const T2 &_rValue)
#define FM_COMPONENT_COMMANDBUTTON
Definition: fmservs.hxx:36
#define FM_PROP_COMMAND
Definition: fmprop.hxx:117
void startMarkListWatching()
Definition: fmvwimp.cxx:1733
void execute(sal_Int32 _nSlotId) const
std::vector< css::uno::Reference< css::form::XForm > > FmFormArray
Definition: fmshimp.hxx:56
static SvxAbstractDialogFactory * Create()
Definition: svxdlg.cxx:23
#define FM_PROP_ISMODIFIED
Definition: fmprop.hxx:114
ConfigItemMode
static const AllSettings & GetSettings()
static VclPtr< vcl::Window > GetWindow(const css::uno::Reference< css::awt::XWindow > &rxWindow)
sal_uInt16 nMouseClicks
Definition: svdview.hxx:110
void onFirstViewActivation(const FmFormModel *_pDocModel)
Definition: fmvwimp.cxx:586
bool IsDesignMode() const
Definition: svdmrkv.hxx:236
#define FM_COL_NUMERICFIELD
Definition: gridcols.hxx:30
#define FM_COMPONENT_FORMATTEDFIELD
Definition: fmservs.hxx:47
bool getBOOL(const Any &_rAny)
#define FM_COMPONENT_RADIOBUTTON
Definition: fmservs.hxx:33
#define FM_PROP_LABEL
Definition: fmprop.hxx:40
css::uno::Reference< css::awt::XControlContainer > const & GetControlContainer(bool _bCreateIfNecessary=true) const
#define FM_PROP_ISNEW
Definition: fmprop.hxx:115
const sal_uInt16 OBJ_FM_NAVIGATIONBAR
Definition: fmglob.hxx:48
sal_Int32 getElementPos(const Reference< css::container::XIndexAccess > &xCont, const Reference< XInterface > &xElement)
Definition: fmtools.cxx:128
static ImplSVEvent * PostUserEvent(const Link< void *, void > &rLink, void *pCaller=nullptr, bool bReferenceLink=false)
const sal_Int16 nObjectTypes[]
Definition: fmshimp.cxx:229
#define FM_COMPONENT_PATTERNFIELD
Definition: fmservs.hxx:46
#define FM_COMPONENT_NUMERICFIELD
Definition: fmservs.hxx:44
SdrMark * GetMark(size_t nNum) const
Definition: svdmark.cxx:229
constexpr::Color COL_LIGHTRED(0xFF, 0x00, 0x00)
#define FM_COL_COMBOBOX
Definition: gridcols.hxx:26
static void saveFilter(const Reference< runtime::XFormController > &_rxController)
Definition: fmshimp.cxx:2946
const sal_uInt16 OBJ_FM_NUMERICFIELD
Definition: fmglob.hxx:40
void append(const OUString &rId, const OUString &rStr)
Reference< XNumberFormatsSupplier > getNumberFormats(const Reference< XConnection > &_rxConn, bool _bAlloweDefault, const Reference< XComponentContext > &_rxContext)
SVX_DLLPRIVATE void ChangeDesignMode(bool bDesign)
Definition: fmview.cxx:200
EmbeddedObjectRef * pObject
#define FM_PROP_STRINGITEMLIST
Definition: fmprop.hxx:59
TRISTATE_TRUE
#define FM_PROP_ALWAYSSHOWCURSOR
Definition: fmprop.hxx:112
bool IsReadOnlyUI() const
virtual SdrObjList * GetSubList() const
Definition: svdobj.cxx:647
bool isRowSetAlive(const Reference< XInterface > &_rxRowSet)
Definition: fmtools.cxx:371
IMPL_LINK_NOARG(FmXFormShell, OnInvalidateSlots_Lock, void *, void)
Definition: fmshimp.cxx:977
const css::lang::Locale & getLocale(bool bResolveSystem=true) const
#define FMURL_COMPONENT_FORMGRIDVIEW
Definition: fmurl.hxx:43
const OUStringLiteral aImgIds[]
Definition: fmshimp.cxx:205
#define FM_COMPONENT_TEXTFIELD
Definition: fmservs.hxx:30
void restoreMarkList(SdrMarkList &_rRestoredMarkList)
Definition: fmvwimp.cxx:1805
#define FM_COMPONENT_GROUPBOX
Definition: fmservs.hxx:34
NONE
void ToggleChildWindow(sal_uInt16)
static const char * aConvertSlots[]
Definition: fmshimp.cxx:181
sal_uInt16 nMouseCode
Definition: svdview.hxx:112
SdrPageWindow * GetPageWindow(sal_uInt32 nIndex) const
Definition: svdpagv.cxx:81
ESelection aNewSelection(GetSelection())
Reference< XController > xController
SuspendPropertyTracking(FmXFormShell &_rShell)
Definition: fmshimp.cxx:2695
static bool isControlList(const SdrMarkList &rMarkList)
Definition: fmshimp.cxx:541
bool IsMore() const
Definition: svditer.hxx:62
OUString SvxResId(const char *pId)
Definition: dialmgr.cxx:28
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
#define FM_COMPONENT_IMAGEBUTTON
Definition: fmservs.hxx:40
const sal_uInt16 OBJ_FM_IMAGEBUTTON
Definition: fmglob.hxx:36
void AddUndo(std::unique_ptr< SdrUndoAction > pUndo)
Definition: svdmodel.cxx:546
SfxFrame & GetFrame() const
int nCount
LoadFormsFlags
Definition: fmshimp.hxx:78
#define FM_PROP_CLASSID
Definition: fmprop.hxx:30
#define FMURL_GRIDVIEW_CLEARVIEW
Definition: fmurl.hxx:44
virtual bool ShouldStepInto(const css::uno::Reference< css::uno::XInterface > &xContainer) const override
Definition: fmshimp.cxx:3959
#define FM_PROP_BOUNDFIELD
Definition: fmprop.hxx:101
#define FM_PROP_APPLYFILTER
Definition: fmprop.hxx:123
const sal_uInt16 OBJ_FM_CONTROL
Definition: fmglob.hxx:25
static void DisposeElement(const css::uno::Reference< css::awt::XControlModel > &xReplaced)
Definition: fmundo.cxx:1209
#define FM_COL_FORMATTEDFIELD
Definition: gridcols.hxx:34
const sal_uInt16 OBJ_FM_PATTERNFIELD
Definition: fmglob.hxx:42
const sal_uInt16 OBJ_FM_EDIT
Definition: fmglob.hxx:27
FmFormPageImpl & GetImpl() const
Definition: fmpage.hxx:62
#define FM_PROP_URL
Definition: fmprop.hxx:127
sal_uInt32 release(bool bUnlockAll=false)
css::uno::Reference< css::lang::XComponent > xComponent
LoopGridsSync
Definition: fmshimp.hxx:61
sal_Int16 getINT16(const Any &_rAny)
#define FM_PROP_NAVIGATION
Definition: fmprop.hxx:41
#define SAL_N_ELEMENTS(arr)
static void RemoveUserEvent(ImplSVEvent *nUserEvent)
SdrObject * GetMarkedSdrObj() const
Definition: svdmark.hxx:68
#define FM_COMPONENT_COMBOBOX
Definition: fmservs.hxx:32
#define FM_COL_TIMEFIELD
Definition: gridcols.hxx:28
#define DBG_UNHANDLED_EXCEPTION(...)
#define FM_COL_PATTERNFIELD
Definition: gridcols.hxx:32
#define TOOLS_WARN_EXCEPTION(area, stream)
#define DBG_ASSERT(sCon, aError)
int i
const sal_uInt16 OBJ_FM_GROUPBOX
Definition: fmglob.hxx:34
bool IsUndoEnabled() const
returns true if undo is currently enabled This returns false if undo was disabled using EnableUndo( f...
Definition: svdmodel.cxx:577
FmFormPage * pPage
Definition: fmshimp.hxx:109
virtual int n_children() const =0
SfxBindings & GetBindings()
#define FM_COMPONENT_LISTBOX
Definition: fmservs.hxx:31
#define FM_COMPONENT_IMAGECONTROL
Definition: fmservs.hxx:50
Any aHelper
virtual bool ShouldHandleElement(const css::uno::Reference< css::uno::XInterface > &_rElement) override
Definition: fmshimp.cxx:517
TRISTATE_FALSE
virtual bool ShouldHandleElement(const css::uno::Reference< css::uno::XInterface > &rElement) override
Definition: fmshimp.cxx:3927
#define FM_PROP_LISTSOURCE
Definition: fmprop.hxx:68
#define FM_COMPONENT_FILECONTROL
Definition: fmservs.hxx:41
#define FM_PROP_REFVALUE
Definition: fmprop.hxx:76
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
const sal_uInt16 OBJ_FM_FILECONTROL
Definition: fmglob.hxx:37
const sal_uInt16 OBJ_FM_COMBOBOX
Definition: fmglob.hxx:32
#define DO_SAFE(statement)
Definition: fmshimp.hxx:59
void setHasBeenActivated()
Definition: fmpgeimp.hxx:82
bool IsGroupObject() const
Definition: svdobj.cxx:642
const sal_uInt16 DatabaseSlotMap[]
Definition: fmshimp.cxx:106
#define FM_PROP_FILTER
Definition: fmprop.hxx:47
bool HasName() const
#define FM_COL_LISTBOX
Definition: gridcols.hxx:33
#define FM_COL_TEXTFIELD
Definition: gridcols.hxx:25
#define FM_COL_CHECKBOX
Definition: gridcols.hxx:27
#define FM_PROP_ROWCOUNT
Definition: fmprop.hxx:32
Shell * m_pShell
LoadFormsFlags nFlags
Definition: fmshimp.hxx:111
void SetFormsCreationHdl(const Link< FmFormPageImpl &, void > &_rFormsCreationHdl)
Definition: fmpgeimp.hxx:86
#define FM_COMPONENT_CHECKBOX
Definition: fmservs.hxx:37
const sal_uInt16 OBJ_FM_CHECKBOX
Definition: fmglob.hxx:31
const sal_uInt16 OBJ_FM_SCROLLBAR
Definition: fmglob.hxx:46
const sal_uInt16 OBJ_FM_FIXEDTEXT
Definition: fmglob.hxx:29
Abstract DrawObject.
Definition: svdobj.hxx:312
#define FM_COL_DATEFIELD
Definition: gridcols.hxx:29
const sal_Int16 DlgSlotMap[]
Definition: fmshimp.cxx:134
Reference< XIntrospection > xIntrospection
#define FM_SUN_COMPONENT_SPINBUTTON
Definition: fmservs.hxx:75
const css::uno::Reference< css::frame::XFrame > & GetFrameInterface() const
const sal_uInt16 OBJ_FM_SPINBUTTON
Definition: fmglob.hxx:47
bool IsReadOnly() const
virtual SdrInventor GetObjInventor() const
Definition: svdobj.cxx:553
const sal_uInt16 OBJ_FM_GRID
Definition: fmglob.hxx:35
virtual VclPtr< AbstractFmSearchDialog > CreateFmSearchDialog(weld::Window *pParent, const OUString &strInitialText, const ::std::vector< OUString > &_rContexts, sal_Int16 nInitialContext, const Link< FmSearchContext &, sal_uInt32 > &lnkContextSupplier)=0
#define FM_COMPONENT_CURRENCYFIELD
Definition: fmservs.hxx:45
#define FM_PROP_HIDDEN
Definition: fmprop.hxx:106
void Activate(bool bSync=false)
Definition: fmvwimp.cxx:736
static Reference< XForm > GetForm(const Reference< XInterface > &_rxElement)
Definition: fmshimp.cxx:584
FmFormPage * GetCurPage()
shortcut to "GetSdrPageView() ? PTR_CAST( FmFormPage, GetSdrPageView() ) : NULL"
Definition: fmview.cxx:123
#define ENSURE_OR_THROW(c, m)
exports com.sun.star. form
SdrModel & getSdrModelFromSdrPage() const
Definition: svdpage.hxx:390
SdrObject * Next()
Definition: svditer.hxx:63
#define FM_COMPONENT_TIMEFIELD
Definition: fmservs.hxx:42
bool HasChildWindow(sal_uInt16)
const sal_Int16 SelObjectSlotMap[]
Definition: fmshimp.cxx:150
const sal_uInt16 OBJ_FM_RADIOBUTTON
Definition: fmglob.hxx:33
#define FM_PROP_CURSORCOLOR
Definition: fmprop.hxx:111
#define FMARG_ATTACHTO_MASTERFORM
Definition: fmurl.hxx:47
SVX_DLLPRIVATE FmXFormView * GetImpl() const
Definition: fmview.hxx:131
const sal_uInt16 OBJ_FM_FORMATTEDFIELD
Definition: fmglob.hxx:45
#define FM_COMPONENT_DATEFIELD
Definition: fmservs.hxx:43
FmXFormShell_Base_Disambiguation(::osl::Mutex &_rMutex)
Definition: fmshimp.cxx:597
#define FMARG_ADDCOL_COLUMNTYPE
Definition: fmurl.hxx:48
#define SAL_WARN_IF(condition, area, stream)
#define FM_COL_CURRENCYFIELD
Definition: gridcols.hxx:31
unsigned char sal_uInt8
void setHasBeenActivated()
Definition: fmvwimp.hxx:212
#define FM_PROP_ACTIVE_CONNECTION
Definition: fmprop.hxx:128
OOO_DLLPUBLIC_DBTOOLS bool isEmbeddedInDatabase(const css::uno::Reference< css::uno::XInterface > &_rxComponent, css::uno::Reference< css::sdbc::XConnection > &_rxActualConnection)
OUString aName
bool KnowsChildWindow(sal_uInt16)
#define FM_SUN_COMPONENT_NAVIGATIONBAR
Definition: fmservs.hxx:76
bool IsSearchableControl(const css::uno::Reference< css::uno::XInterface > &_rxControl, OUString *_pCurrentText)
Definition: fmshimp.cxx:466
bool hasEverBeenActivated() const
Definition: fmvwimp.hxx:211
IMPL_LINK(FmXFormShell, OnFoundData_Lock, FmFoundRecordInformation &, rfriWhere, void)
Definition: fmshimp.cxx:2159
Reference< XComponentContext > getProcessComponentContext()
const sal_uInt16 OBJ_FM_LISTBOX
Definition: fmglob.hxx:30
#define FM_COMPONENT_HIDDENCONTROL
Definition: fmservs.hxx:49
Reference< XConnection > getConnection(const Reference< XRowSet > &_rxRowSet)
const sal_uInt16 OBJ_FM_IMAGECONTROL
Definition: fmglob.hxx:44
bool hasProperty(const OUString &_rName, const Reference< XPropertySet > &_rxSet)
char const sFrameName[]
virtual bool tryToAcquire()
void setCurForm(const css::uno::Reference< css::form::XForm > &xForm)
Definition: fmpgeimp.cxx:351
OUString getLabelName(const Reference< css::beans::XPropertySet > &xControlModel)
Definition: fmtools.cxx:162
void InvalidateShell(const SfxShell &rSh, bool bDeep=false)
#define SAL_WARN(area, stream)
ImplSVEvent * nEventId
Definition: fmshimp.hxx:110
class FmSearchEngine - Impl class for FmSearchDialog
PFormViewPageWindowAdapter findWindow(const css::uno::Reference< css::awt::XControlContainer > &_rxCC) const
Definition: fmvwimp.cxx:516
#define FM_PROP_CONTROLSOURCE
Definition: fmprop.hxx:43
#define FM_PROP_DEFAULTCONTROL
Definition: fmprop.hxx:53
#define DBG_TESTSOLARMUTEX()
A SdrPage contains exactly one SdrObjList and a description of the physical page dimensions (size / m...
Definition: svdpage.hxx:365
#define FM_PROP_BOUNDCOLUMN
Definition: fmprop.hxx:90
const css::uno::Reference< css::form::XForms > & GetForms(bool _bForceCreate=true) const
Definition: fmpage.cxx:84
#define FM_SUN_COMPONENT_SCROLLBAR
Definition: fmservs.hxx:74
#define FMURL_GRIDVIEW_ADDCOLUMN
Definition: fmurl.hxx:45
OUString getString(const Any &_rAny)
static css::uno::Reference< css::awt::XWindow > GetInterface(vcl::Window *pWindow)
#define FM_PROP_CONTROLLABEL
Definition: fmprop.hxx:110
sal_Int16 nContext
Definition: fmsearch.hxx:54
const sal_uInt16 OBJ_FM_HIDDEN
Definition: fmglob.hxx:43
bool hasEverBeenActivated() const
Definition: fmpgeimp.hxx:81
void TransferFormComponentProperties(const Reference< XPropertySet > &xOldProps, const Reference< XPropertySet > &xNewProps, const Locale &_rLocale)
SdrModel * GetModel() const
Definition: svdpntv.hxx:271
SdrHitKind eHit
Definition: svdview.hxx:107
const sal_uInt16 OBJ_FM_BUTTON
Definition: fmglob.hxx:28
#define FM_COMPONENT_FIXEDTEXT
Definition: fmservs.hxx:35
static weld::MessageDialog * CreateMessageDialog(weld::Widget *pParent, VclMessageType eMessageType, VclButtonsType eButtonType, const OUString &rPrimaryMessage, bool bMobile=false)
virtual bool ShouldStepInto(const css::uno::Reference< css::uno::XInterface > &_rContainer) const override
Definition: fmshimp.cxx:507
const sal_uInt16 OBJ_FM_TIMEFIELD
Definition: fmglob.hxx:39
const sal_uInt16 OBJ_FM_CURRENCYFIELD
Definition: fmglob.hxx:41
const sal_uInt16 OBJ_FM_DATEFIELD
Definition: fmglob.hxx:38
sal_uInt16 nPos
void Deactivate(bool bDeactivateController=true)
Definition: fmvwimp.cxx:753
bool any2bool(const css::uno::Any &rAny)
SfxObjectShell * GetObjectShell() const
Definition: fmmodel.hxx:58
LoopGridsFlags
Definition: fmshimp.hxx:66
void getState(sal_Int32 _nSlotId, css::form::runtime::FeatureState &_out_rState) const
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo
css::uno::Any SAL_CALL makeAny(const SharedUNOComponent< INTERFACE, COMPONENT > &value)