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