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