Bug Summary

File:home/maarten/src/libreoffice/core/include/rtl/ref.hxx
Warning:line 192, column 9
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name GroupsSorting.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/reportdesign/inc -I /home/maarten/src/libreoffice/core/reportdesign/source/inc -I /home/maarten/src/libreoffice/core/reportdesign/source/ui/inc -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/reportdesign/source/ui/dlg/GroupsSorting.cxx

/home/maarten/src/libreoffice/core/reportdesign/source/ui/dlg/GroupsSorting.cxx

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

/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx

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#ifndef INCLUDED_VCL_PTR_HXX
21#define INCLUDED_VCL_PTR_HXX
22
23#include <sal/config.h>
24
25#include <rtl/ref.hxx>
26
27#include <utility>
28#include <type_traits>
29
30#ifdef DBG_UTIL
31#ifndef _WIN32
32#include <vcl/vclmain.hxx>
33#endif
34#endif
35
36class VclReferenceBase;
37
38namespace vcl::detail {
39
40template<typename>
41constexpr bool isIncompleteOrDerivedFromVclReferenceBase(...) { return true; }
42
43template<typename T> constexpr bool isIncompleteOrDerivedFromVclReferenceBase(
44 int (*)[sizeof(T)])
45{ return std::is_base_of<VclReferenceBase, T>::value; }
46
47} // namespace vcl::detail
48
49/**
50 * A thin wrapper around rtl::Reference to implement the acquire and dispose semantics we want for references to vcl::Window subclasses.
51 *
52 * For more details on the design please see vcl/README.lifecycle
53 *
54 * @param reference_type must be a subclass of vcl::Window
55 */
56template <class reference_type>
57class VclPtr
58{
59 static_assert(
60 vcl::detail::isIncompleteOrDerivedFromVclReferenceBase<reference_type>(
61 nullptr),
62 "template argument type must be derived from VclReferenceBase");
63
64 ::rtl::Reference<reference_type> m_rInnerRef;
65
66public:
67 /** Constructor...
68 */
69 VclPtr()
70 : m_rInnerRef()
71 {}
72
73 /** Constructor...
74 */
75 VclPtr (reference_type * pBody)
76 : m_rInnerRef(pBody)
77 {}
78
79 /** Constructor... that doesn't take a ref.
80 */
81 VclPtr (reference_type * pBody, __sal_NoAcquire)
82 : m_rInnerRef(pBody, SAL_NO_ACQUIRE)
83 {}
84
85 /** Up-casting conversion constructor: Copies interface reference.
86
87 Does not work for up-casts to ambiguous bases. For the special case of
88 up-casting to Reference< XInterface >, see the corresponding conversion
89 operator.
90
91 @param rRef another reference
92 */
93 template< class derived_type >
94 VclPtr(
95 const VclPtr< derived_type > & rRef,
96 typename std::enable_if<
97 std::is_base_of<reference_type, derived_type>::value, int>::type
98 = 0 )
99 : m_rInnerRef( static_cast<reference_type*>(rRef) )
100 {
101 }
102
103#if defined(DBG_UTIL) && !defined(_WIN32)
104 virtual ~VclPtr()
105 {
106 assert(m_rInnerRef.get() == nullptr || vclmain::isAlive())(static_cast <bool> (m_rInnerRef.get() == nullptr || vclmain
::isAlive()) ? void (0) : __assert_fail ("m_rInnerRef.get() == nullptr || vclmain::isAlive()"
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 106, __extension__ __PRETTY_FUNCTION__))
;
107 // We can be one of the intermediate counts, but if we are the last
108 // VclPtr keeping this object alive, then something forgot to call dispose().
109 assert((!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1)(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef
->isDisposed() || m_rInnerRef->getRefCount() > 1) &&
"someone forgot to call dispose()") ? void (0) : __assert_fail
("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\""
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 110, __extension__ __PRETTY_FUNCTION__))
110 && "someone forgot to call dispose()")(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef
->isDisposed() || m_rInnerRef->getRefCount() > 1) &&
"someone forgot to call dispose()") ? void (0) : __assert_fail
("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\""
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 110, __extension__ __PRETTY_FUNCTION__))
;
111 }
112 VclPtr(VclPtr const &) = default;
113 VclPtr(VclPtr &&) = default;
114 VclPtr & operator =(VclPtr const &) = default;
115 VclPtr & operator =(VclPtr &&) = default;
116#endif
117
118 /**
119 * A construction helper for VclPtr. Since VclPtr types are created
120 * with a reference-count of one - to help fit into the existing
121 * code-flow; this helps us to construct them easily.
122 *
123 * For more details on the design please see vcl/README.lifecycle
124 *
125 * @tparam reference_type must be a subclass of vcl::Window
126 */
127 template<typename... Arg> [[nodiscard]] static VclPtr< reference_type > Create(Arg &&... arg)
128 {
129 return VclPtr< reference_type >( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE );
130 }
131
132 /** Probably most common used: handle->someBodyOp().
133 */
134 reference_type * operator->() const
135 {
136 return m_rInnerRef.get();
137 }
138
139 /** Get the body. Can be used instead of operator->().
140 I.e. handle->someBodyOp() and handle.get()->someBodyOp()
141 are the same.
142 */
143 reference_type * get() const
144 {
145 return m_rInnerRef.get();
146 }
147
148 void set(reference_type *pBody)
149 {
150 m_rInnerRef.set(pBody);
151 }
152
153 void reset(reference_type *pBody)
154 {
155 m_rInnerRef.set(pBody);
156 }
157
158 /** Up-casting copy assignment operator.
159
160 Does not work for up-casts to ambiguous bases.
161
162 @param rRef another reference
163 */
164 template<typename derived_type>
165 typename std::enable_if<
166 std::is_base_of<reference_type, derived_type>::value,
167 VclPtr &>::type
168 operator =(VclPtr<derived_type> const & rRef)
169 {
170 m_rInnerRef.set(rRef.get());
171 return *this;
172 }
173
174 VclPtr & operator =(reference_type * pBody)
175 {
176 m_rInnerRef.set(pBody);
177 return *this;
178 }
179
180 operator reference_type * () const
181 {
182 return m_rInnerRef.get();
183 }
184
185 explicit operator bool () const
186 {
187 return m_rInnerRef.get() != nullptr;
188 }
189
190 void clear()
191 {
192 m_rInnerRef.clear();
193 }
194
195 void reset()
196 {
197 m_rInnerRef.clear();
198 }
199
200 void disposeAndClear()
201 {
202 // hold it alive for the lifetime of this method
203 ::rtl::Reference<reference_type> aTmp(m_rInnerRef);
3
Calling copy constructor for 'Reference<rptui::OFieldExpressionControl>'
6
Returning from copy constructor for 'Reference<rptui::OFieldExpressionControl>'
204 m_rInnerRef.clear(); // we should use some 'swap' method ideally ;-)
7
Calling 'Reference::clear'
14
Returning; memory was released
205 if (aTmp.get()) {
15
Calling 'Reference::get'
206 aTmp->disposeOnce();
207 }
208 }
209
210 /** Needed to place VclPtr's into STL collection.
211 */
212 bool operator< (const VclPtr<reference_type> & handle) const
213 {
214 return (m_rInnerRef < handle.m_rInnerRef);
215 }
216}; // class VclPtr
217
218template<typename T1, typename T2>
219inline bool operator ==(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
220 return p1.get() == p2.get();
221}
222
223template<typename T> inline bool operator ==(VclPtr<T> const & p1, T const * p2)
224{
225 return p1.get() == p2;
226}
227
228template<typename T> inline bool operator ==(VclPtr<T> const & p1, T * p2) {
229 return p1.get() == p2;
230}
231
232template<typename T> inline bool operator ==(T const * p1, VclPtr<T> const & p2)
233{
234 return p1 == p2.get();
235}
236
237template<typename T> inline bool operator ==(T * p1, VclPtr<T> const & p2) {
238 return p1 == p2.get();
239}
240
241template<typename T1, typename T2>
242inline bool operator !=(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
243 return !(p1 == p2);
244}
245
246template<typename T> inline bool operator !=(VclPtr<T> const & p1, T const * p2)
247{
248 return !(p1 == p2);
249}
250
251template<typename T> inline bool operator !=(VclPtr<T> const & p1, T * p2) {
252 return !(p1 == p2);
253}
254
255template<typename T> inline bool operator !=(T const * p1, VclPtr<T> const & p2)
256{
257 return !(p1 == p2);
258}
259
260template<typename T> inline bool operator !=(T * p1, VclPtr<T> const & p2) {
261 return !(p1 == p2);
262}
263
264/**
265 * A construction helper for a temporary VclPtr. Since VclPtr types
266 * are created with a reference-count of one - to help fit into
267 * the existing code-flow; this helps us to construct them easily.
268 * see also VclPtr::Create and ScopedVclPtr
269 *
270 * For more details on the design please see vcl/README.lifecycle
271 *
272 * @param reference_type must be a subclass of vcl::Window
273 */
274template <class reference_type>
275class SAL_WARN_UNUSED__attribute__((warn_unused)) VclPtrInstance final : public VclPtr<reference_type>
276{
277public:
278 template<typename... Arg> VclPtrInstance(Arg &&... arg)
279 : VclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
280 {
281 }
282
283 /**
284 * Override and disallow this, to prevent people accidentally calling it and actually
285 * getting VclPtr::Create and getting a naked VclPtr<> instance
286 */
287 template<typename... Arg> static VclPtrInstance< reference_type > Create(Arg &&... ) = delete;
288};
289
290template <class reference_type>
291class ScopedVclPtr : public VclPtr<reference_type>
292{
293public:
294 /** Constructor...
295 */
296 ScopedVclPtr()
297 : VclPtr<reference_type>()
298 {}
299
300 /** Constructor
301 */
302 ScopedVclPtr (reference_type * pBody)
303 : VclPtr<reference_type>(pBody)
304 {}
305
306 /** Copy constructor...
307 */
308 ScopedVclPtr (const VclPtr<reference_type> & handle)
309 : VclPtr<reference_type>(handle)
310 {}
311
312 /**
313 Assignment that releases the last reference.
314 */
315 void disposeAndReset(reference_type *pBody)
316 {
317 if (pBody != this->get()) {
318 VclPtr<reference_type>::disposeAndClear();
319 VclPtr<reference_type>::set(pBody);
320 }
321 }
322
323 /**
324 Assignment that releases the last reference.
325 */
326 ScopedVclPtr<reference_type>& operator = (reference_type * pBody)
327 {
328 disposeAndReset(pBody);
329 return *this;
330 }
331
332 /** Up-casting conversion constructor: Copies interface reference.
333
334 Does not work for up-casts to ambiguous bases. For the special case of
335 up-casting to Reference< XInterface >, see the corresponding conversion
336 operator.
337
338 @param rRef another reference
339 */
340 template< class derived_type >
341 ScopedVclPtr(
342 const VclPtr< derived_type > & rRef,
343 typename std::enable_if<
344 std::is_base_of<reference_type, derived_type>::value, int>::type
345 = 0 )
346 : VclPtr<reference_type>( rRef )
347 {
348 }
349
350 /** Up-casting assignment operator.
351
352 Does not work for up-casts to ambiguous bases.
353
354 @param rRef another VclPtr
355 */
356 template<typename derived_type>
357 typename std::enable_if<
358 std::is_base_of<reference_type, derived_type>::value,
359 ScopedVclPtr &>::type
360 operator =(VclPtr<derived_type> const & rRef)
361 {
362 disposeAndReset(rRef.get());
363 return *this;
364 }
365
366 /**
367 * Override and disallow this, to prevent people accidentally calling it and actually
368 * getting VclPtr::Create and getting a naked VclPtr<> instance
369 */
370 template<typename... Arg> static ScopedVclPtr< reference_type > Create(Arg &&... ) = delete;
371
372 ~ScopedVclPtr()
373 {
374 VclPtr<reference_type>::disposeAndClear();
375 assert(VclPtr<reference_type>::get() == nullptr)(static_cast <bool> (VclPtr<reference_type>::get(
) == nullptr) ? void (0) : __assert_fail ("VclPtr<reference_type>::get() == nullptr"
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 375, __extension__ __PRETTY_FUNCTION__))
; // make sure there are no lingering references
376 }
377
378private:
379 // Most likely we don't want this default copy-constructor.
380 ScopedVclPtr (const ScopedVclPtr<reference_type> &) = delete;
381 // And certainly we don't want a default assignment operator.
382 ScopedVclPtr<reference_type>& operator = (const ScopedVclPtr<reference_type> &) = delete;
383 // And disallow reset as that doesn't call disposeAndClear on the original reference
384 void reset() = delete;
385 void reset(reference_type *pBody) = delete;
386
387protected:
388 ScopedVclPtr (reference_type * pBody, __sal_NoAcquire)
389 : VclPtr<reference_type>(pBody, SAL_NO_ACQUIRE)
390 {}
391};
392
393/**
394 * A construction helper for ScopedVclPtr. Since VclPtr types are created
395 * with a reference-count of one - to help fit into the existing
396 * code-flow; this helps us to construct them easily.
397 *
398 * For more details on the design please see vcl/README.lifecycle
399 *
400 * @param reference_type must be a subclass of vcl::Window
401 */
402#if defined _MSC_VER
403#pragma warning(push)
404#pragma warning(disable: 4521) // " multiple copy constructors specified"
405#endif
406template <class reference_type>
407class SAL_WARN_UNUSED__attribute__((warn_unused)) ScopedVclPtrInstance final : public ScopedVclPtr<reference_type>
408{
409public:
410 template<typename... Arg> ScopedVclPtrInstance(Arg &&... arg)
411 : ScopedVclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
412 {
413 }
414
415 /**
416 * Override and disallow this, to prevent people accidentally calling it and actually
417 * getting VclPtr::Create and getting a naked VclPtr<> instance
418 */
419 template<typename... Arg> static ScopedVclPtrInstance< reference_type > Create(Arg &&...) = delete;
420
421private:
422 // Prevent the above perfect forwarding ctor from hijacking (accidental)
423 // attempts at ScopedVclPtrInstance copy construction (where the hijacking
424 // would typically lead to somewhat obscure error messages); both non-const
425 // and const variants are needed here, as the ScopedVclPtr base class has a
426 // const--variant copy ctor, so the implicitly declared copy ctor for
427 // ScopedVclPtrInstance would also be the const variant, so non-const copy
428 // construction attempts would be hijacked by the perfect forwarding ctor;
429 // but if we only declared a non-const variant here, the const variant would
430 // no longer be implicitly declared (as there would already be an explicitly
431 // declared copy ctor), so const copy construction attempts would then be
432 // hijacked by the perfect forwarding ctor:
433 ScopedVclPtrInstance(ScopedVclPtrInstance &) = delete;
434 ScopedVclPtrInstance(ScopedVclPtrInstance const &) = delete;
435};
436#if defined _MSC_VER
437#pragma warning(pop)
438#endif
439
440#endif // INCLUDED_VCL_PTR_HXX
441
442/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/rtl/ref.hxx

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#ifndef INCLUDED_RTL_REF_HXX
21#define INCLUDED_RTL_REF_HXX
22
23#include "sal/config.h"
24
25#include <cassert>
26#include <cstddef>
27#include <functional>
28#ifdef LIBO_INTERNAL_ONLY1
29#include <type_traits>
30#endif
31
32#include "sal/types.h"
33
34namespace rtl
35{
36
37/** Template reference class for reference type.
38*/
39template <class reference_type>
40class Reference
41{
42 /** The <b>reference_type</b> body pointer.
43 */
44 reference_type * m_pBody;
45
46
47public:
48 /** Constructor...
49 */
50 Reference()
51 : m_pBody (NULL__null)
52 {}
53
54
55 /** Constructor...
56 */
57 Reference (reference_type * pBody, __sal_NoAcquire)
58 : m_pBody (pBody)
59 {
60 }
61
62 /** Constructor...
63 */
64 Reference (reference_type * pBody)
65 : m_pBody (pBody)
66 {
67 if (m_pBody)
68 m_pBody->acquire();
69 }
70
71 /** Copy constructor...
72 */
73 Reference (const Reference<reference_type> & handle)
74 : m_pBody (handle.m_pBody)
75 {
76 if (m_pBody)
4
Assuming field 'm_pBody' is non-null
5
Taking true branch
77 m_pBody->acquire();
78 }
79
80#ifdef LIBO_INTERNAL_ONLY1
81 /** Move constructor...
82 */
83 Reference (Reference<reference_type> && handle) noexcept
84 : m_pBody (handle.m_pBody)
85 {
86 handle.m_pBody = nullptr;
87 }
88#endif
89
90#if defined LIBO_INTERNAL_ONLY1
91 /** Up-casting conversion constructor: Copies interface reference.
92
93 Does not work for up-casts to ambiguous bases.
94
95 @param rRef another reference
96 */
97 template< class derived_type >
98 inline Reference(
99 const Reference< derived_type > & rRef,
100 std::enable_if_t<std::is_base_of_v<reference_type, derived_type>, int> = 0 )
101 : m_pBody (rRef.get())
102 {
103 if (m_pBody)
104 m_pBody->acquire();
105 }
106#endif
107
108 /** Destructor...
109 */
110 ~Reference() COVERITY_NOEXCEPT_FALSE
111 {
112 if (m_pBody)
113 m_pBody->release();
114 }
115
116 /** Set...
117 Similar to assignment.
118 */
119 Reference<reference_type> &
120 SAL_CALL set (reference_type * pBody)
121 {
122 if (pBody)
123 pBody->acquire();
124 reference_type * const pOld = m_pBody;
125 m_pBody = pBody;
126 if (pOld)
127 pOld->release();
128 return *this;
129 }
130
131 /** Assignment.
132 Unbinds this instance from its body (if bound) and
133 bind it to the body represented by the handle.
134 */
135 Reference<reference_type> &
136 SAL_CALL operator= (const Reference<reference_type> & handle)
137 {
138 return set( handle.m_pBody );
139 }
140
141#ifdef LIBO_INTERNAL_ONLY1
142 /** Assignment.
143 * Unbinds this instance from its body (if bound),
144 * bind it to the body represented by the handle, and
145 * set the body represented by the handle to nullptr.
146 */
147 Reference<reference_type> &
148 operator= (Reference<reference_type> && handle)
149 {
150 // self-movement guts ourself
151 if (m_pBody)
152 m_pBody->release();
153 m_pBody = handle.m_pBody;
154 handle.m_pBody = nullptr;
155 return *this;
156 }
157#endif
158
159 /** Assignment...
160 */
161 Reference<reference_type> &
162 SAL_CALL operator= (reference_type * pBody)
163 {
164 return set( pBody );
165 }
166
167 /** Unbind the body from this handle.
168 Note that for a handle representing a large body,
169 "handle.clear().set(new body());" _might_
170 perform a little bit better than "handle.set(new body());",
171 since in the second case two large objects exist in memory
172 (the old body and the new body).
173 */
174 Reference<reference_type> & SAL_CALL clear()
175 {
176 if (m_pBody
7.1
Field 'm_pBody' is non-null
7.1
Field 'm_pBody' is non-null
7.1
Field 'm_pBody' is non-null
7.1
Field 'm_pBody' is non-null
)
8
Taking true branch
177 {
178 reference_type * const pOld = m_pBody;
179 m_pBody = NULL__null;
180 pOld->release();
9
Calling 'VclReferenceBase::release'
13
Returning; memory was released
181 }
182 return *this;
183 }
184
185
186 /** Get the body. Can be used instead of operator->().
187 I.e. handle->someBodyOp() and handle.get()->someBodyOp()
188 are the same.
189 */
190 reference_type * SAL_CALL get() const
191 {
192 return m_pBody;
16
Use of memory after it is freed
193 }
194
195
196 /** Probably most common used: handle->someBodyOp().
197 */
198 reference_type * SAL_CALL operator->() const
199 {
200 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 200, __extension__ __PRETTY_FUNCTION__))
;
201 return m_pBody;
202 }
203
204
205 /** Allows (*handle).someBodyOp().
206 */
207 reference_type & SAL_CALL operator*() const
208 {
209 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 209, __extension__ __PRETTY_FUNCTION__))
;
210 return *m_pBody;
211 }
212
213
214 /** Returns True if the handle does point to a valid body.
215 */
216 bool SAL_CALL is() const
217 {
218 return (m_pBody != NULL__null);
219 }
220
221#if defined LIBO_INTERNAL_ONLY1
222 /** Returns True if the handle does point to a valid body.
223 */
224 explicit operator bool() const
225 {
226 return is();
227 }
228#endif
229
230 /** Returns True if this points to pBody.
231 */
232 bool SAL_CALL operator== (const reference_type * pBody) const
233 {
234 return (m_pBody == pBody);
235 }
236
237
238 /** Returns True if handle points to the same body.
239 */
240 bool
241 SAL_CALL operator== (const Reference<reference_type> & handle) const
242 {
243 return (m_pBody == handle.m_pBody);
244 }
245
246
247 /** Needed to place References into STL collection.
248 */
249 bool
250 SAL_CALL operator!= (const Reference<reference_type> & handle) const
251 {
252 return (m_pBody != handle.m_pBody);
253 }
254
255
256 /** Needed to place References into STL collection.
257 */
258 bool
259 SAL_CALL operator< (const Reference<reference_type> & handle) const
260 {
261 return (m_pBody < handle.m_pBody);
262 }
263
264
265 /** Needed to place References into STL collection.
266 */
267 bool
268 SAL_CALL operator> (const Reference<reference_type> & handle) const
269 {
270 return (m_pBody > handle.m_pBody);
271 }
272};
273
274} // namespace rtl
275
276#if defined LIBO_INTERNAL_ONLY1
277namespace std
278{
279
280/// @cond INTERNAL
281/**
282 Make rtl::Reference hashable by default for use in STL containers.
283
284 @since LibreOffice 6.3
285*/
286template<typename T>
287struct hash<::rtl::Reference<T>>
288{
289 std::size_t operator()(::rtl::Reference<T> const & s) const
290 { return std::size_t(s.get()); }
291};
292/// @endcond
293
294}
295
296#endif
297
298#endif /* ! INCLUDED_RTL_REF_HXX */
299
300/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/vcl/vclreferencebase.hxx

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#ifndef INCLUDED_VCL_Reference_HXX
20#define INCLUDED_VCL_Reference_HXX
21
22#include <vcl/dllapi.h>
23#include <osl/interlck.h>
24
25class VCL_DLLPUBLIC__attribute__ ((visibility("default"))) VclReferenceBase
26{
27 mutable oslInterlockedCount mnRefCnt;
28
29 template<typename T> friend class VclPtr;
30
31public:
32 void acquire() const
33 {
34 osl_atomic_increment(&mnRefCnt)__sync_add_and_fetch((&mnRefCnt), 1);
35 }
36
37 void release() const
38 {
39 if (osl_atomic_decrement(&mnRefCnt)__sync_sub_and_fetch((&mnRefCnt), 1) == 0)
10
Assuming the condition is true
11
Taking true branch
40 delete this;
12
Memory is released
41 }
42#ifdef DBG_UTIL
43#ifndef _WIN32
44 sal_Int32 getRefCount() const { return mnRefCnt; }
45#endif
46#endif
47
48
49private:
50 VclReferenceBase(const VclReferenceBase&) = delete;
51 VclReferenceBase& operator=(const VclReferenceBase&) = delete;
52
53 bool mbDisposed : 1;
54
55protected:
56 VclReferenceBase();
57protected:
58 virtual ~VclReferenceBase();
59
60protected:
61 virtual void dispose();
62
63public:
64 void disposeOnce();
65 bool isDisposed() const { return mbDisposed; }
66
67};
68#endif