1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
19 #include <GroupsSorting.hxx>
20 #include <connectivity/dbtools.hxx>
21 #include <sot/exchange.hxx>
22 #include <svtools/editbrowsebox.hxx>
23 #include <svtools/imgdef.hxx>
24 #include <com/sun/star/beans/XPropertySet.hpp>
25 #include <com/sun/star/container/XContainerListener.hpp>
26 #include <com/sun/star/report/GroupOn.hpp>
27 #include <com/sun/star/sdbc/DataType.hpp>
29 #include <strings.hrc>
30 #include <rptui_slotid.hrc>
31 #include <core_resource.hxx>
33 #include "GroupExchange.hxx"
34 #include <UITools.hxx>
35 #include <UndoActions.hxx>
36 #include <strings.hxx>
37 #include <ReportController.hxx>
38 #include <ColumnInfo.hxx>
40 #include <cppuhelper/implbase.hxx>
41 #include <comphelper/property.hxx>
42 #include <vcl/settings.hxx>
46 #include <cppuhelper/bootstrap.hxx>
49 #define FIELD_EXPRESSION 1
50 #define GROUPS_START_LEN 5
55 using namespace ::com::sun::star
;
57 using namespace ::comphelper
;
59 static void lcl_addToList_throw( ComboBoxControl
& _rListBox
, ::std::vector
<ColumnInfo
>& o_aColumnList
,const uno::Reference
< container::XNameAccess
>& i_xColumns
)
61 uno::Sequence
< OUString
> aEntries
= i_xColumns
->getElementNames();
62 const OUString
* pEntries
= aEntries
.getConstArray();
63 sal_Int32 nEntries
= aEntries
.getLength();
64 for ( sal_Int32 i
= 0; i
< nEntries
; ++i
, ++pEntries
)
66 uno::Reference
< beans::XPropertySet
> xColumn(i_xColumns
->getByName(*pEntries
),uno::UNO_QUERY_THROW
);
68 if ( xColumn
->getPropertySetInfo()->hasPropertyByName(PROPERTY_LABEL
) )
69 xColumn
->getPropertyValue(PROPERTY_LABEL
) >>= sLabel
;
70 o_aColumnList
.emplace_back(*pEntries
,sLabel
);
71 if ( !sLabel
.isEmpty() )
72 _rListBox
.InsertEntry( sLabel
);
74 _rListBox
.InsertEntry( *pEntries
);
79 * Separated out from OFieldExpressionControl to prevent collision of ref-counted base classes
81 class OFieldExpressionControl
;
82 class OFieldExpressionControlContainerListener
: public ::cppu::WeakImplHelper
< container::XContainerListener
>
84 VclPtr
<OFieldExpressionControl
> mpParent
;
86 explicit OFieldExpressionControlContainerListener(OFieldExpressionControl
* pParent
) : mpParent(pParent
) {}
89 virtual void SAL_CALL
disposing(const css::lang::EventObject
& Source
) override
;
91 virtual void SAL_CALL
elementInserted(const css::container::ContainerEvent
& rEvent
) override
;
92 virtual void SAL_CALL
elementReplaced(const css::container::ContainerEvent
& rEvent
) override
;
93 virtual void SAL_CALL
elementRemoved(const css::container::ContainerEvent
& rEvent
) override
;
96 class OFieldExpressionControl
: public ::svt::EditBrowseBox
98 ::osl::Mutex m_aMutex
;
99 ::std::vector
<sal_Int32
> m_aGroupPositions
;
100 ::std::vector
<ColumnInfo
> m_aColumnInfo
;
101 VclPtr
< ::svt::ComboBoxControl
> m_pComboCell
;
102 sal_Int32 m_nDataPos
;
103 sal_Int32 m_nCurrentPos
;
104 ImplSVEvent
* m_nDeleteEvent
;
105 VclPtr
<OGroupsSortingDialog
> m_pParent
;
107 rtl::Reference
<OFieldExpressionControlContainerListener
> aContainerListener
;
110 OFieldExpressionControl(OGroupsSortingDialog
* _pParentDialog
, vcl::Window
*_pParent
);
111 virtual ~OFieldExpressionControl() override
;
112 virtual void dispose() override
;
114 // XContainerListener
115 /// @throws css::uno::RuntimeException
116 void elementInserted(const css::container::ContainerEvent
& rEvent
);
117 /// @throws css::uno::RuntimeException
118 void elementRemoved(const css::container::ContainerEvent
& rEvent
);
120 virtual Size
GetOptimalSize() const override
;
122 void fillColumns(const uno::Reference
< container::XNameAccess
>& _xColumns
);
124 bool IsDeleteAllowed( );
127 sal_Int32
getGroupPosition(sal_Int32 _nRow
) const { return _nRow
!= BROWSER_ENDOFSELECTION
? m_aGroupPositions
[_nRow
] : sal_Int32(NO_GROUP
); }
129 ::svt::ComboBoxControl
* getExpressionControl() const { return m_pComboCell
; }
131 /** returns the sequence with the selected groups
133 uno::Sequence
<uno::Any
> fillSelectedGroups();
135 /** move groups given by _aGroups
137 void moveGroups(const uno::Sequence
<uno::Any
>& _aGroups
,sal_Int32 _nRow
,bool _bSelect
= true);
139 virtual bool CursorMoving(long nNewRow
, sal_uInt16 nNewCol
) override
;
140 using ::svt::EditBrowseBox::GetRowCount
;
142 virtual bool IsTabAllowed(bool bForward
) const override
;
144 virtual void InitController( ::svt::CellControllerRef
& rController
, long nRow
, sal_uInt16 nCol
) override
;
145 virtual ::svt::CellController
* GetController( long nRow
, sal_uInt16 nCol
) override
;
146 virtual void PaintCell( OutputDevice
& rDev
, const tools::Rectangle
& rRect
, sal_uInt16 nColId
) const override
;
147 virtual bool SeekRow( long nRow
) override
;
148 virtual bool SaveModified() override
;
149 virtual OUString
GetCellText( long nRow
, sal_uInt16 nColId
) const override
;
150 virtual RowStatus
GetRowStatus(long nRow
) const override
;
152 virtual void KeyInput(const KeyEvent
& rEvt
) override
;
153 virtual void Command( const CommandEvent
& rEvt
) override
;
156 virtual void StartDrag( sal_Int8 nAction
, const Point
& rPosPixel
) override
;
157 virtual sal_Int8
AcceptDrop( const BrowserAcceptDropEvent
& rEvt
) override
;
158 virtual sal_Int8
ExecuteDrop( const BrowserExecuteDropEvent
& rEvt
) override
;
160 using BrowseBox::AcceptDrop
;
161 using BrowseBox::ExecuteDrop
;
165 DECL_LINK( CBChangeHdl
, ComboBox
&, void);
168 DECL_LINK( DelayedDelete
, void*, void );
173 void OFieldExpressionControlContainerListener::disposing(const css::lang::EventObject
& )
176 void OFieldExpressionControlContainerListener::elementInserted(const css::container::ContainerEvent
& rEvent
)
177 { mpParent
->elementInserted(rEvent
); }
179 void OFieldExpressionControlContainerListener::elementReplaced(const css::container::ContainerEvent
& )
182 void OFieldExpressionControlContainerListener::elementRemoved(const css::container::ContainerEvent
& rEvent
)
183 { mpParent
->elementRemoved(rEvent
); }
186 // class OFieldExpressionControl
187 OFieldExpressionControl::OFieldExpressionControl(OGroupsSortingDialog
* _pParentDialog
, vcl::Window
*_pParent
)
188 :EditBrowseBox( _pParent
, EditBrowseBoxFlags::NONE
, WB_TABSTOP
,
189 BrowserMode::COLUMNSELECTION
| BrowserMode::MULTISELECTION
| BrowserMode::AUTOSIZE_LASTCOL
|
190 BrowserMode::KEEPHIGHLIGHT
| BrowserMode::HLINES
| BrowserMode::VLINES
)
191 ,m_aGroupPositions(GROUPS_START_LEN
,-1)
192 ,m_pComboCell(nullptr)
195 ,m_nDeleteEvent(nullptr)
196 ,m_pParent(_pParentDialog
)
197 ,m_bIgnoreEvent(false)
198 ,aContainerListener(new OFieldExpressionControlContainerListener(this))
200 SetBorderStyle(WindowBorderStyle::MONO
);
204 OFieldExpressionControl::~OFieldExpressionControl()
210 void OFieldExpressionControl::dispose()
212 uno::Reference
< report::XGroups
> xGroups
= m_pParent
->getGroups();
213 xGroups
->removeContainerListener(aContainerListener
.get());
215 // delete events from queue
217 Application::RemoveUserEvent( m_nDeleteEvent
);
219 m_pComboCell
.disposeAndClear();
221 ::svt::EditBrowseBox::dispose();
224 uno::Sequence
<uno::Any
> OFieldExpressionControl::fillSelectedGroups()
226 uno::Sequence
<uno::Any
> aList
;
227 ::std::vector
<uno::Any
> vClipboardList
;
228 vClipboardList
.reserve(GetSelectRowCount());
230 uno::Reference
<report::XGroups
> xGroups
= m_pParent
->getGroups();
231 sal_Int32 nCount
= xGroups
->getCount();
234 for( long nIndex
=FirstSelectedRow(); nIndex
!= SFX_ENDOFSELECTION
; nIndex
=NextSelectedRow() )
238 if ( m_aGroupPositions
[nIndex
] != NO_GROUP
)
240 uno::Reference
< report::XGroup
> xOrgGroup(xGroups
->getByIndex(m_aGroupPositions
[nIndex
]),uno::UNO_QUERY
);
241 /*uno::Reference< report::XGroup> xCopy = xGroups->createGroup();
242 ::comphelper::copyProperties(xOrgGroup.get(),xCopy.get());*/
243 vClipboardList
.push_back( uno::makeAny(xOrgGroup
) );
246 catch(uno::Exception
&)
248 OSL_FAIL("Can not access group!");
251 if ( !vClipboardList
.empty() )
252 aList
= uno::Sequence
< uno::Any
>(vClipboardList
.data(), vClipboardList
.size());
257 void OFieldExpressionControl::StartDrag( sal_Int8
/*_nAction*/ , const Point
& /*_rPosPixel*/ )
259 if ( m_pParent
&& !m_pParent
->isReadOnly( ) )
261 uno::Sequence
<uno::Any
> aClipboardList
= fillSelectedGroups();
263 if( aClipboardList
.hasElements() )
265 rtl::Reference
<OGroupExchange
> pData
= new OGroupExchange(aClipboardList
);
266 pData
->StartDrag(this, DND_ACTION_MOVE
);
271 sal_Int8
OFieldExpressionControl::AcceptDrop( const BrowserAcceptDropEvent
& rEvt
)
273 sal_Int8 nAction
= DND_ACTION_NONE
;
276 sal_Int32 nPos
= m_pComboCell
->GetSelectedEntryPos();
277 if ( COMBOBOX_ENTRY_NOTFOUND
!= nPos
|| !m_pComboCell
->GetText().isEmpty() )
281 if ( IsDropFormatSupported( OGroupExchange::getReportGroupId() ) && m_pParent
->getGroups()->getCount() > 1 && rEvt
.GetWindow() == &GetDataWindow() )
283 nAction
= DND_ACTION_MOVE
;
288 sal_Int8
OFieldExpressionControl::ExecuteDrop( const BrowserExecuteDropEvent
& rEvt
)
290 sal_Int8 nAction
= DND_ACTION_NONE
;
291 if ( IsDropFormatSupported( OGroupExchange::getReportGroupId() ) )
293 sal_Int32 nRow
= GetRowAtYPosPixel(rEvt
.maPosPixel
.Y(), false);
296 TransferableDataHelper
aDropped( rEvt
.maDropEvent
.Transferable
);
297 uno::Any aDrop
= aDropped
.GetAny(OGroupExchange::getReportGroupId(), OUString());
298 uno::Sequence
< uno::Any
> aGroups
;
300 if ( aGroups
.hasElements() )
302 moveGroups(aGroups
,nRow
);
303 nAction
= DND_ACTION_MOVE
;
309 void OFieldExpressionControl::moveGroups(const uno::Sequence
<uno::Any
>& _aGroups
,sal_Int32 _nRow
,bool _bSelect
)
311 if ( _aGroups
.hasElements() )
313 m_bIgnoreEvent
= true;
315 sal_Int32 nRow
= _nRow
;
316 const OUString
sUndoAction(RptResId(RID_STR_UNDO_MOVE_GROUP
));
317 const UndoContext
aUndoContext( m_pParent
->m_pController
->getUndoManager(), sUndoAction
);
319 uno::Reference
< report::XGroups
> xGroups
= m_pParent
->getGroups();
320 const uno::Any
* pIter
= _aGroups
.getConstArray();
321 const uno::Any
* pEnd
= pIter
+ _aGroups
.getLength();
322 for(;pIter
!= pEnd
;++pIter
)
324 uno::Reference
< report::XGroup
> xGroup(*pIter
,uno::UNO_QUERY
);
327 uno::Sequence
< beans::PropertyValue
> aArgs(1);
328 aArgs
[0].Name
= PROPERTY_GROUP
;
329 aArgs
[0].Value
<<= xGroup
;
330 // we use this way to create undo actions
331 m_pParent
->m_pController
->executeChecked(SID_GROUP_REMOVE
,aArgs
);
333 if ( nRow
> xGroups
->getCount() )
334 nRow
= xGroups
->getCount();
337 aArgs
[1].Name
= PROPERTY_POSITIONY
;
338 aArgs
[1].Value
<<= nRow
;
339 m_pParent
->m_pController
->executeChecked(SID_GROUP_APPEND
,aArgs
);
344 m_bIgnoreEvent
= false;
349 void OFieldExpressionControl::fillColumns(const uno::Reference
< container::XNameAccess
>& _xColumns
)
351 m_pComboCell
->Clear();
352 if ( _xColumns
.is() )
353 lcl_addToList_throw(*m_pComboCell
,m_aColumnInfo
,_xColumns
);
356 void OFieldExpressionControl::lateInit()
358 uno::Reference
< report::XGroups
> xGroups
= m_pParent
->getGroups();
359 sal_Int32 nGroupsCount
= xGroups
->getCount();
360 m_aGroupPositions
.resize(::std::max
<sal_Int32
>(nGroupsCount
,sal_Int32(GROUPS_START_LEN
)),NO_GROUP
);
361 ::std::vector
<sal_Int32
>::iterator aIter
= m_aGroupPositions
.begin();
362 for (sal_Int32 i
= 0; i
< nGroupsCount
; ++i
,++aIter
)
365 if ( ColCount() == 0 )
367 vcl::Font
aFont( GetDataWindow().GetFont() );
368 aFont
.SetWeight( WEIGHT_NORMAL
);
369 GetDataWindow().SetFont( aFont
);
371 // Set font of the headline to light
373 aFont
.SetWeight( WEIGHT_LIGHT
);
376 InsertHandleColumn(static_cast<sal_uInt16
>(GetTextWidth(OUString('0')) * 4)/*, sal_True */);
377 InsertDataColumn( FIELD_EXPRESSION
, RptResId(STR_RPT_EXPRESSION
), 100);
379 m_pComboCell
= VclPtr
<ComboBoxControl
>::Create( &GetDataWindow() );
380 m_pComboCell
->SetSelectHdl(LINK(this,OFieldExpressionControl
,CBChangeHdl
));
381 m_pComboCell
->SetHelpId(HID_RPT_FIELDEXPRESSION
);
383 m_pComboCell
->SetGetFocusHdl(LINK(m_pParent
, OGroupsSortingDialog
, OnControlFocusGot
));
384 m_pComboCell
->SetLoseFocusHdl(LINK(m_pParent
, OGroupsSortingDialog
, OnControlFocusLost
));
388 BrowserMode
nMode(BrowserMode::COLUMNSELECTION
| BrowserMode::MULTISELECTION
| BrowserMode::KEEPHIGHLIGHT
|
389 BrowserMode::HLINES
| BrowserMode::VLINES
| BrowserMode::AUTOSIZE_LASTCOL
| BrowserMode::AUTO_VSCROLL
| BrowserMode::AUTO_HSCROLL
);
390 if( m_pParent
->isReadOnly() )
391 nMode
|= BrowserMode::HIDECURSOR
;
393 xGroups
->addContainerListener(aContainerListener
.get());
396 // not the first call
397 RowRemoved(0, GetRowCount());
399 RowInserted(0, m_aGroupPositions
.size());
403 IMPL_LINK_NOARG( OFieldExpressionControl
, CBChangeHdl
, ComboBox
&, void )
410 bool OFieldExpressionControl::IsTabAllowed(bool /*bForward*/) const
416 bool OFieldExpressionControl::SaveModified()
418 sal_Int32 nRow
= GetCurRow();
419 if ( nRow
!= BROWSER_ENDOFSELECTION
)
423 bool bAppend
= false;
424 uno::Reference
< report::XGroup
> xGroup
;
425 if ( m_aGroupPositions
[nRow
] == NO_GROUP
)
428 OUString
sUndoAction(RptResId(RID_STR_UNDO_APPEND_GROUP
));
429 m_pParent
->m_pController
->getUndoManager().EnterListAction( sUndoAction
, OUString(), 0, ViewShellId(-1) );
430 xGroup
= m_pParent
->getGroups()->createGroup();
431 xGroup
->setHeaderOn(true);
433 uno::Sequence
< beans::PropertyValue
> aArgs(2);
434 aArgs
[0].Name
= PROPERTY_GROUP
;
435 aArgs
[0].Value
<<= xGroup
;
436 // find position where to insert the new group
437 sal_Int32 nGroupPos
= 0;
438 ::std::vector
<sal_Int32
>::iterator aIter
= m_aGroupPositions
.begin();
439 ::std::vector
<sal_Int32
>::const_iterator aEnd
= m_aGroupPositions
.begin() + nRow
;
440 for(;aIter
!= aEnd
;++aIter
)
441 if ( *aIter
!= NO_GROUP
)
442 nGroupPos
= *aIter
+ 1;
443 aArgs
[1].Name
= PROPERTY_POSITIONY
;
444 aArgs
[1].Value
<<= nGroupPos
;
445 m_bIgnoreEvent
= true;
446 m_pParent
->m_pController
->executeChecked(SID_GROUP_APPEND
,aArgs
);
447 m_bIgnoreEvent
= false;
448 OSL_ENSURE(*aIter
== NO_GROUP
,"Illegal iterator!");
449 *aIter
++ = nGroupPos
;
451 aEnd
= m_aGroupPositions
.end();
452 for(;aIter
!= aEnd
;++aIter
)
453 if ( *aIter
!= NO_GROUP
)
457 xGroup
= m_pParent
->getGroup(m_aGroupPositions
[nRow
]);
460 sal_Int32 nPos
= m_pComboCell
->GetSelectedEntryPos();
461 OUString sExpression
;
462 if ( COMBOBOX_ENTRY_NOTFOUND
== nPos
)
463 sExpression
= m_pComboCell
->GetText();
466 sExpression
= m_aColumnInfo
[nPos
].sColumnName
;
468 xGroup
->setExpression( sExpression
);
470 ::rptui::adjustSectionName(xGroup
,nPos
);
473 m_pParent
->m_pController
->getUndoManager().LeaveListAction();
476 if ( Controller().is() )
477 Controller()->ClearModified();
478 if ( GetRowCount() == m_pParent
->getGroups()->getCount() )
480 RowInserted( GetRowCount()-1);
481 m_aGroupPositions
.push_back(NO_GROUP
);
485 m_pParent
->DisplayData(nRow
);
487 catch(uno::Exception
&)
489 OSL_FAIL("OFieldExpressionControl::SaveModified: Exception caught!");
496 OUString
OFieldExpressionControl::GetCellText( long nRow
, sal_uInt16
/*nColId*/ ) const
499 if ( nRow
!= BROWSER_ENDOFSELECTION
&& m_aGroupPositions
[nRow
] != NO_GROUP
)
503 uno::Reference
< report::XGroup
> xGroup
= m_pParent
->getGroup(m_aGroupPositions
[nRow
]);
504 OUString sExpression
= xGroup
->getExpression();
506 auto aIter
= std::find_if(m_aColumnInfo
.begin(), m_aColumnInfo
.end(),
507 [&sExpression
](const ColumnInfo
& rColumnInfo
) { return rColumnInfo
.sColumnName
== sExpression
; });
508 if (aIter
!= m_aColumnInfo
.end() && !aIter
->sLabel
.isEmpty())
509 sExpression
= aIter
->sLabel
;
512 catch (const uno::Exception
&)
514 OSL_FAIL("Exception caught while getting expression value from the group");
521 void OFieldExpressionControl::InitController( CellControllerRef
& /*rController*/, long nRow
, sal_uInt16 nColumnId
)
524 m_pComboCell
->SetText( GetCellText( nRow
, nColumnId
) );
527 bool OFieldExpressionControl::CursorMoving(long nNewRow
, sal_uInt16 nNewCol
)
530 if (!EditBrowseBox::CursorMoving(nNewRow
, nNewCol
))
532 m_nDataPos
= nNewRow
;
533 long nOldDataPos
= GetCurRow();
534 InvalidateStatusCell( m_nDataPos
);
535 InvalidateStatusCell( nOldDataPos
);
537 m_pParent
->SaveData( nOldDataPos
);
538 m_pParent
->DisplayData( m_nDataPos
);
542 CellController
* OFieldExpressionControl::GetController( long /*nRow*/, sal_uInt16
/*nColumnId*/ )
544 ComboBoxCellController
* pCellController
= new ComboBoxCellController( m_pComboCell
);
545 pCellController
->GetComboBox().SetReadOnly(!m_pParent
->m_pController
->isEditable());
546 return pCellController
;
550 bool OFieldExpressionControl::SeekRow( long _nRow
)
552 // the basis class needs the call, because that's how the class knows which line will be painted
553 EditBrowseBox::SeekRow(_nRow
);
554 m_nCurrentPos
= _nRow
;
559 void OFieldExpressionControl::PaintCell( OutputDevice
& rDev
, const tools::Rectangle
& rRect
, sal_uInt16 nColumnId
) const
561 OUString aText
=GetCellText( m_nCurrentPos
, nColumnId
);
563 Point
aPos( rRect
.TopLeft() );
564 Size
aTextSize( GetDataWindow().GetTextWidth( aText
), GetDataWindow().GetTextHeight() );
566 if( aPos
.X() < rRect
.Left() || aPos
.X() + aTextSize
.Width() > rRect
.Right() ||
567 aPos
.Y() < rRect
.Top() || aPos
.Y() + aTextSize
.Height() > rRect
.Bottom() )
568 rDev
.SetClipRegion(vcl::Region(rRect
));
570 rDev
.DrawText( aPos
, aText
);
572 if( rDev
.IsClipRegion() )
573 rDev
.SetClipRegion();
576 EditBrowseBox::RowStatus
OFieldExpressionControl::GetRowStatus(long nRow
) const
578 if (nRow
>= 0 && nRow
== m_nDataPos
)
579 return EditBrowseBox::CURRENT
;
580 if ( nRow
!= BROWSER_ENDOFSELECTION
&& nRow
< static_cast<long>(m_aGroupPositions
.size()) && m_aGroupPositions
[nRow
] != NO_GROUP
)
584 uno::Reference
< report::XGroup
> xGroup
= m_pParent
->getGroup(m_aGroupPositions
[nRow
]);
585 return (xGroup
->getHeaderOn() || xGroup
->getFooterOn())? EditBrowseBox::HEADERFOOTER
: EditBrowseBox::CLEAN
;
587 catch(uno::Exception
&)
589 OSL_FAIL("Exception caught while try to get a group!");
592 return EditBrowseBox::CLEAN
;
595 // XContainerListener
597 void OFieldExpressionControl::elementInserted(const container::ContainerEvent
& evt
)
599 if ( m_bIgnoreEvent
)
601 SolarMutexGuard aSolarGuard
;
602 ::osl::MutexGuard
aGuard( m_aMutex
);
603 sal_Int32 nGroupPos
= 0;
604 if ( evt
.Accessor
>>= nGroupPos
)
606 if ( nGroupPos
>= GetRowCount() )
608 sal_Int32 nAddedRows
= nGroupPos
- GetRowCount();
609 RowInserted(nAddedRows
);
610 for (sal_Int32 i
= 0; i
< nAddedRows
; ++i
)
611 m_aGroupPositions
.push_back(NO_GROUP
);
612 m_aGroupPositions
[nGroupPos
] = nGroupPos
;
616 ::std::vector
<sal_Int32
>::iterator aFind
= m_aGroupPositions
.begin()+ nGroupPos
;
617 if ( aFind
== m_aGroupPositions
.end() )
618 aFind
= ::std::find(m_aGroupPositions
.begin(),m_aGroupPositions
.end(),NO_GROUP
);
620 if ( aFind
!= m_aGroupPositions
.end() )
622 if ( *aFind
!= NO_GROUP
)
623 aFind
= m_aGroupPositions
.insert(aFind
,nGroupPos
);
627 ::std::vector
<sal_Int32
>::const_iterator aEnd
= m_aGroupPositions
.end();
628 for(++aFind
;aFind
!= aEnd
;++aFind
)
629 if ( *aFind
!= NO_GROUP
)
637 void OFieldExpressionControl::elementRemoved(const container::ContainerEvent
& evt
)
639 SolarMutexGuard aSolarGuard
;
640 ::osl::MutexGuard
aGuard( m_aMutex
);
642 if ( m_bIgnoreEvent
)
645 sal_Int32 nGroupPos
= 0;
646 if ( evt
.Accessor
>>= nGroupPos
)
648 std::vector
<sal_Int32
>::iterator aEnd
= m_aGroupPositions
.end();
649 std::vector
<sal_Int32
>::iterator aFind
= std::find(m_aGroupPositions
.begin(), aEnd
, nGroupPos
);
653 for(++aFind
;aFind
!= aEnd
;++aFind
)
654 if ( *aFind
!= NO_GROUP
)
661 bool OFieldExpressionControl::IsDeleteAllowed( )
663 return !m_pParent
->isReadOnly() && GetSelectRowCount() > 0;
666 void OFieldExpressionControl::KeyInput( const KeyEvent
& rEvt
)
668 if (IsDeleteAllowed())
670 if (rEvt
.GetKeyCode().GetCode() == KEY_DELETE
&& // Delete rows
671 !rEvt
.GetKeyCode().IsShift() &&
672 !rEvt
.GetKeyCode().IsMod1())
678 EditBrowseBox::KeyInput(rEvt
);
681 void OFieldExpressionControl::Command(const CommandEvent
& rEvt
)
683 switch (rEvt
.GetCommand())
685 case CommandEventId::ContextMenu
:
687 if (!rEvt
.IsMouseEvent())
689 EditBrowseBox::Command(rEvt
);
693 sal_uInt16 nColId
= GetColumnId(GetColumnAtXPosPixel(rEvt
.GetMousePosPixel().X()));
695 if ( nColId
== HANDLE_ID
)
697 bool bEnable
= false;
698 long nIndex
= FirstSelectedRow();
699 while( nIndex
!= SFX_ENDOFSELECTION
&& !bEnable
)
701 if ( m_aGroupPositions
[nIndex
] != NO_GROUP
)
703 nIndex
= NextSelectedRow();
705 VclBuilder
aBuilder(nullptr, VclBuilderContainer::getUIRootDir(), "modules/dbreport/ui/groupsortmenu.ui", "");
706 VclPtr
<PopupMenu
> aContextMenu(aBuilder
.get_menu("menu"));
707 aContextMenu
->EnableItem(aContextMenu
->GetItemId("delete"), IsDeleteAllowed() && bEnable
);
708 if (aContextMenu
->Execute(this, rEvt
.GetMousePosPixel()))
711 Application::RemoveUserEvent( m_nDeleteEvent
);
712 m_nDeleteEvent
= Application::PostUserEvent( LINK(this, OFieldExpressionControl
, DelayedDelete
), nullptr, true );
718 EditBrowseBox::Command(rEvt
);
723 void OFieldExpressionControl::DeleteRows()
726 bool bIsEditing
= IsEditing();
731 long nIndex
= FirstSelectedRow();
732 if (nIndex
== SFX_ENDOFSELECTION
)
734 nIndex
= GetCurRow();
736 bool bFirstTime
= true;
738 long nOldDataPos
= nIndex
;
739 uno::Sequence
< beans::PropertyValue
> aArgs(1);
740 aArgs
[0].Name
= PROPERTY_GROUP
;
741 m_bIgnoreEvent
= true;
744 if ( m_aGroupPositions
[nIndex
] != NO_GROUP
)
749 OUString
sUndoAction(RptResId(RID_STR_UNDO_REMOVE_SELECTION
));
750 m_pParent
->m_pController
->getUndoManager().EnterListAction( sUndoAction
, OUString(), 0, ViewShellId(-1) );
753 sal_Int32 nGroupPos
= m_aGroupPositions
[nIndex
];
754 uno::Reference
< report::XGroup
> xGroup
= m_pParent
->getGroup(nGroupPos
);
755 aArgs
[0].Value
<<= xGroup
;
756 // we use this way to create undo actions
757 m_pParent
->m_pController
->executeChecked(SID_GROUP_REMOVE
,aArgs
);
759 std::vector
<sal_Int32
>::iterator aEnd
= m_aGroupPositions
.end();
760 std::vector
<sal_Int32
>::iterator aFind
= std::find(m_aGroupPositions
.begin(), aEnd
, nGroupPos
);
764 for(++aFind
;aFind
!= aEnd
;++aFind
)
765 if ( *aFind
!= NO_GROUP
)
769 nIndex
= NextSelectedRow();
773 m_pParent
->m_pController
->getUndoManager().LeaveListAction();
775 m_nDataPos
= GetCurRow();
776 InvalidateStatusCell( nOldDataPos
);
777 InvalidateStatusCell( m_nDataPos
);
779 m_pParent
->DisplayData( m_nDataPos
);
780 m_bIgnoreEvent
= false;
784 IMPL_LINK_NOARG( OFieldExpressionControl
, DelayedDelete
, void*, void )
786 m_nDeleteEvent
= nullptr;
790 Size
OFieldExpressionControl::GetOptimalSize() const
792 return LogicToPixel(Size(106, 75), MapMode(MapUnit::MapAppFont
));
795 // class OGroupsSortingDialog
796 OGroupsSortingDialog::OGroupsSortingDialog(vcl::Window
* _pParent
, bool _bReadOnly
,
797 OReportController
* _pController
)
798 : FloatingWindow(_pParent
, "FloatingSort", "modules/dbreport/ui/floatingsort.ui")
799 , OPropertyChangeListener(m_aMutex
)
800 , m_pController(_pController
)
801 , m_xGroups(m_pController
->getReportDefinition()->getGroups())
802 , m_bReadOnly(_bReadOnly
)
804 get(m_pToolBox
, "toolbox");
805 m_nMoveUpId
= m_pToolBox
->GetItemId(0);
806 m_nMoveDownId
= m_pToolBox
->GetItemId(1);
807 m_nDeleteId
= m_pToolBox
->GetItemId(2);
808 get(m_pOrderLst
, "sorting");
809 get(m_pHeaderLst
, "header");
810 get(m_pFooterLst
, "footer");
811 get(m_pGroupOnLst
, "group");
812 get(m_pGroupIntervalEd
, "interval");
813 get(m_pKeepTogetherLst
, "keep");
814 get(m_pHelpWindow
, "helptext");
815 m_pHelpWindow
->set_height_request(GetTextHeight() * 4);
816 get(m_pProperties
, "properties");
817 m_pFieldExpression
= VclPtr
<OFieldExpressionControl
>::Create(this, get
<vcl::Window
>("box"));
818 m_pFieldExpression
->set_hexpand(true);
819 m_pFieldExpression
->set_vexpand(true);
821 Control
* pControlsLst
[] = { m_pHeaderLst
, m_pFooterLst
, m_pGroupOnLst
, m_pKeepTogetherLst
, m_pOrderLst
, m_pGroupIntervalEd
};
822 for (Control
* i
: pControlsLst
)
824 i
->SetGetFocusHdl(LINK(this, OGroupsSortingDialog
, OnControlFocusGot
));
825 i
->SetLoseFocusHdl(LINK(this, OGroupsSortingDialog
, OnControlFocusLost
));
829 for (size_t i
= 0; i
< SAL_N_ELEMENTS(pControlsLst
) - 1; ++i
)
830 static_cast<ListBox
*>(pControlsLst
[i
])->SetSelectHdl(LINK(this,OGroupsSortingDialog
,LBChangeHdl
));
832 m_pReportListener
= new OPropertyChangeMultiplexer(this,m_pController
->getReportDefinition().get());
833 m_pReportListener
->addProperty(PROPERTY_COMMAND
);
834 m_pReportListener
->addProperty(PROPERTY_COMMANDTYPE
);
836 m_pFieldExpression
->lateInit();
838 m_pFieldExpression
->Show();
840 m_pHelpWindow
->SetControlBackground( GetSettings().GetStyleSettings().GetFaceColor() );
842 m_pToolBox
->SetLineSpacing(true);
843 m_pToolBox
->SetSelectHdl(LINK(this, OGroupsSortingDialog
, OnFormatAction
));
850 OGroupsSortingDialog::~OGroupsSortingDialog()
855 void OGroupsSortingDialog::dispose()
858 m_pReportListener
->dispose();
859 if ( m_pCurrentGroupListener
.is() )
860 m_pCurrentGroupListener
->dispose();
862 m_pProperties
.clear();
864 m_pHeaderLst
.clear();
865 m_pFooterLst
.clear();
866 m_pGroupOnLst
.clear();
867 m_pGroupIntervalEd
.clear();
868 m_pKeepTogetherLst
.clear();
869 m_pHelpWindow
.clear();
870 m_pFieldExpression
.disposeAndClear();
871 FloatingWindow::dispose();
874 void OGroupsSortingDialog::UpdateData( )
876 m_pFieldExpression
->Invalidate();
877 long nCurRow
= m_pFieldExpression
->GetCurRow();
878 m_pFieldExpression
->DeactivateCell();
879 m_pFieldExpression
->ActivateCell(nCurRow
, m_pFieldExpression
->GetCurColumnId());
880 DisplayData(nCurRow
);
883 void OGroupsSortingDialog::DisplayData( sal_Int32 _nRow
)
885 const sal_Int32 nGroupPos
= m_pFieldExpression
->getGroupPosition(_nRow
);
886 const bool bEmpty
= nGroupPos
== NO_GROUP
;
887 m_pProperties
->Enable(!bEmpty
);
891 if ( m_pCurrentGroupListener
.is() )
892 m_pCurrentGroupListener
->dispose();
893 m_pCurrentGroupListener
= nullptr;
896 uno::Reference
< report::XGroup
> xGroup
= getGroup(nGroupPos
);
898 m_pCurrentGroupListener
= new OPropertyChangeMultiplexer(this,xGroup
.get());
899 m_pCurrentGroupListener
->addProperty(PROPERTY_HEADERON
);
900 m_pCurrentGroupListener
->addProperty(PROPERTY_FOOTERON
);
902 displayGroup(xGroup
);
906 void OGroupsSortingDialog::SaveData( sal_Int32 _nRow
)
908 sal_Int32 nGroupPos
= m_pFieldExpression
->getGroupPosition(_nRow
);
909 if ( nGroupPos
== NO_GROUP
)
912 uno::Reference
< report::XGroup
> xGroup
= getGroup(nGroupPos
);
913 if ( m_pHeaderLst
->IsValueChangedFromSaved() )
914 xGroup
->setHeaderOn( m_pHeaderLst
->GetSelectedEntryPos() == 0 );
915 if ( m_pFooterLst
->IsValueChangedFromSaved() )
916 xGroup
->setFooterOn( m_pFooterLst
->GetSelectedEntryPos() == 0 );
917 if ( m_pKeepTogetherLst
->IsValueChangedFromSaved() )
918 xGroup
->setKeepTogether( m_pKeepTogetherLst
->GetSelectedEntryPos() );
919 if ( m_pGroupOnLst
->IsValueChangedFromSaved() )
921 sal_Int16 nGroupOn
= static_cast<sal_Int16
>(reinterpret_cast<sal_IntPtr
>(m_pGroupOnLst
->GetSelectedEntryData()));
922 xGroup
->setGroupOn( nGroupOn
);
924 if ( m_pGroupIntervalEd
->IsValueChangedFromSaved() )
926 xGroup
->setGroupInterval( static_cast<sal_Int32
>(m_pGroupIntervalEd
->GetValue()) );
927 m_pGroupIntervalEd
->SaveValue();
929 if ( m_pOrderLst
->IsValueChangedFromSaved() )
930 xGroup
->setSortAscending( m_pOrderLst
->GetSelectedEntryPos() == 0 );
932 ListBox
* pControls
[] = { m_pHeaderLst
, m_pFooterLst
, m_pGroupOnLst
, m_pKeepTogetherLst
, m_pOrderLst
};
933 for (ListBox
* pControl
: pControls
)
934 pControl
->SaveValue();
938 sal_Int32
OGroupsSortingDialog::getColumnDataType(const OUString
& _sColumnName
)
940 sal_Int32 nDataType
= sdbc::DataType::VARCHAR
;
943 if ( !m_xColumns
.is() )
945 if ( m_xColumns
.is() && m_xColumns
->hasByName(_sColumnName
) )
947 uno::Reference
< beans::XPropertySet
> xColumn(m_xColumns
->getByName(_sColumnName
),uno::UNO_QUERY
);
949 xColumn
->getPropertyValue(PROPERTY_TYPE
) >>= nDataType
;
952 catch(uno::Exception
&)
954 OSL_FAIL("Exception caught while getting the type of a column");
960 IMPL_LINK(OGroupsSortingDialog
, OnControlFocusGot
, Control
&, rControl
, void )
962 if ( m_pFieldExpression
&& m_pFieldExpression
->getExpressionControl() )
964 const std::pair
<Control
*, const char*> pControls
[] = {
965 { m_pFieldExpression
->getExpressionControl(), STR_RPT_HELP_FIELD
},
966 { m_pHeaderLst
, STR_RPT_HELP_HEADER
},
967 { m_pFooterLst
, STR_RPT_HELP_FOOTER
},
968 { m_pGroupOnLst
, STR_RPT_HELP_GROUPON
},
969 { m_pGroupIntervalEd
, STR_RPT_HELP_INTERVAL
},
970 { m_pKeepTogetherLst
, STR_RPT_HELP_KEEP
},
971 { m_pOrderLst
, STR_RPT_HELP_SORT
}
973 for (size_t i
= 0; i
< SAL_N_ELEMENTS(pControls
); ++i
)
975 if (&rControl
== pControls
[i
].first
)
977 ListBox
* pListBox
= dynamic_cast< ListBox
* >( &rControl
);
979 pListBox
->SaveValue();
980 NumericField
* pNumericField
= dynamic_cast< NumericField
* >( &rControl
);
982 pNumericField
->SaveValue();
983 //shows the text given by the id in the multiline edit
984 m_pHelpWindow
->SetText(RptResId(pControls
[i
].second
));
991 IMPL_LINK(OGroupsSortingDialog
, OnControlFocusLost
, Control
&, rControl
, void )
993 if (m_pFieldExpression
&& &rControl
== m_pGroupIntervalEd
)
995 if ( m_pGroupIntervalEd
->IsModified() )
996 SaveData(m_pFieldExpression
->GetCurRow());
1000 IMPL_LINK_NOARG( OGroupsSortingDialog
, OnFormatAction
, ToolBox
*, void )
1003 sal_uInt16 nCommand
= m_pToolBox
->GetCurItemId();
1005 if ( m_pFieldExpression
)
1007 long nIndex
= m_pFieldExpression
->GetCurrRow();
1008 sal_Int32 nGroupPos
= m_pFieldExpression
->getGroupPosition(nIndex
);
1009 uno::Sequence
<uno::Any
> aClipboardList
;
1010 if ( nIndex
>= 0 && nGroupPos
!= NO_GROUP
)
1012 aClipboardList
.realloc(1);
1013 aClipboardList
[0] = m_xGroups
->getByIndex(nGroupPos
);
1015 if ( nCommand
== m_nMoveUpId
)
1019 if ( nCommand
== m_nMoveDownId
)
1023 if ( nCommand
== m_nDeleteId
)
1025 Application::PostUserEvent( LINK(m_pFieldExpression
, OFieldExpressionControl
, DelayedDelete
), nullptr, true );
1029 if ( nIndex
>= 0 && aClipboardList
.hasElements() )
1031 m_pFieldExpression
->SetNoSelection();
1032 m_pFieldExpression
->moveGroups(aClipboardList
,nIndex
,false);
1033 m_pFieldExpression
->DeactivateCell();
1034 m_pFieldExpression
->GoToRow(nIndex
);
1035 m_pFieldExpression
->ActivateCell(nIndex
, m_pFieldExpression
->GetCurColumnId());
1036 DisplayData(nIndex
);
1042 IMPL_LINK( OGroupsSortingDialog
, LBChangeHdl
, ListBox
&, rListBox
, void )
1044 if ( rListBox
.IsValueChangedFromSaved() )
1046 sal_Int32 nRow
= m_pFieldExpression
->GetCurRow();
1047 sal_Int32 nGroupPos
= m_pFieldExpression
->getGroupPosition(nRow
);
1048 if (&rListBox
!= m_pHeaderLst
&& &rListBox
!= m_pFooterLst
)
1050 if ( rListBox
.IsValueChangedFromSaved() )
1052 if ( &rListBox
== m_pGroupOnLst
)
1053 m_pGroupIntervalEd
->Enable( rListBox
.GetSelectedEntryPos() != 0 );
1055 else if ( nGroupPos
!= NO_GROUP
)
1057 uno::Reference
< report::XGroup
> xGroup
= getGroup(nGroupPos
);
1058 uno::Sequence
< beans::PropertyValue
> aArgs(2);
1059 aArgs
[1].Name
= PROPERTY_GROUP
;
1060 aArgs
[1].Value
<<= xGroup
;
1062 if ( m_pHeaderLst
== &rListBox
)
1063 aArgs
[0].Name
= PROPERTY_HEADERON
;
1065 aArgs
[0].Name
= PROPERTY_FOOTERON
;
1067 aArgs
[0].Value
<<= rListBox
.GetSelectedEntryPos() == 0;
1068 m_pController
->executeChecked(m_pHeaderLst
== &rListBox
? SID_GROUPHEADER
: SID_GROUPFOOTER
, aArgs
);
1069 m_pFieldExpression
->InvalidateHandleColumn();
1074 void OGroupsSortingDialog::_propertyChanged(const beans::PropertyChangeEvent
& _rEvent
)
1076 uno::Reference
< report::XGroup
> xGroup(_rEvent
.Source
,uno::UNO_QUERY
);
1078 displayGroup(xGroup
);
1083 void OGroupsSortingDialog::fillColumns()
1085 m_xColumns
= m_pController
->getColumns();
1086 m_pFieldExpression
->fillColumns(m_xColumns
);
1089 void OGroupsSortingDialog::displayGroup(const uno::Reference
<report::XGroup
>& _xGroup
)
1091 m_pHeaderLst
->SelectEntryPos(_xGroup
->getHeaderOn() ? 0 : 1 );
1092 m_pFooterLst
->SelectEntryPos(_xGroup
->getFooterOn() ? 0 : 1 );
1093 sal_Int32 nDataType
= getColumnDataType(_xGroup
->getExpression());
1095 // first clear whole group on list
1096 while(m_pGroupOnLst
->GetEntryCount() > 1 )
1098 m_pGroupOnLst
->RemoveEntry(1);
1103 case sdbc::DataType::LONGVARCHAR
:
1104 case sdbc::DataType::VARCHAR
:
1105 case sdbc::DataType::CHAR
:
1106 m_pGroupOnLst
->InsertEntry(RptResId(STR_RPT_PREFIXCHARS
));
1107 m_pGroupOnLst
->SetEntryData(1,reinterpret_cast<void*>(report::GroupOn::PREFIX_CHARACTERS
));
1109 case sdbc::DataType::DATE
:
1110 case sdbc::DataType::TIME
:
1111 case sdbc::DataType::TIMESTAMP
:
1113 const char* aIds
[] = { STR_RPT_YEAR
, STR_RPT_QUARTER
,STR_RPT_MONTH
,STR_RPT_WEEK
,STR_RPT_DAY
,STR_RPT_HOUR
,STR_RPT_MINUTE
};
1114 for (size_t i
= 0; i
< SAL_N_ELEMENTS(aIds
); ++i
)
1116 m_pGroupOnLst
->InsertEntry(RptResId(aIds
[i
]));
1117 m_pGroupOnLst
->SetEntryData(i
+1,reinterpret_cast<void*>(i
+2));
1122 m_pGroupOnLst
->InsertEntry(RptResId(STR_RPT_INTERVAL
));
1123 m_pGroupOnLst
->SetEntryData(1,reinterpret_cast<void*>(report::GroupOn::INTERVAL
));
1127 switch(_xGroup
->getGroupOn())
1129 case report::GroupOn::DEFAULT
:
1132 case report::GroupOn::PREFIX_CHARACTERS
:
1135 case report::GroupOn::YEAR
:
1138 case report::GroupOn::QUARTAL
:
1141 case report::GroupOn::MONTH
:
1144 case report::GroupOn::WEEK
:
1147 case report::GroupOn::DAY
:
1150 case report::GroupOn::HOUR
:
1153 case report::GroupOn::MINUTE
:
1156 case report::GroupOn::INTERVAL
:
1162 m_pGroupOnLst
->SelectEntryPos(nPos
);
1163 m_pGroupIntervalEd
->SetText(OUString::number(_xGroup
->getGroupInterval()));
1164 m_pGroupIntervalEd
->SaveValue();
1165 m_pGroupIntervalEd
->Enable( nPos
!= 0 );
1166 m_pKeepTogetherLst
->SelectEntryPos(_xGroup
->getKeepTogether());
1167 m_pOrderLst
->SelectEntryPos(_xGroup
->getSortAscending() ? 0 : 1);
1169 ListBox
* pControls
[] = { m_pHeaderLst
, m_pFooterLst
, m_pGroupOnLst
, m_pKeepTogetherLst
, m_pOrderLst
};
1170 for (ListBox
* pControl
: pControls
)
1171 pControl
->SaveValue();
1173 ListBox
* pControlsLst2
[] = { m_pHeaderLst
, m_pFooterLst
, m_pGroupOnLst
, m_pKeepTogetherLst
, m_pOrderLst
};
1174 bool bReadOnly
= !m_pController
->isEditable();
1175 for (ListBox
* i
: pControlsLst2
)
1176 i
->SetReadOnly(bReadOnly
);
1177 m_pGroupIntervalEd
->SetReadOnly(bReadOnly
);
1180 void OGroupsSortingDialog::checkButtons(sal_Int32 _nRow
)
1182 sal_Int32 nGroupCount
= m_xGroups
->getCount();
1183 sal_Int32 nRowCount
= m_pFieldExpression
->GetRowCount();
1184 bool bEnabled
= nGroupCount
> 1;
1186 if (bEnabled
&& _nRow
> 0 )
1188 m_pToolBox
->EnableItem(m_nMoveUpId
);
1192 m_pToolBox
->EnableItem(m_nMoveUpId
, false);
1194 if (bEnabled
&& _nRow
< (nRowCount
- 1) )
1196 m_pToolBox
->EnableItem(m_nMoveDownId
);
1200 m_pToolBox
->EnableItem(m_nMoveDownId
, false);
1203 sal_Int32 nGroupPos
= m_pFieldExpression
->getGroupPosition(_nRow
);
1204 if ( nGroupPos
!= NO_GROUP
)
1206 bool bEnableDelete
= nGroupCount
> 0;
1207 m_pToolBox
->EnableItem(m_nDeleteId
, bEnableDelete
);
1211 m_pToolBox
->EnableItem(m_nDeleteId
, false);
1217 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */