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