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 #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>
28 
29 #include <strings.hrc>
30 #include <rptui_slotid.hrc>
31 #include <core_resource.hxx>
32 #include <helpids.h>
33 #include "GroupExchange.hxx"
34 #include <UITools.hxx>
35 #include <UndoActions.hxx>
36 #include <strings.hxx>
37 #include <ReportController.hxx>
38 #include <ColumnInfo.hxx>
39 
40 #include <cppuhelper/implbase.hxx>
41 #include <comphelper/property.hxx>
42 #include <vcl/settings.hxx>
43 
44 #include <algorithm>
45 
46 #include <cppuhelper/bootstrap.hxx>
47 
48 #define HANDLE_ID           0
49 #define FIELD_EXPRESSION    1
50 #define GROUPS_START_LEN    5
51 #define NO_GROUP            -1
52 
53 namespace rptui
54 {
55 using namespace ::com::sun::star;
56 using namespace svt;
57 using namespace ::comphelper;
58 
lcl_addToList_throw(ComboBoxControl & _rListBox,::std::vector<ColumnInfo> & o_aColumnList,const uno::Reference<container::XNameAccess> & i_xColumns)59     static void lcl_addToList_throw( ComboBoxControl& _rListBox, ::std::vector<ColumnInfo>& o_aColumnList,const uno::Reference< container::XNameAccess>& i_xColumns )
60     {
61         const uno::Sequence< OUString > aEntries = i_xColumns->getElementNames();
62         for ( const OUString& rEntry : aEntries )
63         {
64             uno::Reference< beans::XPropertySet> xColumn(i_xColumns->getByName(rEntry),uno::UNO_QUERY_THROW);
65             OUString sLabel;
66             if ( xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_LABEL) )
67                 xColumn->getPropertyValue(PROPERTY_LABEL) >>= sLabel;
68             o_aColumnList.emplace_back(rEntry,sLabel );
69             if ( !sLabel.isEmpty() )
70                 _rListBox.InsertEntry( sLabel );
71             else
72                 _rListBox.InsertEntry( rEntry );
73         }
74     }
75 
76 /**
77   * Separated out from OFieldExpressionControl to prevent collision of ref-counted base classes
78   */
79 class OFieldExpressionControl;
80 class OFieldExpressionControlContainerListener : public ::cppu::WeakImplHelper< container::XContainerListener >
81 {
82     VclPtr<OFieldExpressionControl> mpParent;
83 public:
OFieldExpressionControlContainerListener(OFieldExpressionControl * pParent)84     explicit OFieldExpressionControlContainerListener(OFieldExpressionControl* pParent) : mpParent(pParent) {}
85 
86     // XEventListener
87     virtual void SAL_CALL disposing(const css::lang::EventObject& Source) override;
88     // XContainerListener
89     virtual void SAL_CALL elementInserted(const css::container::ContainerEvent& rEvent) override;
90     virtual void SAL_CALL elementReplaced(const css::container::ContainerEvent& rEvent) override;
91     virtual void SAL_CALL elementRemoved(const css::container::ContainerEvent& rEvent) override;
92 };
93 
94 class OFieldExpressionControl : public ::svt::EditBrowseBox
95 {
96     ::osl::Mutex                    m_aMutex;
97     ::std::vector<sal_Int32>        m_aGroupPositions;
98     ::std::vector<ColumnInfo>       m_aColumnInfo;
99     VclPtr< ::svt::ComboBoxControl>  m_pComboCell;
100     sal_Int32                       m_nDataPos;
101     sal_Int32                       m_nCurrentPos;
102     ImplSVEvent *                   m_nDeleteEvent;
103     VclPtr<OGroupsSortingDialog>    m_pParent;
104     bool                            m_bIgnoreEvent;
105     rtl::Reference<OFieldExpressionControlContainerListener> aContainerListener;
106 
107 public:
108     OFieldExpressionControl(OGroupsSortingDialog* _pParentDialog, vcl::Window *_pParent);
109     virtual ~OFieldExpressionControl() override;
110     virtual void dispose() override;
111 
112     // XContainerListener
113     /// @throws css::uno::RuntimeException
114     void elementInserted(const css::container::ContainerEvent& rEvent);
115     /// @throws css::uno::RuntimeException
116     void elementRemoved(const css::container::ContainerEvent& rEvent);
117 
118     virtual Size GetOptimalSize() const override;
119 
120     void        fillColumns(const uno::Reference< container::XNameAccess>& _xColumns);
121     void        lateInit();
122     bool    IsDeleteAllowed( ) const;
123     void        DeleteRows();
124 
getGroupPosition(sal_Int32 _nRow) const125     sal_Int32   getGroupPosition(sal_Int32 _nRow) const { return _nRow != BROWSER_ENDOFSELECTION ? m_aGroupPositions[_nRow] : sal_Int32(NO_GROUP); }
126 
getExpressionControl() const127     ::svt::ComboBoxControl*  getExpressionControl() const { return m_pComboCell; }
128 
129     /** returns the sequence with the selected groups
130     */
131     uno::Sequence<uno::Any> fillSelectedGroups();
132 
133     /** move groups given by _aGroups
134     */
135     void moveGroups(const uno::Sequence<uno::Any>& _aGroups,sal_Int32 _nRow,bool _bSelect = true);
136 
137     virtual bool CursorMoving(long nNewRow, sal_uInt16 nNewCol) override;
138     using ::svt::EditBrowseBox::GetRowCount;
139 protected:
140     virtual bool IsTabAllowed(bool bForward) const override;
141 
142     virtual void InitController( ::svt::CellControllerRef& rController, long nRow, sal_uInt16 nCol ) override;
143     virtual ::svt::CellController* GetController( long nRow, sal_uInt16 nCol ) override;
144     virtual void PaintCell( OutputDevice& rDev, const tools::Rectangle& rRect, sal_uInt16 nColId ) const override;
145     virtual bool SeekRow( long nRow ) override;
146     virtual bool SaveModified() override;
147     virtual OUString GetCellText( long nRow, sal_uInt16 nColId ) const override;
148     virtual RowStatus GetRowStatus(long nRow) const override;
149 
150     virtual void KeyInput(const KeyEvent& rEvt) override;
151     virtual void Command( const CommandEvent& rEvt ) override;
152 
153     // D&D
154     virtual void     StartDrag( sal_Int8 nAction, const Point& rPosPixel ) override;
155     virtual sal_Int8 AcceptDrop( const BrowserAcceptDropEvent& rEvt ) override;
156     virtual sal_Int8 ExecuteDrop( const BrowserExecuteDropEvent& rEvt ) override;
157 
158     using BrowseBox::AcceptDrop;
159     using BrowseBox::ExecuteDrop;
160 
161 private:
162 
163     DECL_LINK( CBChangeHdl, ComboBox&, void);
164 
165 public:
166     DECL_LINK( DelayedDelete, void*, void );
167 
168 };
169 
170 
disposing(const css::lang::EventObject &)171 void OFieldExpressionControlContainerListener::disposing(const css::lang::EventObject& )
172 {}
173 
elementInserted(const css::container::ContainerEvent & rEvent)174 void OFieldExpressionControlContainerListener::elementInserted(const css::container::ContainerEvent& rEvent)
175 { mpParent->elementInserted(rEvent); }
176 
elementReplaced(const css::container::ContainerEvent &)177 void OFieldExpressionControlContainerListener::elementReplaced(const css::container::ContainerEvent& )
178 {}
179 
elementRemoved(const css::container::ContainerEvent & rEvent)180 void OFieldExpressionControlContainerListener::elementRemoved(const css::container::ContainerEvent& rEvent)
181 { mpParent->elementRemoved(rEvent); }
182 
183 
184 // class OFieldExpressionControl
OFieldExpressionControl(OGroupsSortingDialog * _pParentDialog,vcl::Window * _pParent)185 OFieldExpressionControl::OFieldExpressionControl(OGroupsSortingDialog* _pParentDialog, vcl::Window *_pParent)
186     :EditBrowseBox( _pParent, EditBrowseBoxFlags::NONE, WB_TABSTOP,
187                     BrowserMode::COLUMNSELECTION | BrowserMode::MULTISELECTION | BrowserMode::AUTOSIZE_LASTCOL |
188                               BrowserMode::KEEPHIGHLIGHT | BrowserMode::HLINES | BrowserMode::VLINES)
189     ,m_aGroupPositions(GROUPS_START_LEN,-1)
190     ,m_pComboCell(nullptr)
191     ,m_nDataPos(-1)
192     ,m_nCurrentPos(-1)
193     ,m_nDeleteEvent(nullptr)
194     ,m_pParent(_pParentDialog)
195     ,m_bIgnoreEvent(false)
196     ,aContainerListener(new OFieldExpressionControlContainerListener(this))
197 {
198     SetBorderStyle(WindowBorderStyle::MONO);
199 }
200 
201 
~OFieldExpressionControl()202 OFieldExpressionControl::~OFieldExpressionControl()
203 {
204     disposeOnce();
205 }
206 
207 
dispose()208 void OFieldExpressionControl::dispose()
209 {
210     uno::Reference< report::XGroups > xGroups = m_pParent->getGroups();
211     xGroups->removeContainerListener(aContainerListener.get());
212 
213     // delete events from queue
214     if( m_nDeleteEvent )
215         Application::RemoveUserEvent( m_nDeleteEvent );
216 
217     m_pComboCell.disposeAndClear();
218     m_pParent.clear();
219     ::svt::EditBrowseBox::dispose();
220 }
221 
fillSelectedGroups()222 uno::Sequence<uno::Any> OFieldExpressionControl::fillSelectedGroups()
223 {
224     uno::Sequence<uno::Any> aList;
225     ::std::vector<uno::Any> vClipboardList;
226     vClipboardList.reserve(GetSelectRowCount());
227 
228     uno::Reference<report::XGroups> xGroups = m_pParent->getGroups();
229     sal_Int32 nCount = xGroups->getCount();
230     if ( nCount >= 1 )
231     {
232         for( long nIndex=FirstSelectedRow(); nIndex != SFX_ENDOFSELECTION; nIndex=NextSelectedRow() )
233         {
234             try
235             {
236                 if ( m_aGroupPositions[nIndex] != NO_GROUP )
237                 {
238                     uno::Reference< report::XGroup> xOrgGroup(xGroups->getByIndex(m_aGroupPositions[nIndex]),uno::UNO_QUERY);
239                     /*uno::Reference< report::XGroup> xCopy = xGroups->createGroup();
240                     ::comphelper::copyProperties(xOrgGroup.get(),xCopy.get());*/
241                     vClipboardList.push_back( uno::makeAny(xOrgGroup) );
242                 }
243             }
244             catch(uno::Exception&)
245             {
246                 OSL_FAIL("Can not access group!");
247             }
248         }
249         if ( !vClipboardList.empty() )
250             aList = uno::Sequence< uno::Any >(vClipboardList.data(), vClipboardList.size());
251     }
252     return aList;
253 }
254 
StartDrag(sal_Int8,const Point &)255 void OFieldExpressionControl::StartDrag( sal_Int8 /*_nAction*/ , const Point& /*_rPosPixel*/ )
256 {
257     if ( m_pParent && !m_pParent->isReadOnly( ) )
258     {
259         uno::Sequence<uno::Any> aClipboardList = fillSelectedGroups();
260 
261         if( aClipboardList.hasElements() )
262         {
263             rtl::Reference<OGroupExchange> pData = new OGroupExchange(aClipboardList);
264             pData->StartDrag(this, DND_ACTION_MOVE );
265         }
266     }
267 }
268 
AcceptDrop(const BrowserAcceptDropEvent & rEvt)269 sal_Int8 OFieldExpressionControl::AcceptDrop( const BrowserAcceptDropEvent& rEvt )
270 {
271     sal_Int8 nAction = DND_ACTION_NONE;
272     if ( IsEditing() )
273     {
274         sal_Int32 nPos = m_pComboCell->GetSelectedEntryPos();
275         if ( COMBOBOX_ENTRY_NOTFOUND != nPos || !m_pComboCell->GetText().isEmpty() )
276             SaveModified();
277         DeactivateCell();
278     }
279     if ( IsDropFormatSupported( OGroupExchange::getReportGroupId() ) && m_pParent->getGroups()->getCount() > 1 && rEvt.GetWindow() == &GetDataWindow() )
280     {
281         nAction = DND_ACTION_MOVE;
282     }
283     return nAction;
284 }
285 
ExecuteDrop(const BrowserExecuteDropEvent & rEvt)286 sal_Int8 OFieldExpressionControl::ExecuteDrop( const BrowserExecuteDropEvent& rEvt )
287 {
288     sal_Int8 nAction = DND_ACTION_NONE;
289     if ( IsDropFormatSupported( OGroupExchange::getReportGroupId() ) )
290     {
291         sal_Int32   nRow = GetRowAtYPosPixel(rEvt.maPosPixel.Y(), false);
292         SetNoSelection();
293 
294         TransferableDataHelper aDropped( rEvt.maDropEvent.Transferable );
295         uno::Any aDrop = aDropped.GetAny(OGroupExchange::getReportGroupId(), OUString());
296         uno::Sequence< uno::Any > aGroups;
297         aDrop >>= aGroups;
298         if ( aGroups.hasElements() )
299         {
300             moveGroups(aGroups,nRow);
301             nAction = DND_ACTION_MOVE;
302         }
303     }
304     return nAction;
305 }
306 
moveGroups(const uno::Sequence<uno::Any> & _aGroups,sal_Int32 _nRow,bool _bSelect)307 void OFieldExpressionControl::moveGroups(const uno::Sequence<uno::Any>& _aGroups,sal_Int32 _nRow,bool _bSelect)
308 {
309     if ( _aGroups.hasElements() )
310     {
311         m_bIgnoreEvent = true;
312         {
313             sal_Int32 nRow = _nRow;
314             const OUString sUndoAction(RptResId(RID_STR_UNDO_MOVE_GROUP));
315             const UndoContext aUndoContext( m_pParent->m_pController->getUndoManager(), sUndoAction );
316 
317             uno::Reference< report::XGroups> xGroups = m_pParent->getGroups();
318             for(const uno::Any& rGroup : _aGroups)
319             {
320                 uno::Reference< report::XGroup> xGroup(rGroup,uno::UNO_QUERY);
321                 if ( xGroup.is() )
322                 {
323                     uno::Sequence< beans::PropertyValue > aArgs(1);
324                     aArgs[0].Name = PROPERTY_GROUP;
325                     aArgs[0].Value <<= xGroup;
326                     // we use this way to create undo actions
327                     m_pParent->m_pController->executeChecked(SID_GROUP_REMOVE,aArgs);
328                     aArgs.realloc(2);
329                     if ( nRow > xGroups->getCount() )
330                         nRow = xGroups->getCount();
331                     if ( _bSelect )
332                         SelectRow(nRow);
333                     aArgs[1].Name = PROPERTY_POSITIONY;
334                     aArgs[1].Value <<= nRow;
335                     m_pParent->m_pController->executeChecked(SID_GROUP_APPEND,aArgs);
336                     ++nRow;
337                 }
338             }
339         }
340         m_bIgnoreEvent = false;
341         Invalidate();
342     }
343 }
344 
fillColumns(const uno::Reference<container::XNameAccess> & _xColumns)345 void OFieldExpressionControl::fillColumns(const uno::Reference< container::XNameAccess>& _xColumns)
346 {
347     m_pComboCell->Clear();
348     if ( _xColumns.is() )
349         lcl_addToList_throw(*m_pComboCell,m_aColumnInfo,_xColumns);
350 }
351 
lateInit()352 void OFieldExpressionControl::lateInit()
353 {
354     uno::Reference< report::XGroups > xGroups = m_pParent->getGroups();
355     sal_Int32 nGroupsCount = xGroups->getCount();
356     m_aGroupPositions.resize(::std::max<sal_Int32>(nGroupsCount,sal_Int32(GROUPS_START_LEN)),NO_GROUP);
357     ::std::vector<sal_Int32>::iterator aIter = m_aGroupPositions.begin();
358     for (sal_Int32 i = 0; i < nGroupsCount; ++i,++aIter)
359         *aIter = i;
360 
361     if ( ColCount() == 0 )
362     {
363         vcl::Font aFont( GetDataWindow().GetFont() );
364         aFont.SetWeight( WEIGHT_NORMAL );
365         GetDataWindow().SetFont( aFont );
366 
367         // Set font of the headline to light
368         aFont = GetFont();
369         aFont.SetWeight( WEIGHT_LIGHT );
370         SetFont(aFont);
371 
372         InsertHandleColumn(static_cast<sal_uInt16>(GetTextWidth(OUString('0')) * 4)/*, sal_True */);
373         InsertDataColumn( FIELD_EXPRESSION, RptResId(STR_RPT_EXPRESSION), 100);
374 
375         m_pComboCell = VclPtr<ComboBoxControl>::Create( &GetDataWindow() );
376         m_pComboCell->SetSelectHdl(LINK(this,OFieldExpressionControl,CBChangeHdl));
377         m_pComboCell->SetHelpId(HID_RPT_FIELDEXPRESSION);
378 
379         m_pComboCell->SetGetFocusHdl(LINK(m_pParent, OGroupsSortingDialog, OnControlFocusGot));
380         m_pComboCell->SetLoseFocusHdl(LINK(m_pParent, OGroupsSortingDialog, OnControlFocusLost));
381 
382 
383         // set browse mode
384         BrowserMode nMode(BrowserMode::COLUMNSELECTION | BrowserMode::MULTISELECTION  | BrowserMode::KEEPHIGHLIGHT |
385                           BrowserMode::HLINES | BrowserMode::VLINES       | BrowserMode::AUTOSIZE_LASTCOL | BrowserMode::AUTO_VSCROLL | BrowserMode::AUTO_HSCROLL);
386         if( m_pParent->isReadOnly() )
387             nMode |= BrowserMode::HIDECURSOR;
388         SetMode(nMode);
389         xGroups->addContainerListener(aContainerListener.get());
390     }
391     else
392         // not the first call
393         RowRemoved(0, GetRowCount());
394 
395     RowInserted(0, m_aGroupPositions.size());
396 }
397 
398 
IMPL_LINK_NOARG(OFieldExpressionControl,CBChangeHdl,ComboBox &,void)399 IMPL_LINK_NOARG( OFieldExpressionControl, CBChangeHdl, ComboBox&, void )
400 {
401 
402     SaveModified();
403 }
404 
405 
IsTabAllowed(bool) const406 bool OFieldExpressionControl::IsTabAllowed(bool /*bForward*/) const
407 {
408     return false;
409 }
410 
411 
SaveModified()412 bool OFieldExpressionControl::SaveModified()
413 {
414     sal_Int32 nRow = GetCurRow();
415     if ( nRow != BROWSER_ENDOFSELECTION )
416     {
417         try
418         {
419             bool bAppend = false;
420             uno::Reference< report::XGroup> xGroup;
421             if ( m_aGroupPositions[nRow] == NO_GROUP )
422             {
423                 bAppend = true;
424                 OUString sUndoAction(RptResId(RID_STR_UNDO_APPEND_GROUP));
425                 m_pParent->m_pController->getUndoManager().EnterListAction( sUndoAction, OUString(), 0, ViewShellId(-1) );
426                 xGroup = m_pParent->getGroups()->createGroup();
427                 xGroup->setHeaderOn(true);
428 
429                 uno::Sequence< beans::PropertyValue > aArgs(2);
430                 aArgs[0].Name = PROPERTY_GROUP;
431                 aArgs[0].Value <<= xGroup;
432                 // find position where to insert the new group
433                 sal_Int32 nGroupPos = 0;
434                 ::std::vector<sal_Int32>::iterator aIter = m_aGroupPositions.begin();
435                 ::std::vector<sal_Int32>::const_iterator aEnd  = m_aGroupPositions.begin() + nRow;
436                 for(;aIter != aEnd;++aIter)
437                     if ( *aIter != NO_GROUP )
438                         nGroupPos = *aIter + 1;
439                 aArgs[1].Name = PROPERTY_POSITIONY;
440                 aArgs[1].Value <<= nGroupPos;
441                 m_bIgnoreEvent = true;
442                 m_pParent->m_pController->executeChecked(SID_GROUP_APPEND,aArgs);
443                 m_bIgnoreEvent = false;
444                 OSL_ENSURE(*aIter == NO_GROUP ,"Illegal iterator!");
445                 *aIter++ = nGroupPos;
446 
447                 aEnd  = m_aGroupPositions.end();
448                 for(;aIter != aEnd;++aIter)
449                     if ( *aIter != NO_GROUP )
450                         ++*aIter;
451             }
452             else
453                 xGroup = m_pParent->getGroup(m_aGroupPositions[nRow]);
454             if ( xGroup.is() )
455             {
456                 sal_Int32 nPos = m_pComboCell->GetSelectedEntryPos();
457                 OUString sExpression;
458                 if ( COMBOBOX_ENTRY_NOTFOUND == nPos )
459                     sExpression = m_pComboCell->GetText();
460                 else
461                 {
462                     sExpression = m_aColumnInfo[nPos].sColumnName;
463                 }
464                 xGroup->setExpression( sExpression );
465 
466                 ::rptui::adjustSectionName(xGroup,nPos);
467 
468                 if ( bAppend )
469                     m_pParent->m_pController->getUndoManager().LeaveListAction();
470             }
471 
472             if ( Controller().is() )
473                 Controller()->ClearModified();
474             if ( GetRowCount() == m_pParent->getGroups()->getCount() )
475             {
476                 RowInserted( GetRowCount()-1);
477                 m_aGroupPositions.push_back(NO_GROUP);
478             }
479 
480             GoToRow(nRow);
481             m_pParent->DisplayData(nRow);
482         }
483         catch(uno::Exception&)
484         {
485             OSL_FAIL("OFieldExpressionControl::SaveModified: Exception caught!");
486         }
487     }
488 
489     return true;
490 }
491 
GetCellText(long nRow,sal_uInt16) const492 OUString OFieldExpressionControl::GetCellText( long nRow, sal_uInt16 /*nColId*/ ) const
493 {
494     OUString sText;
495     if ( nRow != BROWSER_ENDOFSELECTION && m_aGroupPositions[nRow] != NO_GROUP )
496     {
497         try
498         {
499             uno::Reference< report::XGroup> xGroup = m_pParent->getGroup(m_aGroupPositions[nRow]);
500             OUString sExpression = xGroup->getExpression();
501 
502             auto aIter = std::find_if(m_aColumnInfo.begin(), m_aColumnInfo.end(),
503                 [&sExpression](const ColumnInfo& rColumnInfo) { return rColumnInfo.sColumnName == sExpression; });
504             if (aIter != m_aColumnInfo.end() && !aIter->sLabel.isEmpty())
505                 sExpression = aIter->sLabel;
506             sText = sExpression;
507         }
508         catch (const uno::Exception&)
509         {
510             OSL_FAIL("Exception caught while getting expression value from the group");
511         }
512     }
513     return sText;
514 }
515 
516 
InitController(CellControllerRef &,long nRow,sal_uInt16 nColumnId)517 void OFieldExpressionControl::InitController( CellControllerRef& /*rController*/, long nRow, sal_uInt16 nColumnId )
518 {
519 
520     m_pComboCell->SetText( GetCellText( nRow, nColumnId ) );
521 }
522 
CursorMoving(long nNewRow,sal_uInt16 nNewCol)523 bool OFieldExpressionControl::CursorMoving(long nNewRow, sal_uInt16 nNewCol)
524 {
525 
526     if (!EditBrowseBox::CursorMoving(nNewRow, nNewCol))
527         return false;
528     m_nDataPos = nNewRow;
529     long nOldDataPos = GetCurRow();
530     InvalidateStatusCell( m_nDataPos );
531     InvalidateStatusCell( nOldDataPos );
532 
533     m_pParent->SaveData( nOldDataPos );
534     m_pParent->DisplayData( m_nDataPos );
535     return true;
536 }
537 
GetController(long,sal_uInt16)538 CellController* OFieldExpressionControl::GetController( long /*nRow*/, sal_uInt16 /*nColumnId*/ )
539 {
540     ComboBoxCellController* pCellController = new ComboBoxCellController( m_pComboCell );
541     pCellController->GetComboBox().SetReadOnly(!m_pParent->m_pController->isEditable());
542     return pCellController;
543 }
544 
545 
SeekRow(long _nRow)546 bool OFieldExpressionControl::SeekRow( long _nRow )
547 {
548     // the basis class needs the call, because that's how the class knows which line will be painted
549     EditBrowseBox::SeekRow(_nRow);
550     m_nCurrentPos = _nRow;
551     return true;
552 }
553 
554 
PaintCell(OutputDevice & rDev,const tools::Rectangle & rRect,sal_uInt16 nColumnId) const555 void OFieldExpressionControl::PaintCell( OutputDevice& rDev, const tools::Rectangle& rRect, sal_uInt16 nColumnId ) const
556 {
557     OUString aText  =GetCellText( m_nCurrentPos, nColumnId );
558 
559     Point aPos( rRect.TopLeft() );
560     Size aTextSize( GetDataWindow().GetTextWidth( aText ), GetDataWindow().GetTextHeight() );
561 
562     if( aPos.X() < rRect.Left() || aPos.X() + aTextSize.Width() > rRect.Right() ||
563         aPos.Y() < rRect.Top() || aPos.Y() + aTextSize.Height() > rRect.Bottom() )
564         rDev.SetClipRegion(vcl::Region(rRect));
565 
566     rDev.DrawText( aPos, aText );
567 
568     if( rDev.IsClipRegion() )
569         rDev.SetClipRegion();
570 }
571 
GetRowStatus(long nRow) const572 EditBrowseBox::RowStatus OFieldExpressionControl::GetRowStatus(long nRow) const
573 {
574     if (nRow >= 0 && nRow == m_nDataPos)
575         return EditBrowseBox::CURRENT;
576     if ( nRow != BROWSER_ENDOFSELECTION && nRow < static_cast<long>(m_aGroupPositions.size()) && m_aGroupPositions[nRow] != NO_GROUP )
577     {
578         try
579         {
580             uno::Reference< report::XGroup> xGroup = m_pParent->getGroup(m_aGroupPositions[nRow]);
581             return (xGroup->getHeaderOn() || xGroup->getFooterOn())? EditBrowseBox::HEADERFOOTER : EditBrowseBox::CLEAN;
582         }
583         catch(uno::Exception&)
584         {
585             OSL_FAIL("Exception caught while try to get a group!");
586         }
587     }
588     return EditBrowseBox::CLEAN;
589 }
590 
591 // XContainerListener
592 
elementInserted(const container::ContainerEvent & evt)593 void OFieldExpressionControl::elementInserted(const container::ContainerEvent& evt)
594 {
595     if ( m_bIgnoreEvent )
596         return;
597     SolarMutexGuard aSolarGuard;
598     ::osl::MutexGuard aGuard( m_aMutex );
599     sal_Int32 nGroupPos = 0;
600     if ( evt.Accessor >>= nGroupPos )
601     {
602         if ( nGroupPos >= GetRowCount() )
603         {
604             sal_Int32 nAddedRows = nGroupPos - GetRowCount();
605             RowInserted(nAddedRows);
606             for (sal_Int32 i = 0; i < nAddedRows; ++i)
607                 m_aGroupPositions.push_back(NO_GROUP);
608             m_aGroupPositions[nGroupPos] = nGroupPos;
609         }
610         else
611         {
612             ::std::vector<sal_Int32>::iterator aFind = m_aGroupPositions.begin()+ nGroupPos;
613             if ( aFind == m_aGroupPositions.end() )
614                 aFind = ::std::find(m_aGroupPositions.begin(),m_aGroupPositions.end(),NO_GROUP);
615 
616             if ( aFind != m_aGroupPositions.end() )
617             {
618                 if ( *aFind != NO_GROUP )
619                     aFind = m_aGroupPositions.insert(aFind,nGroupPos);
620                 else
621                     *aFind = nGroupPos;
622 
623                 ::std::vector<sal_Int32>::const_iterator aEnd  = m_aGroupPositions.end();
624                 for(++aFind;aFind != aEnd;++aFind)
625                     if ( *aFind != NO_GROUP )
626                         ++*aFind;
627             }
628         }
629         Invalidate();
630     }
631 }
632 
elementRemoved(const container::ContainerEvent & evt)633 void OFieldExpressionControl::elementRemoved(const container::ContainerEvent& evt)
634 {
635     SolarMutexGuard aSolarGuard;
636     ::osl::MutexGuard aGuard( m_aMutex );
637 
638     if ( m_bIgnoreEvent )
639         return;
640 
641     sal_Int32 nGroupPos = 0;
642     if ( evt.Accessor >>= nGroupPos )
643     {
644         std::vector<sal_Int32>::iterator aEnd = m_aGroupPositions.end();
645         std::vector<sal_Int32>::iterator aFind = std::find(m_aGroupPositions.begin(), aEnd, nGroupPos);
646         if (aFind != aEnd)
647         {
648             *aFind = NO_GROUP;
649             for(++aFind;aFind != aEnd;++aFind)
650                 if ( *aFind != NO_GROUP )
651                     --*aFind;
652             Invalidate();
653         }
654     }
655 }
656 
IsDeleteAllowed() const657 bool OFieldExpressionControl::IsDeleteAllowed( ) const
658 {
659     return !m_pParent->isReadOnly() && GetSelectRowCount() > 0;
660 }
661 
KeyInput(const KeyEvent & rEvt)662 void OFieldExpressionControl::KeyInput( const KeyEvent& rEvt )
663 {
664     if (IsDeleteAllowed())
665     {
666         if (rEvt.GetKeyCode().GetCode() == KEY_DELETE &&    // Delete rows
667             !rEvt.GetKeyCode().IsShift() &&
668             !rEvt.GetKeyCode().IsMod1())
669         {
670             DeleteRows();
671             return;
672         }
673     }
674     EditBrowseBox::KeyInput(rEvt);
675 }
676 
Command(const CommandEvent & rEvt)677 void OFieldExpressionControl::Command(const CommandEvent& rEvt)
678 {
679     switch (rEvt.GetCommand())
680     {
681         case CommandEventId::ContextMenu:
682         {
683             if (!rEvt.IsMouseEvent())
684             {
685                 EditBrowseBox::Command(rEvt);
686                 return;
687             }
688 
689             sal_uInt16 nColId = GetColumnId(GetColumnAtXPosPixel(rEvt.GetMousePosPixel().X()));
690 
691             if ( nColId == HANDLE_ID )
692             {
693                 bool bEnable = false;
694                 long nIndex = FirstSelectedRow();
695                 while( nIndex != SFX_ENDOFSELECTION && !bEnable )
696                 {
697                     if ( m_aGroupPositions[nIndex] != NO_GROUP )
698                         bEnable = true;
699                     nIndex = NextSelectedRow();
700                 }
701                 VclBuilder aBuilder(nullptr, VclBuilderContainer::getUIRootDir(), "modules/dbreport/ui/groupsortmenu.ui", "");
702                 VclPtr<PopupMenu> aContextMenu(aBuilder.get_menu("menu"));
703                 aContextMenu->EnableItem(aContextMenu->GetItemId("delete"), IsDeleteAllowed() && bEnable);
704                 if (aContextMenu->Execute(this, rEvt.GetMousePosPixel()))
705                 {
706                     if( m_nDeleteEvent )
707                         Application::RemoveUserEvent( m_nDeleteEvent );
708                     m_nDeleteEvent = Application::PostUserEvent( LINK(this, OFieldExpressionControl, DelayedDelete), nullptr, true );
709                 }
710             }
711             [[fallthrough]];
712         }
713         default:
714             EditBrowseBox::Command(rEvt);
715     }
716 
717 }
718 
DeleteRows()719 void OFieldExpressionControl::DeleteRows()
720 {
721 
722     bool bIsEditing = IsEditing();
723     if (bIsEditing)
724     {
725         DeactivateCell();
726     }
727     long nIndex = FirstSelectedRow();
728     if (nIndex == SFX_ENDOFSELECTION)
729     {
730         nIndex = GetCurRow();
731     }
732     bool bFirstTime = true;
733 
734     long nOldDataPos = nIndex;
735     uno::Sequence< beans::PropertyValue > aArgs(1);
736     aArgs[0].Name = PROPERTY_GROUP;
737     m_bIgnoreEvent = true;
738     while( nIndex >= 0 )
739     {
740         if ( m_aGroupPositions[nIndex] != NO_GROUP )
741         {
742             if ( bFirstTime )
743             {
744                 bFirstTime = false;
745                 OUString sUndoAction(RptResId(RID_STR_UNDO_REMOVE_SELECTION));
746                 m_pParent->m_pController->getUndoManager().EnterListAction( sUndoAction, OUString(), 0, ViewShellId(-1) );
747             }
748 
749             sal_Int32 nGroupPos = m_aGroupPositions[nIndex];
750             uno::Reference< report::XGroup> xGroup = m_pParent->getGroup(nGroupPos);
751             aArgs[0].Value <<= xGroup;
752             // we use this way to create undo actions
753             m_pParent->m_pController->executeChecked(SID_GROUP_REMOVE,aArgs);
754 
755             std::vector<sal_Int32>::iterator aEnd  = m_aGroupPositions.end();
756             std::vector<sal_Int32>::iterator aFind = std::find(m_aGroupPositions.begin(), aEnd, nGroupPos);
757             if (aFind != aEnd)
758             {
759                 *aFind = NO_GROUP;
760                 for(++aFind;aFind != aEnd;++aFind)
761                     if ( *aFind != NO_GROUP )
762                         --*aFind;
763             }
764         }
765         nIndex = NextSelectedRow();
766     }
767 
768     if ( !bFirstTime )
769         m_pParent->m_pController->getUndoManager().LeaveListAction();
770 
771     m_nDataPos = GetCurRow();
772     InvalidateStatusCell( nOldDataPos );
773     InvalidateStatusCell( m_nDataPos );
774     ActivateCell();
775     m_pParent->DisplayData( m_nDataPos );
776     m_bIgnoreEvent = false;
777     Invalidate();
778 }
779 
IMPL_LINK_NOARG(OFieldExpressionControl,DelayedDelete,void *,void)780 IMPL_LINK_NOARG( OFieldExpressionControl, DelayedDelete, void*, void )
781 {
782     m_nDeleteEvent = nullptr;
783     DeleteRows();
784 }
785 
GetOptimalSize() const786 Size OFieldExpressionControl::GetOptimalSize() const
787 {
788     return LogicToPixel(Size(106, 75), MapMode(MapUnit::MapAppFont));
789 }
790 
791 // class OGroupsSortingDialog
OGroupsSortingDialog(vcl::Window * _pParent,bool _bReadOnly,OReportController * _pController)792 OGroupsSortingDialog::OGroupsSortingDialog(vcl::Window* _pParent, bool _bReadOnly,
793                                            OReportController* _pController)
794     : FloatingWindow(_pParent, "FloatingSort", "modules/dbreport/ui/floatingsort.ui")
795     , OPropertyChangeListener(m_aMutex)
796     , m_pController(_pController)
797     , m_xGroups(m_pController->getReportDefinition()->getGroups())
798     , m_bReadOnly(_bReadOnly)
799 {
800     get(m_pToolBox, "toolbox");
801     m_nMoveUpId = m_pToolBox->GetItemId(0);
802     m_nMoveDownId = m_pToolBox->GetItemId(1);
803     m_nDeleteId = m_pToolBox->GetItemId(2);
804     get(m_pOrderLst, "sorting");
805     get(m_pHeaderLst, "header");
806     get(m_pFooterLst, "footer");
807     get(m_pGroupOnLst, "group");
808     get(m_pGroupIntervalEd, "interval");
809     get(m_pKeepTogetherLst, "keep");
810     get(m_pHelpWindow, "helptext");
811     m_pHelpWindow->set_height_request(GetTextHeight() * 4);
812     get(m_pProperties, "properties");
813     m_pFieldExpression = VclPtr<OFieldExpressionControl>::Create(this, get<vcl::Window>("box"));
814     m_pFieldExpression->set_hexpand(true);
815     m_pFieldExpression->set_vexpand(true);
816 
817     Control* pControlsLst[] = { m_pHeaderLst, m_pFooterLst, m_pGroupOnLst, m_pKeepTogetherLst, m_pOrderLst, m_pGroupIntervalEd};
818     for (Control* i : pControlsLst)
819     {
820         i->SetGetFocusHdl(LINK(this, OGroupsSortingDialog, OnControlFocusGot));
821         i->SetLoseFocusHdl(LINK(this, OGroupsSortingDialog, OnControlFocusLost));
822         i->Show();
823     }
824 
825     for (size_t i = 0; i < SAL_N_ELEMENTS(pControlsLst) - 1; ++i)
826         static_cast<ListBox*>(pControlsLst[i])->SetSelectHdl(LINK(this,OGroupsSortingDialog,LBChangeHdl));
827 
828     m_pReportListener = new OPropertyChangeMultiplexer(this,m_pController->getReportDefinition().get());
829     m_pReportListener->addProperty(PROPERTY_COMMAND);
830     m_pReportListener->addProperty(PROPERTY_COMMANDTYPE);
831 
832     m_pFieldExpression->lateInit();
833     fillColumns();
834     m_pFieldExpression->Show();
835 
836     m_pHelpWindow->SetControlBackground( GetSettings().GetStyleSettings().GetFaceColor() );
837 
838     m_pToolBox->SetLineSpacing(true);
839     m_pToolBox->SetSelectHdl(LINK(this, OGroupsSortingDialog, OnFormatAction));
840 
841     checkButtons(0);
842 
843     Show();
844 }
845 
~OGroupsSortingDialog()846 OGroupsSortingDialog::~OGroupsSortingDialog()
847 {
848     disposeOnce();
849 }
850 
dispose()851 void OGroupsSortingDialog::dispose()
852 {
853     m_xColumns.clear();
854     m_pReportListener->dispose();
855     if ( m_pCurrentGroupListener.is() )
856         m_pCurrentGroupListener->dispose();
857     m_pToolBox.clear();
858     m_pProperties.clear();
859     m_pOrderLst.clear();
860     m_pHeaderLst.clear();
861     m_pFooterLst.clear();
862     m_pGroupOnLst.clear();
863     m_pGroupIntervalEd.clear();
864     m_pKeepTogetherLst.clear();
865     m_pHelpWindow.clear();
866     m_pFieldExpression.disposeAndClear();
867     FloatingWindow::dispose();
868 }
869 
UpdateData()870 void OGroupsSortingDialog::UpdateData( )
871 {
872     m_pFieldExpression->Invalidate();
873     long nCurRow = m_pFieldExpression->GetCurRow();
874     m_pFieldExpression->DeactivateCell();
875     m_pFieldExpression->ActivateCell(nCurRow, m_pFieldExpression->GetCurColumnId());
876     DisplayData(nCurRow);
877 }
878 
DisplayData(sal_Int32 _nRow)879 void OGroupsSortingDialog::DisplayData( sal_Int32 _nRow )
880 {
881     const sal_Int32 nGroupPos = m_pFieldExpression->getGroupPosition(_nRow);
882     const bool bEmpty = nGroupPos == NO_GROUP;
883     m_pProperties->Enable(!bEmpty);
884 
885     checkButtons(_nRow);
886 
887     if ( m_pCurrentGroupListener.is() )
888         m_pCurrentGroupListener->dispose();
889     m_pCurrentGroupListener = nullptr;
890     if (!bEmpty)
891     {
892         uno::Reference< report::XGroup> xGroup = getGroup(nGroupPos);
893 
894         m_pCurrentGroupListener = new OPropertyChangeMultiplexer(this,xGroup.get());
895         m_pCurrentGroupListener->addProperty(PROPERTY_HEADERON);
896         m_pCurrentGroupListener->addProperty(PROPERTY_FOOTERON);
897 
898         displayGroup(xGroup);
899     }
900 }
901 
SaveData(sal_Int32 _nRow)902 void OGroupsSortingDialog::SaveData( sal_Int32 _nRow)
903 {
904     sal_Int32 nGroupPos = m_pFieldExpression->getGroupPosition(_nRow);
905     if ( nGroupPos == NO_GROUP )
906         return;
907 
908     uno::Reference< report::XGroup> xGroup = getGroup(nGroupPos);
909     if ( m_pHeaderLst->IsValueChangedFromSaved() )
910         xGroup->setHeaderOn( m_pHeaderLst->GetSelectedEntryPos() == 0 );
911     if ( m_pFooterLst->IsValueChangedFromSaved() )
912         xGroup->setFooterOn( m_pFooterLst->GetSelectedEntryPos() == 0 );
913     if ( m_pKeepTogetherLst->IsValueChangedFromSaved() )
914         xGroup->setKeepTogether( m_pKeepTogetherLst->GetSelectedEntryPos() );
915     if ( m_pGroupOnLst->IsValueChangedFromSaved() )
916     {
917         sal_Int16 nGroupOn = static_cast<sal_Int16>(reinterpret_cast<sal_IntPtr>(m_pGroupOnLst->GetSelectedEntryData()));
918         xGroup->setGroupOn( nGroupOn );
919     }
920     if ( m_pGroupIntervalEd->IsValueChangedFromSaved() )
921     {
922         xGroup->setGroupInterval( static_cast<sal_Int32>(m_pGroupIntervalEd->GetValue()) );
923         m_pGroupIntervalEd->SaveValue();
924     }
925     if ( m_pOrderLst->IsValueChangedFromSaved() )
926         xGroup->setSortAscending( m_pOrderLst->GetSelectedEntryPos() == 0 );
927 
928     ListBox* pControls[] = { m_pHeaderLst, m_pFooterLst, m_pGroupOnLst, m_pKeepTogetherLst, m_pOrderLst};
929     for (ListBox* pControl : pControls)
930         pControl->SaveValue();
931 }
932 
933 
getColumnDataType(const OUString & _sColumnName)934 sal_Int32 OGroupsSortingDialog::getColumnDataType(const OUString& _sColumnName)
935 {
936     sal_Int32 nDataType = sdbc::DataType::VARCHAR;
937     try
938     {
939         if ( !m_xColumns.is() )
940             fillColumns();
941         if ( m_xColumns.is() && m_xColumns->hasByName(_sColumnName) )
942         {
943             uno::Reference< beans::XPropertySet> xColumn(m_xColumns->getByName(_sColumnName),uno::UNO_QUERY);
944             if ( xColumn.is() )
945                 xColumn->getPropertyValue(PROPERTY_TYPE) >>= nDataType;
946         }
947     }
948     catch(uno::Exception&)
949     {
950         OSL_FAIL("Exception caught while getting the type of a column");
951     }
952 
953     return nDataType;
954 }
955 
IMPL_LINK(OGroupsSortingDialog,OnControlFocusGot,Control &,rControl,void)956 IMPL_LINK(OGroupsSortingDialog, OnControlFocusGot, Control&, rControl, void )
957 {
958     if ( m_pFieldExpression && m_pFieldExpression->getExpressionControl() )
959     {
960         const std::pair<Control*, const char*> pControls[] = {
961             { m_pFieldExpression->getExpressionControl(), STR_RPT_HELP_FIELD },
962             { m_pHeaderLst, STR_RPT_HELP_HEADER },
963             { m_pFooterLst, STR_RPT_HELP_FOOTER },
964             { m_pGroupOnLst, STR_RPT_HELP_GROUPON },
965             { m_pGroupIntervalEd, STR_RPT_HELP_INTERVAL },
966             { m_pKeepTogetherLst, STR_RPT_HELP_KEEP },
967             { m_pOrderLst, STR_RPT_HELP_SORT }
968         };
969         for (size_t i = 0; i < SAL_N_ELEMENTS(pControls); ++i)
970         {
971             if (&rControl == pControls[i].first)
972             {
973                 ListBox* pListBox = dynamic_cast< ListBox* >( &rControl );
974                 if ( pListBox )
975                     pListBox->SaveValue();
976                 NumericField* pNumericField = dynamic_cast< NumericField* >( &rControl );
977                 if ( pNumericField )
978                     pNumericField->SaveValue();
979                 //shows the text given by the id in the multiline edit
980                 m_pHelpWindow->SetText(RptResId(pControls[i].second));
981                 break;
982             }
983         }
984     }
985 }
986 
IMPL_LINK(OGroupsSortingDialog,OnControlFocusLost,Control &,rControl,void)987 IMPL_LINK(OGroupsSortingDialog, OnControlFocusLost, Control&, rControl, void )
988 {
989     if (m_pFieldExpression && &rControl == m_pGroupIntervalEd)
990     {
991         if ( m_pGroupIntervalEd->IsModified() )
992             SaveData(m_pFieldExpression->GetCurRow());
993     }
994 }
995 
IMPL_LINK_NOARG(OGroupsSortingDialog,OnFormatAction,ToolBox *,void)996 IMPL_LINK_NOARG( OGroupsSortingDialog, OnFormatAction, ToolBox*, void )
997 {
998 
999     sal_uInt16 nCommand = m_pToolBox->GetCurItemId();
1000 
1001     if ( m_pFieldExpression )
1002     {
1003         long nIndex = m_pFieldExpression->GetCurrRow();
1004         sal_Int32 nGroupPos = m_pFieldExpression->getGroupPosition(nIndex);
1005         uno::Sequence<uno::Any> aClipboardList;
1006         if ( nIndex >= 0 && nGroupPos != NO_GROUP )
1007         {
1008             aClipboardList.realloc(1);
1009             aClipboardList[0] = m_xGroups->getByIndex(nGroupPos);
1010         }
1011         if ( nCommand == m_nMoveUpId )
1012         {
1013             --nIndex;
1014         }
1015         if ( nCommand == m_nMoveDownId )
1016         {
1017             ++nIndex;
1018         }
1019         if ( nCommand == m_nDeleteId )
1020         {
1021             Application::PostUserEvent( LINK(m_pFieldExpression, OFieldExpressionControl, DelayedDelete), nullptr, true );
1022         }
1023         else
1024         {
1025             if ( nIndex >= 0 && aClipboardList.hasElements() )
1026             {
1027                 m_pFieldExpression->SetNoSelection();
1028                 m_pFieldExpression->moveGroups(aClipboardList,nIndex,false);
1029                 m_pFieldExpression->DeactivateCell();
1030                 m_pFieldExpression->GoToRow(nIndex);
1031                 m_pFieldExpression->ActivateCell(nIndex, m_pFieldExpression->GetCurColumnId());
1032                 DisplayData(nIndex);
1033             }
1034         }
1035     }
1036 }
1037 
IMPL_LINK(OGroupsSortingDialog,LBChangeHdl,ListBox &,rListBox,void)1038 IMPL_LINK( OGroupsSortingDialog, LBChangeHdl, ListBox&, rListBox, void )
1039 {
1040     if ( rListBox.IsValueChangedFromSaved() )
1041     {
1042         sal_Int32 nRow = m_pFieldExpression->GetCurRow();
1043         sal_Int32 nGroupPos = m_pFieldExpression->getGroupPosition(nRow);
1044         if (&rListBox != m_pHeaderLst && &rListBox != m_pFooterLst)
1045         {
1046             if ( rListBox.IsValueChangedFromSaved() )
1047                 SaveData(nRow);
1048             if ( &rListBox == m_pGroupOnLst )
1049                 m_pGroupIntervalEd->Enable( rListBox.GetSelectedEntryPos() != 0 );
1050         }
1051         else if ( nGroupPos != NO_GROUP )
1052         {
1053             uno::Reference< report::XGroup> xGroup = getGroup(nGroupPos);
1054             uno::Sequence< beans::PropertyValue > aArgs(2);
1055             aArgs[1].Name = PROPERTY_GROUP;
1056             aArgs[1].Value <<= xGroup;
1057 
1058             if ( m_pHeaderLst  == &rListBox )
1059                 aArgs[0].Name = PROPERTY_HEADERON;
1060             else
1061                 aArgs[0].Name = PROPERTY_FOOTERON;
1062 
1063             aArgs[0].Value <<= rListBox.GetSelectedEntryPos() == 0;
1064             m_pController->executeChecked(m_pHeaderLst  == &rListBox ? SID_GROUPHEADER : SID_GROUPFOOTER, aArgs);
1065             m_pFieldExpression->InvalidateHandleColumn();
1066         }
1067     }
1068 }
1069 
_propertyChanged(const beans::PropertyChangeEvent & _rEvent)1070 void OGroupsSortingDialog::_propertyChanged(const beans::PropertyChangeEvent& _rEvent)
1071 {
1072     uno::Reference< report::XGroup > xGroup(_rEvent.Source,uno::UNO_QUERY);
1073     if ( xGroup.is() )
1074         displayGroup(xGroup);
1075     else
1076         fillColumns();
1077 }
1078 
fillColumns()1079 void OGroupsSortingDialog::fillColumns()
1080 {
1081     m_xColumns = m_pController->getColumns();
1082     m_pFieldExpression->fillColumns(m_xColumns);
1083 }
1084 
displayGroup(const uno::Reference<report::XGroup> & _xGroup)1085 void OGroupsSortingDialog::displayGroup(const uno::Reference<report::XGroup>& _xGroup)
1086 {
1087     m_pHeaderLst->SelectEntryPos(_xGroup->getHeaderOn() ? 0 : 1 );
1088     m_pFooterLst->SelectEntryPos(_xGroup->getFooterOn() ? 0 : 1 );
1089     sal_Int32 nDataType = getColumnDataType(_xGroup->getExpression());
1090 
1091     // first clear whole group on list
1092     while(m_pGroupOnLst->GetEntryCount() > 1 )
1093     {
1094         m_pGroupOnLst->RemoveEntry(1);
1095     }
1096 
1097     switch(nDataType)
1098     {
1099         case sdbc::DataType::LONGVARCHAR:
1100         case sdbc::DataType::VARCHAR:
1101         case sdbc::DataType::CHAR:
1102             m_pGroupOnLst->InsertEntry(RptResId(STR_RPT_PREFIXCHARS));
1103             m_pGroupOnLst->SetEntryData(1,reinterpret_cast<void*>(report::GroupOn::PREFIX_CHARACTERS));
1104             break;
1105         case sdbc::DataType::DATE:
1106         case sdbc::DataType::TIME:
1107         case sdbc::DataType::TIMESTAMP:
1108             {
1109                 const char* aIds[] = { STR_RPT_YEAR, STR_RPT_QUARTER,STR_RPT_MONTH,STR_RPT_WEEK,STR_RPT_DAY,STR_RPT_HOUR,STR_RPT_MINUTE };
1110                 for (size_t i = 0; i < SAL_N_ELEMENTS(aIds); ++i)
1111                 {
1112                     m_pGroupOnLst->InsertEntry(RptResId(aIds[i]));
1113                     m_pGroupOnLst->SetEntryData(i+1,reinterpret_cast<void*>(i+2));
1114                 }
1115             }
1116             break;
1117         default:
1118             m_pGroupOnLst->InsertEntry(RptResId(STR_RPT_INTERVAL));
1119             m_pGroupOnLst->SetEntryData(1,reinterpret_cast<void*>(report::GroupOn::INTERVAL));
1120             break;
1121     }
1122     sal_Int32 nPos = 0;
1123     switch(_xGroup->getGroupOn())
1124     {
1125         case report::GroupOn::DEFAULT:
1126             nPos = 0;
1127             break;
1128         case report::GroupOn::PREFIX_CHARACTERS:
1129             nPos = 1;
1130             break;
1131         case report::GroupOn::YEAR:
1132             nPos = 1;
1133             break;
1134         case report::GroupOn::QUARTAL:
1135             nPos = 2;
1136             break;
1137         case report::GroupOn::MONTH:
1138             nPos = 3;
1139             break;
1140         case report::GroupOn::WEEK:
1141             nPos = 4;
1142             break;
1143         case report::GroupOn::DAY:
1144             nPos = 5;
1145             break;
1146         case report::GroupOn::HOUR:
1147             nPos = 6;
1148             break;
1149         case report::GroupOn::MINUTE:
1150             nPos = 7;
1151             break;
1152         case report::GroupOn::INTERVAL:
1153             nPos = 1;
1154             break;
1155         default:
1156             nPos = 0;
1157     }
1158     m_pGroupOnLst->SelectEntryPos(nPos);
1159     m_pGroupIntervalEd->SetText(OUString::number(_xGroup->getGroupInterval()));
1160     m_pGroupIntervalEd->SaveValue();
1161     m_pGroupIntervalEd->Enable( nPos != 0 );
1162     m_pKeepTogetherLst->SelectEntryPos(_xGroup->getKeepTogether());
1163     m_pOrderLst->SelectEntryPos(_xGroup->getSortAscending() ? 0 : 1);
1164 
1165     ListBox* pControls[] = { m_pHeaderLst, m_pFooterLst, m_pGroupOnLst, m_pKeepTogetherLst, m_pOrderLst};
1166     for (ListBox* pControl : pControls)
1167         pControl->SaveValue();
1168 
1169     ListBox* pControlsLst2[] = { m_pHeaderLst, m_pFooterLst, m_pGroupOnLst, m_pKeepTogetherLst, m_pOrderLst};
1170     bool bReadOnly = !m_pController->isEditable();
1171     for (ListBox* i : pControlsLst2)
1172         i->SetReadOnly(bReadOnly);
1173     m_pGroupIntervalEd->SetReadOnly(bReadOnly);
1174 }
1175 
checkButtons(sal_Int32 _nRow)1176 void OGroupsSortingDialog::checkButtons(sal_Int32 _nRow)
1177 {
1178     sal_Int32 nGroupCount = m_xGroups->getCount();
1179     sal_Int32 nRowCount = m_pFieldExpression->GetRowCount();
1180     bool bEnabled = nGroupCount > 1;
1181 
1182     if (bEnabled && _nRow > 0 )
1183     {
1184         m_pToolBox->EnableItem(m_nMoveUpId);
1185     }
1186     else
1187     {
1188         m_pToolBox->EnableItem(m_nMoveUpId, false);
1189     }
1190     if (bEnabled && _nRow < (nRowCount - 1) )
1191     {
1192         m_pToolBox->EnableItem(m_nMoveDownId);
1193     }
1194     else
1195     {
1196         m_pToolBox->EnableItem(m_nMoveDownId, false);
1197     }
1198 
1199     sal_Int32 nGroupPos = m_pFieldExpression->getGroupPosition(_nRow);
1200     if ( nGroupPos != NO_GROUP )
1201     {
1202         bool bEnableDelete = nGroupCount > 0;
1203         m_pToolBox->EnableItem(m_nDeleteId, bEnableDelete);
1204     }
1205     else
1206     {
1207         m_pToolBox->EnableItem(m_nDeleteId, false);
1208     }
1209 }
1210 
1211 } // rptui
1212 
1213 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1214