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