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