LibreOffice Module svx (master)  1
filtnav.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 <memory>
21 #include <filtnav.hxx>
22 #include <fmexch.hxx>
23 #include <helpids.h>
24 #include <fmprop.hxx>
25 #include <svx/strings.hrc>
26 
27 #include <com/sun/star/awt/XControlModel.hpp>
28 #include <com/sun/star/awt/XControl.hpp>
29 #include <com/sun/star/form/runtime/XFormController.hpp>
30 #include <com/sun/star/lang/XUnoTunnel.hpp>
31 #include <com/sun/star/util/NumberFormatter.hpp>
32 #include <com/sun/star/beans/XFastPropertySet.hpp>
33 #include <com/sun/star/sdb/SQLContext.hpp>
34 
36 #include <comphelper/string.hxx>
37 #include <connectivity/dbtools.hxx>
38 #include <connectivity/sqlnode.hxx>
39 #include <cppuhelper/implbase.hxx>
41 #include <fmservs.hxx>
42 #include <fmshimp.hxx>
43 #include <sfx2/dispatch.hxx>
44 #include <sfx2/objitem.hxx>
45 #include <sfx2/objsh.hxx>
46 #include <sfx2/request.hxx>
47 #include <svx/dialmgr.hxx>
48 #include <svx/fmshell.hxx>
49 #include <svx/fmtools.hxx>
50 #include <svx/svxids.hrc>
51 #include <vcl/settings.hxx>
52 #include <tools/diagnose_ex.h>
53 #include <vcl/commandevent.hxx>
54 #include <vcl/event.hxx>
55 #include <vcl/svlbitm.hxx>
56 #include <vcl/treelistentry.hxx>
57 #include <vcl/viewdataentry.hxx>
58 #include <vcl/svapp.hxx>
59 
60 #include <bitmaps.hlst>
61 
62 #include <functional>
63 
64 #define DROP_ACTION_TIMER_INITIAL_TICKS 10
65  // it takes this long for the scrolling to begin
66 #define DROP_ACTION_TIMER_SCROLL_TICKS 3
67  // a line is scrolled in these intervals
68 #define DROP_ACTION_TIMER_TICK_BASE 10
69  // this is the basis for multiplying both figures (in ms)
70 
71 using namespace ::svxform;
72 using namespace ::connectivity;
73 using namespace ::dbtools;
74 
75 
76 namespace svxform
77 {
78 
79 
80  using ::com::sun::star::uno::Reference;
81  using ::com::sun::star::container::XIndexAccess;
82  using ::com::sun::star::uno::UNO_QUERY;
84  using ::com::sun::star::form::runtime::XFormController;
85  using ::com::sun::star::form::runtime::XFilterController;
86  using ::com::sun::star::form::runtime::XFilterControllerListener;
87  using ::com::sun::star::form::runtime::FilterEvent;
88  using ::com::sun::star::lang::EventObject;
89  using ::com::sun::star::uno::RuntimeException;
90  using ::com::sun::star::form::XForm;
91  using ::com::sun::star::container::XChild;
92  using ::com::sun::star::awt::XControl;
93  using ::com::sun::star::sdbc::XConnection;
94  using ::com::sun::star::util::XNumberFormatsSupplier;
95  using ::com::sun::star::util::XNumberFormatter;
96  using ::com::sun::star::util::NumberFormatter;
97  using ::com::sun::star::sdbc::XRowSet;
98  using ::com::sun::star::lang::Locale;
99  using ::com::sun::star::sdb::SQLContext;
100  using ::com::sun::star::uno::XInterface;
101  using ::com::sun::star::uno::UNO_QUERY_THROW;
102  using ::com::sun::star::uno::UNO_SET_THROW;
103  using ::com::sun::star::uno::Exception;
104  using ::com::sun::star::uno::Sequence;
105 
106 
108  : m_pFormItem(nullptr)
109 {
110 }
111 
113 {
115 }
116 
117 
119 {
120  static SotClipboardFormatId s_nFormat =
121  SotExchange::RegisterFormatName("application/x-openoffice;windows_formatname=\"form.FilterControlExchange\"");
122  DBG_ASSERT(static_cast<SotClipboardFormatId>(-1) != s_nFormat, "OFilterExchangeHelper::getFormatId: bad exchange id!");
123  return s_nFormat;
124 }
125 
126 
128 {
129  return new OFilterItemExchange;
130 }
131 
132 
134 {
135  return Image();
136 }
137 
139 {
140 }
141 
143 {
144  return Image(StockImage::Yes, RID_SVXBMP_FORM);
145 }
146 
147 FmFilterItem* FmFilterItems::Find( const ::sal_Int32 _nFilterComponentIndex ) const
148 {
149  for ( auto & pData : m_aChildren )
150  {
151  FmFilterItem& rCondition = dynamic_cast<FmFilterItem&>(*pData);
152  if ( _nFilterComponentIndex == rCondition.GetComponentIndex() )
153  return &rCondition;
154  }
155  return nullptr;
156 }
157 
159 {
160  return Image(StockImage::Yes, RID_SVXBMP_FILTER);
161 }
162 
164  const OUString& aFieldName,
165  const OUString& aText,
166  const sal_Int32 _nComponentIndex )
167  :FmFilterData(pParent, aText)
168  ,m_aFieldName(aFieldName)
169  ,m_nComponentIndex( _nComponentIndex )
170 {
171 }
172 
174 {
175  return Image(StockImage::Yes, RID_SVXBMP_FIELD);
176 }
177 
178 // Hints for communication between model and view
179 
180 namespace {
181 
182 class FmFilterHint : public SfxHint
183 {
184  FmFilterData* const m_pData;
185 
186 public:
187  explicit FmFilterHint(FmFilterData* pData):m_pData(pData){}
188  FmFilterData* GetData() const { return m_pData; }
189 };
190 
191 class FmFilterInsertedHint : public FmFilterHint
192 {
193  size_t const m_nPos; // Position relative to the parent of the data
194 
195 public:
196  FmFilterInsertedHint(FmFilterData* pData, size_t nRelPos)
197  :FmFilterHint(pData)
198  ,m_nPos(nRelPos){}
199 
200  size_t GetPos() const { return m_nPos; }
201 };
202 
203 class FmFilterRemovedHint : public FmFilterHint
204 {
205 public:
206  explicit FmFilterRemovedHint(FmFilterData* pData)
207  :FmFilterHint(pData){}
208 };
209 
210 
211 class FmFilterTextChangedHint : public FmFilterHint
212 {
213 public:
214  explicit FmFilterTextChangedHint(FmFilterData* pData)
215  :FmFilterHint(pData){}
216 };
217 
218 class FilterClearingHint : public SfxHint
219 {
220 public:
221  FilterClearingHint(){}
222 };
223 
224 class FmFilterCurrentChangedHint : public SfxHint
225 {
226 public:
227  FmFilterCurrentChangedHint(){}
228 };
229 
230 }
231 
232 // class FmFilterAdapter, listener at the FilterControls
233 class FmFilterAdapter : public ::cppu::WeakImplHelper< XFilterControllerListener >
234 {
236  Reference< XIndexAccess > m_xControllers;
237 
238 public:
239  FmFilterAdapter(FmFilterModel* pModel, const Reference< XIndexAccess >& xControllers);
240 
241 // XEventListener
242  virtual void SAL_CALL disposing(const EventObject& Source) override;
243 
244 // XFilterControllerListener
245  virtual void SAL_CALL predicateExpressionChanged( const FilterEvent& Event ) override;
246  virtual void SAL_CALL disjunctiveTermRemoved( const FilterEvent& Event ) override;
247  virtual void SAL_CALL disjunctiveTermAdded( const FilterEvent& Event ) override;
248 
249 // helpers
251  void dispose();
252 
253  void AddOrRemoveListener( const Reference< XIndexAccess >& _rxControllers, const bool _bAdd );
254 
255  static void setText(sal_Int32 nPos,
256  const FmFilterItem* pFilterItem,
257  const OUString& rText);
258 };
259 
260 
261 FmFilterAdapter::FmFilterAdapter(FmFilterModel* pModel, const Reference< XIndexAccess >& xControllers)
262  :m_pModel( pModel )
263  ,m_xControllers( xControllers )
264 {
266 }
267 
268 
270 {
272 }
273 
274 
275 void FmFilterAdapter::AddOrRemoveListener( const Reference< XIndexAccess >& _rxControllers, const bool _bAdd )
276 {
277  for (sal_Int32 i = 0, nLen = _rxControllers->getCount(); i < nLen; ++i)
278  {
279  Reference< XIndexAccess > xElement( _rxControllers->getByIndex(i), UNO_QUERY );
280 
281  // step down
282  AddOrRemoveListener( xElement, _bAdd );
283 
284  // handle this particular controller
285  Reference< XFilterController > xController( xElement, UNO_QUERY );
286  OSL_ENSURE( xController.is(), "FmFilterAdapter::InsertElements: no XFilterController, cannot sync data!" );
287  if ( xController.is() )
288  {
289  if ( _bAdd )
290  xController->addFilterControllerListener( this );
291  else
292  xController->removeFilterControllerListener( this );
293  }
294  }
295 }
296 
297 
298 void FmFilterAdapter::setText(sal_Int32 nRowPos,
299  const FmFilterItem* pFilterItem,
300  const OUString& rText)
301 {
302  FmFormItem* pFormItem = dynamic_cast<FmFormItem*>( pFilterItem->GetParent()->GetParent() );
303  assert(pFormItem);
304  try
305  {
306  Reference< XFilterController > xController( pFormItem->GetController(), UNO_QUERY_THROW );
307  xController->setPredicateExpression( pFilterItem->GetComponentIndex(), nRowPos, rText );
308  }
309  catch( const Exception& )
310  {
312  }
313 }
314 
315 
316 // XEventListener
317 
318 void SAL_CALL FmFilterAdapter::disposing(const EventObject& /*e*/)
319 {
320 }
321 
322 
323 namespace
324 {
325  OUString lcl_getLabelName_nothrow( const Reference< XControl >& _rxControl )
326  {
327  OUString sLabelName;
328  try
329  {
330  Reference< XPropertySet > xModel( _rxControl->getModel(), UNO_QUERY_THROW );
331  sLabelName = getLabelName( xModel );
332  }
333  catch( const Exception& )
334  {
336  }
337  return sLabelName;
338  }
339 
340  Reference< XPropertySet > lcl_getBoundField_nothrow( const Reference< XControl >& _rxControl )
341  {
342  Reference< XPropertySet > xField;
343  try
344  {
345  Reference< XPropertySet > xModelProps( _rxControl->getModel(), UNO_QUERY_THROW );
346  xField.set( xModelProps->getPropertyValue( FM_PROP_BOUNDFIELD ), UNO_QUERY_THROW );
347  }
348  catch( const Exception& )
349  {
351  }
352  return xField;
353  }
354 }
355 
356 // XFilterControllerListener
357 
358 void FmFilterAdapter::predicateExpressionChanged( const FilterEvent& Event )
359 {
360  SolarMutexGuard aGuard;
361 
362  if ( !m_pModel )
363  return;
364 
365  // the controller which sent the event
366  Reference< XFormController > xController( Event.Source, UNO_QUERY_THROW );
367  Reference< XFilterController > xFilterController( Event.Source, UNO_QUERY_THROW );
368  Reference< XForm > xForm( xController->getModel(), UNO_QUERY_THROW );
369 
370  FmFormItem* pFormItem = m_pModel->Find( m_pModel->m_aChildren, xForm );
371  OSL_ENSURE( pFormItem, "FmFilterAdapter::predicateExpressionChanged: don't know this form!" );
372  if ( !pFormItem )
373  return;
374 
375  const sal_Int32 nActiveTerm( xFilterController->getActiveTerm() );
376 
377  FmFilterData* pData = pFormItem->GetChildren()[nActiveTerm].get();
378  FmFilterItems& rFilter = dynamic_cast<FmFilterItems&>(*pData);
379  FmFilterItem* pFilterItem = rFilter.Find( Event.FilterComponent );
380  if ( pFilterItem )
381  {
382  if ( !Event.PredicateExpression.isEmpty())
383  {
384  pFilterItem->SetText( Event.PredicateExpression );
385  // notify the UI
386  FmFilterTextChangedHint aChangeHint(pFilterItem);
387  m_pModel->Broadcast( aChangeHint );
388  }
389  else
390  {
391  // no text anymore so remove the condition
392  m_pModel->Remove(pFilterItem);
393  }
394  }
395  else
396  {
397  // searching the component by field name
398  OUString aFieldName( lcl_getLabelName_nothrow( xFilterController->getFilterComponent( Event.FilterComponent ) ) );
399 
400  std::unique_ptr<FmFilterItem> pNewFilterItem(new FmFilterItem(&rFilter, aFieldName, Event.PredicateExpression, Event.FilterComponent));
401  m_pModel->Insert(rFilter.GetChildren().end(), std::move(pNewFilterItem));
402  }
403 
404  // ensure there's one empty term in the filter, just in case the active term was previously empty
405  m_pModel->EnsureEmptyFilterRows( *pFormItem );
406 }
407 
408 
409 void SAL_CALL FmFilterAdapter::disjunctiveTermRemoved( const FilterEvent& Event )
410 {
411  SolarMutexGuard aGuard;
412 
413  Reference< XFormController > xController( Event.Source, UNO_QUERY_THROW );
414  Reference< XFilterController > xFilterController( Event.Source, UNO_QUERY_THROW );
415  Reference< XForm > xForm( xController->getModel(), UNO_QUERY_THROW );
416 
417  FmFormItem* pFormItem = m_pModel->Find( m_pModel->m_aChildren, xForm );
418  OSL_ENSURE( pFormItem, "FmFilterAdapter::disjunctiveTermRemoved: don't know this form!" );
419  if ( !pFormItem )
420  return;
421 
422  auto& rTermItems = pFormItem->GetChildren();
423  const bool bValidIndex = ( Event.DisjunctiveTerm >= 0 ) && ( static_cast<size_t>(Event.DisjunctiveTerm) < rTermItems.size() );
424  OSL_ENSURE( bValidIndex, "FmFilterAdapter::disjunctiveTermRemoved: invalid term index!" );
425  if ( !bValidIndex )
426  return;
427 
428  // if the first term was removed, then the to-be first term needs its text updated
429  if ( Event.DisjunctiveTerm == 0 )
430  {
431  rTermItems[1]->SetText( SvxResId(RID_STR_FILTER_FILTER_FOR));
432  FmFilterTextChangedHint aChangeHint( rTermItems[1].get() );
433  m_pModel->Broadcast( aChangeHint );
434  }
435 
436  // finally remove the entry from the model
437  m_pModel->Remove( rTermItems.begin() + Event.DisjunctiveTerm );
438 
439  // ensure there's one empty term in the filter, just in case the currently removed one was the last empty one
440  m_pModel->EnsureEmptyFilterRows( *pFormItem );
441 }
442 
443 
444 void SAL_CALL FmFilterAdapter::disjunctiveTermAdded( const FilterEvent& Event )
445 {
446  SolarMutexGuard aGuard;
447 
448  Reference< XFormController > xController( Event.Source, UNO_QUERY_THROW );
449  Reference< XFilterController > xFilterController( Event.Source, UNO_QUERY_THROW );
450  Reference< XForm > xForm( xController->getModel(), UNO_QUERY_THROW );
451 
452  FmFormItem* pFormItem = m_pModel->Find( m_pModel->m_aChildren, xForm );
453  OSL_ENSURE( pFormItem, "FmFilterAdapter::disjunctiveTermAdded: don't know this form!" );
454  if ( !pFormItem )
455  return;
456 
457  const sal_Int32 nInsertPos = Event.DisjunctiveTerm;
458  bool bValidIndex = ( nInsertPos >= 0 ) && ( static_cast<size_t>(nInsertPos) <= pFormItem->GetChildren().size() );
459  if ( !bValidIndex )
460  {
461  OSL_FAIL( "FmFilterAdapter::disjunctiveTermAdded: invalid index!" );
462  return;
463  }
464 
465  auto insertPos = pFormItem->GetChildren().begin() + nInsertPos;
466 
467  // "Filter for" for first position, "Or" for the other positions
468  std::unique_ptr<FmFilterItems> pFilterItems(new FmFilterItems(pFormItem, (nInsertPos?SvxResId(RID_STR_FILTER_FILTER_OR):SvxResId(RID_STR_FILTER_FILTER_FOR))));
469  m_pModel->Insert( insertPos, std::move(pFilterItems) );
470 }
471 
472 
474  :FmParentData(nullptr, OUString())
476  ,m_pCurrentItems(nullptr)
477 {
478 }
479 
480 
482 {
483  Clear();
484 }
485 
486 
488 {
489  // notify
490  FilterClearingHint aClearedHint;
491  Broadcast( aClearedHint );
492 
493  // lose endings
494  if (m_pAdapter.is())
495  {
496  m_pAdapter->dispose();
497  m_pAdapter.clear();
498  }
499 
500  m_pCurrentItems = nullptr;
501  m_xController = nullptr;
502  m_xControllers = nullptr;
503 
504  m_aChildren.clear();
505 }
506 
507 
508 void FmFilterModel::Update(const Reference< XIndexAccess > & xControllers, const Reference< XFormController > & xCurrent)
509 {
510  if ( xCurrent == m_xController )
511  return;
512 
513  if (!xControllers.is())
514  {
515  Clear();
516  return;
517  }
518 
519  // there is only a new current controller
520  if ( m_xControllers != xControllers )
521  {
522  Clear();
523 
524  m_xControllers = xControllers;
525  Update(m_xControllers, this);
526 
527  DBG_ASSERT(xCurrent.is(), "FmFilterModel::Update(...) no current controller");
528 
529  // Listening for TextChanges
530  m_pAdapter = new FmFilterAdapter(this, xControllers);
531 
532  SetCurrentController(xCurrent);
533  EnsureEmptyFilterRows( *this );
534  }
535  else
536  SetCurrentController(xCurrent);
537 }
538 
539 
540 void FmFilterModel::Update(const Reference< XIndexAccess > & xControllers, FmParentData* pParent)
541 {
542  try
543  {
544  sal_Int32 nCount = xControllers->getCount();
545  for ( sal_Int32 i = 0; i < nCount; ++i )
546  {
547  Reference< XFormController > xController( xControllers->getByIndex(i), UNO_QUERY_THROW );
548 
549  Reference< XPropertySet > xFormProperties( xController->getModel(), UNO_QUERY_THROW );
550  OUString aName;
551  OSL_VERIFY( xFormProperties->getPropertyValue( FM_PROP_NAME ) >>= aName );
552 
553  // Insert a new item for the form
554  FmFormItem* pFormItem = new FmFormItem( pParent, xController, aName );
555  Insert( pParent->GetChildren().end(), std::unique_ptr<FmFilterData>(pFormItem) );
556 
557  Reference< XFilterController > xFilterController( pFormItem->GetFilterController(), UNO_SET_THROW );
558 
559  // insert the existing filters for the form
560  OUString aTitle(SvxResId(RID_STR_FILTER_FILTER_FOR));
561 
562  const Sequence< Sequence< OUString > > aExpressions = xFilterController->getPredicateExpressions();
563  for ( auto const & conjunctionTerm : aExpressions )
564  {
565  // we always display one row, even if there's no term to be displayed
566  FmFilterItems* pFilterItems = new FmFilterItems( pFormItem, aTitle );
567  Insert( pFormItem->GetChildren().end(), std::unique_ptr<FmFilterData>(pFilterItems) );
568 
569  const Sequence< OUString >& rDisjunction( conjunctionTerm );
570  sal_Int32 nComponentIndex = -1;
571  for ( const OUString& rDisjunctiveTerm : rDisjunction )
572  {
573  ++nComponentIndex;
574 
575  if ( rDisjunctiveTerm.isEmpty() )
576  // no condition for this particular component in this particular conjunction term
577  continue;
578 
579  // determine the display name of the control
580  const Reference< XControl > xFilterControl( xFilterController->getFilterComponent( nComponentIndex ) );
581  const OUString sDisplayName( lcl_getLabelName_nothrow( xFilterControl ) );
582 
583  // insert a new entry
584  std::unique_ptr<FmFilterItem> pANDCondition(new FmFilterItem( pFilterItems, sDisplayName, rDisjunctiveTerm, nComponentIndex ));
585  Insert( pFilterItems->GetChildren().end(), std::move(pANDCondition) );
586  }
587 
588  // title for the next conditions
589  aTitle = SvxResId( RID_STR_FILTER_FILTER_OR );
590  }
591 
592  // now add dependent controllers
593  Update( xController, pFormItem );
594  }
595  }
596  catch( const Exception& )
597  {
599  }
600 }
601 
602 
603 FmFormItem* FmFilterModel::Find(const ::std::vector<std::unique_ptr<FmFilterData>>& rItems, const Reference< XFormController > & xController) const
604 {
605  for (const auto& rItem : rItems)
606  {
607  FmFormItem* pForm = dynamic_cast<FmFormItem*>( rItem.get() );
608  if (pForm)
609  {
610  if ( xController == pForm->GetController() )
611  return pForm;
612  else
613  {
614  pForm = Find(pForm->GetChildren(), xController);
615  if (pForm)
616  return pForm;
617  }
618  }
619  }
620  return nullptr;
621 }
622 
623 
624 FmFormItem* FmFilterModel::Find(const ::std::vector<std::unique_ptr<FmFilterData>>& rItems, const Reference< XForm >& xForm) const
625 {
626  for (const auto& rItem : rItems)
627  {
628  FmFormItem* pForm = dynamic_cast<FmFormItem*>( rItem.get() );
629  if (pForm)
630  {
631  if (xForm == pForm->GetController()->getModel())
632  return pForm;
633  else
634  {
635  pForm = Find(pForm->GetChildren(), xForm);
636  if (pForm)
637  return pForm;
638  }
639  }
640  }
641  return nullptr;
642 }
643 
644 
645 void FmFilterModel::SetCurrentController(const Reference< XFormController > & xCurrent)
646 {
647  if ( xCurrent == m_xController )
648  return;
649 
650  m_xController = xCurrent;
651 
652  FmFormItem* pItem = Find( m_aChildren, xCurrent );
653  if ( !pItem )
654  return;
655 
656  try
657  {
658  Reference< XFilterController > xFilterController( m_xController, UNO_QUERY_THROW );
659  const sal_Int32 nActiveTerm( xFilterController->getActiveTerm() );
660  if ( pItem->GetChildren().size() > static_cast<size_t>(nActiveTerm) )
661  {
662  SetCurrentItems( static_cast< FmFilterItems* >( pItem->GetChildren()[ nActiveTerm ].get() ) );
663  }
664  }
665  catch( const Exception& )
666  {
668  }
669 }
670 
671 
673 {
674  // insert the condition behind the last filter items
675  auto iter = std::find_if(_rFormItem.GetChildren().rbegin(), _rFormItem.GetChildren().rend(),
676  [](const std::unique_ptr<FmFilterData>& rChild) { return dynamic_cast<const FmFilterItems*>(rChild.get()) != nullptr; });
677 
678  sal_Int32 nInsertPos = iter.base() - _rFormItem.GetChildren().begin();
679  // delegate this to the FilterController, it will notify us, which will let us update our model
680  try
681  {
682  Reference< XFilterController > xFilterController( _rFormItem.GetFilterController(), UNO_SET_THROW );
683  if ( nInsertPos >= xFilterController->getDisjunctiveTerms() )
684  xFilterController->appendEmptyDisjunctiveTerm();
685  }
686  catch( const Exception& )
687  {
689  }
690 }
691 
692 void FmFilterModel::Insert(const ::std::vector<std::unique_ptr<FmFilterData>>::iterator& rPos, std::unique_ptr<FmFilterData> pData)
693 {
694  auto pTemp = pData.get();
695  size_t nPos;
696  ::std::vector<std::unique_ptr<FmFilterData>>& rItems = pData->GetParent()->GetChildren();
697  if (rPos == rItems.end())
698  {
699  nPos = rItems.size();
700  rItems.push_back(std::move(pData));
701  }
702  else
703  {
704  nPos = rPos - rItems.begin();
705  rItems.insert(rPos, std::move(pData));
706  }
707 
708  // notify the UI
709  FmFilterInsertedHint aInsertedHint(pTemp, nPos);
710  Broadcast( aInsertedHint );
711 }
712 
714 {
715  FmParentData* pParent = pData->GetParent();
716  ::std::vector<std::unique_ptr<FmFilterData>>& rItems = pParent->GetChildren();
717 
718  // erase the item from the model
719  auto i = ::std::find_if(rItems.begin(), rItems.end(),
720  [&](const std::unique_ptr<FmFilterData>& p) { return p.get() == pData; } );
721  DBG_ASSERT(i != rItems.end(), "FmFilterModel::Remove(): unknown Item");
722  // position within the parent
723  sal_Int32 nPos = i - rItems.begin();
724  if (dynamic_cast<const FmFilterItems*>( pData) != nullptr)
725  {
726  FmFormItem* pFormItem = static_cast<FmFormItem*>(pParent);
727 
728  try
729  {
730  Reference< XFilterController > xFilterController( pFormItem->GetFilterController(), UNO_SET_THROW );
731 
732  bool bEmptyLastTerm = ( ( nPos == 0 ) && xFilterController->getDisjunctiveTerms() == 1 );
733  if ( bEmptyLastTerm )
734  {
735  // remove all children (by setting an empty predicate expression)
736  ::std::vector< std::unique_ptr<FmFilterData> >& rChildren = static_cast<FmFilterItems*>(pData)->GetChildren();
737  while ( !rChildren.empty() )
738  {
739  auto removePos = rChildren.end() - 1;
740  if (FmFilterItem* pFilterItem = dynamic_cast<FmFilterItem*>( removePos->get() ))
741  {
742  FmFilterAdapter::setText( nPos, pFilterItem, OUString() );
743  }
744  Remove( removePos );
745  }
746  }
747  else
748  {
749  xFilterController->removeDisjunctiveTerm( nPos );
750  }
751  }
752  catch( const Exception& )
753  {
755  }
756  }
757  else // FormItems can not be deleted
758  {
759  FmFilterItem& rFilterItem = dynamic_cast<FmFilterItem&>(*pData);
760 
761  // if it's the last condition remove the parent
762  if (rItems.size() == 1)
763  Remove(rFilterItem.GetParent());
764  else
765  {
766  // find the position of the father within his father
767  ::std::vector<std::unique_ptr<FmFilterData>>& rParentParentItems = pData->GetParent()->GetParent()->GetChildren();
768  auto j = ::std::find_if(rParentParentItems.begin(), rParentParentItems.end(),
769  [&](const std::unique_ptr<FmFilterData>& p) { return p.get() == rFilterItem.GetParent(); });
770  DBG_ASSERT(j != rParentParentItems.end(), "FmFilterModel::Remove(): unknown Item");
771  sal_Int32 nParentPos = j - rParentParentItems.begin();
772 
773  // EmptyText removes the filter
774  FmFilterAdapter::setText(nParentPos, &rFilterItem, OUString());
775  Remove( i );
776  }
777  }
778 }
779 
780 void FmFilterModel::Remove( const ::std::vector<std::unique_ptr<FmFilterData>>::iterator& rPos )
781 {
782  // remove from parent's child list
783  std::unique_ptr<FmFilterData> pData = std::move(*rPos);
784  pData->GetParent()->GetChildren().erase( rPos );
785 
786  // notify the view, this will remove the actual SvTreeListEntry
787  FmFilterRemovedHint aRemoveHint( pData.get() );
788  Broadcast( aRemoveHint );
789 }
790 
791 
792 bool FmFilterModel::ValidateText(FmFilterItem const * pItem, OUString& rText, OUString& rErrorMsg) const
793 {
794  FmFormItem* pFormItem = dynamic_cast<FmFormItem*>( pItem->GetParent()->GetParent() );
795  assert(pFormItem);
796  try
797  {
798  Reference< XFormController > xFormController( pFormItem->GetController() );
799  // obtain the connection of the form belonging to the controller
800  Reference< XRowSet > xRowSet( xFormController->getModel(), UNO_QUERY_THROW );
801  Reference< XConnection > xConnection( getConnection( xRowSet ) );
802 
803  // obtain a number formatter for this connection
804  // TODO: shouldn't this be cached?
805  Reference< XNumberFormatsSupplier > xFormatSupplier = getNumberFormats( xConnection, true );
806  Reference< XNumberFormatter > xFormatter( NumberFormatter::create( comphelper::getProcessComponentContext() ), UNO_QUERY_THROW );
807  xFormatter->attachNumberFormatsSupplier( xFormatSupplier );
808 
809  // get the field (database column) which the item is responsible for
810  Reference< XFilterController > xFilterController( xFormController, UNO_QUERY_THROW );
811  Reference< XPropertySet > xField( lcl_getBoundField_nothrow( xFilterController->getFilterComponent( pItem->GetComponentIndex() ) ), UNO_SET_THROW );
812 
813  // parse the given text as filter predicate
814  OUString aErr, aTxt( rText );
815  std::unique_ptr< OSQLParseNode > pParseNode = predicateTree( aErr, aTxt, xFormatter, xField );
816  rErrorMsg = aErr;
817  rText = aTxt;
818  if ( pParseNode != nullptr )
819  {
820  OUString aPreparedText;
822  pParseNode->parseNodeToPredicateStr(
823  aPreparedText, xConnection, xFormatter, xField, OUString(), aAppLocale, OUString("."), getParseContext() );
824  rText = aPreparedText;
825  return true;
826  }
827  }
828  catch( const Exception& )
829  {
831  }
832 
833  return false;
834 }
835 
836 
837 void FmFilterModel::Append(FmFilterItems* pItems, std::unique_ptr<FmFilterItem> pFilterItem)
838 {
839  Insert(pItems->GetChildren().end(), std::move(pFilterItem));
840 }
841 
842 
843 void FmFilterModel::SetTextForItem(FmFilterItem* pItem, const OUString& rText)
844 {
845  ::std::vector<std::unique_ptr<FmFilterData>>& rItems = pItem->GetParent()->GetParent()->GetChildren();
846  auto i = ::std::find_if(rItems.begin(), rItems.end(),
847  [&](const std::unique_ptr<FmFilterData>& p) { return p.get() == pItem->GetParent(); });
848  sal_Int32 nParentPos = i - rItems.begin();
849 
850  FmFilterAdapter::setText(nParentPos, pItem, rText);
851 
852  if (rText.isEmpty())
853  Remove(pItem);
854  else
855  {
856  // Change the text
857  pItem->SetText(rText);
858  FmFilterTextChangedHint aChangeHint(pItem);
859  Broadcast( aChangeHint );
860  }
861 }
862 
863 
865 {
866  if (m_pCurrentItems == pCurrent)
867  return;
868 
869  // search for the condition
870  if (pCurrent)
871  {
872  FmFormItem* pFormItem = static_cast<FmFormItem*>(pCurrent->GetParent());
873  ::std::vector<std::unique_ptr<FmFilterData>>& rItems = pFormItem->GetChildren();
874  auto i = ::std::find_if(rItems.begin(), rItems.end(),
875  [&](const std::unique_ptr<FmFilterData>& p) { return p.get() == pCurrent; });
876 
877  if (i != rItems.end())
878  {
879  // determine the filter position
880  sal_Int32 nPos = i - rItems.begin();
881  try
882  {
883  Reference< XFilterController > xFilterController( pFormItem->GetFilterController(), UNO_SET_THROW );
884  xFilterController->setActiveTerm( nPos );
885  }
886  catch( const Exception& )
887  {
889  }
890 
891  if ( m_xController != pFormItem->GetController() )
892  // calls SetCurrentItems again
893  SetCurrentController( pFormItem->GetController() );
894  else
895  m_pCurrentItems = pCurrent;
896  }
897  else
898  m_pCurrentItems = nullptr;
899  }
900  else
901  m_pCurrentItems = nullptr;
902 
903 
904  // notify the UI
905  FmFilterCurrentChangedHint aHint;
906  Broadcast( aHint );
907 }
908 
909 
911 {
912  // checks whether for each form there's one free level for input
913  ::std::vector< std::unique_ptr<FmFilterData> >& rChildren = _rItem.GetChildren();
914  bool bAppendLevel = dynamic_cast<const FmFormItem*>(&_rItem) != nullptr;
915 
916  for ( const auto& rpChild : rChildren )
917  {
918  FmFilterItems* pItems = dynamic_cast<FmFilterItems*>( rpChild.get() );
919  if ( pItems && pItems->GetChildren().empty() )
920  {
921  bAppendLevel = false;
922  break;
923  }
924 
925  FmFormItem* pFormItem = dynamic_cast<FmFormItem*>( rpChild.get() );
926  if (pFormItem)
927  {
928  EnsureEmptyFilterRows( *pFormItem );
929  continue;
930  }
931  }
932 
933  if ( bAppendLevel )
934  {
935  FmFormItem* pFormItem = dynamic_cast<FmFormItem*>( &_rItem );
936  OSL_ENSURE( pFormItem, "FmFilterModel::EnsureEmptyFilterRows: no FmFormItem, but a FmFilterItems child?" );
937  if ( pFormItem )
938  AppendFilterItems( *pFormItem );
939  }
940 }
941 
942 namespace {
943 
944 class FmFilterItemsString : public SvLBoxString
945 {
946 public:
947  explicit FmFilterItemsString(const OUString& rStr)
948  : SvLBoxString(rStr)
949  {
950  }
951 
952  virtual void Paint(const Point& rPos, SvTreeListBox& rDev, vcl::RenderContext& rRenderContext,
953  const SvViewDataEntry* pView, const SvTreeListEntry& rEntry) override;
954  virtual void InitViewData( SvTreeListBox* pView,SvTreeListEntry* pEntry, SvViewDataItem* pViewData = nullptr) override;
955 };
956 
957 }
958 
959 const int nxDBmp = 12;
960 
961 void FmFilterItemsString::Paint(const Point& rPos, SvTreeListBox& rDev, vcl::RenderContext& rRenderContext,
962  const SvViewDataEntry* /*pView*/, const SvTreeListEntry& rEntry)
963 {
964  FmFilterItems* pRow = static_cast<FmFilterItems*>(rEntry.GetUserData());
965  FmFormItem* pForm = static_cast<FmFormItem*>(pRow->GetParent());
966 
967  // current filter is significant painted
968  const bool bIsCurrentFilter = pForm->GetChildren()[ pForm->GetFilterController()->getActiveTerm() ].get() == pRow;
969  if (bIsCurrentFilter)
970  {
971  rRenderContext.Push(PushFlags::LINECOLOR);
972  rRenderContext.SetLineColor(rRenderContext.GetTextColor());
973 
974  Size aSize(GetWidth(&rDev, &rEntry), GetHeight(&rDev, &rEntry));
975  tools::Rectangle aRect(rPos, aSize);
976  Point aFirst(rPos.X(), aRect.Bottom() - 6);
977  Point aSecond(aFirst .X() + 2, aFirst.Y() + 3);
978 
979  rRenderContext.DrawLine(aFirst, aSecond);
980 
981  aFirst = aSecond;
982  aFirst.AdjustX(1 );
983  aSecond.AdjustX(6 );
984  aSecond.AdjustY( -5 );
985 
986  rRenderContext.DrawLine(aFirst, aSecond);
987  rRenderContext.Pop();
988  }
989 
990  rRenderContext.DrawText(Point(rPos.X() + nxDBmp, rPos.Y()), GetText());
991 }
992 
993 
994 void FmFilterItemsString::InitViewData( SvTreeListBox* pView,SvTreeListEntry* pEntry, SvViewDataItem* pViewData)
995 {
996  if( !pViewData )
997  pViewData = pView->GetViewDataItem( pEntry, this );
998 
999  Size aSize(pView->GetTextWidth(GetText()), pView->GetTextHeight());
1000  aSize.AdjustWidth(nxDBmp );
1001  pViewData->mnWidth = aSize.Width();
1002  pViewData->mnHeight = aSize.Height();
1003 }
1004 
1005 namespace {
1006 
1007 class FmFilterString : public SvLBoxString
1008 {
1009  OUString m_aName;
1010 
1011 public:
1012  FmFilterString( const OUString& rStr, const OUString& aName)
1013  : SvLBoxString(rStr)
1014  , m_aName(aName)
1015  {
1016  m_aName += ": ";
1017  }
1018 
1019  virtual void Paint(const Point& rPos, SvTreeListBox& rDev, vcl::RenderContext& rRenderContext,
1020  const SvViewDataEntry* pView, const SvTreeListEntry& rEntry) override;
1021  virtual void InitViewData( SvTreeListBox* pView,SvTreeListEntry* pEntry, SvViewDataItem* pViewData = nullptr) override;
1022 };
1023 
1024 }
1025 
1026 const int nxD = 4;
1027 
1028 void FmFilterString::InitViewData( SvTreeListBox* pView,SvTreeListEntry* pEntry, SvViewDataItem* pViewData)
1029 {
1030  if( !pViewData )
1031  pViewData = pView->GetViewDataItem( pEntry, this );
1032 
1033  vcl::Font aOldFont( pView->GetFont());
1034  vcl::Font aFont( aOldFont );
1035  aFont.SetWeight(WEIGHT_BOLD);
1036  pView->Control::SetFont( aFont );
1037 
1038  Size aSize(pView->GetTextWidth(m_aName), pView->GetTextHeight());
1039  pView->Control::SetFont( aOldFont );
1040  aSize.AdjustWidth(pView->GetTextWidth(GetText()) + nxD );
1041  pViewData->mnWidth = aSize.Width();
1042  pViewData->mnHeight = aSize.Height();
1043 }
1044 
1045 void FmFilterString::Paint(const Point& rPos, SvTreeListBox& rDev, vcl::RenderContext& rRenderContext,
1046  const SvViewDataEntry* /*pView*/, const SvTreeListEntry& /*rEntry*/)
1047 {
1048  rRenderContext.Push(PushFlags::FONT);
1049  vcl::Font aFont(rRenderContext.GetFont());
1050  aFont.SetWeight(WEIGHT_BOLD);
1051  rRenderContext.SetFont(aFont);
1052 
1053  Point aPos(rPos);
1054  rRenderContext.DrawText(aPos, m_aName);
1055 
1056  // position for the second text
1057  aPos.AdjustX(rDev.GetTextWidth(m_aName) + nxD );
1058  rRenderContext.Pop();
1059  rDev.DrawText(aPos, GetText());
1060 }
1061 
1064  ,m_pEditingCurrently( nullptr )
1065  ,m_aControlExchange( this )
1066  ,m_aTimerCounter( 0 )
1067  ,m_aDropActionType( DA_SCROLLUP )
1068 {
1070 
1072  Image(StockImage::Yes, RID_SVXBMP_COLLAPSEDNODE),
1073  Image(StockImage::Yes, RID_SVXBMP_EXPANDEDNODE)
1074  );
1075 
1076  m_pModel.reset( new FmFilterModel() );
1078 
1079  EnableInplaceEditing( true );
1080  SetSelectionMode(SelectionMode::Multiple);
1081 
1082  SetDragDropMode(DragDropMode::ALL);
1083 
1084  m_aDropActionTimer.SetInvokeHandler(LINK(this, FmFilterNavigator, OnDropActionTimer));
1085 }
1086 
1087 
1089 {
1090  disposeOnce();
1091 }
1092 
1094 {
1095  EndListening( *m_pModel );
1096  m_pModel.reset();
1098 }
1099 
1100 
1101 void FmFilterNavigator::UpdateContent(const Reference< XIndexAccess > & xControllers, const Reference< XFormController > & xCurrent)
1102 {
1103  if (xCurrent == m_pModel->GetCurrentController())
1104  return;
1105 
1106  m_pModel->Update(xControllers, xCurrent);
1107 
1108  // expand the filters for the current controller
1109  SvTreeListEntry* pEntry = FindEntry(m_pModel->GetCurrentForm());
1110  if (pEntry && !IsExpanded(pEntry))
1111  {
1112  SelectAll(false);
1113 
1114  if (!IsExpanded(pEntry))
1115  Expand(pEntry);
1116 
1117  pEntry = FindEntry(m_pModel->GetCurrentItems());
1118  if (pEntry)
1119  {
1120  if (!IsExpanded(pEntry))
1121  Expand(pEntry);
1122  Select(pEntry);
1123  }
1124  }
1125 }
1126 
1127 
1129 {
1130  m_pEditingCurrently = pEntry;
1131  if (!SvTreeListBox::EditingEntry( pEntry, rSelection ))
1132  return false;
1133 
1134  return pEntry && dynamic_cast<const FmFilterItem*>(static_cast<FmFilterData*>(pEntry->GetUserData())) != nullptr;
1135 }
1136 
1137 
1138 bool FmFilterNavigator::EditedEntry( SvTreeListEntry* pEntry, const OUString& rNewText )
1139 {
1140  DBG_ASSERT(pEntry == m_pEditingCurrently, "FmFilterNavigator::EditedEntry: suspicious entry!");
1141  m_pEditingCurrently = nullptr;
1142 
1143  if (EditingCanceled())
1144  return true;
1145 
1146  DBG_ASSERT(dynamic_cast<const FmFilterItem*>(static_cast<FmFilterData*>(pEntry->GetUserData())) != nullptr,
1147  "FmFilterNavigator::EditedEntry() wrong entry");
1148 
1149  OUString aText(comphelper::string::strip(rNewText, ' '));
1150  if (aText.isEmpty())
1151  {
1152  // deleting the entry asynchron
1153  PostUserEvent(LINK(this, FmFilterNavigator, OnRemove), pEntry, true);
1154  }
1155  else
1156  {
1157  OUString aErrorMsg;
1158 
1159  if (m_pModel->ValidateText(static_cast<FmFilterItem*>(pEntry->GetUserData()), aText, aErrorMsg))
1160  {
1161  GrabFocus();
1162  // this will set the text at the FmFilterItem, as well as update any filter controls
1163  // which are connected to this particular entry
1164  m_pModel->SetTextForItem( static_cast< FmFilterItem* >( pEntry->GetUserData() ), aText );
1165 
1166  SetCursor( pEntry, true );
1167  SetEntryText( pEntry, aText );
1168  }
1169  else
1170  {
1171  // display the error and return sal_False
1172  SQLContext aError;
1173  aError.Message = SvxResId(RID_STR_SYNTAXERROR);
1174  aError.Details = aErrorMsg;
1175  displayException(aError, this);
1176 
1177  return false;
1178  }
1179  }
1180  return true;
1181 }
1182 
1183 
1184 IMPL_LINK( FmFilterNavigator, OnRemove, void*, p, void )
1185 {
1186  SvTreeListEntry* pEntry = static_cast<SvTreeListEntry*>(p);
1187  // now remove the entry
1188  m_pModel->Remove(static_cast<FmFilterData*>(pEntry->GetUserData()));
1189 }
1190 
1191 
1192 IMPL_LINK_NOARG(FmFilterNavigator, OnDropActionTimer, Timer *, void)
1193 {
1194  if (--m_aTimerCounter > 0)
1195  return;
1196 
1197  switch (m_aDropActionType)
1198  {
1199  case DA_SCROLLUP :
1200  ScrollOutputArea(1);
1201  m_aTimerCounter = DROP_ACTION_TIMER_SCROLL_TICKS;
1202  break;
1203  case DA_SCROLLDOWN :
1204  ScrollOutputArea(-1);
1205  m_aTimerCounter = DROP_ACTION_TIMER_SCROLL_TICKS;
1206  break;
1207  case DA_EXPANDNODE:
1208  {
1209  SvTreeListEntry* pToExpand = GetEntry(m_aTimerTriggered);
1210  if (pToExpand && (GetChildCount(pToExpand) > 0) && !IsExpanded(pToExpand))
1211  Expand(pToExpand);
1212  m_aDropActionTimer.Stop();
1213  }
1214  break;
1215  }
1216 }
1217 
1218 
1220 {
1221  Point aDropPos = rEvt.maPosPixel;
1222 
1223  // possible DropActions scroll and expand
1224  if (rEvt.mbLeaving)
1225  {
1228  }
1229  else
1230  {
1231  bool bNeedTrigger = false;
1232  // first entry ?
1233  if ((aDropPos.Y() >= 0) && (aDropPos.Y() < GetEntryHeight()))
1234  {
1236  bNeedTrigger = true;
1237  }
1238  else
1239  {
1240  if ((aDropPos.Y() < GetSizePixel().Height()) && (aDropPos.Y() >= GetSizePixel().Height() - GetEntryHeight()))
1241  {
1243  bNeedTrigger = true;
1244  }
1245  else
1246  { // is it an entry with children, and not yet expanded?
1247  SvTreeListEntry* pDroppedOn = GetEntry(aDropPos);
1248  if (pDroppedOn && (GetChildCount(pDroppedOn) > 0) && !IsExpanded(pDroppedOn))
1249  {
1250  // -> expand
1252  bNeedTrigger = true;
1253  }
1254  }
1255  }
1256  if (bNeedTrigger && (m_aTimerTriggered != aDropPos))
1257  {
1259  // remember DropPos because there are QueryDrops even though the mouse was not moved
1260  m_aTimerTriggered = aDropPos;
1262  {
1265  }
1266  }
1267  else if (!bNeedTrigger)
1269  }
1270 
1272  return DND_ACTION_NONE;
1273 
1275  return DND_ACTION_NONE;
1276 
1277  // do we contain the formitem?
1279  return DND_ACTION_NONE;
1280 
1281  SvTreeListEntry* pDropTarget = GetEntry(aDropPos);
1282  if (!pDropTarget)
1283  return DND_ACTION_NONE;
1284 
1285  FmFilterData* pData = static_cast<FmFilterData*>(pDropTarget->GetUserData());
1286  FmFormItem* pForm = nullptr;
1287  if (dynamic_cast<const FmFilterItem*>(pData) != nullptr)
1288  {
1289  pForm = dynamic_cast<FmFormItem*>( pData->GetParent()->GetParent() );
1290  if (pForm != m_aControlExchange->getFormItem())
1291  return DND_ACTION_NONE;
1292  }
1293  else if (dynamic_cast<const FmFilterItems*>( pData) != nullptr)
1294  {
1295  pForm = dynamic_cast<FmFormItem*>( pData->GetParent() );
1296  if (pForm != m_aControlExchange->getFormItem())
1297  return DND_ACTION_NONE;
1298  }
1299  else
1300  return DND_ACTION_NONE;
1301 
1302  return rEvt.mnAction;
1303 }
1304 
1305 namespace
1306 {
1307  FmFilterItems* getTargetItems(SvTreeListEntry const * _pTarget)
1308  {
1309  FmFilterData* pData = static_cast<FmFilterData*>(_pTarget->GetUserData());
1310  FmFilterItems* pTargetItems = dynamic_cast<FmFilterItems*>(pData);
1311  if (!pTargetItems)
1312  pTargetItems = dynamic_cast<FmFilterItems*>(pData->GetParent());
1313  return pTargetItems;
1314  }
1315 }
1316 
1318 {
1319  // you can't scroll after dropping...
1322 
1324  return DND_ACTION_NONE;
1325 
1326  Point aDropPos = rEvt.maPosPixel;
1327  SvTreeListEntry* pDropTarget = GetEntry( aDropPos );
1328  if (!pDropTarget)
1329  return DND_ACTION_NONE;
1330 
1331  // search the container where to add the items
1332  FmFilterItems* pTargetItems = getTargetItems(pDropTarget);
1333  SelectAll(false);
1334  SvTreeListEntry* pEntry = FindEntry(pTargetItems);
1335  Select(pEntry);
1336  SetCurEntry(pEntry);
1337 
1339 
1340  return DND_ACTION_COPY;
1341 }
1342 
1343 
1345  const OUString& rStr,
1346  const Image& rImg1,
1347  const Image& rImg2)
1348 {
1349  SvTreeListBox::InitEntry( pEntry, rStr, rImg1, rImg2 );
1350  std::unique_ptr<SvLBoxString> pString;
1351 
1352  if (dynamic_cast<const FmFilterItem*>(static_cast<FmFilterData*>(pEntry->GetUserData())) != nullptr)
1353  pString.reset(new FmFilterString(rStr,
1354  static_cast<FmFilterItem*>(pEntry->GetUserData())->GetFieldName()));
1355  else if (dynamic_cast<const FmFilterItems*>(static_cast<FmFilterData*>(pEntry->GetUserData())) != nullptr)
1356  pString.reset(new FmFilterItemsString(rStr));
1357 
1358  if (pString)
1359  pEntry->ReplaceItem(std::move(pString), 1 );
1360 }
1361 
1362 
1363 bool FmFilterNavigator::Select( SvTreeListEntry* pEntry, bool bSelect )
1364 {
1365  if (bSelect == IsSelected(pEntry)) // This happens sometimes. I think the basic class errs too much on the side of caution. ;)
1366  return true;
1367 
1368  if (SvTreeListBox::Select(pEntry, bSelect))
1369  {
1370  if (bSelect)
1371  {
1372  FmFormItem* pFormItem = nullptr;
1373  if ( dynamic_cast<const FmFilterItem*>(static_cast<FmFilterData*>(pEntry->GetUserData())) != nullptr)
1374  pFormItem = static_cast<FmFormItem*>(static_cast<FmFilterItem*>(pEntry->GetUserData())->GetParent()->GetParent());
1375  else if (dynamic_cast<const FmFilterItems*>(static_cast<FmFilterData*>(pEntry->GetUserData())) != nullptr)
1376  pFormItem = static_cast<FmFormItem*>(static_cast<FmFilterItem*>(pEntry->GetUserData())->GetParent()->GetParent());
1377  else if (dynamic_cast<const FmFormItem*>(static_cast<FmFilterData*>(pEntry->GetUserData())) != nullptr)
1378  pFormItem = static_cast<FmFormItem*>(pEntry->GetUserData());
1379 
1380  if (pFormItem)
1381  {
1382  // will the controller be exchanged?
1383  if (dynamic_cast<const FmFilterItem*>(static_cast<FmFilterData*>(pEntry->GetUserData())) != nullptr)
1384  m_pModel->SetCurrentItems(static_cast<FmFilterItems*>(static_cast<FmFilterItem*>(pEntry->GetUserData())->GetParent()));
1385  else if (dynamic_cast<const FmFilterItems*>(static_cast<FmFilterData*>(pEntry->GetUserData())) != nullptr)
1386  m_pModel->SetCurrentItems(static_cast<FmFilterItems*>(pEntry->GetUserData()));
1387  else if (dynamic_cast<const FmFormItem*>(static_cast<FmFilterData*>(pEntry->GetUserData())) != nullptr)
1388  m_pModel->SetCurrentController(static_cast<FmFormItem*>(pEntry->GetUserData())->GetController());
1389  }
1390  }
1391  return true;
1392  }
1393  else
1394  return false;
1395 }
1396 
1397 void FmFilterNavigator::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
1398 {
1399  if (const FmFilterInsertedHint* pInsertHint = dynamic_cast<const FmFilterInsertedHint*>(&rHint))
1400  {
1401  Insert(pInsertHint->GetData(), pInsertHint->GetPos());
1402  }
1403  else if( dynamic_cast<const FilterClearingHint*>(&rHint) )
1404  {
1406  }
1407  else if (const FmFilterRemovedHint* pRemoveHint = dynamic_cast<const FmFilterRemovedHint*>(&rHint))
1408  {
1409  Remove(pRemoveHint->GetData());
1410  }
1411  else if (const FmFilterTextChangedHint *pChangeHint = dynamic_cast<const FmFilterTextChangedHint*>(&rHint))
1412  {
1413  SvTreeListEntry* pEntry = FindEntry(pChangeHint->GetData());
1414  if (pEntry)
1415  SetEntryText( pEntry, pChangeHint->GetData()->GetText());
1416  }
1417  else if( dynamic_cast<const FmFilterCurrentChangedHint*>(&rHint) )
1418  {
1419  // invalidate the entries
1420  for (SvTreeListEntry* pEntry = First(); pEntry != nullptr;
1421  pEntry = Next(pEntry))
1422  GetModel()->InvalidateEntry( pEntry );
1423  }
1424 }
1425 
1427 {
1428  SvTreeListEntry* pEntry = nullptr;
1429  if (pItem)
1430  {
1431  for (pEntry = First(); pEntry != nullptr; pEntry = Next( pEntry ))
1432  {
1433  FmFilterData* pEntryItem = static_cast<FmFilterData*>(pEntry->GetUserData());
1434  if (pEntryItem == pItem)
1435  break;
1436  }
1437  }
1438  return pEntry;
1439 }
1440 
1441 
1443 {
1444  const FmParentData* pParent = pItem->GetParent() ? pItem->GetParent() : GetFilterModel();
1445 
1446  // insert the item
1447  SvTreeListEntry* pParentEntry = FindEntry( pParent );
1448  InsertEntry( pItem->GetText(), pItem->GetImage(), pItem->GetImage(), pParentEntry, false, nPos, pItem );
1449  if ( pParentEntry )
1450  Expand( pParentEntry );
1451 }
1452 
1453 
1455 {
1456  // the entry for the data
1457  SvTreeListEntry* pEntry = FindEntry(pItem);
1458 
1459  if (pEntry == m_pEditingCurrently)
1460  // cancel editing
1461  EndEditing(true);
1462 
1463  if (pEntry)
1464  GetModel()->Remove( pEntry );
1465 }
1466 
1467 FmFormItem* FmFilterNavigator::getSelectedFilterItems(::std::vector<FmFilterItem*>& _rItemList)
1468 {
1469  // be sure that the data is only used within only one form!
1470  FmFormItem* pFirstItem = nullptr;
1471 
1472  bool bHandled = true;
1473  bool bFoundSomething = false;
1474  for (SvTreeListEntry* pEntry = FirstSelected();
1475  bHandled && pEntry != nullptr;
1476  pEntry = NextSelected(pEntry))
1477  {
1478  FmFilterItem* pFilter = dynamic_cast<FmFilterItem*>( static_cast<FmFilterData*>(pEntry->GetUserData()) );
1479  if (pFilter)
1480  {
1481  FmFormItem* pForm = dynamic_cast<FmFormItem*>( pFilter->GetParent()->GetParent() );
1482  if (!pForm)
1483  bHandled = false;
1484  else if (!pFirstItem)
1485  pFirstItem = pForm;
1486  else if (pFirstItem != pForm)
1487  bHandled = false;
1488 
1489  if (bHandled)
1490  {
1491  _rItemList.push_back(pFilter);
1492  bFoundSomething = true;
1493  }
1494  }
1495  }
1496  if ( !bHandled || !bFoundSomething )
1497  pFirstItem = nullptr;
1498  return pFirstItem;
1499 }
1500 
1501 void FmFilterNavigator::insertFilterItem(const ::std::vector<FmFilterItem*>& _rFilterList,FmFilterItems* _pTargetItems,bool _bCopy)
1502 {
1503  for (FmFilterItem* pLookupItem : _rFilterList)
1504  {
1505  if ( pLookupItem->GetParent() == _pTargetItems )
1506  continue;
1507 
1508  FmFilterItem* pFilterItem = _pTargetItems->Find( pLookupItem->GetComponentIndex() );
1509  OUString aText = pLookupItem->GetText();
1510  if ( !pFilterItem )
1511  {
1512  pFilterItem = new FmFilterItem( _pTargetItems, pLookupItem->GetFieldName(), aText, pLookupItem->GetComponentIndex() );
1513  m_pModel->Append( _pTargetItems, std::unique_ptr<FmFilterItem>(pFilterItem) );
1514  }
1515 
1516  if ( !_bCopy )
1517  m_pModel->Remove( pLookupItem );
1518 
1519  // now set the text for the new dragged item
1520  m_pModel->SetTextForItem( pFilterItem, aText );
1521  }
1522 
1523  m_pModel->EnsureEmptyFilterRows( *_pTargetItems->GetParent() );
1524 }
1525 
1526 
1527 void FmFilterNavigator::StartDrag( sal_Int8 /*_nAction*/, const Point& /*_rPosPixel*/ )
1528 {
1529  EndSelection();
1530 
1531  // be sure that the data is only used within an only one form!
1533 
1534  ::std::vector<FmFilterItem*> aItemList;
1535  if ( FmFormItem* pFirstItem = getSelectedFilterItems(aItemList) )
1536  {
1538  m_aControlExchange->setFormItem(pFirstItem);
1540  }
1541 }
1542 
1543 
1545 {
1546  bool bHandled = false;
1547  switch (rEvt.GetCommand())
1548  {
1549  case CommandEventId::ContextMenu:
1550  {
1551  // the place where it was clicked
1552  Point aWhere;
1553  SvTreeListEntry* pClicked = nullptr;
1554  if (rEvt.IsMouseEvent())
1555  {
1556  aWhere = rEvt.GetMousePosPixel();
1557  pClicked = GetEntry(aWhere);
1558  if (pClicked == nullptr)
1559  break;
1560 
1561  if (!IsSelected(pClicked))
1562  {
1563  SelectAll(false);
1564  Select(pClicked);
1565  SetCurEntry(pClicked);
1566  }
1567  }
1568  else
1569  {
1570  pClicked = GetCurEntry();
1571  if (!pClicked)
1572  break;
1573  aWhere = GetEntryPosition( pClicked );
1574  }
1575 
1576  ::std::vector<FmFilterData*> aSelectList;
1577  for (SvTreeListEntry* pEntry = FirstSelected();
1578  pEntry != nullptr;
1579  pEntry = NextSelected(pEntry))
1580  {
1581  // don't delete forms
1582  FmFormItem* pForm = dynamic_cast<FmFormItem*>( static_cast<FmFilterData*>(pEntry->GetUserData()) );
1583  if (!pForm)
1584  aSelectList.push_back(static_cast<FmFilterData*>(pEntry->GetUserData()));
1585  }
1586  if (aSelectList.size() == 1)
1587  {
1588  // don't delete the only empty row of a form
1589  FmFilterItems* pFilterItems = dynamic_cast<FmFilterItems*>( aSelectList[0] );
1590  if (pFilterItems && pFilterItems->GetChildren().empty()
1591  && pFilterItems->GetParent()->GetChildren().size() == 1)
1592  aSelectList.clear();
1593  }
1594 
1595  VclBuilder aBuilder(nullptr, VclBuilderContainer::getUIRootDir(), "svx/ui/filtermenu.ui", "");
1596  VclPtr<PopupMenu> aContextMenu(aBuilder.get_menu("menu"));
1597 
1598  // every condition could be deleted except the first one if it's the only one
1599  aContextMenu->EnableItem(aContextMenu->GetItemId("delete"), !aSelectList.empty());
1600 
1601 
1602  bool bEdit = dynamic_cast<FmFilterItem*>( static_cast<FmFilterData*>(pClicked->GetUserData()) ) != nullptr &&
1603  IsSelected(pClicked) && GetSelectionCount() == 1;
1604 
1605  aContextMenu->EnableItem(aContextMenu->GetItemId("edit"), bEdit);
1606  aContextMenu->EnableItem(aContextMenu->GetItemId("isnull"), bEdit);
1607  aContextMenu->EnableItem(aContextMenu->GetItemId("isnotnull"), bEdit);
1608 
1609  aContextMenu->RemoveDisabledEntries(true, true);
1610  aContextMenu->Execute(this, aWhere);
1611  OString sIdent = aContextMenu->GetCurItemIdent();
1612  if (sIdent == "edit")
1613  EditEntry( pClicked );
1614  else if (sIdent == "isnull")
1615  {
1616  OUString aErrorMsg;
1617  OUString aText = "IS NULL";
1618  m_pModel->ValidateText(static_cast<FmFilterItem*>(pClicked->GetUserData()),
1619  aText, aErrorMsg);
1620  m_pModel->SetTextForItem(static_cast<FmFilterItem*>(pClicked->GetUserData()), aText);
1621  }
1622  else if (sIdent == "isnotnull")
1623  {
1624  OUString aErrorMsg;
1625  OUString aText = "IS NOT NULL";
1626 
1627  m_pModel->ValidateText(static_cast<FmFilterItem*>(pClicked->GetUserData()),
1628  aText, aErrorMsg);
1629  m_pModel->SetTextForItem(static_cast<FmFilterItem*>(pClicked->GetUserData()), aText);
1630  }
1631  else if (sIdent == "delete")
1632  {
1633  DeleteSelection();
1634  }
1635  bHandled = true;
1636  }
1637  break;
1638  default: break;
1639  }
1640 
1641  if (!bHandled)
1642  SvTreeListBox::Command( rEvt );
1643 }
1644 
1646 {
1647  SvTreeListEntry* pEntry = _pStartWith ? _pStartWith : LastSelected();
1648  pEntry = Next(pEntry);
1649  // we need the next filter entry
1650  while( pEntry && GetChildCount( pEntry ) == 0 && pEntry != Last() )
1651  pEntry = Next(pEntry);
1652  return pEntry;
1653 }
1654 
1656 {
1657  SvTreeListEntry* pEntry = _pStartWith ? _pStartWith : FirstSelected();
1658  pEntry = Prev(pEntry);
1659  // check if the previous entry is a filter, if so get the next prev
1660  if ( pEntry && GetChildCount( pEntry ) != 0 )
1661  {
1662  pEntry = Prev(pEntry);
1663  // if the entry is still no leaf return
1664  if ( pEntry && GetChildCount( pEntry ) != 0 )
1665  pEntry = nullptr;
1666  }
1667  return pEntry;
1668 }
1669 
1671 {
1672  const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode();
1673 
1674  switch ( rKeyCode.GetCode() )
1675  {
1676  case KEY_UP:
1677  case KEY_DOWN:
1678  {
1679  if ( !rKeyCode.IsMod1() || !rKeyCode.IsMod2() || rKeyCode.IsShift() )
1680  break;
1681 
1682  ::std::vector<FmFilterItem*> aItemList;
1683  if ( !getSelectedFilterItems( aItemList ) )
1684  break;
1685 
1686  ::std::function<SvTreeListEntry*(FmFilterNavigator *, SvTreeListEntry*)> getter = ::std::mem_fn(&FmFilterNavigator::getNextEntry);
1687  if ( rKeyCode.GetCode() == KEY_UP )
1688  getter = ::std::mem_fn(&FmFilterNavigator::getPrevEntry);
1689 
1690  SvTreeListEntry* pTarget = getter( this, nullptr );
1691  if ( !pTarget )
1692  break;
1693 
1694  FmFilterItems* pTargetItems = getTargetItems( pTarget );
1695  if ( !pTargetItems )
1696  break;
1697 
1698  ::std::vector<FmFilterItem*>::const_iterator aEnd = aItemList.end();
1699  bool bNextTargetItem = true;
1700  while ( bNextTargetItem )
1701  {
1702  ::std::vector<FmFilterItem*>::const_iterator i = aItemList.begin();
1703  for (; i != aEnd; ++i)
1704  {
1705  if ( (*i)->GetParent() == pTargetItems )
1706  {
1707  pTarget = getter(this,pTarget);
1708  if ( !pTarget )
1709  return;
1710  pTargetItems = getTargetItems( pTarget );
1711  break;
1712  }
1713  else
1714  {
1715  FmFilterItem* pFilterItem = pTargetItems->Find( (*i)->GetComponentIndex() );
1716  // we found the text component so jump above
1717  if ( pFilterItem )
1718  {
1719  pTarget = getter( this, pTarget );
1720  if ( !pTarget )
1721  return;
1722 
1723  pTargetItems = getTargetItems( pTarget );
1724  break;
1725  }
1726  }
1727  }
1728  bNextTargetItem = i != aEnd && pTargetItems;
1729  }
1730 
1731  if ( pTargetItems )
1732  {
1733  insertFilterItem( aItemList, pTargetItems, false );
1734  return;
1735  }
1736  }
1737  break;
1738 
1739  case KEY_DELETE:
1740  {
1741  if ( rKeyCode.GetModifier() )
1742  break;
1743 
1744  if ( !IsSelected( First() ) || GetEntryCount() > 1 )
1745  DeleteSelection();
1746  return;
1747  }
1748  }
1749 
1750  SvTreeListBox::KeyInput(rKEvt);
1751 }
1752 
1753 
1755 {
1756  // to avoid the deletion of an entry twice (e.g. deletion of a parent and afterward
1757  // the deletion of its child, I have to shrink the selection list
1758  ::std::vector<SvTreeListEntry*> aEntryList;
1759  for (SvTreeListEntry* pEntry = FirstSelected();
1760  pEntry != nullptr;
1761  pEntry = NextSelected(pEntry))
1762  {
1763  FmFilterItem* pFilterItem = dynamic_cast<FmFilterItem*>( static_cast<FmFilterData*>(pEntry->GetUserData()) );
1764  if (pFilterItem && IsSelected(GetParent(pEntry)))
1765  continue;
1766 
1767  FmFormItem* pForm = dynamic_cast<FmFormItem*>( static_cast<FmFilterData*>(pEntry->GetUserData()) );
1768  if (!pForm)
1769  aEntryList.push_back(pEntry);
1770  }
1771 
1772  // Remove the selection
1773  SelectAll(false);
1774 
1775  for (::std::vector<SvTreeListEntry*>::reverse_iterator i = aEntryList.rbegin();
1776  // link problems with operator ==
1777  i.base() != aEntryList.rend().base(); ++i)
1778  {
1779  m_pModel->Remove(static_cast<FmFilterData*>((*i)->GetUserData()));
1780  }
1781 }
1782 
1784  vcl::Window* _pParent )
1786  ,SfxControllerItem( SID_FM_FILTER_NAVIGATOR_CONTROL, *_pBindings )
1787 {
1788  SetHelpId( HID_FILTER_NAVIGATOR_WIN );
1789 
1791  m_pNavigator->Show();
1792  SetText( SvxResId(RID_STR_FILTER_NAVIGATOR) );
1794 }
1795 
1796 
1798 {
1799  disposeOnce();
1800 }
1801 
1803 {
1804  m_pNavigator.disposeAndClear();
1807 }
1808 
1809 
1811 {
1812  if (!m_pNavigator)
1813  return;
1814 
1815  if (!pFormShell)
1816  m_pNavigator->UpdateContent( nullptr, nullptr );
1817  else
1818  {
1819  Reference<XFormController> const xController(pFormShell->GetImpl()->getActiveInternalController_Lock());
1820  Reference< XIndexAccess > xContainer;
1821  if (xController.is())
1822  {
1823  Reference< XChild > xChild = xController;
1824  for (Reference< XInterface > xParent(xChild->getParent());
1825  xParent.is();
1826  xParent = xChild.is() ? xChild->getParent() : Reference< XInterface > ())
1827  {
1828  xContainer.set(xParent, UNO_QUERY);
1829  xChild.set(xParent, UNO_QUERY);
1830  }
1831  }
1832  m_pNavigator->UpdateContent(xContainer, xController);
1833  }
1834 }
1835 
1836 
1837 void FmFilterNavigatorWin::StateChanged( sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState )
1838 {
1839  if( !pState || SID_FM_FILTER_NAVIGATOR_CONTROL != nSID )
1840  return;
1841 
1842  if( eState >= SfxItemState::DEFAULT )
1843  {
1844  FmFormShell* pShell = dynamic_cast<FmFormShell*>( static_cast<const SfxObjectItem*>(pState)->GetShell() );
1845  UpdateContent( pShell );
1846  }
1847  else
1848  UpdateContent( nullptr );
1849 }
1850 
1851 
1853 {
1854  if ( m_pNavigator && m_pNavigator->IsEditingActive() )
1855  m_pNavigator->EndEditing();
1856 
1857  if ( m_pNavigator && m_pNavigator->IsEditingActive() )
1858  // the EndEditing was vetoed (perhaps of an syntax error or such)
1859  return false;
1860 
1861  UpdateContent( nullptr );
1862  return SfxDockingWindow::Close();
1863 }
1864 
1865 
1867 {
1868  SfxDockingWindow::FillInfo( rInfo );
1869  rInfo.bVisible = false;
1870 }
1871 
1872 
1874 {
1875  if ( ( eAlign == SfxChildAlignment::TOP ) || ( eAlign == SfxChildAlignment::BOTTOM ) )
1876  return Size();
1877 
1878  return SfxDockingWindow::CalcDockingSize( eAlign );
1879 }
1880 
1881 
1883 {
1884  switch (eAlign)
1885  {
1886  case SfxChildAlignment::LEFT:
1887  case SfxChildAlignment::RIGHT:
1888  case SfxChildAlignment::NOALIGNMENT:
1889  return eAlign;
1890  default:
1891  break;
1892  }
1893 
1894  return eActAlign;
1895 }
1896 
1897 
1899 {
1901 
1902  Size aLogOutputSize = PixelToLogic(GetOutputSizePixel(), MapMode(MapUnit::MapAppFont));
1903  Size aLogExplSize = aLogOutputSize;
1904  aLogExplSize.AdjustWidth( -6 );
1905  aLogExplSize.AdjustHeight( -6 );
1906 
1907  Point aExplPos = LogicToPixel(Point(3,3), MapMode(MapUnit::MapAppFont));
1908  Size aExplSize = LogicToPixel(aLogExplSize, MapMode(MapUnit::MapAppFont));
1909 
1910  m_pNavigator->SetPosSizePixel( aExplPos, aExplSize );
1911 }
1912 
1914 {
1915  // oj #97405#
1916  if ( m_pNavigator )
1917  m_pNavigator->GrabFocus();
1918 }
1919 
1920 SFX_IMPL_DOCKINGWINDOW( FmFilterNavigatorWinMgr, SID_FM_FILTER_NAVIGATOR )
1921 
1922 
1923 FmFilterNavigatorWinMgr::FmFilterNavigatorWinMgr( vcl::Window *_pParent, sal_uInt16 _nId,
1924  SfxBindings *_pBindings, SfxChildWinInfo* _pInfo )
1925  :SfxChildWindow( _pParent, _nId )
1926 {
1927  SetWindow( VclPtr<FmFilterNavigatorWin>::Create( _pBindings, this, _pParent ) );
1928  static_cast<SfxDockingWindow*>(GetWindow())->Initialize( _pInfo );
1929 }
1930 
1931 
1932 }
1933 
1934 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual ~FmFilterModel() override
Definition: filtnav.cxx:481
friend class FmFilterAdapter
Definition: filtnav.hxx:152
WinBits const WB_ROLLABLE
virtual Image GetImage() const override
Definition: filtnav.cxx:173
const Color & GetTextColor() const
void DrawText(const Point &rStartPt, const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, MetricVector *pVector=nullptr, OUString *pDisplayText=nullptr, const SalLayoutGlyphs *pLayoutCache=nullptr)
WinBits const WB_DOCKABLE
void UpdateContent(const css::uno::Reference< css::container::XIndexAccess > &xControllers, const css::uno::Reference< css::form::runtime::XFormController > &xCurrent)
Definition: filtnav.cxx:1101
virtual SfxChildAlignment CheckAlignment(SfxChildAlignment, SfxChildAlignment) override
Definition: filtnav.cxx:1882
void EnsureEmptyFilterRows(FmParentData &_rItem)
Definition: filtnav.cxx:910
SvTreeListEntry * NextSelected(SvTreeListEntry *pEntry) const
static SotClipboardFormatId RegisterFormatName(const OUString &rName)
void insertFilterItem(const ::std::vector< FmFilterItem * > &_rFilterList, FmFilterItems *_pTargetItems, bool _bCopy)
inserts the filter items into the tree model and creates new FilterItems if needed.
Definition: filtnav.cxx:1501
#define KEY_DELETE
virtual bool EditedEntry(SvTreeListEntry *pEntry, const OUString &rNewText) override
Definition: filtnav.cxx:1138
FmFilterNavigator(vcl::Window *pParent)
Definition: filtnav.cxx:1062
void InvalidateEntry(SvTreeListEntry *)
SvTreeListEntry * FindEntry(const FmFilterData *pItem) const
Definition: filtnav.cxx:1426
virtual void SAL_CALL disjunctiveTermRemoved(const FilterEvent &Event) override
Definition: filtnav.cxx:409
long AdjustWidth(long n)
#define DND_ACTION_COPY
virtual Image GetImage() const override
Definition: filtnav.cxx:158
const OSystemParseContext * getParseContext() const
FmXFormShell * GetImpl() const
Definition: fmshell.hxx:118
const LanguageTag & GetUILanguageTag() const
virtual void Command(const CommandEvent &rCEvt) override
void startDrag(sal_Int8 nDragSourceActions)
Definition: fmexch.cxx:353
void Insert(FmFilterData *pItem, sal_uLong nPos)
Definition: filtnav.cxx:1442
virtual ~FmFilterNavigatorWin() override
Definition: filtnav.cxx:1797
void setDraggedEntries(const ::std::vector< FmFilterItem * > &_rList)
Definition: filtnav.hxx:201
long Height() const
signed char sal_Int8
SvTreeList * GetModel() const
static SotClipboardFormatId getFormatId()
Definition: filtnav.cxx:118
WinBits const WB_HASBUTTONSATROOT
sal_uIntPtr sal_uLong
unsigned short m_aTimerCounter
Definition: filtnav.hxx:237
void Remove(FmFilterData *pFilterItem)
Definition: filtnav.cxx:713
sal_uLong GetEntryCount() const
std::shared_ptr< ContentProperties > const pData
static const AllSettings & GetSettings()
virtual Size GetSizePixel() const
void SetWeight(FontWeight)
#define DND_ACTION_COPYMOVE
sal_uInt16 GetCode() const
void SetCursor(SvTreeListEntry *pEntry, bool bForceNoSelect=false)
void SetEntryText(SvTreeListEntry *, const OUString &)
void SetCurEntry(SvTreeListEntry *_pEntry)
void SetHelpId(const OString &)
virtual void Notify(SfxBroadcaster &rBC, const SfxHint &rHint) override
Definition: filtnav.cxx:1397
virtual void SAL_CALL disposing(const EventObject &Source) override
Definition: filtnav.cxx:318
Reference< XNumberFormatsSupplier > getNumberFormats(const Reference< XConnection > &_rxConn, bool _bAlloweDefault, const Reference< XComponentContext > &_rxContext)
SvTreeListEntry * GetCurEntry() const
long AdjustHeight(long n)
SvTreeListEntry * LastSelected() const
virtual ~FmParentData() override
Definition: filtnav.cxx:138
virtual void Command(const CommandEvent &rEvt) override
Definition: filtnav.cxx:1544
const css::lang::Locale & getLocale(bool bResolveSystem=true) const
virtual void SAL_CALL predicateExpressionChanged(const FilterEvent &Event) override
Definition: filtnav.cxx:358
void SetText(const OUString &rText)
Definition: filtnav.hxx:68
void setFormItem(FmFormItem *_pItem)
Definition: filtnav.hxx:204
FmFilterItem * Find(const ::sal_Int32 _nFilterComponentIndex) const
Definition: filtnav.cxx:147
bool IsActive() const
WEIGHT_BOLD
void AddFormat(SotClipboardFormatId nFormat)
Reference< XIndexAccess > m_xControllers
Definition: filtnav.cxx:236
void UpdateContent(FmFormShell const *pFormShell)
Definition: filtnav.cxx:1810
sal_Int64 WinBits
css::uno::Reference< css::container::XIndexAccess > m_xControllers
Definition: filtnav.hxx:154
virtual OLocalExchange * createExchange() const override
Definition: filtnav.cxx:127
Reference< XController > xController
SvViewDataItem * GetViewDataItem(SvTreeListEntry const *, SvLBoxItem const *)
std::unique_ptr< ::connectivity::OSQLParseNode > predicateTree(OUString &_rErrorMessage, const OUString &_rStatement, const css::uno::Reference< css::util::XNumberFormatter > &_rxFormatter, const css::uno::Reference< css::beans::XPropertySet > &_rxField) const
OUString SvxResId(const char *pId)
Definition: dialmgr.cxx:28
virtual void Resize() override
Definition: filtnav.cxx:1898
SvTreeListEntry * FirstSelected() const
const vcl::Font & GetFont() const
#define X
bool IsMouseEvent() const
void SetDragDropMode(DragDropMode)
const DataFlavorExVector & GetDataFlavorExVector() const
virtual void KeyInput(const KeyEvent &rKEvt) override
int nCount
#define DND_ACTION_NONE
void SetFloatingSize(const Size &rSize)
const int nxDBmp
Definition: filtnav.cxx:959
#define FM_PROP_BOUNDFIELD
Definition: fmprop.hxx:101
const FmFilterModel * GetFilterModel() const
Definition: filtnav.hxx:250
void Append(FmFilterItems *pItems, std::unique_ptr< FmFilterItem > pFilterItem)
Definition: filtnav.cxx:837
void EndEditing(bool bCancel=false)
FmFilterAdapter(FmFilterModel *pModel, const Reference< XIndexAccess > &xControllers)
Definition: filtnav.cxx:261
void SelectAll(bool bSelect, bool bPaint=true)
sal_uInt16 GetModifier() const
SotClipboardFormatId
virtual bool Close() override
FmParentData * GetParent() const
Definition: filtnav.hxx:70
void Update(const css::uno::Reference< css::container::XIndexAccess > &xControllers, const css::uno::Reference< css::form::runtime::XFormController > &xCurrent)
OString strip(const OString &rIn, sal_Char c)
static void AppendFilterItems(FmFormItem &_rItem)
Definition: filtnav.cxx:672
void DrawLine(const Point &rStartPt, const Point &rEndPt)
short GetEntryHeight() const
void EnableInplaceEditing(bool bEnable)
void FillInfo(SfxChildWinInfo &rInfo) const override
Definition: filtnav.cxx:1866
virtual void StartDrag(sal_Int8 nAction, const Point &rPosPixel) override
Definition: filtnav.cxx:1527
rtl::Reference< FmFilterAdapter > m_pAdapter
Definition: filtnav.hxx:156
OUString m_aName
Definition: filtnav.cxx:1009
void Remove(FmFilterData const *pItem)
Definition: filtnav.cxx:1454
bool EditingCanceled() const
FmFormItem * getFormItem() const
Definition: filtnav.hxx:202
virtual void GetFocus() override
Definition: filtnav.cxx:1913
#define DBG_UNHANDLED_EXCEPTION(...)
void SetLineColor()
virtual void KeyInput(const KeyEvent &rKEvt) override
Definition: filtnav.cxx:1670
virtual void InitEntry(SvTreeListEntry *pEntry, const OUString &rStr, const Image &rImg1, const Image &rImg2) override
Definition: filtnav.cxx:1344
virtual void AddSupportedFormats() override
Definition: filtnav.cxx:112
bool ValidateText(FmFilterItem const *pItem, OUString &rText, OUString &rErrorMsg) const
Definition: filtnav.cxx:792
virtual bool EditingEntry(SvTreeListEntry *pEntry, Selection &)
Shell * GetShell()
#define DBG_ASSERT(sCon, aError)
bool Remove(const SvTreeListEntry *pEntry)
SvTreeListEntry * m_pEditingCurrently
Definition: filtnav.hxx:232
virtual void dispose()
class SAL_NO_VTABLE XPropertySet
Definition: xmlexchg.hxx:31
virtual Size CalcDockingSize(SfxChildAlignment)
void displayException(const Any &_rExcept, vcl::Window *_pParent)
Definition: fmtools.cxx:121
IMPL_LINK(DataNavigatorWindow, ModelSelectListBoxHdl, ListBox &, rBox, void)
Definition: datanavi.cxx:1421
const ::std::vector< FmFilterItem * > & getDraggedEntries() const
Definition: filtnav.hxx:200
#define DROP_ACTION_TIMER_INITIAL_TICKS
Definition: filtnav.cxx:64
SAL_DLLPRIVATE const css::uno::Reference< css::form::runtime::XFormController > & getActiveInternalController_Lock() const
Definition: fmshimp.hxx:350
bool isDragSource() const
Definition: fmexch.hxx:108
int i
const css::uno::Reference< css::form::runtime::XFormController > & GetController() const
Definition: filtnav.hxx:109
bool IsSelected(SvTreeListEntry *pEntry) const
virtual Image GetImage() const
Definition: filtnav.cxx:133
void * GetUserData() const
CommandEventId GetCommand() const
long Bottom() const
size_t const m_nPos
Definition: filtnav.cxx:193
virtual void Start() override
FmFilterItems * m_pCurrentItems
Definition: filtnav.hxx:157
SvTreeListEntry * getPrevEntry(SvTreeListEntry *_pStartWith)
Definition: filtnav.cxx:1655
virtual SvTreeListEntry * InsertEntry(const OUString &rText, SvTreeListEntry *pParent=nullptr, bool bChildrenOnDemand=false, sal_uLong nPos=TREELIST_APPEND, void *pUserData=nullptr)
void Insert(const ::std::vector< std::unique_ptr< FmFilterData >>::iterator &rPos, std::unique_ptr< FmFilterData > pFilterItem)
Definition: filtnav.cxx:692
void StartListening(SfxBroadcaster &rBroadcaster, DuplicateHandling eDuplicateHanding=DuplicateHandling::Unexpected)
static OUString getUIRootDir()
virtual void InitEntry(SvTreeListEntry *, const OUString &, const Image &, const Image &)
virtual bool Expand(SvTreeListEntry *pParent)
#define HID_FILTER_NAVIGATOR_WIN
Definition: helpids.h:49
void SetTimeout(sal_uInt64 nTimeoutMs)
void GrabFocus()
long GetTextHeight() const
vcl::Window * GetParent() const
FmFilterModel * m_pModel
Definition: filtnav.cxx:235
long X() const
virtual sal_Int8 AcceptDrop(const AcceptDropEvent &rEvt) override
Definition: filtnav.cxx:1219
virtual void SAL_CALL disjunctiveTermAdded(const FilterEvent &Event) override
Definition: filtnav.cxx:444
FmFilterData *const m_pData
Definition: filtnav.cxx:184
void EnableItem(sal_uInt16 nItemId, bool bEnable=true)
Point GetEntryPosition(SvTreeListEntry *) const
OFilterExchangeHelper m_aControlExchange
Definition: filtnav.hxx:233
const Point & GetMousePosPixel() const
SvTreeListEntry * Next(SvTreeListEntry *pEntry) const
IMPL_LINK_NOARG(XFormsPage, TbxSelectHdl, ToolBox *, void)
Definition: datanavi.cxx:399
WinBits const WB_HASLINES
WinBits const WB_3DLOOK
bool IsExpanded(SvTreeListEntry *pEntry) const
WinBits const WB_SIZEABLE
SvTreeListEntry * First() const
SvTreeListEntry * getNextEntry(SvTreeListEntry *_pStartWith)
Definition: filtnav.cxx:1645
static void setText(sal_Int32 nPos, const FmFilterItem *pFilterItem, const OUString &rText)
Definition: filtnav.cxx:298
sal_uInt16 GetChildCount() const
FmFormItem * getSelectedFilterItems(::std::vector< FmFilterItem * > &_rItemList)
returns the first form item and the selected FilterItems in the vector
Definition: filtnav.cxx:1467
const vcl::KeyCode & GetKeyCode() const
const OUString & GetText() const
Definition: filtnav.hxx:69
void Broadcast(const SfxHint &rHint)
void SetSelectionMode(SelectionMode)
bool IsShift() const
virtual sal_Int8 ExecuteDrop(const ExecuteDropEvent &rEvt) override
Definition: filtnav.cxx:1317
css::uno::Reference< css::form::runtime::XFormController > m_xController
Definition: filtnav.hxx:155
virtual void FillInfo(SfxChildWinInfo &) const
const int nxD
Definition: filtnav.cxx:1026
#define KEY_DOWN
SfxItemState
SfxChildAlignment
void SetCurrentItems(FmFilterItems *pCurrent)
Definition: filtnav.cxx:864
void Stop()
FmFormItem * Find(const ::std::vector< std::unique_ptr< FmFilterData >> &rItems, const css::uno::Reference< css::form::runtime::XFormController > &xController) const
#define HID_FILTER_NAVIGATOR
Definition: helpids.h:48
WinBits const WB_BORDER
void SetFont(const vcl::Font &rNewFont)
FmFilterItem(FmFilterItems *pParent, const OUString &aFieldName, const OUString &aCondition, const sal_Int32 _nComponentIndex)
Definition: filtnav.cxx:163
void ReplaceItem(std::unique_ptr< SvLBoxItem > pNewItem, size_t nPos)
ImplSVEvent * PostUserEvent(const Link< void *, void > &rLink, void *pCaller=nullptr, bool bReferenceLink=false)
OUString aName
FmFilterNavigatorWin(SfxBindings *pBindings, SfxChildWindow *pMgr, vcl::Window *pParent)
Definition: filtnav.cxx:1783
::std::vector< std::unique_ptr< FmFilterData > > m_aChildren
Definition: filtnav.hxx:79
SvTreeListEntry * GetEntry(SvTreeListEntry *pParent, sal_uLong nPos) const
virtual void dispose() override
Definition: filtnav.cxx:1093
virtual bool Close() override
Definition: filtnav.cxx:1852
bool IsMod1() const
static VclPtr< reference_type > Create(Arg &&...arg)
void EndListening(SfxBroadcaster &rBroadcaster, bool bRemoveAllDuplicates=false)
void EndSelection()
virtual bool Select(SvTreeListEntry *pEntry, bool bSelect=true) override
Definition: filtnav.cxx:1363
void SetNodeBitmaps(const Image &rCollapsedNodeBmp, const Image &rExpandedNodeBmp)
void * p
Reference< XComponentContext > getProcessComponentContext()
void SetCurrentController(const css::uno::Reference< css::form::runtime::XFormController > &xController)
Definition: filtnav.cxx:645
SvTreeListEntry * Last() const
virtual Size CalcDockingSize(SfxChildAlignment) override
Definition: filtnav.cxx:1873
void SetInvokeHandler(const Link< Timer *, void > &rLink)
PopupMenu * get_menu(const OString &sID)
DROP_ACTION m_aDropActionType
Definition: filtnav.hxx:239
void EditEntry(SvTreeListEntry *pEntry)
std::unique_ptr< FmFilterModel > m_pModel
Definition: filtnav.hxx:231
const css::uno::Reference< css::form::runtime::XFilterController > & GetFilterController() const
Definition: filtnav.hxx:112
long GetTextWidth(const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, vcl::TextLayoutCache const *=nullptr, SalLayoutGlyphs const *const pLayoutCache=nullptr) const
Reference< XConnection > getConnection(const Reference< XRowSet > &_rxRowSet)
void SetTextForItem(FmFilterItem *pItem, const OUString &rText)
Definition: filtnav.cxx:843
::std::vector< std::unique_ptr< FmFilterData > > & GetChildren()
Definition: filtnav.hxx:87
virtual void dispose() override
virtual bool EditingEntry(SvTreeListEntry *pEntry, Selection &rSelection) override
Definition: filtnav.cxx:1128
WinBits const WB_HASBUTTONS
OUString getLabelName(const Reference< css::beans::XPropertySet > &xControlModel)
Definition: fmtools.cxx:195
Reference< XModel > xModel
class FmSearchEngine - Impl class for FmSearchDialog
sal_Int32 GetComponentIndex() const
Definition: filtnav.hxx:142
virtual void Resize() override
WinBits const WB_STDMODELESS
virtual bool Select(SvTreeListEntry *pEntry, bool bSelect=true)
static bool hasFormat(const DataFlavorExVector &_rFormats)
Definition: filtnav.hxx:210
VclPtr< FmFilterNavigator > m_pNavigator
Definition: filtnav.hxx:303
#define DROP_ACTION_TIMER_SCROLL_TICKS
Definition: filtnav.cxx:66
sal_Int8 mnAction
virtual void dispose() override
void StateChanged(sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem *pState) override
Definition: filtnav.cxx:1837
sal_uLong GetSelectionCount() const
void Push(PushFlags nFlags=PushFlags::ALL)
void AddOrRemoveListener(const Reference< XIndexAccess > &_rxControllers, const bool _bAdd)
Definition: filtnav.cxx:275
virtual Image GetImage() const override
Definition: filtnav.cxx:142
virtual ~FmFilterNavigator() override
Definition: filtnav.cxx:1088
SvTreeListEntry * Prev(SvTreeListEntry *pEntry) const
long Y() const
sal_uInt16 nPos
virtual void dispose() override
Definition: filtnav.cxx:1802
#define DROP_ACTION_TIMER_TICK_BASE
Definition: filtnav.cxx:68
OUString sDisplayName
#define KEY_UP
bool IsMod2() const