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